1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00
This commit is contained in:
Shlomi Fish 2017-04-17 18:16:53 +03:00
parent 414d78aff7
commit b53d1d163c
15 changed files with 929 additions and 574 deletions

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,4 +19,4 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,7 +19,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
__all__ = ['Card'] __all__ = ['Card']
@ -42,12 +42,12 @@ class _HideableCard(AbstractCard):
return return
self.item.config(state="hidden") self.item.config(state="hidden")
self.hide_stack = stack self.hide_stack = stack
##print "hide:", self.id, self.item.coords() # print "hide:", self.id, self.item.coords()
def unhide(self): def unhide(self):
if self.hide_stack is None: if self.hide_stack is None:
return 0 return 0
##print "unhide:", self.id, self.item.coords() # print "unhide:", self.id, self.item.coords()
self.item.config(state="normal") self.item.config(state="normal")
self.hide_stack = None self.hide_stack = None
return 1 return 1
@ -70,9 +70,10 @@ class _OneImageCard(_HideableCard):
self._back_image = game.getCardBackImage(deck, suit, rank) self._back_image = game.getCardBackImage(deck, suit, rank)
self._shade_image = game.getCardShadeImage() self._shade_image = game.getCardShadeImage()
self._active_image = self._back_image self._active_image = self._back_image
self.item = MfxCanvasImage(game.canvas, self.x, self.y, image=self._active_image, anchor="nw") self.item = MfxCanvasImage(
game.canvas, self.x, self.y, image=self._active_image, anchor="nw")
self.shade_item = None self.shade_item = None
##self._setImage = self.item.config # self._setImage = self.item.config
def _setImage(self, image): def _setImage(self, image):
if image is not self._active_image: if image is not self._active_image:
@ -181,8 +182,12 @@ class _TwoImageCard(_HideableCard):
def __init__(self, id, deck, suit, rank, game, x=0, y=0): def __init__(self, id, deck, suit, rank, game, x=0, y=0):
_HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y) _HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y)
self.item = MfxCanvasGroup(game.canvas) self.item = MfxCanvasGroup(game.canvas)
self.__face = MfxCanvasImage(game.canvas, self.x, self.y, image=game.getCardFaceImage(deck, suit, rank), anchor="nw") self.__face = MfxCanvasImage(
self.__back = MfxCanvasImage(game.canvas, self.x, self.y, image=game.getCardBackImage(deck, suit, rank), anchor="nw") game.canvas, self.x, self.y, image=game.getCardFaceImage(
deck, suit, rank), anchor="nw")
self.__back = MfxCanvasImage(
game.canvas, self.x, self.y, image=game.getCardBackImage(
deck, suit, rank), anchor="nw")
self.__face.addtag(self.item) self.__face.addtag(self.item)
self.__back.addtag(self.item) self.__back.addtag(self.item)
@ -216,15 +221,19 @@ class _TwoImageCardWithHideItem(_HideableCard):
def __init__(self, id, deck, suit, rank, game, x=0, y=0): def __init__(self, id, deck, suit, rank, game, x=0, y=0):
_HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y) _HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y)
self.item = MfxCanvasGroup(game.canvas) self.item = MfxCanvasGroup(game.canvas)
self.__face = MfxCanvasImage(game.canvas, self.x, self.y + 11000, image=game.getCardFaceImage(deck, suit, rank), anchor="nw") self.__face = MfxCanvasImage(
self.__back = MfxCanvasImage(game.canvas, self.x, self.y, image=game.getCardBackImage(deck, suit, rank), anchor="nw") game.canvas, self.x, self.y + 11000, image=game.getCardFaceImage(
deck, suit, rank), anchor="nw")
self.__back = MfxCanvasImage(
game.canvas, self.x, self.y, image=game.getCardBackImage(
deck, suit, rank), anchor="nw")
self.__face.addtag(self.item) self.__face.addtag(self.item)
self.__back.addtag(self.item) self.__back.addtag(self.item)
def showFace(self, unhide=1): def showFace(self, unhide=1):
if not self.face_up: if not self.face_up:
self.__back.move(0, 10000) self.__back.move(0, 10000)
##self.__face.tkraise() # self.__face.tkraise()
self.__face.move(0, -11000) self.__face.move(0, -11000)
self.tkraise(unhide) self.tkraise(unhide)
self.face_up = 1 self.face_up = 1
@ -232,7 +241,7 @@ class _TwoImageCardWithHideItem(_HideableCard):
def showBack(self, unhide=1): def showBack(self, unhide=1):
if self.face_up: if self.face_up:
self.__face.move(0, 11000) self.__face.move(0, 11000)
##self.__back.tkraise() # self.__back.tkraise()
self.__back.move(0, -10000) self.__back.move(0, -10000)
self.tkraise(unhide) self.tkraise(unhide)
self.face_up = 0 self.face_up = 0
@ -241,10 +250,8 @@ class _TwoImageCardWithHideItem(_HideableCard):
self.__back.config(image=image) self.__back.config(image=image)
# choose the implementation # choose the implementation
Card = _TwoImageCardWithHideItem Card = _TwoImageCardWithHideItem
Card = _TwoImageCard Card = _TwoImageCard
Card = _OneImageCardWithHideByConfig Card = _OneImageCardWithHideByConfig
Card = _OneImageCard Card = _OneImageCard

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,25 +19,21 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
__all__ = ['ColorsDialog']
# imports # imports
import Tkinter import Tkinter
from tkColorChooser import askcolor from tkColorChooser import askcolor
# PySol imports # PySol imports
from pysollib.mygettext import _, n_ from pysollib.mygettext import _
from pysollib.mfxutil import KwStruct from pysollib.mfxutil import KwStruct
# Toolkit imports
from pysollib.tk.tkwidget import MfxDialog
# ************************************************************************ # ************************************************************************
# * # *
# ************************************************************************ # ************************************************************************
class BaseColorsDialog: class BaseColorsDialog:
def _calcFrame(self): def _calcFrame(self):
return self._calcToolkit().Frame return self._calcToolkit().Frame
@ -50,7 +46,8 @@ class BaseColorsDialog:
def __init__(self, parent, title, app, **kw): def __init__(self, parent, title, app, **kw):
kw = self.initKw(kw) kw = self.initKw(kw)
self._calc_MfxDialog().__init__(self, parent, title, kw.resizable, kw.default) self._calc_MfxDialog().__init__(
self, parent, title, kw.resizable, kw.default)
top_frame, bottom_frame = self.createFrames(kw) top_frame, bottom_frame = self.createFrames(kw)
self.createBitmaps(top_frame, kw) self.createBitmaps(top_frame, kw)
@ -85,14 +82,16 @@ class BaseColorsDialog:
(_('Highlight same rank 2:'), self.samerank_2_var), (_('Highlight same rank 2:'), self.samerank_2_var),
(_('Hint arrow:'), self.hintarrow_var), (_('Hint arrow:'), self.hintarrow_var),
(_('Highlight not matching:'), self.not_matching_var), (_('Highlight not matching:'), self.not_matching_var),
): ):
self._calcLabel()(frame, text=title, anchor='w', self._calcLabel()(
).grid(row=row, column=0, sticky='we') frame, text=title, anchor='w',).grid(
row=row, column=0, sticky='we')
l = Tkinter.Label(frame, width=10, height=2, l = Tkinter.Label(frame, width=10, height=2,
bg=var.get(), textvariable=var) bg=var.get(), textvariable=var)
l.grid(row=row, column=1, padx=5) l.grid(row=row, column=1, padx=5)
b = self._calcButton()(frame, text=_('Change...'), width=10, b = self._calcButton()(
command=lambda l=l: self.selectColor(l)) frame, text=_('Change...'), width=10,
command=lambda l=l: self.selectColor(l))
b.grid(row=row, column=2) b.grid(row=row, column=2)
row += 1 row += 1
# #
@ -117,7 +116,7 @@ class BaseColorsDialog:
else: else:
if c and c[1]: if c and c[1]:
label.configure(bg=c[1]) label.configure(bg=c[1])
#label.configure(text=c[1]) # don't work # label.configure(text=c[1]) # don't work
label.setvar(label.cget('textvariable'), c[1]) label.setvar(label.cget('textvariable'), c[1])
def initKw(self, kw): def initKw(self, kw):
@ -126,7 +125,3 @@ class BaseColorsDialog:
default=0, default=0,
) )
return self._calc_MfxDialog().initKw(self, kw) return self._calc_MfxDialog().initKw(self, kw)

View file

