mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-22 03:04:09 -04:00
Compare commits
7 commits
7255ad9e68
...
7da41a93be
Author | SHA1 | Date | |
---|---|---|---|
|
7da41a93be | ||
|
934db8da3b | ||
|
c6811cca29 | ||
|
91f785c574 | ||
|
bb2769a63a | ||
|
1c79d5437e | ||
|
24ccdf634b |
19 changed files with 264 additions and 141 deletions
|
@ -63,7 +63,7 @@ sudo urpmi git make pygtk2 pygtk2.0-libglade gnome-python-canvas tkinter
|
||||||
On Debian / Ubuntu / etc. you can do:
|
On Debian / Ubuntu / etc. you can do:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt-get install -y cpanminus libperl-dev make perl python-glade2 python-gnome2 python-gnome2-dev python-gtk2 python-setuptools python-tk
|
sudo apt-get install cpanminus make perl python3-setuptools python3-tk
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Step 2 - build PySol.
|
#### Step 2 - build PySol.
|
||||||
|
|
|
@ -1075,60 +1075,52 @@ Please select a %(correct_type)s type cardset.
|
||||||
# set offsets from options.cfg
|
# set offsets from options.cfg
|
||||||
if cs.ident in self.opt.offsets:
|
if cs.ident in self.opt.offsets:
|
||||||
cs.CARD_XOFFSET, cs.CARD_YOFFSET = self.opt.offsets[cs.ident]
|
cs.CARD_XOFFSET, cs.CARD_YOFFSET = self.opt.offsets[cs.ident]
|
||||||
|
|
||||||
if cs.CARDD > self.top.winfo_screendepth():
|
|
||||||
return None
|
|
||||||
return cs
|
return cs
|
||||||
|
|
||||||
def initCardsets(self):
|
def initCardsets(self):
|
||||||
|
"""Load all valid cardset config.txt files and ignore invalid ones.
|
||||||
|
"""
|
||||||
|
screendepth = self.top.winfo_screendepth()
|
||||||
manager = self.cardset_manager
|
manager = self.cardset_manager
|
||||||
# find all available cardsets
|
# find all available cardsets
|
||||||
dirs = manager.getSearchDirs(self, ("cardsets", ""), "PYSOL_CARDSETS")
|
dirs = manager.getSearchDirs(self, ("cardsets", ""), "PYSOL_CARDSETS")
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
dirs += manager.getSearchDirs(self, "cardsets-*")
|
dirs += manager.getSearchDirs(self, "cardsets-*")
|
||||||
# print dirs
|
found = []
|
||||||
found, t = [], {}
|
found_names = [] # (to check for duplicates)
|
||||||
fnames = {} # (to check for duplicates)
|
|
||||||
for dirname in dirs:
|
for dirname in dirs:
|
||||||
dirname = dirname.strip()
|
|
||||||
try:
|
try:
|
||||||
names = []
|
subdirs = [os.path.join(dirname, subdir)
|
||||||
if dirname and os.path.isdir(dirname) and dirname not in t:
|
for subdir in os.listdir(dirname)
|
||||||
t[dirname] = 1
|
if subdir.startswith('cardset-')]
|
||||||
names = os.listdir(dirname)
|
|
||||||
names.sort()
|
|
||||||
for name in names:
|
|
||||||
if not name.startswith('cardset-'):
|
|
||||||
continue
|
|
||||||
d = os.path.join(dirname, name)
|
|
||||||
if not os.path.isdir(d):
|
|
||||||
continue
|
|
||||||
f = os.path.join(d, "config.txt")
|
|
||||||
if os.path.isfile(f):
|
|
||||||
try:
|
|
||||||
cs = self._readCardsetConfig(d, f)
|
|
||||||
if cs:
|
|
||||||
# from pprint import pprint
|
|
||||||
# print cs.name
|
|
||||||
# pprint(cs.__dict__)
|
|
||||||
back = cs.backnames[cs.backindex]
|
|
||||||
f1 = os.path.join(d, back)
|
|
||||||
f2 = os.path.join(d, "shade" + cs.ext)
|
|
||||||
if (cs.ext in IMAGE_EXTENSIONS and
|
|
||||||
cs.name not in fnames and
|
|
||||||
os.path.isfile(f1) and
|
|
||||||
os.path.isfile(f2)):
|
|
||||||
found.append(cs)
|
|
||||||
# print '+', cs.name
|
|
||||||
fnames[cs.name] = 1
|
|
||||||
else:
|
|
||||||
print_err('failed to parse cardset file: %s'
|
|
||||||
% f)
|
|
||||||
except Exception:
|
|
||||||
# traceback.print_exc()
|
|
||||||
pass
|
|
||||||
except EnvironmentError:
|
except EnvironmentError:
|
||||||
pass
|
traceback.print_exc()
|
||||||
|
continue
|
||||||
|
subdirs.sort()
|
||||||
|
for d in subdirs:
|
||||||
|
config_txt_path = os.path.join(d, "config.txt")
|
||||||
|
if not os.path.isfile(config_txt_path):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
cs = self._readCardsetConfig(d, config_txt_path)
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
cs = None
|
||||||
|
if not cs:
|
||||||
|
print_err('failed to parse cardset file: %s'
|
||||||
|
% config_txt_path)
|
||||||
|
continue
|
||||||
|
back = cs.backnames[cs.backindex]
|
||||||
|
back_im_path = os.path.join(d, back)
|
||||||
|
shade_im_path = os.path.join(d, "shade" + cs.ext)
|
||||||
|
if (cs.name not in found_names and
|
||||||
|
cs.ext in IMAGE_EXTENSIONS and
|
||||||
|
cs.CARDD <= screendepth and
|
||||||
|
os.path.isfile(back_im_path) and
|
||||||
|
os.path.isfile(shade_im_path)):
|
||||||
|
found.append(cs)
|
||||||
|
found_names.append(cs.name)
|
||||||
|
|
||||||
# register cardsets
|
# register cardsets
|
||||||
for obj in found:
|
for obj in found:
|
||||||
if not manager.getByName(obj.name):
|
if not manager.getByName(obj.name):
|
||||||
|
|
|
@ -671,12 +671,19 @@ class Game(object):
|
||||||
print_err('max_rounds <= 1, but talon.texts.rounds is not None: '
|
print_err('max_rounds <= 1, but talon.texts.rounds is not None: '
|
||||||
'%s' % class_name, 2)
|
'%s' % class_name, 2)
|
||||||
|
|
||||||
|
def _calcMouseBind(self, binding_format):
|
||||||
|
"""docstring for _calcMouseBind"""
|
||||||
|
return self.app.opt.calcCustomMouseButtonsBinding(binding_format)
|
||||||
|
|
||||||
def initBindings(self):
|
def initBindings(self):
|
||||||
# note: a Game is only allowed to bind self.canvas and not to self.top
|
# note: a Game is only allowed to bind self.canvas and not to self.top
|
||||||
# bind(self.canvas, "<Double-1>", self.undoHandler)
|
# bind(self.canvas, "<Double-1>", self.undoHandler)
|
||||||
bind(self.canvas, "<1>", self.undoHandler)
|
bind(self.canvas,
|
||||||
bind(self.canvas, "<2>", self.dropHandler)
|
self._calcMouseBind("<{mouse_button1}>"), self.undoHandler)
|
||||||
bind(self.canvas, "<3>", self.redoHandler)
|
bind(self.canvas,
|
||||||
|
self._calcMouseBind("<{mouse_button2}>"), self.dropHandler)
|
||||||
|
bind(self.canvas,
|
||||||
|
self._calcMouseBind("<{mouse_button3}>"), self.redoHandler)
|
||||||
bind(self.canvas, '<Unmap>', self._unmapHandler)
|
bind(self.canvas, '<Unmap>', self._unmapHandler)
|
||||||
bind(self.canvas, '<Configure>', self._configureHandler, add=True)
|
bind(self.canvas, '<Configure>', self._configureHandler, add=True)
|
||||||
|
|
||||||
|
|
|
@ -222,6 +222,9 @@ class Mahjongg_RowStack(OpenStack):
|
||||||
for s in self.game.s.rows[self.id+1:]:
|
for s in self.game.s.rows[self.id+1:]:
|
||||||
s.group.tkraise()
|
s.group.tkraise()
|
||||||
|
|
||||||
|
def _calcMouseBind(self, binding_format):
|
||||||
|
return self.game.app.opt.calcCustomMouseButtonsBinding(binding_format)
|
||||||
|
|
||||||
# In Mahjongg games type there are a lot of stacks, so we optimize
|
# In Mahjongg games type there are a lot of stacks, so we optimize
|
||||||
# and don't create bindings that are not used anyway.
|
# and don't create bindings that are not used anyway.
|
||||||
def initBindings(self):
|
def initBindings(self):
|
||||||
|
@ -231,9 +234,21 @@ class Mahjongg_RowStack(OpenStack):
|
||||||
# bind(group, "<3>", self._Stack__controlclickEventHandler)
|
# bind(group, "<3>", self._Stack__controlclickEventHandler)
|
||||||
# bind(group, "<Control-1>", self._Stack__controlclickEventHandler)
|
# bind(group, "<Control-1>", self._Stack__controlclickEventHandler)
|
||||||
#
|
#
|
||||||
bind(group, "<1>", self.__clickEventHandler)
|
bind(
|
||||||
bind(group, "<3>", self.__controlclickEventHandler)
|
group,
|
||||||
bind(group, "<Control-1>", self.__controlclickEventHandler)
|
self._calcMouseBind("<{mouse_button1}>"),
|
||||||
|
self.__clickEventHandler
|
||||||
|
)
|
||||||
|
bind(
|
||||||
|
group,
|
||||||
|
self._calcMouseBind("<{mouse_button3}>"),
|
||||||
|
self.__controlclickEventHandler
|
||||||
|
)
|
||||||
|
bind(
|
||||||
|
group,
|
||||||
|
self._calcMouseBind("<Control-{mouse_button1}>"),
|
||||||
|
self.__controlclickEventHandler
|
||||||
|
)
|
||||||
# bind(group, "<Enter>", self._Stack__enterEventHandler)
|
# bind(group, "<Enter>", self._Stack__enterEventHandler)
|
||||||
# bind(group, "<Leave>", self._Stack__leaveEventHandler)
|
# bind(group, "<Leave>", self._Stack__leaveEventHandler)
|
||||||
|
|
||||||
|
|
|
@ -60,9 +60,20 @@ class Matrix_RowStack(OpenStack):
|
||||||
# the tile (from Tk's stacking view)
|
# the tile (from Tk's stacking view)
|
||||||
return len(self.cards) - 1
|
return len(self.cards) - 1
|
||||||
|
|
||||||
|
def _calcMouseBind(self, binding_format):
|
||||||
|
return self.game.app.opt.calcCustomMouseButtonsBinding(binding_format)
|
||||||
|
|
||||||
def initBindings(self):
|
def initBindings(self):
|
||||||
bind(self.group, "<1>", self._Stack__clickEventHandler)
|
bind(
|
||||||
bind(self.group, "<Control-1>", self._Stack__controlclickEventHandler)
|
self.group,
|
||||||
|
self._calcMouseBind("<{mouse_button1}>"),
|
||||||
|
self._Stack__clickEventHandler
|
||||||
|
)
|
||||||
|
bind(
|
||||||
|
self.group,
|
||||||
|
self._calcMouseBind("<Control-{mouse_button1}>"),
|
||||||
|
self._Stack__controlclickEventHandler,
|
||||||
|
)
|
||||||
|
|
||||||
def getBottomImage(self):
|
def getBottomImage(self):
|
||||||
return self.game.app.images.getBlankBottom()
|
return self.game.app.images.getBlankBottom()
|
||||||
|
|
|
@ -117,7 +117,7 @@ def init():
|
||||||
else:
|
else:
|
||||||
pysollib.settings.USE_TILE = True
|
pysollib.settings.USE_TILE = True
|
||||||
# "can't invoke event <<ThemeChanged>>: application has been destroyed"
|
# "can't invoke event <<ThemeChanged>>: application has been destroyed"
|
||||||
# root.destroy()
|
root.destroy()
|
||||||
tkinter._default_root = None
|
tkinter._default_root = None
|
||||||
|
|
||||||
# check FreeCell-Solver
|
# check FreeCell-Solver
|
||||||
|
|
|
@ -43,6 +43,17 @@ import validate
|
||||||
# * Options
|
# * Options
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
|
||||||
|
_global_settings = {}
|
||||||
|
|
||||||
|
|
||||||
|
def calcCustomMouseButtonsBinding(binding_format):
|
||||||
|
assert _global_settings['mouse_button1']
|
||||||
|
return binding_format.format(
|
||||||
|
mouse_button1=_global_settings['mouse_button1'],
|
||||||
|
mouse_button2=_global_settings['mouse_button2'],
|
||||||
|
mouse_button3=_global_settings['mouse_button3'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
configspec = '''
|
configspec = '''
|
||||||
[general]
|
[general]
|
||||||
|
@ -253,6 +264,9 @@ class Options:
|
||||||
('solver_max_iterations', 'int'),
|
('solver_max_iterations', 'int'),
|
||||||
('solver_iterations_output_step', 'int'),
|
('solver_iterations_output_step', 'int'),
|
||||||
('solver_preset', 'string'),
|
('solver_preset', 'string'),
|
||||||
|
('mouse_button1', 'int'),
|
||||||
|
('mouse_button2', 'int'),
|
||||||
|
('mouse_button3', 'int'),
|
||||||
# ('toolbar_vars', 'list'),
|
# ('toolbar_vars', 'list'),
|
||||||
# ('recent_gameid', 'list'),
|
# ('recent_gameid', 'list'),
|
||||||
# ('favorite_gameid', 'list'),
|
# ('favorite_gameid', 'list'),
|
||||||
|
@ -320,6 +334,9 @@ class Options:
|
||||||
self.num_cards = False
|
self.num_cards = False
|
||||||
self.helpbar = False
|
self.helpbar = False
|
||||||
self.splashscreen = True
|
self.splashscreen = True
|
||||||
|
self.mouse_button1 = 1
|
||||||
|
self.mouse_button2 = 2
|
||||||
|
self.mouse_button3 = 3
|
||||||
self.mouse_type = 'drag-n-drop' # or 'sticky-mouse' or 'point-n-click'
|
self.mouse_type = 'drag-n-drop' # or 'sticky-mouse' or 'point-n-click'
|
||||||
self.mouse_undo = False # use mouse for undo/redo
|
self.mouse_undo = False # use mouse for undo/redo
|
||||||
self.negative_bottom = True
|
self.negative_bottom = True
|
||||||
|
@ -751,3 +768,20 @@ class Options:
|
||||||
self.offsets[key] = val
|
self.offsets[key] = val
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# mouse buttons swap
|
||||||
|
def _positive(button):
|
||||||
|
return max([button, 1])
|
||||||
|
_global_settings['mouse_button1'] = _positive(self.mouse_button1)
|
||||||
|
_global_settings['mouse_button2'] = _positive(self.mouse_button2)
|
||||||
|
_global_settings['mouse_button3'] = _positive(self.mouse_button3)
|
||||||
|
|
||||||
|
def calcCustomMouseButtonsBinding(self, binding_format):
|
||||||
|
"""docstring for calcCustomMouseButtonsBinding"""
|
||||||
|
def _positive(button):
|
||||||
|
return max([button, 1])
|
||||||
|
return binding_format.format(
|
||||||
|
mouse_button1=_positive(self.mouse_button1),
|
||||||
|
mouse_button2=_positive(self.mouse_button2),
|
||||||
|
mouse_button3=_positive(self.mouse_button3),
|
||||||
|
)
|
||||||
|
|
|
@ -123,6 +123,8 @@ class ResourceManager:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getSearchDirs(self, app, search, env=None):
|
def getSearchDirs(self, app, search, env=None):
|
||||||
|
"""Get a list of normalized directory paths. The returned list has no
|
||||||
|
duplicates."""
|
||||||
if isinstance(search, str):
|
if isinstance(search, str):
|
||||||
search = (search,)
|
search = (search,)
|
||||||
result = []
|
result = []
|
||||||
|
|
|
@ -269,22 +269,35 @@ class Stack:
|
||||||
if self.is_visible:
|
if self.is_visible:
|
||||||
self.initBindings()
|
self.initBindings()
|
||||||
|
|
||||||
|
def _calcMouseBind(self, binding_format):
|
||||||
|
return self.game.app.opt.calcCustomMouseButtonsBinding(binding_format)
|
||||||
|
|
||||||
# bindings {view widgets bind to controller}
|
# bindings {view widgets bind to controller}
|
||||||
def initBindings(self):
|
def initBindings(self):
|
||||||
group = self.group
|
group = self.group
|
||||||
bind(group, "<1>", self.__clickEventHandler)
|
bind(group, self._calcMouseBind("<{mouse_button1}>"),
|
||||||
|
self.__clickEventHandler)
|
||||||
# bind(group, "<B1-Motion>", self.__motionEventHandler)
|
# bind(group, "<B1-Motion>", self.__motionEventHandler)
|
||||||
bind(group, "<Motion>", self.__motionEventHandler)
|
bind(group, "<Motion>", self.__motionEventHandler)
|
||||||
bind(group, "<ButtonRelease-1>", self.__releaseEventHandler)
|
bind(group, self._calcMouseBind("<ButtonRelease-{mouse_button1}>"),
|
||||||
bind(group, "<Control-1>", self.__controlclickEventHandler)
|
self.__releaseEventHandler)
|
||||||
bind(group, "<Shift-1>", self.__shiftclickEventHandler)
|
bind(group, self._calcMouseBind("<Control-{mouse_button1}>"),
|
||||||
bind(group, "<Double-1>", self.__doubleclickEventHandler)
|
self.__controlclickEventHandler)
|
||||||
bind(group, "<3>", self.__rightclickEventHandler)
|
bind(group, self._calcMouseBind("<Shift-{mouse_button1}>"),
|
||||||
bind(group, "<2>", self.__middleclickEventHandler)
|
self.__shiftclickEventHandler)
|
||||||
bind(group, "<Control-3>", self.__middleclickEventHandler)
|
bind(group, self._calcMouseBind("<Double-{mouse_button1}>"),
|
||||||
# bind(group, "<Control-2>", self.__controlmiddleclickEventHandler)
|
self.__doubleclickEventHandler)
|
||||||
# bind(group, "<Shift-3>", self.__shiftrightclickEventHandler)
|
bind(group, self._calcMouseBind("<{mouse_button3}>"),
|
||||||
# bind(group, "<Double-2>", "")
|
self.__rightclickEventHandler)
|
||||||
|
bind(group, self._calcMouseBind("<{mouse_button2}>"),
|
||||||
|
self.__middleclickEventHandler)
|
||||||
|
bind(group, self._calcMouseBind("<Control-{mouse_button3}>"),
|
||||||
|
self.__middleclickEventHandler)
|
||||||
|
# bind(group, self._calcMouseBind(
|
||||||
|
# "<Control-{mouse_button2}>"), self.__controlmiddleclickEventHandler)
|
||||||
|
# bind(group, self._calcMouseBind("<Shift-{mouse_button3}>"),
|
||||||
|
# self.__shiftrightclickEventHandler)
|
||||||
|
# bind(group, self._calcMouseBind("<Double-{mouse_button2}>"), "")
|
||||||
bind(group, "<Enter>", self.__enterEventHandler)
|
bind(group, "<Enter>", self.__enterEventHandler)
|
||||||
bind(group, "<Leave>", self.__leaveEventHandler)
|
bind(group, "<Leave>", self.__leaveEventHandler)
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,30 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
self.scale_y.grid(
|
self.scale_y.grid(
|
||||||
row=2, column=0, sticky='ew', padx=padx, pady=pady)
|
row=2, column=0, sticky='ew', padx=padx, pady=pady)
|
||||||
#
|
#
|
||||||
|
# sliders at new position
|
||||||
|
cs = self.manager.get(self.tree.selection_key)
|
||||||
|
|
||||||
|
var = tkinter.IntVar()
|
||||||
|
self.x_offset = PysolScale(
|
||||||
|
left_frame, label=_('X offset:'),
|
||||||
|
from_=5, to=100, resolution=1,
|
||||||
|
orient='horizontal', variable=var,
|
||||||
|
value=cs.CARD_XOFFSET
|
||||||
|
)
|
||||||
|
|
||||||
|
self.x_offset.grid(row=3, column=0, sticky='ew',
|
||||||
|
padx=padx, pady=pady)
|
||||||
|
|
||||||
|
var = tkinter.IntVar()
|
||||||
|
self.y_offset = PysolScale(
|
||||||
|
left_frame, label=_('Y offset:'),
|
||||||
|
from_=5, to=100, resolution=1,
|
||||||
|
orient='horizontal', variable=var,
|
||||||
|
value=cs.CARD_YOFFSET
|
||||||
|
)
|
||||||
|
self.y_offset.grid(row=4, column=0, sticky='ew',
|
||||||
|
padx=padx, pady=pady)
|
||||||
|
|
||||||
self.auto_scale = tkinter.BooleanVar()
|
self.auto_scale = tkinter.BooleanVar()
|
||||||
self.auto_scale.set(app.opt.auto_scale)
|
self.auto_scale.set(app.opt.auto_scale)
|
||||||
check = ttk.Checkbutton(
|
check = ttk.Checkbutton(
|
||||||
|
@ -272,7 +296,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
takefocus=False,
|
takefocus=False,
|
||||||
command=self._updateAutoScale
|
command=self._updateAutoScale
|
||||||
)
|
)
|
||||||
check.grid(row=3, column=0, columnspan=2, sticky='ew',
|
check.grid(row=5, column=0, columnspan=2, sticky='ew',
|
||||||
padx=padx, pady=pady)
|
padx=padx, pady=pady)
|
||||||
#
|
#
|
||||||
self.preserve_aspect = tkinter.BooleanVar()
|
self.preserve_aspect = tkinter.BooleanVar()
|
||||||
|
@ -283,7 +307,7 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
takefocus=False,
|
takefocus=False,
|
||||||
# command=self._updateScale
|
# command=self._updateScale
|
||||||
)
|
)
|
||||||
self.aspect_check.grid(row=4, column=0, sticky='ew',
|
self.aspect_check.grid(row=6, column=0, sticky='ew',
|
||||||
padx=padx, pady=pady)
|
padx=padx, pady=pady)
|
||||||
self._updateAutoScale()
|
self._updateAutoScale()
|
||||||
#
|
#
|
||||||
|
@ -312,9 +336,6 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
MfxDialog.destroy(self)
|
MfxDialog.destroy(self)
|
||||||
|
|
||||||
def initKw(self, kw):
|
def initKw(self, kw):
|
||||||
if USE_PIL:
|
|
||||||
s = (_("&Info / Settings..."), 10)
|
|
||||||
else:
|
|
||||||
s = (_("&Info..."), 10)
|
s = (_("&Info..."), 10)
|
||||||
kw = KwStruct(kw,
|
kw = KwStruct(kw,
|
||||||
strings=(s, 'sep',
|
strings=(s, 'sep',
|
||||||
|
@ -328,10 +349,21 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
if button in (0, 1): # Load/Cancel
|
if button in (0, 1): # Load/Cancel
|
||||||
self.key = self.tree.selection_key
|
self.key = self.tree.selection_key
|
||||||
self.tree.n_expansions = 1 # save xyview in any case
|
self.tree.n_expansions = 1 # save xyview in any case
|
||||||
|
|
||||||
|
# save the values
|
||||||
|
try:
|
||||||
|
self.cardset_values = self.x_offset.get(), self.y_offset.get()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
if USE_PIL:
|
if USE_PIL:
|
||||||
auto_scale = bool(self.auto_scale.get())
|
auto_scale = bool(self.auto_scale.get())
|
||||||
if button == 1:
|
if button == 1:
|
||||||
self.app.menubar.tkopt.auto_scale.set(auto_scale)
|
self.app.menubar.tkopt.auto_scale.set(auto_scale)
|
||||||
|
|
||||||
|
# no changes
|
||||||
|
self.cardset_values = None
|
||||||
|
|
||||||
if auto_scale:
|
if auto_scale:
|
||||||
self.scale_values = (self.app.opt.scale_x,
|
self.scale_values = (self.app.opt.scale_x,
|
||||||
self.app.opt.scale_y,
|
self.app.opt.scale_y,
|
||||||
|
@ -350,7 +382,11 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
title = CARDSET.capitalize()+" "+cs.name
|
title = CARDSET.capitalize()+" "+cs.name
|
||||||
d = CardsetInfoDialog(self.top, title=title, cardset=cs,
|
d = CardsetInfoDialog(self.top, title=title, cardset=cs,
|
||||||
images=self.preview_images)
|
images=self.preview_images)
|
||||||
|
try:
|
||||||
self.cardset_values = d.cardset_values
|
self.cardset_values = d.cardset_values
|
||||||
|
except Exception:
|
||||||
|
self.cardset_values = None
|
||||||
|
|
||||||
return
|
return
|
||||||
MfxDialog.mDone(self, button)
|
MfxDialog.mDone(self, button)
|
||||||
|
|
||||||
|
@ -380,6 +416,15 @@ class SelectCardsetDialogWithPreview(MfxDialog):
|
||||||
self.preview_key = -1
|
self.preview_key = -1
|
||||||
return
|
return
|
||||||
names, columns = cs.getPreviewCardNames()
|
names, columns = cs.getPreviewCardNames()
|
||||||
|
|
||||||
|
# if cardset has changed, set default values
|
||||||
|
if key != self.preview_key:
|
||||||
|
self.x_offset.config(value=cs.CARD_XOFFSET)
|
||||||
|
self.x_offset.set(cs.CARD_XOFFSET)
|
||||||
|
|
||||||
|
self.y_offset.config(value=cs.CARD_YOFFSET)
|
||||||
|
self.y_offset.set(cs.CARD_YOFFSET)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# ???names, columns = cs.getPreviewCardNames()
|
# ???names, columns = cs.getPreviewCardNames()
|
||||||
for n in names:
|
for n in names:
|
||||||
|
@ -482,39 +527,13 @@ class CardsetInfoDialog(MfxDialog):
|
||||||
info_frame.rowconfigure(frow, weight=1)
|
info_frame.rowconfigure(frow, weight=1)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
if USE_PIL:
|
|
||||||
padx = 4
|
|
||||||
pady = 0
|
|
||||||
settings_frame = ttk.LabelFrame(frame, text=_('Settings'))
|
|
||||||
settings_frame.grid(row=row, column=0, columnspan=2, sticky='ew',
|
|
||||||
padx=0, pady=5, ipadx=5, ipady=5)
|
|
||||||
row += 1
|
|
||||||
var = tkinter.IntVar()
|
|
||||||
self.x_offset = PysolScale(
|
|
||||||
settings_frame, label=_('X offset:'),
|
|
||||||
from_=5, to=40, resolution=1,
|
|
||||||
orient='horizontal', variable=var,
|
|
||||||
value=cardset.CARD_XOFFSET,
|
|
||||||
# command=self._updateScale
|
|
||||||
)
|
|
||||||
self.x_offset.grid(row=0, column=0, sticky='ew',
|
|
||||||
padx=padx, pady=pady)
|
|
||||||
var = tkinter.IntVar()
|
|
||||||
self.y_offset = PysolScale(
|
|
||||||
settings_frame, label=_('Y offset:'),
|
|
||||||
from_=5, to=40, resolution=1,
|
|
||||||
orient='horizontal', variable=var,
|
|
||||||
value=cardset.CARD_YOFFSET,
|
|
||||||
# command=self._updateScale
|
|
||||||
)
|
|
||||||
self.y_offset.grid(row=1, column=0, sticky='ew',
|
|
||||||
padx=padx, pady=pady)
|
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
# bg = top_frame["bg"]
|
# bg = top_frame["bg"]
|
||||||
bg = 'white'
|
bg = 'white'
|
||||||
text_w = tkinter.Text(frame, bd=1, relief="sunken", wrap="word",
|
text_w = tkinter.Text(frame, bd=1, relief="sunken", wrap="word",
|
||||||
padx=4, width=64, height=16, bg=bg)
|
padx=4, width=64, height=8, bg=bg)
|
||||||
text_w.grid(row=row, column=0, sticky='nsew')
|
text_w.grid(row=row, column=0, sticky='nsew')
|
||||||
sb = ttk.Scrollbar(frame)
|
sb = ttk.Scrollbar(frame)
|
||||||
sb.grid(row=row, column=1, sticky='ns')
|
sb.grid(row=row, column=1, sticky='ns')
|
||||||
|
@ -538,23 +557,3 @@ class CardsetInfoDialog(MfxDialog):
|
||||||
focus = self.createButtons(bottom_frame, kw)
|
focus = self.createButtons(bottom_frame, kw)
|
||||||
# focus = text_w
|
# focus = text_w
|
||||||
self.mainloop(focus, kw.timeout)
|
self.mainloop(focus, kw.timeout)
|
||||||
|
|
||||||
def initKw(self, kw):
|
|
||||||
if USE_PIL:
|
|
||||||
strings = (_("&Save"), _("&Cancel"))
|
|
||||||
else:
|
|
||||||
strings = (_("&OK"),)
|
|
||||||
kw = KwStruct(kw,
|
|
||||||
strings=strings,
|
|
||||||
default=0,
|
|
||||||
resizable=True,
|
|
||||||
separator=True,
|
|
||||||
)
|
|
||||||
return MfxDialog.initKw(self, kw)
|
|
||||||
|
|
||||||
def mDone(self, button):
|
|
||||||
if USE_PIL and button == 0:
|
|
||||||
self.cardset_values = self.x_offset.get(), self.y_offset.get()
|
|
||||||
else:
|
|
||||||
self.cardset_values = None
|
|
||||||
MfxDialog.mDone(self, button)
|
|
||||||
|
|
|
@ -244,9 +244,20 @@ class MfxTreeInCanvas(MfxScrolledCanvas):
|
||||||
# self.style.text_normal_bg = self.canvas.option_get(
|
# self.style.text_normal_bg = self.canvas.option_get(
|
||||||
# 'background', self.canvas.cget("background"))
|
# 'background', self.canvas.cget("background"))
|
||||||
#
|
#
|
||||||
bind(self.canvas, "<ButtonPress-1>", self.singleClick)
|
from pysollib.options import calcCustomMouseButtonsBinding
|
||||||
bind(self.canvas, "<Double-Button-1>", self.doubleClick)
|
bind(
|
||||||
# bind(self.canvas, "<ButtonRelease-1>", xxx)
|
self.canvas,
|
||||||
|
calcCustomMouseButtonsBinding("<ButtonPress-{mouse_button1}>"),
|
||||||
|
self.singleClick
|
||||||
|
)
|
||||||
|
bind(
|
||||||
|
self.canvas,
|
||||||
|
calcCustomMouseButtonsBinding("<Double-Button-{mouse_button1}>"),
|
||||||
|
self.doubleClick
|
||||||
|
)
|
||||||
|
# bind(self.canvas,
|
||||||
|
# calcCustomMouseButtonsBinding(
|
||||||
|
# "<ButtonRelease-{mouse_button1}>"), xxx)
|
||||||
self.pack(fill='both', expand=True)
|
self.pack(fill='both', expand=True)
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
|
|
|
@ -320,7 +320,11 @@ class PysolAboutDialog(MfxMessageDialog):
|
||||||
url_label = ttk.Label(frame, text=kw.url, font=font,
|
url_label = ttk.Label(frame, text=kw.url, font=font,
|
||||||
foreground='blue', cursor='hand2')
|
foreground='blue', cursor='hand2')
|
||||||
url_label.pack()
|
url_label.pack()
|
||||||
url_label.bind('<1>', self._urlClicked)
|
from pysollib.options import calcCustomMouseButtonsBinding
|
||||||
|
url_label.bind(
|
||||||
|
calcCustomMouseButtonsBinding('<{mouse_button1}>'),
|
||||||
|
self._urlClicked
|
||||||
|
)
|
||||||
#
|
#
|
||||||
focus = self.createButtons(bottom_frame, kw)
|
focus = self.createButtons(bottom_frame, kw)
|
||||||
self.mainloop(focus, kw.timeout)
|
self.mainloop(focus, kw.timeout)
|
||||||
|
|
|
@ -158,6 +158,7 @@ class PysolToolbarTk:
|
||||||
|
|
||||||
def __init__(self, top, menubar, dir,
|
def __init__(self, top, menubar, dir,
|
||||||
size=0, relief='flat', compound='none'):
|
size=0, relief='flat', compound='none'):
|
||||||
|
from pysollib.options import calcCustomMouseButtonsBinding
|
||||||
self.top = top
|
self.top = top
|
||||||
self.menubar = menubar
|
self.menubar = menubar
|
||||||
self.side = -1
|
self.side = -1
|
||||||
|
@ -192,7 +193,10 @@ class PysolToolbarTk:
|
||||||
):
|
):
|
||||||
if label is None:
|
if label is None:
|
||||||
sep = self._createSeparator()
|
sep = self._createSeparator()
|
||||||
sep.bind("<3>", self.rightclickHandler)
|
sep.bind(
|
||||||
|
calcCustomMouseButtonsBinding("<{mouse_button3}>"),
|
||||||
|
self.rightclickHandler
|
||||||
|
)
|
||||||
elif label == 'Pause':
|
elif label == 'Pause':
|
||||||
self._createButton(label, f, check=True, tooltip=t)
|
self._createButton(label, f, check=True, tooltip=t)
|
||||||
else:
|
else:
|
||||||
|
@ -209,8 +213,14 @@ class PysolToolbarTk:
|
||||||
self._createLabel("player", label=n_('Player'),
|
self._createLabel("player", label=n_('Player'),
|
||||||
tooltip=_("Player options"))
|
tooltip=_("Player options"))
|
||||||
#
|
#
|
||||||
self.player_label.bind("<1>", self.mOptPlayerOptions)
|
self.player_label.bind(
|
||||||
self.frame.bind("<3>", self.rightclickHandler)
|
calcCustomMouseButtonsBinding("<{mouse_button1}>"),
|
||||||
|
self.mOptPlayerOptions
|
||||||
|
)
|
||||||
|
self.frame.bind(
|
||||||
|
calcCustomMouseButtonsBinding("<{mouse_button3}>"),
|
||||||
|
self.rightclickHandler
|
||||||
|
)
|
||||||
#
|
#
|
||||||
self.setCompound(compound, force=True)
|
self.setCompound(compound, force=True)
|
||||||
|
|
||||||
|
|
|
@ -487,7 +487,12 @@ class AllGames_StatsDialog(MfxDialog):
|
||||||
self.nodes = {}
|
self.nodes = {}
|
||||||
self.canvas = self.sc.canvas
|
self.canvas = self.sc.canvas
|
||||||
self.canvas.dialog = self
|
self.canvas.dialog = self
|
||||||
bind(self.canvas, "<1>", self.singleClick)
|
from pysollib.options import calcCustomMouseButtonsBinding
|
||||||
|
bind(
|
||||||
|
self.canvas,
|
||||||
|
calcCustomMouseButtonsBinding("<{mouse_button1}>"),
|
||||||
|
self.singleClick
|
||||||
|
)
|
||||||
self.fillCanvas(player, title)
|
self.fillCanvas(player, title)
|
||||||
bbox = self.canvas.bbox("all")
|
bbox = self.canvas.bbox("all")
|
||||||
# print bbox
|
# print bbox
|
||||||
|
|
|
@ -171,7 +171,17 @@ class PysolToolbarTk:
|
||||||
#
|
#
|
||||||
self.frame = tkinter.Frame(top, relief=TkSettings.toolbar_relief,
|
self.frame = tkinter.Frame(top, relief=TkSettings.toolbar_relief,
|
||||||
bd=TkSettings.toolbar_borderwidth)
|
bd=TkSettings.toolbar_borderwidth)
|
||||||
#
|
|
||||||
|
from pysollib.options import calcCustomMouseButtonsBinding
|
||||||
|
|
||||||
|
def _bind2sep(sep):
|
||||||
|
sep.bind(
|
||||||
|
calcCustomMouseButtonsBinding("<{mouse_button1}>"),
|
||||||
|
self.clickHandler)
|
||||||
|
sep.bind(
|
||||||
|
calcCustomMouseButtonsBinding("<{mouse_button3}>"),
|
||||||
|
self.rightclickHandler)
|
||||||
|
|
||||||
for label, f, t in (
|
for label, f, t in (
|
||||||
(n_("New"), self.mNewGame, _("New game")),
|
(n_("New"), self.mNewGame, _("New game")),
|
||||||
(n_("Restart"), self.mRestart, _("Restart the\ncurrent game")),
|
(n_("Restart"), self.mRestart, _("Restart the\ncurrent game")),
|
||||||
|
@ -192,8 +202,7 @@ class PysolToolbarTk:
|
||||||
):
|
):
|
||||||
if label is None:
|
if label is None:
|
||||||
sep = self._createSeparator()
|
sep = self._createSeparator()
|
||||||
sep.bind("<1>", self.clickHandler)
|
_bind2sep(sep)
|
||||||
sep.bind("<3>", self.rightclickHandler)
|
|
||||||
elif label == 'Pause':
|
elif label == 'Pause':
|
||||||
self._createButton(label, f, check=True, tooltip=t)
|
self._createButton(label, f, check=True, tooltip=t)
|
||||||
else:
|
else:
|
||||||
|
@ -201,17 +210,17 @@ class PysolToolbarTk:
|
||||||
self.pause_button.config(variable=menubar.tkopt.pause)
|
self.pause_button.config(variable=menubar.tkopt.pause)
|
||||||
|
|
||||||
sep = self._createFlatSeparator()
|
sep = self._createFlatSeparator()
|
||||||
sep.bind("<1>", self.clickHandler)
|
_bind2sep(sep)
|
||||||
sep.bind("<3>", self.rightclickHandler)
|
|
||||||
self._createLabel("player", label=n_('Player'),
|
self._createLabel("player", label=n_('Player'),
|
||||||
tooltip=_("Player options"))
|
tooltip=_("Player options"))
|
||||||
#
|
#
|
||||||
self.player_label.bind("<1>", self.mOptPlayerOptions)
|
self.player_label.bind(
|
||||||
|
calcCustomMouseButtonsBinding("<{mouse_button1}>"),
|
||||||
|
self.mOptPlayerOptions)
|
||||||
# self.player_label.bind("<3>",self.mOptPlayerOptions)
|
# self.player_label.bind("<3>",self.mOptPlayerOptions)
|
||||||
self.popup = MfxMenu(master=None, label=n_('Toolbar'), tearoff=0)
|
self.popup = MfxMenu(master=None, label=n_('Toolbar'), tearoff=0)
|
||||||
createToolbarMenu(menubar, self.popup)
|
createToolbarMenu(menubar, self.popup)
|
||||||
self.frame.bind("<1>", self.clickHandler)
|
_bind2sep(self.frame)
|
||||||
self.frame.bind("<3>", self.rightclickHandler)
|
|
||||||
#
|
#
|
||||||
self.setCompound(compound, force=True)
|
self.setCompound(compound, force=True)
|
||||||
|
|
||||||
|
|
|
@ -646,7 +646,13 @@ class PysolMenubarTkCommon:
|
||||||
if self.progress:
|
if self.progress:
|
||||||
self.progress.update(step=1)
|
self.progress.update(step=1)
|
||||||
|
|
||||||
|
# macOS: tk creates the menu item "Help->PySolFC Help", therefore
|
||||||
|
# we will not create a duplicate "Help->Contents" item.
|
||||||
|
# The tk-provided menu item expects this callback.
|
||||||
|
self.top.createcommand('tk::mac::ShowHelp', self.mHelp)
|
||||||
|
|
||||||
menu = MfxMenu(self.menubar, label=n_("&Help"))
|
menu = MfxMenu(self.menubar, label=n_("&Help"))
|
||||||
|
if WIN_SYSTEM != "aqua":
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
label=n_("&Contents"),
|
label=n_("&Contents"),
|
||||||
command=self.mHelp, accelerator=m+"F1")
|
command=self.mHelp, accelerator=m+"F1")
|
||||||
|
|
|
@ -104,7 +104,11 @@ class tkHTMLWriter(formatter.NullWriter):
|
||||||
url = self.anchor[0]
|
url = self.anchor[0]
|
||||||
tag = "href_" + url
|
tag = "href_" + url
|
||||||
self.text.tag_add(tag, self.anchor_mark, "insert")
|
self.text.tag_add(tag, self.anchor_mark, "insert")
|
||||||
self.text.tag_bind(tag, "<1>", self.createCallback(url))
|
from pysollib.options import calcCustomMouseButtonsBinding
|
||||||
|
self.text.tag_bind(
|
||||||
|
tag,
|
||||||
|
calcCustomMouseButtonsBinding("<{mouse_button1}>"),
|
||||||
|
self.createCallback(url))
|
||||||
self.text.tag_bind(
|
self.text.tag_bind(
|
||||||
tag, "<Enter>", lambda e: self.anchor_enter(url))
|
tag, "<Enter>", lambda e: self.anchor_enter(url))
|
||||||
self.text.tag_bind(tag, "<Leave>", self.anchor_leave)
|
self.text.tag_bind(tag, "<Leave>", self.anchor_leave)
|
||||||
|
|
|
@ -112,6 +112,7 @@ def make_help_toplevel(app, title=None):
|
||||||
from pysollib.winsystems import init_root_window
|
from pysollib.winsystems import init_root_window
|
||||||
window = tkinter.Toplevel(class_=TITLE)
|
window = tkinter.Toplevel(class_=TITLE)
|
||||||
init_root_window(window, app)
|
init_root_window(window, app)
|
||||||
|
window.tkraise()
|
||||||
return window
|
return window
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Usage:
|
Command to create a macOS app bundle:
|
||||||
python setup.py py2app
|
PYTHONPATH=. python3 setup_osx.py py2app
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
Loading…
Add table
Reference in a new issue