From 138bfe335cd02de261cdf589407384c2f50498ed Mon Sep 17 00:00:00 2001 From: skomoroh Date: Fri, 4 Aug 2006 21:15:30 +0000 Subject: [PATCH] + 6 new games * improved findcarddialog git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@38 efabe8c0-fbe8-4139-b769-b5e6d273206e --- pysollib/game.py | 4 +- pysollib/games/camelot.py | 208 ++++++++++++++++++++++++++++++++ pysollib/games/fan.py | 44 ++++++- pysollib/games/katzenschwanz.py | 110 +++++++++++++++++ pysollib/games/numerica.py | 1 - pysollib/games/sthelena.py | 159 ++++++++++++++++++++++++ pysollib/tk/findcarddialog.py | 54 ++++++--- 7 files changed, 557 insertions(+), 23 deletions(-) diff --git a/pysollib/game.py b/pysollib/game.py index 055e2054..77fb3c5e 100644 --- a/pysollib/game.py +++ b/pysollib/game.py @@ -1159,7 +1159,7 @@ class Game: # redeal cards (used in RedealTalonStack; all cards already in talon) def redealCards(self): - pass + raise SubclassResponsibility # the actual hint class (or None) Hint_Class = DefaultHint @@ -1467,6 +1467,8 @@ for %d moves. def _highlightCards(self, info, sleep=1.5): if not info: return 0 + if self.pause: + return 0 items = [] for s, c1, c2, color in info: assert c1 in s.cards and c2 in s.cards diff --git a/pysollib/games/camelot.py b/pysollib/games/camelot.py index 0231c7e5..02378c6b 100644 --- a/pysollib/games/camelot.py +++ b/pysollib/games/camelot.py @@ -370,6 +370,209 @@ class OpenSlyFox(SlyFox): l.defaultStackGroups() +# /*********************************************************************** +# // Princess Patience +# ************************************************************************/ + +class PrincessPatience_RowStack(SS_RowStack): + + def canMoveCards(self, cards): + if not SS_RowStack.canMoveCards(self, cards): + return False + index = list(self.game.s.rows).index(self) + col = index % 4 + row = index / 4 + if index < 16: # left + for i in range(col+1, 4): + r = self.game.s.rows[row*4+i] + if r.cards: + return False + else: # right + for i in range(0, col): + r = self.game.s.rows[row*4+i] + if r.cards: + return False + return True + + def acceptsCards(self, from_stack, cards): + if not SS_RowStack.acceptsCards(self, from_stack, cards): + return False + if not self.cards: + return from_stack is self.game.s.waste + return True + + +class PrincessPatience(Game): + RowStack_Class = PrincessPatience_RowStack + + def createGame(self, max_rounds=1): + + l, s = Layout(self), self.s + self.setSize(l.XM+11*l.XS, l.YM+5*l.YS) + + y = l.YM + for i in range(4): + x = l.XM + for j in range(4): + stack = self.RowStack_Class(x, y, self, max_move=1) + s.rows.append(stack) + stack.CARD_YOFFSET = 0 + x += l.XS + y += l.YS + y = l.YM + for i in range(4): + x = l.XM+7*l.XS + for j in range(4): + stack = self.RowStack_Class(x, y, self, max_move=1) + s.rows.append(stack) + stack.CARD_YOFFSET = 0 + x += l.XS + y += l.YS + + x, y = l.XM+4.5*l.XS, l.YM + for i in range(4): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i)) + s.foundations.append(SS_FoundationStack(x+l.XS, y, self, suit=i)) + y += l.YS + + x, y = l.XM+4.5*l.XS, self.height-l.YS + s.talon = WasteTalonStack(x, y, self, max_rounds=max_rounds) + l.createText(s.talon, 'sw') + x += l.XS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 'se') + + l.defaultStackGroups() + + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + + shallHighlightMatch = Game._shallHighlightMatch_SS + + +# /*********************************************************************** +# // Grandmamma's Patience +# ************************************************************************/ + +class GrandmammasPatience_Talon(OpenTalonStack): + rightclickHandler = OpenStack.rightclickHandler + doubleclickHandler = OpenStack.doubleclickHandler + + +class GrandmammasPatience_RowStack(BasicRowStack): + def acceptsCards(self, from_stack, cards): + if not BasicRowStack.acceptsCards(self, from_stack, cards): + return False + return from_stack not in self.game.s.rows + + +class GrandmammasPatience(Game): + + def createGame(self): + + l, s = Layout(self), self.s + h0 = l.YS+4*l.YOFFSET + self.setSize(l.XM+11*l.XS, l.YM+2*l.YS+2*h0) + self.base_rank = ANY_RANK + + x, y = l.XM, l.YM + s.talon = GrandmammasPatience_Talon(x, y, self) + l.createText(s.talon, 'ne') + + x, y = self.width-4*l.XS, l.YM + for i in range(4): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i, + dir=-1, mod=13, max_move=0, base_rank=ANY_RANK)) + x += l.XS + stack = s.foundations[0] + tx, ty, ta, tf = l.getTextAttr(stack, "sw") + font = self.app.getFont("canvas_default") + stack.texts.misc = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + x, y = self.width-4*l.XS, self.height-l.YS + for i in range(4): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i, + mod=13, max_move=0, base_rank=ANY_RANK)) + x += l.XS + stack = s.foundations[4] + tx, ty, ta, tf = l.getTextAttr(stack, "sw") + font = self.app.getFont("canvas_default") + stack.texts.misc = MfxCanvasText(self.canvas, + tx, ty, anchor=ta, font=font) + + y = l.YM+l.YS + for i in range(2): + x = l.XM + for j in range(11): + s.rows.append(GrandmammasPatience_RowStack(x, y, self, + max_accept=1, max_cards=2)) + x += l.XS + y += h0 + + x, y = l.XM, self.height-l.YS + for i in range(4): + s.reserves.append(ReserveStack(x, y, self)) + x += l.XS + + l.defaultStackGroups() + self.sg.dropstacks.append(s.talon) + + + def startGame(self): + c = self.s.talon.cards[-1] + self.base_rank = c.rank + to_stack = self.s.foundations[c.suit] + self.flipMove(self.s.talon) + self.moveMove(1, self.s.talon, to_stack, frames=0) + for s in self.s.foundations[:4]: + s.cap.base_rank = c.rank + for s in self.s.foundations[4:]: + s.cap.base_rank = (c.rank+1)%13 + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.fillStack() + + + def fillStack(self, stack): + if stack in self.s.rows and not stack.cards: + if self.s.talon.cards: + old_state = self.enterState(self.S_FILL) + self.s.talon.moveMove(1, stack) + self.leaveState(old_state) + + def updateText(self): + if self.preview > 1: + return + base_rank = self.base_rank + if base_rank == ANY_RANK: + t1 = t2 = '' + else: + t1 = RANKS[base_rank]+_(" Descending") + t2 = RANKS[(base_rank+1)%13]+_(" Ascending") + self.s.foundations[0].texts.misc.config(text=t1) + self.s.foundations[4].texts.misc.config(text=t2) + + + def _restoreGameHook(self, game): + self.base_rank = game.loadinfo.base_rank + for s in self.s.foundations[:4]: + s.cap.base_rank = self.base_rank + for s in self.s.foundations[4:]: + s.cap.base_rank = (self.base_rank+1)%13 + + def _loadGameHook(self, p): + self.loadinfo.addattr(base_rank=None) # register extra load var. + self.loadinfo.base_rank = p.load() + + def _saveGameHook(self, p): + p.dump(self.base_rank) + + + # register the game registerGame(GameInfo(280, Camelot, "Camelot", GI.GT_1DECK_TYPE, 1, 0, GI.SL_BALANCED)) @@ -377,4 +580,9 @@ registerGame(GameInfo(610, SlyFox, "Sly Fox", GI.GT_NUMERICA, 2, 0, GI.SL_BALANCED)) registerGame(GameInfo(614, OpenSlyFox, "Open Sly Fox", GI.GT_NUMERICA | GI.GT_ORIGINAL, 2, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(623, PrincessPatience, "Princess Patience", + GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) +registerGame(GameInfo(622, GrandmammasPatience, "Grandmamma's Patience", + GI.GT_NUMERICA, 2, 0, GI.SL_MOSTLY_SKILL)) + diff --git a/pysollib/games/fan.py b/pysollib/games/fan.py index c0d339bd..169f8c3c 100644 --- a/pysollib/games/fan.py +++ b/pysollib/games/fan.py @@ -68,7 +68,7 @@ class Fan(Game): # game layout # - def createGame(self, rows=(5,5,5,3), playcards=9, reserves=0): + def createGame(self, rows=(5,5,5,3), playcards=9, reserves=0, texts=False): # create layout l, s = Layout(self), self.s @@ -106,6 +106,12 @@ class Fan(Game): x += w x, y = self.width - l.XS, self.height - l.YS s.talon = self.Talon_Class(x, y, self) + if texts: + tx, ty, ta, tf = l.getTextAttr(s.talon, "nn") + font = self.app.getFont("canvas_default") + s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + # define stack-groups l.defaultStackGroups() @@ -601,6 +607,40 @@ class TroikaPlus(Troika): ## self.s.talon.dealRow(rows=self.s.rows[:-1]) +# /*********************************************************************** +# // Fascination Fan +# ************************************************************************/ + +class FascinationFan_Talon(RedealTalonStack): + def dealCards(self, sound=0): + RedealTalonStack.redealCards(self, shuffle=True, sound=sound) + +class FascinationFan(Fan): + Talon_Class = StackWrapper(FascinationFan_Talon, max_rounds=7) + #Talon_Class = StackWrapper(LaBelleLucie_Talon, max_rounds=7) + RowStack_Class = StackWrapper(AC_RowStack, base_rank=NO_RANK) + + def createGame(self): + Fan.createGame(self, texts=True) + + def startGame(self): + for i in range(2): + self.s.talon.dealRow(rows=self.s.rows[:17], flip=0, frames=0) + self.startDealSample() + self.s.talon.dealRow() + + def redealCards(self): + nrows = len(self.s.talon.cards)/3 + if len(self.s.talon.cards)%3: nrows += 1 + self.s.talon.dealRowAvail(rows=self.s.rows[:nrows], flip=0, frames=4) + self.s.talon.dealRowAvail(rows=self.s.rows[:nrows], flip=0, frames=4) + self.s.talon.dealRowAvail(frames=4) + for r in self.s.rows[nrows-2:nrows]: + if r.canFlipCard(): r.flipMove() + + shallHighlightMatch = Game._shallHighlightMatch_AC + + # register the game registerGame(GameInfo(56, Fan, "Fan", @@ -637,4 +677,6 @@ registerGame(GameInfo(516, Troika, "Troika", GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) registerGame(GameInfo(517, TroikaPlus, "Troika +", GI.GT_FAN_TYPE | GI.GT_OPEN, 1, 0, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(625, FascinationFan, "Fascination Fan", + GI.GT_FAN_TYPE, 1, 6, GI.SL_BALANCED)) diff --git a/pysollib/games/katzenschwanz.py b/pysollib/games/katzenschwanz.py index 970a1a02..25ce1f77 100644 --- a/pysollib/games/katzenschwanz.py +++ b/pysollib/games/katzenschwanz.py @@ -41,6 +41,7 @@ from pysollib.stack import * from pysollib.game import Game from pysollib.layout import Layout from pysollib.hint import DefaultHint, FreeCellType_Hint, CautiousDefaultHint +from pysollib.pysoltk import MfxCanvasText # /*********************************************************************** @@ -463,6 +464,113 @@ class Glencoe(Intrigue): ] +# /*********************************************************************** +# // Step-Up +# ************************************************************************/ + +class StepUp_Foundation(SS_FoundationStack): + def acceptsCards(self, from_stack, cards): + if not SS_FoundationStack.acceptsCards(self, from_stack, cards): + return False + if from_stack in self.game.s.reserves: + return True + for r in self.game.s.reserves: + if not r.cards: + return True + return False + +class StepUp_Talon(WasteTalonStack): + def canDealCards(self): + if not WasteTalonStack.canDealCards(self): + return False + for r in self.game.s.reserves: + if not r.cards: + return False + return True + +class StepUp_RowStack(AC_RowStack): + def acceptsCards(self, from_stack, cards): + if not AC_RowStack.acceptsCards(self, from_stack, cards): + return False + if (from_stack in self.game.s.reserves or + from_stack in self.game.s.foundations): + return False + return True + + +class StepUp(Game): + + def createGame(self): + l, s = Layout(self), self.s + self.setSize(l.XM+13*l.XS, l.YM+7*l.YS) + self.base_rank = ANY_RANK + + x, y = l.XM+2.5*l.XS, l.YM + for i in range(8): + s.foundations.append(StepUp_Foundation(x, y, self, + suit=i%4, mod=13, base_rank=ANY_RANK)) + x += l.XS + tx, ty, ta, tf = l.getTextAttr(s.foundations[0], "sw") + font = self.app.getFont("canvas_default") + self.texts.info = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + + x, y = l.XM, l.YM+l.YS + for i in range(13): + s.reserves.append(ReserveStack(x, y, self)) + x += l.XS + x, y = l.XM+2*l.XS, l.YM+2*l.YS + for i in range(9): + s.rows.append(StepUp_RowStack(x, y, self, max_move=1, mod=13)) + x += l.XS + + x, y = l.XM, l.YM+2.5*l.YS + s.talon = StepUp_Talon(x, y, self, max_rounds=1) + l.createText(s.talon, 'se') + y += l.YS + s.waste = WasteStack(x, y, self) + l.createText(s.waste, 'se') + + l.defaultStackGroups() + + + def startGame(self): + c = self.s.talon.cards[-1] + self.base_rank = c.rank + self.s.talon.flipMove() + self.s.talon.moveMove(1, self.s.foundations[c.suit], frames=0) + for s in self.s.foundations: + s.cap.base_rank = c.rank + self.s.talon.dealRow(rows=self.s.reserves, frames=0) + self.startDealSample() + self.s.talon.dealRow() + self.s.talon.dealCards() + + def updateText(self): + if self.preview > 1: + return + base_rank = self.base_rank + if base_rank == ANY_RANK: + t = '' + else: + t = RANKS[base_rank] + self.texts.info.config(text=t) + + def _restoreGameHook(self, game): + self.base_rank = game.loadinfo.base_rank + for s in self.s.foundations: + s.cap.base_rank = self.base_rank + + def _loadGameHook(self, p): + self.loadinfo.addattr(base_rank=None) # register extra load var. + self.loadinfo.base_rank = p.load() + + def _saveGameHook(self, p): + p.dump(self.base_rank) + + shallHighlightMatch = Game._shallHighlightMatch_ACW + + # register the game registerGame(GameInfo(141, DerKatzenschwanz, "Cat's Tail", GI.GT_FREECELL | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL, @@ -488,6 +596,8 @@ registerGame(GameInfo(612, Glencoe, "Glencoe", registerGame(GameInfo(616, LaggardLady, "Laggard Lady", GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED, rules_filename="intrigue.html")) +registerGame(GameInfo(624, StepUp, "Step-Up", + GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) diff --git a/pysollib/games/numerica.py b/pysollib/games/numerica.py index a53121af..14fe6608 100644 --- a/pysollib/games/numerica.py +++ b/pysollib/games/numerica.py @@ -730,7 +730,6 @@ class AnnoDomini(Numerica): - # register the game registerGame(GameInfo(257, Numerica, "Numerica", GI.GT_NUMERICA | GI.GT_CONTRIB, 1, 0, GI.SL_BALANCED, diff --git a/pysollib/games/sthelena.py b/pysollib/games/sthelena.py index 1fb75243..d7f679b6 100644 --- a/pysollib/games/sthelena.py +++ b/pysollib/games/sthelena.py @@ -169,6 +169,161 @@ class BoxKite(StHelena): +# /*********************************************************************** +# // Les Quatre Coins +# ************************************************************************/ + +class LesQuatreCoins_RowStack(UD_RK_RowStack): + def acceptsCards(self, from_stack, cards): + if not UD_RK_RowStack.acceptsCards(self, from_stack, cards): + return False + return len(self.game.s.talon.cards) == 0 + + +class LesQuatreCoins_Talon(RedealTalonStack): + + def canDealCards(self): + if self.round == self.max_rounds: + return len(self.cards) != 0 + return not self.game.isGameWon() + + def dealCards(self, sound=0): + if not self.cards: + RedealTalonStack.redealCards(self, sound=0) + if sound and not self.game.demo: + self.game.startDealSample() + rows = self.game.s.rows + rows = rows[:1]+rows[4:8]+(rows[2],rows[1])+rows[8:]+rows[3:4] + num_cards = self.dealRowAvail(rows=rows) + if sound and not self.game.demo: + self.game.stopSamples() + return num_cards + + +class LesQuatreCoins_Foundation(SS_FoundationStack): + def acceptsCards(self, from_stack, cards): + if not SS_FoundationStack.acceptsCards(self, from_stack, cards): + return False + if not self.cards: + return True + if self.game.s.talon.cards: + if from_stack in self.game.s.rows[4:]: + i = list(self.game.s.foundations).index(self) + j = list(self.game.s.rows).index(from_stack) + return i == j-4 + return True + + +class LesQuatreCoins(Game): + Hint_Class = CautiousDefaultHint + + def createGame(self): + + l, s = Layout(self), self.s + self.setSize(l.XM+7*l.XS, l.YM+5*l.YS) + + for i, j in ((0,0),(5,0),(0,4),(5,4)): + x, y = l.XM+l.XS+i*l.XS, l.YM+j*l.YS + stack = LesQuatreCoins_RowStack(x, y, self, + max_move=1, base_rank=NO_RANK) + s.rows.append(stack) + stack.CARD_YOFFSET = 0 + for x in (l.XM+2*l.XS, l.XM+5*l.XS): + y = l.YM+l.YS/2 + for j in range(4): + stack = LesQuatreCoins_RowStack(x, y, self, + max_move=1, base_rank=NO_RANK) + s.rows.append(stack) + stack.CARD_YOFFSET = 0 + y += l.YS + x, y = l.XM+3*l.XS, l.YM+l.YS/2 + for i in range(4): + s.foundations.append(LesQuatreCoins_Foundation(x, y, self, suit=i)) + y += l.YS + x, y = l.XM+4*l.XS, l.YM+l.YS/2 + for i in range(4): + s.foundations.append(LesQuatreCoins_Foundation(x, y, self, suit=i, + base_rank=KING, dir=-1)) + y += l.YS + + x, y = l.XM, l.YM+2*l.YS + s.talon = LesQuatreCoins_Talon(x, y, self, max_rounds=3) + l.createText(s.talon, 's') + tx, ty, ta, tf = l.getTextAttr(s.talon, "nn") + font = self.app.getFont("canvas_default") + s.talon.texts.rounds = MfxCanvasText(self.canvas, tx, ty, + anchor=ta, font=font) + + l.defaultStackGroups() + + + def startGame(self): + self.startDealSample() + self.s.talon.dealCards() + + shallHighlightMatch = Game._shallHighlightMatch_RK + + +# /*********************************************************************** +# // Regal Family +# ************************************************************************/ + +class RegalFamily_RowStack(UD_SS_RowStack): + def acceptsCards(self, from_stack, cards): + if not UD_SS_RowStack.acceptsCards(self, from_stack, cards): + return False + return len(self.game.s.talon.cards) == 0 + + +class RegalFamily(Game): + Hint_Class = CautiousDefaultHint + + def createGame(self): + + l, s = Layout(self), self.s + self.setSize(l.XM+8*l.XS, l.YM+5*l.YS) + + for i, j in ((0,0),(1,0),(2,0),(3,0),(4,0),(5,0),(6,0), + (6,1),(6,2),(6,3), + (6,4),(5,4),(4,4),(3,4),(2,4),(1,4),(0,4), + (0,3),(0,2),(0,1) + ): + x, y = l.XM+l.XS+i*l.XS, l.YM+j*l.YS + stack = RegalFamily_RowStack(x, y, self, + max_move=1, base_rank=NO_RANK) + s.rows.append(stack) + stack.CARD_YOFFSET = 0 + + x, y = l.XM+3*l.XS, l.YM+l.YS + for i in range(3): + s.foundations.append(SS_FoundationStack(x, y, self, suit=i, + base_rank=9, mod=13, dir=-1)) + s.foundations.append(SS_FoundationStack(x, y+2*l.YS, self, suit=i, + base_rank=9, mod=13, dir=-1)) + x += l.XS + x, y = l.XM+3*l.XS, l.YM+2*l.YS + s.foundations.append(SS_FoundationStack(x, y, self, suit=3, + base_rank=ACE, mod=13)) + x += 2*l.XS + s.foundations.append(SS_FoundationStack(x, y, self, suit=3, + base_rank=JACK, mod=13, dir=-1)) + + x, y = l.XM, l.YM+2*l.YS + s.talon = DealRowTalonStack(x, y, self) + l.createText(s.talon, 's') + + l.defaultStackGroups() + + + def startGame(self): + self.startDealSample() + self.s.talon.dealRow() + + + shallHighlightMatch = Game._shallHighlightMatch_SS + + + # register the game registerGame(GameInfo(302, StHelena, "St. Helena", GI.GT_2DECK_TYPE, 2, 2, GI.SL_BALANCED, @@ -177,4 +332,8 @@ registerGame(GameInfo(302, StHelena, "St. Helena", )) registerGame(GameInfo(408, BoxKite, "Box Kite", GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) +registerGame(GameInfo(620, LesQuatreCoins, "Les Quatre Coins", + GI.GT_2DECK_TYPE, 2, 2, GI.SL_MOSTLY_SKILL)) +registerGame(GameInfo(621, RegalFamily, "Regal Family", + GI.GT_2DECK_TYPE, 2, 0, GI.SL_BALANCED)) diff --git a/pysollib/tk/findcarddialog.py b/pysollib/tk/findcarddialog.py index cd2115d8..f42c370f 100644 --- a/pysollib/tk/findcarddialog.py +++ b/pysollib/tk/findcarddialog.py @@ -60,10 +60,12 @@ class FindCardDialog(Tkinter.Toplevel): self.images_dir = os.path.join(dir, 'small-emblems') self.label_width, self.label_height = SMALL_EMBLEMS_SIZE self.canvas = MfxCanvas(self, bg='white') + ##self.canvas = MfxCanvas(self, bg='black') self.canvas.pack(expand=True, fill='both') # self.groups = [] self.highlight_items = None + self.busy = False self.connectGame(game) # bind(self, "WM_DELETE_WINDOW", self.destroy) @@ -83,7 +85,7 @@ class FindCardDialog(Tkinter.Toplevel): im = FindCardDialog.CARD_IMAGES.get((rank, suit)) if im is None: r = '%02d' % (rank+1) - s = 'csdh'[suit] + s = 'cshd'[suit] fn = os.path.join(dir, r+s+'.gif') im = makeImage(file=fn) FindCardDialog.CARD_IMAGES[(rank, suit)] = im @@ -91,22 +93,22 @@ class FindCardDialog(Tkinter.Toplevel): cim.addtag(group) cim.lower() # -## rect_width = 4 -## x1, y1 = x0+dx, y0+dy -## rect = MfxCanvasRectangle(self.canvas, x0, y0, x1, y1, -## width=rect_width, -## fill=None, -## outline='red', -## state='hidden') -## rect.addtag(group) - rect = None + rect_width = 4 + x1, y1 = x0+dx, y0+dy + rect = MfxCanvasRectangle(self.canvas, x0+1, y0+1, x1-1, y1-1, + width=rect_width, + fill=None, + outline='red', + state='hidden' + ) + rect.addtag(group) # bind(group, '', lambda e, suit=suit, rank=rank, rect=rect: - self.enterEvent(suit, rank, rect)) + self.enterEvent(suit, rank, rect, group)) bind(group, '', lambda e, suit=suit, rank=rank, rect=rect: - self.leaveEvent(suit, rank, rect)) + self.leaveEvent(suit, rank, rect, group)) self.groups.append(group) def connectGame(self, game): @@ -129,28 +131,36 @@ class FindCardDialog(Tkinter.Toplevel): w, h = dx*j+2, dy*i+2 self.canvas.config(width=w, height=h) - def enterEvent(self, suit, rank, rect): - ##print 'enterEvent', suit, rank + def enterEvent(self, suit, rank, rect, group): + ##print 'enterEvent', suit, rank, self.busy + if self.busy: return + self.busy = True self.highlight_items = self.game.highlightCard(suit, rank) if not self.highlight_items: self.highlight_items = [] if self.highlight_items: self.timer = after(self, self.normal_timeout, self.timeoutEvent) - return rect.config(state='normal') + self.canvas.update_idletasks() + self.busy = False - def leaveEvent(self, suit, rank, rect): - ##print 'leaveEvent', suit, rank + def leaveEvent(self, suit, rank, rect, group): + ##print 'leaveEvent', suit, rank, self.busy + if self.busy: return + self.busy = True if self.highlight_items: for i in self.highlight_items: i.delete() - #self.game.canvas.update_idletasks() - #self.canvas.update_idletasks() + self.highlight_items = [] if self.timer: after_cancel(self.timer) self.timer = None - return rect.config(state='hidden') + if self.game.canvas: + self.game.canvas.update_idletasks() + self.canvas.update_idletasks() + self.busy = False + def timeoutEvent(self, *event): if self.highlight_items: @@ -174,6 +184,9 @@ class FindCardDialog(Tkinter.Toplevel): after_cancel(self.timer) self.timer = None self.wm_withdraw() + if self.highlight_items: + for i in self.highlight_items: + i.delete() Tkinter.Toplevel.destroy(self) @@ -203,3 +216,4 @@ def destroy_find_card_dialog(): pass find_card_dialog = None +