@ -1,19 +1,21 @@
import Tkinter import Tkinter
from pysollib.mygettext import _, n_ from pysollib.mygettext import _
from pysollib.mfxutil import KwStruct from pysollib.mfxutil import KwStruct
class BaseEditTextDialog: class BaseEditTextDialog:
def __init__(self, parent, title, text, **kw): def __init__(self, parent, title, text, **kw):
kw = self.initKw(kw) kw = self.initKw(kw)
self._calc_MfxDialog().__init__(self, parent, title, kw.resizable, kw.default) self._calc_MfxDialog().__init__(
self, parent, title, kw.resizable, kw.default)
top_frame, bottom_frame = self.createFrames(kw) top_frame, bottom_frame = self.createFrames(kw)
self.createBitmaps(top_frame, kw) self.createBitmaps(top_frame, kw)
# #
self.text_w = Tkinter.Text(top_frame, bd=1, relief="sunken", self.text_w = Tkinter.Text(top_frame, bd=1, relief="sunken",
wrap="word", width=64, height=16) wrap="word", width=64, height=16)
self.text_w.pack(side='left', fill="both", expand=True) self.text_w.pack(side='left', fill="both", expand=True)
###self.text_w.pack(side='top', padx=kw.padx, pady=kw.pady) # self.text_w.pack(side='top', padx=kw.padx, pady=kw.pady)
vbar = self._calcToolkit().Scrollbar(top_frame) vbar = self._calcToolkit().Scrollbar(top_frame)
vbar.pack(side='right', fill='y') vbar.pack(side='right', fill='y')
self.text_w["yscrollcommand"] = vbar.set self.text_w["yscrollcommand"] = vbar.set
@ -49,5 +51,3 @@ class BaseEditTextDialog:
def mCancel(self, *event): # ignore <Escape> def mCancel(self, *event): # ignore <Escape>
pass pass

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,7 +19,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
__all__ = ['create_find_card_dialog', __all__ = ['create_find_card_dialog',
'connect_game_find_card_dialog', 'connect_game_find_card_dialog',
@ -31,12 +31,13 @@ import os
import Tkinter import Tkinter
# PySol imports # PySol imports
from pysollib.mygettext import _, n_ from pysollib.mygettext import _
# Toolkit imports # Toolkit imports
from pysollib.ui.tktile.tkutil import after, after_cancel from pysollib.ui.tktile.tkutil import after, after_cancel
from pysollib.ui.tktile.tkutil import bind, unbind_destroy, makeImage from pysollib.ui.tktile.tkutil import bind, unbind_destroy, makeImage
from pysollib.ui.tktile.tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle from pysollib.ui.tktile.tkcanvas import MfxCanvas, MfxCanvasGroup, \
MfxCanvasImage, MfxCanvasRectangle
from pysollib.settings import TITLE from pysollib.settings import TITLE
@ -48,8 +49,9 @@ from pysollib.settings import TITLE
LARGE_EMBLEMS_SIZE = (38, 34) LARGE_EMBLEMS_SIZE = (38, 34)
SMALL_EMBLEMS_SIZE = (31, 21) SMALL_EMBLEMS_SIZE = (31, 21)
class FindCardDialog(Tkinter.Toplevel): class FindCardDialog(Tkinter.Toplevel):
CARD_IMAGES = {} # key: (rank, suit) CARD_IMAGES = {} # key: (rank, suit)
def __init__(self, parent, game, dir, size='large'): def __init__(self, parent, game, dir, size='large'):
Tkinter.Toplevel.__init__(self) Tkinter.Toplevel.__init__(self)
@ -57,7 +59,7 @@ class FindCardDialog(Tkinter.Toplevel):
self.title(title) self.title(title)
self.wm_resizable(False, False) self.wm_resizable(False, False)
# #
##self.images_dir = dir # self.images_dir = dir
if size == 'large': if size == 'large':
self.images_dir = os.path.join(dir, 'large') self.images_dir = os.path.join(dir, 'large')
self.label_width, self.label_height = LARGE_EMBLEMS_SIZE self.label_width, self.label_height = LARGE_EMBLEMS_SIZE
@ -65,7 +67,7 @@ class FindCardDialog(Tkinter.Toplevel):
self.images_dir = os.path.join(dir, 'small') self.images_dir = os.path.join(dir, 'small')
self.label_width, self.label_height = SMALL_EMBLEMS_SIZE self.label_width, self.label_height = SMALL_EMBLEMS_SIZE
self.canvas = MfxCanvas(self, bg='white') self.canvas = MfxCanvas(self, bg='white')
##self.canvas = MfxCanvas(self, bg='black') # self.canvas = MfxCanvas(self, bg='black')
self.canvas.pack(expand=True, fill='both') self.canvas.pack(expand=True, fill='both')
# #
self.groups = [] self.groups = []
@ -76,8 +78,9 @@ class FindCardDialog(Tkinter.Toplevel):
bind(self, "WM_DELETE_WINDOW", self.destroy) bind(self, "WM_DELETE_WINDOW", self.destroy)
bind(self, "<Escape>", self.destroy) bind(self, "<Escape>", self.destroy)
# #
##self.normal_timeout = 400 # in milliseconds # self.normal_timeout = 400 # in milliseconds
self.normal_timeout = int(1000*game.app.opt.timeouts['highlight_samerank']) self.normal_timeout = int(
1000*game.app.opt.timeouts['highlight_samerank'])
self.hidden_timeout = 200 self.hidden_timeout = 200
self.timer = None self.timer = None
@ -140,9 +143,11 @@ class FindCardDialog(Tkinter.Toplevel):
self.wm_geometry('') # cancel user-specified geometry self.wm_geometry('') # cancel user-specified geometry
def enterEvent(self, suit, rank, rect, group): def enterEvent(self, suit, rank, rect, group):
##print 'enterEvent', suit, rank, self.busy # print 'enterEvent', suit, rank, self.busy
if self.busy: return if self.busy:
if self.game.demo: return return
if self.game.demo:
return
self.busy = True self.busy = True
self.highlight_items = self.game.highlightCard(suit, rank) self.highlight_items = self.game.highlightCard(suit, rank)
if not self.highlight_items: if not self.highlight_items:
@ -154,8 +159,9 @@ class FindCardDialog(Tkinter.Toplevel):
self.busy = False self.busy = False
def leaveEvent(self, suit, rank, rect, group): def leaveEvent(self, suit, rank, rect, group):
##print 'leaveEvent', suit, rank, self.busy # print 'leaveEvent', suit, rank, self.busy
if self.busy: return if self.busy:
return
self.busy = True self.busy = True
if self.highlight_items: if self.highlight_items:
for i in self.highlight_items: for i in self.highlight_items:
@ -170,7 +176,6 @@ class FindCardDialog(Tkinter.Toplevel):
self.canvas.update_idletasks() self.canvas.update_idletasks()
self.busy = False self.busy = False
def timeoutEvent(self, *event): def timeoutEvent(self, *event):
if self.highlight_items: if self.highlight_items:
state = self.highlight_items[0].cget('state') state = self.highlight_items[0].cget('state')
@ -199,31 +204,31 @@ class FindCardDialog(Tkinter.Toplevel):
Tkinter.Toplevel.destroy(self) Tkinter.Toplevel.destroy(self)
find_card_dialog = None find_card_dialog = None
def create_find_card_dialog(parent, game, dir): def create_find_card_dialog(parent, game, dir):
global find_card_dialog global find_card_dialog
try: try:
find_card_dialog.wm_deiconify() find_card_dialog.wm_deiconify()
find_card_dialog.tkraise() find_card_dialog.tkraise()
except: except:
##traceback.print_exc() # traceback.print_exc()
find_card_dialog = FindCardDialog(parent, game, dir) find_card_dialog = FindCardDialog(parent, game, dir)
def connect_game_find_card_dialog(game): def connect_game_find_card_dialog(game):
try: try:
find_card_dialog.connectGame(game) find_card_dialog.connectGame(game)
except: except:
pass pass
def destroy_find_card_dialog(): def destroy_find_card_dialog():
global find_card_dialog global find_card_dialog
try: try:
find_card_dialog.destroy() find_card_dialog.destroy()
except: except:
##traceback.print_exc() # traceback.print_exc()
pass pass
find_card_dialog = None find_card_dialog = None

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,11 +19,11 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# PySol imports # PySol imports
from pysollib.mygettext import _, n_ from pysollib.mygettext import _
from pysollib.mfxutil import KwStruct from pysollib.mfxutil import KwStruct
from pysollib.gamedb import GI from pysollib.gamedb import GI
@ -31,10 +31,12 @@ from pysollib.gamedb import GI
# * # *
# ************************************************************************ # ************************************************************************
class BaseGameInfoDialog: class BaseGameInfoDialog:
def __init__(self, parent, title, app, **kw): def __init__(self, parent, title, app, **kw):
kw = self.initKw(kw) kw = self.initKw(kw)
self._calc_MfxDialog().__init__(self, parent, title, kw.resizable, kw.default) self._calc_MfxDialog().__init__(
self, parent, title, kw.resizable, kw.default)
top_frame, bottom_frame = self.createFrames(kw) top_frame, bottom_frame = self.createFrames(kw)
self.createBitmaps(top_frame, kw) self.createBitmaps(top_frame, kw)
@ -46,9 +48,12 @@ class BaseGameInfoDialog:
gi = game.gameinfo gi = game.gameinfo
# #
if gi.redeals == -2: redeals = 'VARIABLE' if gi.redeals == -2:
elif gi.redeals == -1: redeals = 'UNLIMITED' redeals = 'VARIABLE'
else: redeals = str(gi.redeals) elif gi.redeals == -1:
redeals = 'UNLIMITED'
else:
redeals = str(gi.redeals)
cat = '<none>' cat = '<none>'
type = '<none>' type = '<none>'
flags = [] flags = []
@ -59,7 +64,7 @@ class BaseGameInfoDialog:
cat = attr cat = attr
elif attr.startswith('GT_'): elif attr.startswith('GT_'):
t = getattr(GI, attr) t = getattr(GI, attr)
if t < (1<<12)-1: if t < (1 << 12)-1:
if gi.si.game_type == t: if gi.si.game_type == t:
type = attr type = attr
else: else:
@ -102,10 +107,12 @@ class BaseGameInfoDialog:
('Hint:', hint), ('Hint:', hint),
): ):
if t: if t:
self._calcToolkit().Label(frame, text=n, anchor='w' self._calcToolkit().Label(
).grid(row=row, column=0, sticky='nw') frame, text=n, anchor='w').grid(
self._calcToolkit().Label(frame, text=t, anchor='w', justify='left' row=row, column=0, sticky='nw')
).grid(row=row, column=1, sticky='nw') self._calcToolkit().Label(
frame, text=t, anchor='w', justify='left').grid(
row=row, column=1, sticky='nw')
row += 1 row += 1
if game.s.talon: if game.s.talon:
@ -118,7 +125,7 @@ class BaseGameInfoDialog:
('Foundations:', game.s.foundations,), ('Foundations:', game.s.foundations,),
('Rows:', game.s.rows,), ('Rows:', game.s.rows,),
('Reserves:', game.s.reserves,), ('Reserves:', game.s.reserves,),
): ):
if s: if s:
self.showStacks(frame, row, t, s) self.showStacks(frame, row, t, s)
row += 1 row += 1
@ -128,8 +135,9 @@ class BaseGameInfoDialog:
self.mainloop(focus, kw.timeout) self.mainloop(focus, kw.timeout)
def showStacks(self, frame, row, title, stacks): def showStacks(self, frame, row, title, stacks):
self._calcToolkit().Label(frame, text=title, anchor='w' self._calcToolkit().Label(
).grid(row=row, column=0, sticky='nw') frame, text=title, anchor='w').grid(
row=row, column=0, sticky='nw')
if isinstance(stacks, (list, tuple)): if isinstance(stacks, (list, tuple)):
fs = {} fs = {}
for f in stacks: for f in stacks:
@ -141,8 +149,9 @@ class BaseGameInfoDialog:
t = '\n'.join(['%s (%d)' % (i[0], i[1]) for i in fs.items()]) t = '\n'.join(['%s (%d)' % (i[0], i[1]) for i in fs.items()])
else: else:
t = stacks.__class__.__name__ t = stacks.__class__.__name__
self._calcToolkit().Label(frame, text=t, anchor='w', justify='left' self._calcToolkit().Label(
).grid(row=row, column=1, sticky='nw') frame, text=t, anchor='w', justify='left').grid(
row=row, column=1, sticky='nw')
def initKw(self, kw): def initKw(self, kw):
kw = KwStruct(kw, kw = KwStruct(kw,

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,7 +19,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# ************************************************************************ # ************************************************************************
# * Nodes # * Nodes
@ -28,23 +28,27 @@
# imports # imports
import tkFont import tkFont
class BaseSelectDialogTreeLeaf: class BaseSelectDialogTreeLeaf:
def drawSymbol(self, x, y, **kw): def drawSymbol(self, x, y, **kw):
if self.tree.nodes.get(self.symbol_id) is not self: if self.tree.nodes.get(self.symbol_id) is not self:
self.symbol_id = self.tree.canvas.create_image(x, y, self.symbol_id = self.tree.canvas.create_image(
x, y,
image=self.tree.data.img[2+(self.key is None)], anchor="nw") image=self.tree.data.img[2+(self.key is None)], anchor="nw")
self.tree.nodes[self.symbol_id] = self self.tree.nodes[self.symbol_id] = self
class BaseSelectDialogTreeNode: class BaseSelectDialogTreeNode:
def __init__(self, tree, text, select_func, expanded=0, parent_node=None): def __init__(self, tree, text, select_func, expanded=0, parent_node=None):
self._calc_MfxTreeNode().__init__(self, tree, parent_node, text, key=None, expanded=expanded) self._calc_MfxTreeNode().__init__(
self, tree, parent_node, text, key=None, expanded=expanded)
# callable or a tuple/list of MfxTreeNodes # callable or a tuple/list of MfxTreeNodes
self.select_func = select_func self.select_func = select_func
def drawSymbol(self, x, y, **kw): def drawSymbol(self, x, y, **kw):
if self.tree.nodes.get(self.symbol_id) is not self: if self.tree.nodes.get(self.symbol_id) is not self:
self.symbol_id = self.tree.canvas.create_image(x, y, self.symbol_id = self.tree.canvas.create_image(
x, y,
image=self.tree.data.img[self.expanded], anchor="nw") image=self.tree.data.img[self.expanded], anchor="nw")
self.tree.nodes[self.symbol_id] = self self.tree.nodes[self.symbol_id] = self
@ -52,7 +56,7 @@ class BaseSelectDialogTreeNode:
# cached values # cached values
if self.subnodes is not None: if self.subnodes is not None:
return self.subnodes return self.subnodes
##print self.whoami() # print self.whoami()
if isinstance(self.select_func, (tuple, list)): if isinstance(self.select_func, (tuple, list)):
return self.select_func return self.select_func
return self._getContents() return self._getContents()
@ -68,6 +72,7 @@ class BaseSelectDialogTreeNode:
class SelectDialogTreeData: class SelectDialogTreeData:
img = [] # loaded in Application.loadImages3 img = [] # loaded in Application.loadImages3
def __init__(self): def __init__(self):
self.tree_xview = (0.0, 1.0) self.tree_xview = (0.0, 1.0)
self.tree_yview = (0.0, 1.0) self.tree_yview = (0.0, 1.0)
@ -95,9 +100,10 @@ class BaseSelectDialogTreeCanvas:
if parent and parent.winfo_screenheight() >= 800: if parent and parent.winfo_screenheight() >= 800:
height = 30 * disty height = 30 * disty
self.lines = height / disty self.lines = height / disty
self._calc_MfxTreeInCanvas().__init__(self, parent, self.data.rootnodes, self._calc_MfxTreeInCanvas().__init__(
width=width, height=height, self, parent, self.data.rootnodes,
hbar=hbar, vbar=vbar) width=width, height=height,
hbar=hbar, vbar=vbar)
self.style.distx = 20 self.style.distx = 20
self.style.disty = disty self.style.disty = disty
self.style.width = 16 # width of symbol self.style.width = 16 # width of symbol
@ -111,12 +117,12 @@ class BaseSelectDialogTreeCanvas:
self.draw() self.draw()
self.updateSelection(key) self.updateSelection(key)
if self.hbar: if self.hbar:
##print self.data.tree_yview # print self.data.tree_yview
##print self.canvas.xview() # print self.canvas.xview()
self.canvas.xview_moveto(self.data.tree_xview[0]) self.canvas.xview_moveto(self.data.tree_xview[0])
if self.vbar: if self.vbar:
##print self.data.tree_yview # print self.data.tree_yview
##print self.canvas.yview() # print self.canvas.yview()
self.canvas.yview_moveto(self.data.tree_yview[0]) self.canvas.yview_moveto(self.data.tree_yview[0])
def destroy(self): def destroy(self):
@ -157,4 +163,3 @@ class BaseSelectDialogTreeCanvas:
node.expanded = not node.expanded node.expanded = not node.expanded
self.redraw() self.redraw()
return "break" return "break"

View file

@ -1,25 +1,27 @@
import Tkinter import Tkinter
from pysollib.mygettext import _, n_ from pysollib.mygettext import _
from pysollib.ui.tktile.tkconst import EVENT_HANDLED from pysollib.ui.tktile.tkconst import EVENT_HANDLED
from pysollib.settings import TITLE from pysollib.settings import TITLE
class BaseSolverDialog: class BaseSolverDialog:
def __init__(self, parent, app, **kw): def __init__(self, parent, app, **kw):
self.parent = parent self.parent = parent
self.app = app self.app = app
title = TITLE+' - FreeCell Solver' title = TITLE+' - FreeCell Solver'
kw = self.initKw(kw) kw = self.initKw(kw)
self._calc_MfxDialog().__init__(self, parent, title, kw.resizable, kw.default) self._calc_MfxDialog().__init__(
self, parent, title, kw.resizable, kw.default)
top_frame, bottom_frame = self.createFrames(kw) top_frame, bottom_frame = self.createFrames(kw)
self.createBitmaps(top_frame, kw) self.createBitmaps(top_frame, kw)
# #
self.solving_methods = { self.solving_methods = {
'A*': 'a-star', 'A*': 'a-star',
'Breadth-First Search': 'bfs', 'Breadth-First Search': 'bfs',
'Depth-First Search': 'soft-dfs', # default 'Depth-First Search': 'soft-dfs', # default
'A randomized DFS': 'random-dfs', 'A randomized DFS': 'random-dfs',
##'"Soft" DFS': 'soft-dfs', # '"Soft" DFS': 'soft-dfs',
} }
self.games = {} # key: gamename; value: gameid self.games = {} # key: gamename; value: gameid
@ -30,8 +32,9 @@ class BaseSolverDialog:
# #
row = 0 row = 0
self._calcToolkit().Label(frame, text=_('Game:'), anchor='w' self._calcToolkit().Label(
).grid(row=row, column=0, sticky='ew', padx=2, pady=2) frame, text=_('Game:'), anchor='w').grid(
row=row, column=0, sticky='ew', padx=2, pady=2)
games = app.getGamesForSolver() games = app.getGamesForSolver()
gamenames = [''] gamenames = ['']
for id in games: for id in games:
@ -44,8 +47,9 @@ class BaseSolverDialog:
# #
row += 1 row += 1
self._calcToolkit().Label(frame, text=_('Preset:'), anchor='w' self._calcToolkit().Label(
).grid(row=row, column=0, sticky='ew', padx=2, pady=2) frame, text=_('Preset:'), anchor='w').grid(
row=row, column=0, sticky='ew', padx=2, pady=2)
presets = app.opt.solver_presets presets = app.opt.solver_presets
self.presets = presets self.presets = presets
self.preset_var = self._createPresetVar(frame, row) self.preset_var = self._createPresetVar(frame, row)
@ -54,8 +58,9 @@ class BaseSolverDialog:
row += 1 row += 1
self.max_iters_var = Tkinter.IntVar() self.max_iters_var = Tkinter.IntVar()
self.max_iters_var.set(10e4) self.max_iters_var.set(10e4)
self._calcToolkit().Label(frame, text=_('Max iterations:'), anchor='w' self._calcToolkit().Label(
).grid(row=row, column=0, sticky='ew', padx=2, pady=2) frame, text=_('Max iterations:'), anchor='w').grid(
row=row, column=0, sticky='ew', padx=2, pady=2)
spin = Tkinter.Spinbox(frame, bg='white', from_=1000, to=10e6, spin = Tkinter.Spinbox(frame, bg='white', from_=1000, to=10e6,
increment=1000, textvariable=self.max_iters_var) increment=1000, textvariable=self.max_iters_var)
spin.grid(row=row, column=1, sticky='w', padx=2, pady=2) spin.grid(row=row, column=1, sticky='w', padx=2, pady=2)
@ -68,27 +73,31 @@ class BaseSolverDialog:
w.grid(row=row, column=0, columnspan=2, sticky='ew', padx=2, pady=2) w.grid(row=row, column=0, columnspan=2, sticky='ew', padx=2, pady=2)
# #
label_frame = self._calcToolkit().LabelFrame(top_frame, text=_('Progress')) label_frame = self._calcToolkit().LabelFrame(
top_frame, text=_('Progress'))
label_frame.pack(expand=True, fill='both', padx=6, pady=2) label_frame.pack(expand=True, fill='both', padx=6, pady=2)
#label_frame.columnconfigure(0, weight=1) # label_frame.columnconfigure(0, weight=1)
label_frame.columnconfigure(1, weight=1) label_frame.columnconfigure(1, weight=1)
# #
frow = 0 frow = 0
self._calcToolkit().Label(label_frame, text=_('Iteration:'), anchor='w' self._calcToolkit().Label(
).grid(row=frow, column=0, sticky='ew', padx=4, pady=2) label_frame, text=_('Iteration:'), anchor='w').grid(
row=frow, column=0, sticky='ew', padx=4, pady=2)
lb = self._calcToolkit().Label(label_frame, anchor='w') lb = self._calcToolkit().Label(label_frame, anchor='w')
lb.grid(row=frow, column=1, sticky='ew', padx=4, pady=2) lb.grid(row=frow, column=1, sticky='ew', padx=4, pady=2)
self.iter_label = lb self.iter_label = lb
frow += 1 frow += 1
self._calcToolkit().Label(label_frame, text=_('Depth:'), anchor='w' self._calcToolkit().Label(
).grid(row=frow, column=0, sticky='ew', padx=4, pady=2) label_frame, text=_('Depth:'), anchor='w').grid(
row=frow, column=0, sticky='ew', padx=4, pady=2)
lb = self._calcToolkit().Label(label_frame, anchor='w') lb = self._calcToolkit().Label(label_frame, anchor='w')
lb.grid(row=frow, column=1, sticky='ew', padx=4, pady=2) lb.grid(row=frow, column=1, sticky='ew', padx=4, pady=2)
self.depth_label = lb self.depth_label = lb
frow += 1 frow += 1
self._calcToolkit().Label(label_frame, text=_('Stored-States:'), anchor='w' self._calcToolkit().Label(
).grid(row=frow, column=0, sticky='ew', padx=4, pady=2) label_frame, text=_('Stored-States:'), anchor='w').grid(
row=frow, column=0, sticky='ew', padx=4, pady=2)
lb = self._calcToolkit().Label(label_frame, anchor='w') lb = self._calcToolkit().Label(label_frame, anchor='w')
lb.grid(row=frow, column=1, sticky='ew', padx=4, pady=2) lb.grid(row=frow, column=1, sticky='ew', padx=4, pady=2)
self.states_label = lb self.states_label = lb
@ -106,7 +115,6 @@ class BaseSolverDialog:
self.connectGame(self.app.game) self.connectGame(self.app.game)
self.mainloop(focus, kw.timeout, transient=False) self.mainloop(focus, kw.timeout, transient=False)
def mDone(self, button): def mDone(self, button):
if button == 0: if button == 0:
self.startSolving() self.startSolving()
@ -147,7 +155,7 @@ class BaseSolverDialog:
self._reset() self._reset()
game = self.app.game game = self.app.game
solver = game.Solver_Class(game, self) # create solver instance solver = game.Solver_Class(game, self) # create solver instance
game.solver = solver game.solver = solver
preset = self.preset_var.get() preset = self.preset_var.get()
max_iters = self.max_iters_var.get() max_iters = self.max_iters_var.get()
@ -162,7 +170,10 @@ class BaseSolverDialog:
self.result_label['text'] = t self.result_label['text'] = t
self.play_button.config(state='normal') self.play_button.config(state='normal')
else: else:
self.result_label['text'] = (_('I could not solve this game.') if solver.solver_state == 'unsolved' else _('Iterations count exceeded (Intractable)')) self.result_label['text'] = \
(_('I could not solve this game.')
if solver.solver_state == 'unsolved'
else _('Iterations count exceeded (Intractable)'))
self.play_button.config(state='disabled') self.play_button.config(state='disabled')
def startPlay(self): def startPlay(self):
@ -185,20 +196,23 @@ class BaseSolverDialog:
self.states_label['text'] = kw['states'] self.states_label['text'] = kw['states']
self.top.update_idletasks() self.top.update_idletasks()
solver_dialog = None solver_dialog = None
def connect_game_solver_dialog(game): def connect_game_solver_dialog(game):
try: try:
solver_dialog.connectGame(game) solver_dialog.connectGame(game)
except: except:
pass pass
def destroy_solver_dialog(): def destroy_solver_dialog():
global solver_dialog global solver_dialog
try: try:
solver_dialog.destroy() solver_dialog.destroy()
except: except:
##traceback.print_exc() # traceback.print_exc()
pass pass
solver_dialog = None solver_dialog = None
@ -208,6 +222,5 @@ def reset_solver_dialog():
try: try:
solver_dialog.reset() solver_dialog.reset()
except: except:
##traceback.print_exc() # traceback.print_exc()
pass pass

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,7 +19,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
__all__ = ['MfxCanvasGroup', __all__ = ['MfxCanvasGroup',
'MfxCanvasImage', 'MfxCanvasImage',
@ -36,7 +36,7 @@ import Canvas
from pysollib.mfxutil import Image, ImageTk from pysollib.mfxutil import Image, ImageTk
# Toolkit imports # Toolkit imports
from pysollib.ui.tktile.tkutil import bind, unbind_destroy, loadImage from pysollib.ui.tktile.tkutil import unbind_destroy, loadImage
# ************************************************************************ # ************************************************************************
@ -49,14 +49,18 @@ class MfxCanvasGroup(Canvas.Group):
# register ourself so that we can unbind from the canvas # register ourself so that we can unbind from the canvas
assert self.id not in self.canvas.items assert self.id not in self.canvas.items
self.canvas.items[self.id] = self self.canvas.items[self.id] = self
def addtag(self, tag, option="withtag"): def addtag(self, tag, option="withtag"):
self.canvas.addtag(tag, option, self.id) self.canvas.addtag(tag, option, self.id)
def delete(self): def delete(self):
del self.canvas.items[self.id] del self.canvas.items[self.id]
Canvas.Group.delete(self) Canvas.Group.delete(self)
def gettags(self): def gettags(self):
return self.canvas.tk.splitlist(self._do("gettags")) return self.canvas.tk.splitlist(self._do("gettags"))
class MfxCanvasImage(Canvas.ImageItem): class MfxCanvasImage(Canvas.ImageItem):
def __init__(self, canvas, x, y, **kwargs): def __init__(self, canvas, x, y, **kwargs):
self.init_coord = x, y self.init_coord = x, y
@ -69,16 +73,21 @@ class MfxCanvasImage(Canvas.ImageItem):
Canvas.ImageItem.__init__(self, canvas, x, y, **kwargs) Canvas.ImageItem.__init__(self, canvas, x, y, **kwargs)
if group: if group:
self.addtag(group) self.addtag(group)
def moveTo(self, x, y): def moveTo(self, x, y):
c = self.coords() c = self.coords()
self.move(x - int(c[0]), y - int(c[1])) self.move(x - int(c[0]), y - int(c[1]))
def show(self): def show(self):
self.config(state='normal') self.config(state='normal')
def hide(self): def hide(self):
self.config(state='hidden') self.config(state='hidden')
MfxCanvasLine = Canvas.Line MfxCanvasLine = Canvas.Line
class MfxCanvasRectangle(Canvas.Rectangle): class MfxCanvasRectangle(Canvas.Rectangle):
def __init__(self, canvas, *args, **kwargs): def __init__(self, canvas, *args, **kwargs):
group = None group = None
@ -89,6 +98,7 @@ class MfxCanvasRectangle(Canvas.Rectangle):
if group: if group:
self.addtag(group) self.addtag(group)
class MfxCanvasText(Canvas.CanvasText): class MfxCanvasText(Canvas.CanvasText):
def __init__(self, canvas, x, y, preview=-1, **kwargs): def __init__(self, canvas, x, y, preview=-1, **kwargs):
self.init_coord = x, y self.init_coord = x, y
@ -108,6 +118,7 @@ class MfxCanvasText(Canvas.CanvasText):
canvas._text_items.append(self) canvas._text_items.append(self)
if group: if group:
self.addtag(group) self.addtag(group)
def moveTo(self, x, y): def moveTo(self, x, y):
dx, dy = x - self.x, y - self.y dx, dy = x - self.x, y - self.y
self.x, self.y = x, y self.x, self.y = x, y
@ -141,10 +152,10 @@ class MfxCanvas(Tkinter.Canvas):
self.bind('<Configure>', self.setBackgroundImage) self.bind('<Configure>', self.setBackgroundImage)
def setBackgroundImage(self, event=None): def setBackgroundImage(self, event=None):
##print 'setBackgroundImage', self._bg_img # print 'setBackgroundImage', self._bg_img
if not hasattr(self, '_bg_img'): if not hasattr(self, '_bg_img'):
return return
if not self._bg_img: # solid color if not self._bg_img: # solid color
return return
stretch = self._stretch_bg_image stretch = self._stretch_bg_image
save_aspect = self._save_aspect_bg_image save_aspect = self._save_aspect_bg_image
@ -161,7 +172,7 @@ class MfxCanvas(Tkinter.Canvas):
image = ImageTk.PhotoImage(im) image = ImageTk.PhotoImage(im)
else: else:
image = ImageTk.PhotoImage(self._bg_img) image = ImageTk.PhotoImage(self._bg_img)
else: # not Image else: # not Image
stretch = 0 stretch = 0
image = self._bg_img image = self._bg_img
for id in self.__tiles: for id in self.__tiles:
@ -184,7 +195,8 @@ class MfxCanvas(Tkinter.Canvas):
sw, sh = self._geometry() sw, sh = self._geometry()
for x in range(-self.xmargin, sw, iw): for x in range(-self.xmargin, sw, iw):
for y in range(-self.ymargin, sh, ih): for y in range(-self.ymargin, sh, ih):
id = self._x_create("image", x, y, image=image, anchor="nw") id = self._x_create(
"image", x, y, image=image, anchor="nw")
self.tag_lower(id) # also see tag_lower above self.tag_lower(id) # also see tag_lower above
self.__tiles.append(id) self.__tiles.append(id)
return 1 return 1
@ -202,7 +214,6 @@ class MfxCanvas(Tkinter.Canvas):
h = max(h, sh) h = max(h, sh)
return w, h return w, h
# #
# top-image support # top-image support
# #
@ -211,33 +222,28 @@ class MfxCanvas(Tkinter.Canvas):
return Tkinter.Canvas._create(self, itemType, args, kw) return Tkinter.Canvas._create(self, itemType, args, kw)
def _create(self, itemType, args, kw): def _create(self, itemType, args, kw):
##print "_create:", itemType, args, kw # print "_create:", itemType, args, kw
id = Tkinter.Canvas._create(self, itemType, args, kw) id = Tkinter.Canvas._create(self, itemType, args, kw)
if self.__tops: if self.__tops:
self.tk.call(self._w, "lower", id, self.__tops[0]) self.tk.call(self._w, "lower", id, self.__tops[0])
return id return id
def tag_raise(self, id, aboveThis=None): def tag_raise(self, id, aboveThis=None):
##print "tag_raise:", id, aboveThis # print "tag_raise:", id, aboveThis
if aboveThis is None and self.__tops: if aboveThis is None and self.__tops:
self.tk.call(self._w, "lower", id, self.__tops[0]) self.tk.call(self._w, "lower", id, self.__tops[0])
else: else:
self.tk.call(self._w, "raise", id, aboveThis) self.tk.call(self._w, "raise", id, aboveThis)
def tag_lower(self, id, belowThis=None): def tag_lower(self, id, belowThis=None):
##print "tag_lower:", id, belowThis # print "tag_lower:", id, belowThis
if belowThis is None and self.__tiles: if belowThis is None and self.__tiles:
self.tk.call(self._w, "raise", id, self.__tiles[-1]) self.tk.call(self._w, "raise", id, self.__tiles[-1])
else: else:
self.tk.call(self._w, "lower", id, belowThis) self.tk.call(self._w, "lower", id, belowThis)
#
#
#
def setInitialSize(self, width, height, margins=True, scrollregion=True): def setInitialSize(self, width, height, margins=True, scrollregion=True):
#print 'Canvas.setInitialSize:', width, height, scrollregion # print 'Canvas.setInitialSize:', width, height, scrollregion
if self.preview: if self.preview:
self.config(width=width, height=height, self.config(width=width, height=height,
scrollregion=(0, 0, width, height)) scrollregion=(0, 0, width, height))
@ -255,11 +261,6 @@ class MfxCanvas(Tkinter.Canvas):
# no scrolls # no scrolls
self.config(scrollregion=(-dx, -dy, dx, dy)) self.config(scrollregion=(-dx, -dy, dx, dy))
#
#
#
# delete all CanvasItems, but keep the background and top tiles # delete all CanvasItems, but keep the background and top tiles
def deleteAllItems(self): def deleteAllItems(self):
self._text_items = [] self._text_items = []
@ -276,18 +277,18 @@ class MfxCanvas(Tkinter.Canvas):
if stack.cards[i].item.tag in current: if stack.cards[i].item.tag in current:
return i return i
else: else:
## current = self.find("withtag", "current") # get item ids # current = self.find("withtag", "current") # get item ids
## for i in range(len(stack.cards)): # for i in range(len(stack.cards)):
## if stack.cards[i].item.id in current: # if stack.cards[i].item.id in current:
## return i # return i
if self.preview: if self.preview:
dx, dy = 0, 0 dx, dy = 0, 0
else: else:
dx, dy = -self.xmargin, -self.ymargin dx, dy = -self.xmargin, -self.ymargin
x = event.x+dx+self.xview()[0]*int(self.cget('width')) x = event.x+dx+self.xview()[0]*int(self.cget('width'))
y = event.y+dy+self.yview()[0]*int(self.cget('height')) y = event.y+dy+self.yview()[0]*int(self.cget('height'))
##x, y = event.x, event.y # x, y = event.x, event.y
items = list(self.find_overlapping(x,y,x,y)) items = list(self.find_overlapping(x, y, x, y))
items.reverse() items.reverse()
for item in items: for item in items:
for i in range(len(stack.cards)): for i in range(len(stack.cards)):
@ -303,16 +304,17 @@ class MfxCanvas(Tkinter.Canvas):
v = [] v = []
for i in (1, 3, 5): for i in (1, 3, 5):
v.append(int(c[i:i+2], 16)) v.append(int(c[i:i+2], 16))
luminance = (0.212671 * v[0] + 0.715160 * v[1] + 0.072169 * v[2]) / 255 luminance = (0.212671 * v[0] + 0.715160 * v[1] + 0.072169 * v[2]) \
##print c, ":", v, "luminance", luminance / 255
color = ("#000000", "#ffffff") [luminance < 0.3] # print c, ":", v, "luminance", luminance
color = ("#000000", "#ffffff")[luminance < 0.3]
if self._text_color != color: if self._text_color != color:
self._text_color = color self._text_color = color
for item in self._text_items: for item in self._text_items:
item.config(fill=self._text_color) item.config(fill=self._text_color)
def setTile(self, image, stretch=0, save_aspect=0): def setTile(self, image, stretch=0, save_aspect=0):
##print 'setTile:', image, stretch # print 'setTile:', image, stretch
if image: if image:
if Image: if Image:
try: try:
@ -352,12 +354,12 @@ class MfxCanvas(Tkinter.Canvas):
return 1 return 1
iw, ih = image.width(), image.height() iw, ih = image.width(), image.height()
if cw <= 0: if cw <= 0:
##cw = max(int(self.cget("width")), self.winfo_width()) # cw = max(int(self.cget("width")), self.winfo_width())
cw = self.winfo_width() cw = self.winfo_width()
if ch <= 0: if ch <= 0:
##ch = max(int(self.cget("height")), self.winfo_height()) # ch = max(int(self.cget("height")), self.winfo_height())
ch = self.winfo_height() ch = self.winfo_height()
###print iw, ih, cw, ch # print iw, ih, cw, ch
x = (cw-iw)/2-self.xmargin+self.xview()[0]*int(self.cget('width')) x = (cw-iw)/2-self.xmargin+self.xview()[0]*int(self.cget('width'))
y = (ch-ih)/2-self.ymargin+self.yview()[0]*int(self.cget('height')) y = (ch-ih)/2-self.ymargin+self.yview()[0]*int(self.cget('height'))
id = self._x_create("image", x, y, image=image, anchor="nw") id = self._x_create("image", x, y, image=image, anchor="nw")
@ -377,7 +379,6 @@ class MfxCanvas(Tkinter.Canvas):
for item in self.items.values(): for item in self.items.values():
item.config(state='normal') item.config(state='normal')
# #
# restricted but fast _bind and _substitute # restricted but fast _bind and _substitute
# #
@ -385,7 +386,7 @@ class MfxCanvas(Tkinter.Canvas):
def _bind(self, what, sequence, func, add, needcleanup=1): def _bind(self, what, sequence, func, add, needcleanup=1):
funcid = self._register(func, self._substitute, needcleanup) funcid = self._register(func, self._substitute, needcleanup)
cmd = ('%sif {"[%s %s]" == "break"} break\n' % cmd = ('%sif {"[%s %s]" == "break"} break\n' %
(add and '+' or '', funcid, "%x %y")) (add and '+' or '', funcid, "%x %y"))
self.tk.call(what + (sequence, cmd)) self.tk.call(what + (sequence, cmd))
return funcid return funcid
@ -401,4 +402,3 @@ class MfxCanvas(Tkinter.Canvas):
except ValueError: except ValueError:
e.y = args[1] e.y = args[1]
return (e,) return (e,)

View file

@ -41,33 +41,33 @@ __all__ = ['EVENT_HANDLED',
# imports # imports
import Tkinter import Tkinter
from pysollib.mygettext import _, n_ from pysollib.mygettext import n_
# ************************************************************************ # ************************************************************************
# * constants # * constants
# ************************************************************************ # ************************************************************************
EVENT_HANDLED = "break" EVENT_HANDLED = "break"
EVENT_PROPAGATE = None EVENT_PROPAGATE = None
CURSOR_DRAG = "hand1" CURSOR_DRAG = "hand1"
CURSOR_WATCH = "watch" CURSOR_WATCH = "watch"
CURSOR_DOWN_ARROW = 'sb_down_arrow' CURSOR_DOWN_ARROW = 'sb_down_arrow'
ANCHOR_CENTER = Tkinter.CENTER ANCHOR_CENTER = Tkinter.CENTER
ANCHOR_N = Tkinter.N ANCHOR_N = Tkinter.N
ANCHOR_NW = Tkinter.NW ANCHOR_NW = Tkinter.NW
ANCHOR_NE = Tkinter.NE ANCHOR_NE = Tkinter.NE
ANCHOR_S = Tkinter.S ANCHOR_S = Tkinter.S
ANCHOR_SW = Tkinter.SW ANCHOR_SW = Tkinter.SW
ANCHOR_SE = Tkinter.SE ANCHOR_SE = Tkinter.SE
ANCHOR_W = Tkinter.W ANCHOR_W = Tkinter.W
ANCHOR_E = Tkinter.E ANCHOR_E = Tkinter.E
COMPOUNDS = ( COMPOUNDS = (
##(Tkinter.BOTTOM, 'bottom'), # (Tkinter.BOTTOM, 'bottom'),
##(Tkinter.CENTER, 'center'), # (Tkinter.CENTER, 'center'),
##(Tkinter.RIGHT, 'right'), # (Tkinter.RIGHT, 'right'),
(Tkinter.NONE, n_('Icons only')), (Tkinter.NONE, n_('Icons only')),
(Tkinter.TOP, n_('Text below icons')), (Tkinter.TOP, n_('Text below icons')),
(Tkinter.LEFT, n_('Text beside icons')), (Tkinter.LEFT, n_('Text beside icons')),
@ -89,4 +89,3 @@ TOOLBAR_BUTTONS = (
"quit", "quit",
"player", "player",
) )

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,10 +19,11 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
import os import os
import htmllib, formatter import htmllib
import formatter
import Tkinter import Tkinter
from pysollib.ui.tktile.tkutil import bind, unbind_destroy from pysollib.ui.tktile.tkutil import bind, unbind_destroy
@ -36,6 +37,7 @@ REMOTE_PROTOCOLS = ("ftp:", "gopher:", "http:", "mailto:", "news:", "telnet:")
# * # *
# ************************************************************************ # ************************************************************************
class tkHTMLWriter(formatter.NullWriter): class tkHTMLWriter(formatter.NullWriter):
def __init__(self, text, viewer, app): def __init__(self, text, viewer, app):
formatter.NullWriter.__init__(self) formatter.NullWriter.__init__(self)
@ -43,7 +45,6 @@ class tkHTMLWriter(formatter.NullWriter):
self.text = text self.text = text
self.viewer = viewer self.viewer = viewer
##
if app: if app:
font = app.getFont("sans") font = app.getFont("sans")
fixed = app.getFont("fixed") fixed = app.getFont("fixed")
@ -52,17 +53,18 @@ class tkHTMLWriter(formatter.NullWriter):
fixed = ('courier', 12) fixed = ('courier', 12)
size = font[1] size = font[1]
sign = 1 sign = 1
if size < 0: sign = -1 if size < 0:
sign = -1
self.fontmap = { self.fontmap = {
"h1" : (font[0], size + 12*sign, "bold"), "h1": (font[0], size + 12*sign, "bold"),
"h2" : (font[0], size + 8*sign, "bold"), "h2": (font[0], size + 8*sign, "bold"),
"h3" : (font[0], size + 6*sign, "bold"), "h3": (font[0], size + 6*sign, "bold"),
"h4" : (font[0], size + 4*sign, "bold"), "h4": (font[0], size + 4*sign, "bold"),
"h5" : (font[0], size + 2*sign, "bold"), "h5": (font[0], size + 2*sign, "bold"),
"h6" : (font[0], size + 1*sign, "bold"), "h6": (font[0], size + 1*sign, "bold"),
"bold" : (font[0], size, "bold"), "bold": (font[0], size, "bold"),
"italic" : (font[0], size, "italic"), "italic": (font[0], size, "italic"),
"pre" : fixed, "pre": fixed,
} }
self.text.config(cursor=self.viewer.defcursor, font=font) self.text.config(cursor=self.viewer.defcursor, font=font)
@ -80,6 +82,7 @@ class tkHTMLWriter(formatter.NullWriter):
def __init__(self, viewer, arg): def __init__(self, viewer, arg):
self.viewer = viewer self.viewer = viewer
self.arg = arg self.arg = arg
def __call__(self, *args): def __call__(self, *args):
self.viewer.updateHistoryXYView() self.viewer.updateHistoryXYView()
return self.viewer.display(self.arg) return self.viewer.display(self.arg)
@ -90,7 +93,7 @@ class tkHTMLWriter(formatter.NullWriter):
def anchor_bgn(self, href, name, type): def anchor_bgn(self, href, name, type):
if href: if href:
##self.text.update_idletasks() # update display during parsing # self.text.update_idletasks() # update display during parsing
self.anchor = (href, name, type) self.anchor = (href, name, type)
self.anchor_mark = self.text.index("insert") self.anchor_mark = self.text.index("insert")
@ -100,7 +103,8 @@ class tkHTMLWriter(formatter.NullWriter):
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)) self.text.tag_bind(tag, "<1>", self.createCallback(url))
self.text.tag_bind(tag, "<Enter>", lambda e: self.anchor_enter(url)) self.text.tag_bind(
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)
fg = 'blue' fg = 'blue'
u = self.viewer.normurl(url, with_protocol=False) u = self.viewer.normurl(url, with_protocol=False)
@ -121,12 +125,12 @@ class tkHTMLWriter(formatter.NullWriter):
def new_font(self, font): def new_font(self, font):
# end the current font # end the current font
if self.font: if self.font:
##print "end_font(%s)" % `self.font` # print "end_font(%s)" % `self.font`
self.text.tag_add(self.font, self.font_mark, "insert") self.text.tag_add(self.font, self.font_mark, "insert")
self.font = None self.font = None
# start the new font # start the new font
if font: if font:
##print "start_font(%s)" % `font` # print "start_font(%s)" % `font`
self.font_mark = self.text.index("insert") self.font_mark = self.text.index("insert")
if font[0] in self.fontmap: if font[0] in self.fontmap:
self.font = font[0] self.font = font[0]
@ -143,9 +147,9 @@ class tkHTMLWriter(formatter.NullWriter):
self.indent = " " * level self.indent = " " * level
def send_label_data(self, data): def send_label_data(self, data):
##self.write(self.indent + data + " ") # self.write(self.indent + data + " ")
self.write(self.indent) self.write(self.indent)
if data == '*': # <li> if data == '*': # <li>
img = self.viewer.symbols_img.get('disk') img = self.viewer.symbols_img.get('disk')
if img: if img:
self.text.image_create(index='insert', image=img, self.text.image_create(index='insert', image=img,
@ -194,7 +198,9 @@ class tkHTMLParser(htmllib.HTMLParser):
self.ddpop() self.ddpop()
def handle_image(self, src, alt, ismap, align, width, height): def handle_image(self, src, alt, ismap, align, width, height):
self.formatter.writer.viewer.showImage(src, alt, ismap, align, width, height) self.formatter.writer.viewer.showImage(
src, alt, ismap, align, width, height)
class Base_HTMLViewer: class Base_HTMLViewer:
def initBindings(self): def initBindings(self):
@ -214,10 +220,12 @@ class Base_HTMLViewer:
unbind_destroy(self.parent) unbind_destroy(self.parent)
try: try:
self.parent.wm_withdraw() self.parent.wm_withdraw()
except: pass except:
pass
try: try:
self.parent.destroy() self.parent.destroy()
except: pass except:
pass
self.parent = None self.parent = None
def _yview(self, *args): def _yview(self, *args):
@ -226,14 +234,19 @@ class Base_HTMLViewer:
def page_up(self, *event): def page_up(self, *event):
return self._yview('scroll', -1, 'page') return self._yview('scroll', -1, 'page')
def page_down(self, *event): def page_down(self, *event):
return self._yview('scroll', 1, 'page') return self._yview('scroll', 1, 'page')
def unit_up(self, *event): def unit_up(self, *event):
return self._yview('scroll', -1, 'unit') return self._yview('scroll', -1, 'unit')
def unit_down(self, *event): def unit_down(self, *event):
return self._yview('scroll', 1, 'unit') return self._yview('scroll', 1, 'unit')
def scroll_top(self, *event): def scroll_top(self, *event):
return self._yview('moveto', 0) return self._yview('moveto', 0)
def scroll_bottom(self, *event): def scroll_bottom(self, *event):
return self._yview('moveto', 1) return self._yview('moveto', 1)
@ -251,7 +264,7 @@ class Base_HTMLViewer:
if relpath and baseurl and not os.path.isabs(url): if relpath and baseurl and not os.path.isabs(url):
h1, t1 = os.path.split(url) h1, t1 = os.path.split(url)
h2, t2 = os.path.split(baseurl) h2, t2 = os.path.split(baseurl)
if cmp(h1, h2) != 0: if h1 != h2:
url = os.path.join(h2, h1, t1) url = os.path.join(h2, h1, t1)
url = os.path.normpath(url) url = os.path.normpath(url)
return url return url
@ -279,8 +292,8 @@ class Base_HTMLViewer:
# (is this a multithread problem with Tkinter ?) # (is this a multithread problem with Tkinter ?)
if self.app and self.app.game: if self.app and self.app.game:
self.app.game.stopDemo() self.app.game.stopDemo()
##self.app.game._cancelDrag() # self.app.game._cancelDrag()
##pass # pass
# ftp: and http: would work if we use urllib, but this widget is # ftp: and http: would work if we use urllib, but this widget is
# far too limited to display anything but our documentation... # far too limited to display anything but our documentation...
@ -310,12 +323,15 @@ to open the following URL:
data = file.read() data = file.read()
file.close() file.close()
file = None file = None
except Exception, ex: except Exception as ex:
if file: file.close() if file:
self.errorDialog(_("Unable to service request:\n") + url + "\n\n" + str(ex)) file.close()
self.errorDialog(_("Unable to service request:\n") + url +
"\n\n" + str(ex))
return return
except: except:
if file: file.close() if file:
file.close()
self.errorDialog(_("Unable to service request:\n") + url) self.errorDialog(_("Unable to service request:\n") + url)
return return
@ -325,7 +341,7 @@ to open the following URL:
if add: if add:
self.addHistory(self.url, xview=xview, yview=yview) self.addHistory(self.url, xview=xview, yview=yview)
##print self.history.index, self.history.list # print self.history.index, self.history.list
if self.history.index > 1: if self.history.index > 1:
self.backButton.config(state="normal") self.backButton.config(state="normal")
else: else:
@ -339,11 +355,11 @@ to open the following URL:
self.defcursor = self.handcursor = "watch" self.defcursor = self.handcursor = "watch"
self.text.config(cursor=self.defcursor) self.text.config(cursor=self.defcursor)
self.text.update_idletasks() self.text.update_idletasks()
##self.frame.config(cursor=self.defcursor) # self.frame.config(cursor=self.defcursor)
##self.frame.update_idletasks() # self.frame.update_idletasks()
self.text.config(state="normal") self.text.config(state="normal")
self.text.delete("1.0", "end") self.text.delete("1.0", "end")
##self.images = {} # self.images = {}
writer = tkHTMLWriter(self.text, self, self.app) writer = tkHTMLWriter(self.text, self, self.app)
fmt = formatter.AbstractFormatter(writer) fmt = formatter.AbstractFormatter(writer)
parser = tkHTMLParser(fmt) parser = tkHTMLParser(fmt)
@ -358,17 +374,17 @@ to open the following URL:
self.parent.wm_iconname(parser.title) self.parent.wm_iconname(parser.title)
self.defcursor, self.handcursor = old_c1, old_c2 self.defcursor, self.handcursor = old_c1, old_c2
self.text.config(cursor=self.defcursor) self.text.config(cursor=self.defcursor)
##self.frame.config(cursor=self.defcursor) # self.frame.config(cursor=self.defcursor)
def addHistory(self, url, xview=0, yview=0): def addHistory(self, url, xview=0, yview=0):
if url not in self.visited_urls: if url not in self.visited_urls:
self.visited_urls.append(url) self.visited_urls.append(url)
if self.history.index > 0: if self.history.index > 0:
u, xv, yv = self.history.list[self.history.index-1] u, xv, yv = self.history.list[self.history.index-1]
if cmp(u, url) == 0: if u == url:
self.updateHistoryXYView() self.updateHistoryXYView()
return return
del self.history.list[self.history.index : ] del self.history.list[self.history.index:]
self.history.list.append((url, xview, yview)) self.history.list.append((url, xview, yview))
self.history.index = self.history.index + 1 self.history.index = self.history.index + 1
@ -394,15 +410,16 @@ to open the following URL:
self.display(url, add=0, relpath=0, xview=xview, yview=yview) self.display(url, add=0, relpath=0, xview=xview, yview=yview)
def goHome(self, *event): def goHome(self, *event):
if self.home and cmp(self.home, self.url) != 0: if self.home and self.home != self.url:
self.updateHistoryXYView() self.updateHistoryXYView()
self.display(self.home, relpath=0) self.display(self.home, relpath=0)
def errorDialog(self, msg): def errorDialog(self, msg):
d = self._calc_MfxMessageDialog()(self.parent, title=TITLE+" HTML Problem", self._calc_MfxMessageDialog()(
text=msg, self.parent, title=TITLE+" HTML Problem",
##bitmap="warning", # FIXME: this interp don't have images text=msg,
strings=(_("&OK"),), default=0) # bitmap="warning", # FIXME: this interp don't have images
strings=(_("&OK"),), default=0)
def getImage(self, fn): def getImage(self, fn):
if fn in self.images: if fn in self.images:

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,24 +19,24 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
__all__ = ['wm_withdraw', __all__ = ['wm_withdraw',
'wm_deiconify', 'wm_deiconify',
'wm_map', 'wm_map',
'wm_get_geometry', 'wm_get_geometry',
#'setTransient', # 'setTransient',
#'makeToplevel', # 'makeToplevel',
'make_help_toplevel', 'make_help_toplevel',
'bind', 'bind',
'unbind_destroy', 'unbind_destroy',
'after', 'after',
'after_idle', 'after_idle',
'after_cancel', 'after_cancel',
#'makeImage', # 'makeImage',
'copyImage', 'copyImage',
'loadImage', 'loadImage',
#'fillImage', # 'fillImage',
'createImage', 'createImage',
'shadowImage', 'shadowImage',
'markImage', 'markImage',
@ -62,9 +62,11 @@ from pysollib.settings import TITLE, WIN_SYSTEM
def wm_withdraw(window): def wm_withdraw(window):
window.wm_withdraw() window.wm_withdraw()
def wm_deiconify(window): def wm_deiconify(window):
window.wm_deiconify() window.wm_deiconify()
def wm_map(window, maximized=0): def wm_map(window, maximized=0):
if window.wm_state() != "iconic": if window.wm_state() != "iconic":
if maximized and WIN_SYSTEM == "win32": if maximized and WIN_SYSTEM == "win32":
@ -72,8 +74,10 @@ def wm_map(window, maximized=0):
else: else:
wm_deiconify(window) wm_deiconify(window)
__wm_get_geometry_re = re.compile(r"^(\d+)x(\d+)\+([\-]?\d+)\+([\-]?\d+)$") __wm_get_geometry_re = re.compile(r"^(\d+)x(\d+)\+([\-]?\d+)\+([\-]?\d+)$")
def wm_get_geometry(window): def wm_get_geometry(window):
g = window.wm_geometry() g = window.wm_geometry()
m = __wm_get_geometry_re.search(g) m = __wm_get_geometry_re.search(g)
@ -110,22 +114,24 @@ def setTransient(window, parent, relx=None, rely=None, expose=1):
if expose: if expose:
window.wm_deiconify() window.wm_deiconify()
def makeToplevel(parent, title=None): def makeToplevel(parent, title=None):
# Create a Toplevel window. # Create a Toplevel window.
# #
# This is a shortcut for a Toplevel() instantiation plus calls to # This is a shortcut for a Toplevel() instantiation plus calls to
# set the title and icon name of the window. # set the title and icon name of the window.
window = Tkinter.Toplevel(parent) #, class_=TITLE) window = Tkinter.Toplevel(parent) # , class_=TITLE)
##window.wm_group(parent) # window.wm_group(parent)
##window.wm_command("") # window.wm_command("")
if WIN_SYSTEM == "x11": if WIN_SYSTEM == "x11":
window.wm_command("/bin/true") window.wm_command("/bin/true")
##window.wm_protocol("WM_SAVE_YOURSELF", None) # window.wm_protocol("WM_SAVE_YOURSELF", None)
if title: if title:
window.wm_title(title) window.wm_title(title)
window.wm_iconname(title) window.wm_iconname(title)
return window return window
def make_help_toplevel(app, title=None): def make_help_toplevel(app, title=None):
# Create an independent Toplevel window. # Create an independent Toplevel window.
from pysollib.winsystems import init_root_window from pysollib.winsystems import init_root_window
@ -145,8 +151,10 @@ def __getWidgetXY(widget, parent, relx=None, rely=None,
m_x = m_y = 0 m_x = m_y = 0
m_width, m_height = s_width, s_height m_width, m_height = s_width, s_height
if parent and parent.winfo_ismapped(): if parent and parent.winfo_ismapped():
##print parent.wm_geometry() # print parent.wm_geometry()
##print parent.winfo_geometry(), parent.winfo_x(), parent.winfo_y(), parent.winfo_rootx(), parent.winfo_rooty(), parent.winfo_vrootx(), parent.winfo_vrooty() # print parent.winfo_geometry(), parent.winfo_x(), parent.winfo_y(), \
# parent.winfo_rootx(), parent.winfo_rooty(), parent.winfo_vrootx(),\
# parent.winfo_vrooty()
m_x = m_y = None m_x = m_y = None
if WIN_SYSTEM == "win32": if WIN_SYSTEM == "win32":
try: try:
@ -158,24 +166,34 @@ def __getWidgetXY(widget, parent, relx=None, rely=None,
m_y = parent.winfo_y() m_y = parent.winfo_y()
m_width = parent.winfo_width() m_width = parent.winfo_width()
m_height = parent.winfo_height() m_height = parent.winfo_height()
if relx is None: relx = 0.5 if relx is None:
if rely is None: rely = 0.3 relx = 0.5
if rely is None:
rely = 0.3
else: else:
if relx is None: relx = 0.5 if relx is None:
if rely is None: rely = 0.5 relx = 0.5
if rely is None:
rely = 0.5
m_x = max(m_x, 0) m_x = max(m_x, 0)
m_y = max(m_y, 0) m_y = max(m_y, 0)
else: else:
if relx is None: relx = 0.5 if relx is None:
if rely is None: rely = 0.3 relx = 0.5
if rely is None:
rely = 0.3
x = m_x + int((m_width - w_width) * relx) x = m_x + int((m_width - w_width) * relx)
y = m_y + int((m_height - w_height) * rely) y = m_y + int((m_height - w_height) * rely)
##print x, y, w_width, w_height, m_x, m_y, m_width, m_height # print x, y, w_width, w_height, m_x, m_y, m_width, m_height
# make sure the widget is fully on screen # make sure the widget is fully on screen
if x < 0: x = 0 if x < 0:
elif x + w_width + 32 > s_width: x = max(0, (s_width - w_width) / 2) x = 0
if y < 0: y = 0 elif x + w_width + 32 > s_width:
elif y + w_height + 32 > s_height: y = max(0, (s_height - w_height) / 2) x = max(0, (s_width - w_width) / 2)
if y < 0:
y = 0
elif y + w_height + 32 > s_height:
y = max(0, (s_height - w_height) / 2)
return x, y return x, y
@ -186,15 +204,16 @@ def __getWidgetXY(widget, parent, relx=None, rely=None,
__mfx_bindings = {} __mfx_bindings = {}
__mfx_wm_protocols = ("WM_DELETE_WINDOW", "WM_TAKE_FOCUS", "WM_SAVE_YOURSELF") __mfx_wm_protocols = ("WM_DELETE_WINDOW", "WM_TAKE_FOCUS", "WM_SAVE_YOURSELF")
def bind(widget, sequence, func, add=None): def bind(widget, sequence, func, add=None):
##assert callable(func) # XXX: removed in py3k # assert callable(func) # XXX: removed in py3k
if sequence in __mfx_wm_protocols: if sequence in __mfx_wm_protocols:
funcid = widget._register(func) funcid = widget._register(func)
widget.tk.call("wm", "protocol", widget._w, sequence, funcid) widget.tk.call("wm", "protocol", widget._w, sequence, funcid)
elif add is None: elif add is None:
funcid = widget.bind(sequence, func) funcid = widget.bind(sequence, func)
else: else:
##add = add and "+" or "" # add = add and "+" or ""
funcid = widget.bind(sequence, func, add) funcid = widget.bind(sequence, func, add)
k = id(widget) k = id(widget)
if k in __mfx_bindings: if k in __mfx_bindings:
@ -202,24 +221,25 @@ def bind(widget, sequence, func, add=None):
else: else:
__mfx_bindings[k] = [(sequence, funcid)] __mfx_bindings[k] = [(sequence, funcid)]
def unbind_destroy(widget): def unbind_destroy(widget):
if widget is None: if widget is None:
return return
k = id(widget) k = id(widget)
if k in __mfx_bindings: if k in __mfx_bindings:
for sequence, funcid in __mfx_bindings[k]: for sequence, funcid in __mfx_bindings[k]:
##print widget, sequence, funcid # print widget, sequence, funcid
try: try:
if sequence in __mfx_wm_protocols: if sequence in __mfx_wm_protocols:
widget.tk.call("wm", "protocol", widget._w, sequence, "") widget.tk.call("wm", "protocol", widget._w, sequence, "")
##widget.deletecommand(funcid) # widget.deletecommand(funcid)
else: else:
widget.unbind(sequence, funcid) widget.unbind(sequence, funcid)
except Tkinter.TclError: except Tkinter.TclError:
pass pass
del __mfx_bindings[k] del __mfx_bindings[k]
##for k in __mfx_bindings.keys(): print __mfx_bindings[k] # for k in __mfx_bindings.keys(): print __mfx_bindings[k]
##print len(__mfx_bindings.keys()) # print len(__mfx_bindings.keys())
# ************************************************************************ # ************************************************************************
@ -231,9 +251,11 @@ def after(widget, ms, func, *args):
command = widget._tclCommands[-1] command = widget._tclCommands[-1]
return (timer, command, widget) return (timer, command, widget)
def after_idle(widget, func, *args): def after_idle(widget, func, *args):
return after(widget, "idle", func, *args) return after(widget, "idle", func, *args)
def after_cancel(t): def after_cancel(t):
if t is not None: if t is not None:
t[2].after_cancel(t[0]) t[2].after_cancel(t[0])
@ -258,6 +280,7 @@ if Image:
self._pil_image_orig = pil_image_orig self._pil_image_orig = pil_image_orig
else: else:
self._pil_image_orig = image self._pil_image_orig = image
def subsample(self, r): def subsample(self, r):
im = self._pil_image im = self._pil_image
w, h = im.size w, h = im.size
@ -265,10 +288,11 @@ if Image:
im = im.resize((w, h)) im = im.resize((w, h))
im = PIL_Image(image=im) im = PIL_Image(image=im)
return im return im
def resize(self, xf, yf): def resize(self, xf, yf):
w, h = self._pil_image_orig.size w, h = self._pil_image_orig.size
w0, h0 = int(w*xf), int(h*yf) w0, h0 = int(w*xf), int(h*yf)
im = self._pil_image_orig.resize((w0,h0), Image.ANTIALIAS) im = self._pil_image_orig.resize((w0, h0), Image.ANTIALIAS)
return PIL_Image(image=im, pil_image_orig=self._pil_image_orig) return PIL_Image(image=im, pil_image_orig=self._pil_image_orig)
@ -278,7 +302,7 @@ def makeImage(file=None, data=None, dither=None, alpha=None):
assert file is not None assert file is not None
kw["file"] = file kw["file"] = file
else: else:
#assert data is not None # assert data is not None
kw["data"] = data kw["data"] = data
if Image: if Image:
# use PIL # use PIL
@ -290,12 +314,15 @@ def makeImage(file=None, data=None, dither=None, alpha=None):
return Tkinter.PhotoImage(data=data) return Tkinter.PhotoImage(data=data)
return Tkinter.PhotoImage(**kw) return Tkinter.PhotoImage(**kw)
loadImage = makeImage loadImage = makeImage
def copyImage(image, x, y, width, height): def copyImage(image, x, y, width, height):
if Image: if Image:
if isinstance(image, PIL_Image): if isinstance(image, PIL_Image):
return ImageTk.PhotoImage(image._pil_image.crop((x, y, x+width, y+height))) return ImageTk.PhotoImage(
image._pil_image.crop((x, y, x+width, y+height)))
dest = Tkinter.PhotoImage(width=width, height=height) dest = Tkinter.PhotoImage(width=width, height=height)
assert dest.width() == width assert dest.width() == width
assert dest.height() == height assert dest.height() == height
@ -305,6 +332,7 @@ def copyImage(image, x, y, width, height):
assert dest.height() == height assert dest.height() == height
return dest return dest
def fillImage(image, fill, outline=None): def fillImage(image, fill, outline=None):
if not fill and not outline: if not fill and not outline:
return return
@ -336,6 +364,7 @@ def fillImage(image, fill, outline=None):
assert len(f) == height assert len(f) == height
image.put(f) image.put(f)
def createImage(width, height, fill, outline=None): def createImage(width, height, fill, outline=None):
image = Tkinter.PhotoImage(width=width, height=height) image = Tkinter.PhotoImage(width=width, height=height)
assert image.width() == width assert image.width() == width
@ -344,6 +373,7 @@ def createImage(width, height, fill, outline=None):
fillImage(image, fill, outline) fillImage(image, fill, outline)
return image return image
def shadowImage(image, color='#3896f8', factor=0.3): def shadowImage(image, color='#3896f8', factor=0.3):
if not hasattr(image, '_pil_image'): if not hasattr(image, '_pil_image'):
return None return None
@ -359,6 +389,7 @@ def shadowImage(image, color='#3896f8', factor=0.3):
out = Image.composite(tmp, im, im) out = Image.composite(tmp, im, im)
return PIL_Image(image=out) return PIL_Image(image=out)
def markImage(image): def markImage(image):
assert Image assert Image
if 1: # shadow if 1: # shadow
@ -370,6 +401,7 @@ def markImage(image):
out = Image.composite(tmp, image, image) out = Image.composite(tmp, image, image)
return out return out
def _createBottomImage(image, color='white', backfile=None): def _createBottomImage(image, color='white', backfile=None):
th = 1 # thickness th = 1 # thickness
sh = Image.new('RGBA', image.size, color) sh = Image.new('RGBA', image.size, color)
@ -379,7 +411,7 @@ def _createBottomImage(image, color='white', backfile=None):
tmp = Image.new('RGBA', size, color) tmp = Image.new('RGBA', size, color)
tmp.putalpha(60) tmp.putalpha(60)
mask = out.resize(size, Image.ANTIALIAS) mask = out.resize(size, Image.ANTIALIAS)
out.paste(tmp, (th,th), mask) out.paste(tmp, (th, th), mask)
if backfile: if backfile:
back = Image.open(backfile).convert('RGBA') back = Image.open(backfile).convert('RGBA')
w0, h0 = back.size w0, h0 = back.size
@ -387,11 +419,12 @@ def _createBottomImage(image, color='white', backfile=None):
a = min(float(w1)/w0, float(h1)/h0) a = min(float(w1)/w0, float(h1)/h0)
a = a*0.9 a = a*0.9
w0, h0 = int(w0*a), int(h0*a) w0, h0 = int(w0*a), int(h0*a)
back = back.resize((w0,h0), Image.ANTIALIAS) back = back.resize((w0, h0), Image.ANTIALIAS)
x, y = (w1 - w0) / 2, (h1 - h0) / 2 x, y = (w1 - w0) / 2, (h1 - h0) / 2
out.paste(back, (x,y), back) out.paste(back, (x, y), back)
return out return out
def createBottom(maskimage, color='white', backfile=None): def createBottom(maskimage, color='white', backfile=None):
if not hasattr(maskimage, '_pil_image'): if not hasattr(maskimage, '_pil_image'):
return None return None
@ -399,6 +432,7 @@ def createBottom(maskimage, color='white', backfile=None):
out = _createBottomImage(maskimage, color, backfile) out = _createBottomImage(maskimage, color, backfile)
return PIL_Image(image=out) return PIL_Image(image=out)
def resizeBottom(image, maskimage, color='white', backfile=None): def resizeBottom(image, maskimage, color='white', backfile=None):
maskimage = maskimage._pil_image maskimage = maskimage._pil_image
out = _createBottomImage(maskimage, color, backfile) out = _createBottomImage(maskimage, color, backfile)
@ -411,4 +445,3 @@ def resizeBottom(image, maskimage, color='white', backfile=None):
def get_text_width(text, font, root=None): def get_text_width(text, font, root=None):
return Font(root=root, font=font).measure(text) return Font(root=root, font=font).measure(text)

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*- # -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
# #
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer # Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co. # Copyright (C) 2003 Mt. Hood Playing Card Co.
@ -19,17 +19,17 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# ---------------------------------------------------------------------------## # ---------------------------------------------------------------------------
__all__ = ['TclError', __all__ = ['TclError',
'MfxRoot'] 'MfxRoot']
# imports # imports
import Tkinter import Tkinter
from pysollib.ui.tktile.tkconst import EVENT_PROPAGATE
TclError = Tkinter.TclError TclError = Tkinter.TclError
# PySol imports # PySol imports
from pysollib.ui.tktile.tkconst import EVENT_PROPAGATE
# ************************************************************************ # ************************************************************************
@ -43,11 +43,11 @@ class MfxRoot(Tkinter.Tk):
self.app = None self.app = None
self.wm_protocol('WM_DELETE_WINDOW', self.wmDeleteWindow) self.wm_protocol('WM_DELETE_WINDOW', self.wmDeleteWindow)
# for interruptible sleep # for interruptible sleep
#self.sleep_var = Tkinter.IntVar(self) # self.sleep_var = Tkinter.IntVar(self)
#self.sleep_var.set(0) # self.sleep_var.set(0)
self.sleep_var = 0 self.sleep_var = 0
self.after_id = None self.after_id = None
##self.bind('<ButtonPress>', self._sleepEvent, add=True) # self.bind('<ButtonPress>', self._sleepEvent, add=True)
def connectApp(self, app): def connectApp(self, app):
self.app = app self.app = app
@ -56,7 +56,8 @@ class MfxRoot(Tkinter.Tk):
# under Unix an update_idletasks() would be enough... # under Unix an update_idletasks() would be enough...
def busyUpdate(self): def busyUpdate(self):
game = None game = None
if self.app: game = self.app.game if self.app:
game = self.app.game
if not game: if not game:
self.update() self.update()
else: else:
@ -71,16 +72,16 @@ class MfxRoot(Tkinter.Tk):
self.after_idle(self.quit) self.after_idle(self.quit)
def screenshot(self, filename): def screenshot(self, filename):
##print 'MfxRoot.screenshot not yet implemented' # print 'MfxRoot.screenshot not yet implemented'
pass pass
def setCursor(self, cursor): def setCursor(self, cursor):
if 0: if 0:
## FIXME: this causes ugly resizes ! # FIXME: this causes ugly resizes !
Tkinter.Tk.config(self, cursor=cursor) Tkinter.Tk.config(self, cursor=cursor)
elif 0: elif 0:
## and this is even worse # and this is even worse
##print self.children # print self.children
for v in self.children.values(): for v in self.children.values():
v.config(cursor=cursor) v.config(cursor=cursor)
else: else:
@ -91,10 +92,10 @@ class MfxRoot(Tkinter.Tk):
# #
def sleep(self, seconds): def sleep(self, seconds):
#time.sleep(seconds) # time.sleep(seconds)
self.after(int(seconds*1000)) self.after(int(seconds*1000))
return return
print 'sleep', seconds print('sleep', seconds)
timeout = int(seconds*1000) timeout = int(seconds*1000)
self.sleep_var = 0 self.sleep_var = 0
while timeout > 0: while timeout > 0:
@ -104,7 +105,7 @@ class MfxRoot(Tkinter.Tk):
break break
self.after(100) self.after(100)
timeout -= 100 timeout -= 100
print 'finish sleep' print('finish sleep')
return return
if self.after_id: if self.after_id:
self.after_cancel(self.after_id) self.after_cancel(self.after_id)
@ -115,22 +116,22 @@ class MfxRoot(Tkinter.Tk):
if self.after_id: if self.after_id:
self.after_cancel(self.after_id) self.after_cancel(self.after_id)
self.after_id = None self.after_id = None
print 'finish sleep' print('finish sleep')
def _sleepEvent(self, *args): def _sleepEvent(self, *args):
return return
print '_sleepEvent', args print('_sleepEvent', args)
self.interruptSleep() self.interruptSleep()
return EVENT_PROPAGATE return EVENT_PROPAGATE
def interruptSleep(self): def interruptSleep(self):
return return
print 'interruptSleep' print('interruptSleep')
self.update() self.update()
self.update_idletasks() self.update_idletasks()
self.sleep_var = 1 self.sleep_var = 1
#self.sleep_var.set(0) # self.sleep_var.set(0)
#self.after_idle(self.sleep_var.set, 0) # self.after_idle(self.sleep_var.set, 0)
# #
# #
@ -143,5 +144,5 @@ class MfxRoot(Tkinter.Tk):
if self.app and self.app.menubar: if self.app and self.app.menubar:
self.app.menubar.mQuit() self.app.menubar.mQuit()
else: else:
##self.after_idle(self.quit) # self.after_idle(self.quit)
pass pass

View file

@ -10,7 +10,7 @@ use String::ShellQuote qw/ shell_quote /;
# my $cmd = shell_quote( 'flake8', '.' ); # my $cmd = shell_quote( 'flake8', '.' );
my $cmd = shell_quote( 'flake8', my $cmd = shell_quote( 'flake8',
grep { not($_ eq './pysollib/pysoltk.py' or $_ eq './pysollib/tile/ttk.py') } glob('./pysollib/*.py ./pysollib/[cmpw]*/*.py ./pysollib/tile/*.py') ); grep { not($_ eq './pysollib/pysoltk.py' or $_ eq './pysollib/tile/ttk.py') } glob('./pysollib/*.py ./pysollib/[cmpuw]*/*.py ./pysollib/tile/*.py ./pysollib/ui/tktile/*.py') );
# TEST # TEST
eq_or_diff( scalar(`$cmd`), '', "flake8 is happy with the code." ); eq_or_diff( scalar(`$cmd`), '', "flake8 is happy with the code." );