1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00

- new option: `save games geometry'

- 5 new games: `double russian solitaire', `zodiac', `spike',
  `phantom blockade', `moving left'
- tkhtmlviewer: highlight visited urls


git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@8 efabe8c0-fbe8-4139-b769-b5e6d273206e
This commit is contained in:
skomoroh 2006-06-14 21:19:47 +00:00
parent 6aeb81c763
commit 9e2fedb915
19 changed files with 386 additions and 139 deletions

View file

@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PySol 0.0.1\n" "Project-Id-Version: PySol 0.0.1\n"
"POT-Creation-Date: Sun Jun 11 00:30:03 2006\n" "POT-Creation-Date: Sun Jun 11 10:16:06 2006\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"

View file

@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: Sun Jun 11 00:29:57 2006\n" "POT-Creation-Date: Sun Jun 11 10:16:01 2006\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -2142,7 +2142,7 @@ msgid "Show hint arrow (in Shisen-Sho games)"
msgstr "" msgstr ""
#: pysollib/tk/menubar.py:341 #: pysollib/tk/menubar.py:341
msgid "&Sound" msgid "&Sound..."
msgstr "" msgstr ""
#: pysollib/tk/menubar.py:349 #: pysollib/tk/menubar.py:349

View file

@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PySol 0.0.1\n" "Project-Id-Version: PySol 0.0.1\n"
"POT-Creation-Date: Sun Jun 11 00:30:03 2006\n" "POT-Creation-Date: Sun Jun 11 10:16:06 2006\n"
"PO-Revision-Date: 2006-06-10 11:07+0400\n" "PO-Revision-Date: 2006-06-10 11:07+0400\n"
"Last-Translator: Скоморох <skomoroh@gmail.com>\n" "Last-Translator: Скоморох <skomoroh@gmail.com>\n"
"Language-Team: Russian <ru@li.org>\n" "Language-Team: Russian <ru@li.org>\n"

View file

@ -5,8 +5,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PySol 0.0.1\n" "Project-Id-Version: PySol 0.0.1\n"
"POT-Creation-Date: Sun Jun 11 00:29:57 2006\n" "POT-Creation-Date: Sun Jun 11 10:16:01 2006\n"
"PO-Revision-Date: 2006-06-11 00:32+0400\n" "PO-Revision-Date: 2006-06-12 15:31+0400\n"
"Last-Translator: Скоморох <skomoroh@gmail.com>\n" "Last-Translator: Скоморох <skomoroh@gmail.com>\n"
"Language-Team: Russian <ru@li.org>\n" "Language-Team: Russian <ru@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -2280,8 +2280,8 @@ msgid "Show hint arrow (in Shisen-Sho games)"
msgstr "Показывать стрелку (в Шисен-Сё)" msgstr "Показывать стрелку (в Шисен-Сё)"
#: pysollib/tk/menubar.py:341 #: pysollib/tk/menubar.py:341
msgid "&Sound" msgid "&Sound..."
msgstr "&Звук" msgstr "&Звук..."
#: pysollib/tk/menubar.py:349 #: pysollib/tk/menubar.py:349
msgid "Cards&et..." msgid "Cards&et..."
@ -2289,7 +2289,7 @@ msgstr "Коло&да..."
#: pysollib/tk/menubar.py:350 #: pysollib/tk/menubar.py:350
msgid "Table t&ile..." msgid "Table t&ile..."
msgstr "&Игровой стол..." msgstr "Игровой &стол..."
#: pysollib/tk/menubar.py:352 #: pysollib/tk/menubar.py:352
msgid "Card &background" msgid "Card &background"
@ -2313,7 +2313,7 @@ msgstr "&Негативные контуры карты"
#: pysollib/tk/menubar.py:357 #: pysollib/tk/menubar.py:357
msgid "A&nimations" msgid "A&nimations"
msgstr "&Анимация" msgstr "Анимаци&я"
#: pysollib/tk/menubar.py:358 #: pysollib/tk/menubar.py:358
msgid "&None" msgid "&None"
@ -2353,11 +2353,11 @@ msgstr "Тайма&уты..."
#: pysollib/tk/menubar.py:369 #: pysollib/tk/menubar.py:369
msgid "&Toolbar" msgid "&Toolbar"
msgstr "Панель &инструментов" msgstr "Панель и&нструментов"
#: pysollib/tk/menubar.py:371 #: pysollib/tk/menubar.py:371
msgid "Stat&usbar" msgid "Stat&usbar"
msgstr "Панель состояния" msgstr "Панель с&остояния"
#: pysollib/tk/menubar.py:372 #: pysollib/tk/menubar.py:372
msgid "Show &statusbar" msgid "Show &statusbar"
@ -2373,11 +2373,11 @@ msgstr "Показывать панель помощи"
#: pysollib/tk/menubar.py:375 #: pysollib/tk/menubar.py:375
msgid "&Demo logo" msgid "&Demo logo"
msgstr "&Демо лого" msgstr "Д&емо лого"
#: pysollib/tk/menubar.py:376 #: pysollib/tk/menubar.py:376
msgid "Startup splash sc&reen" msgid "Startup splash sc&reen"
msgstr "Окно &запуска" msgstr "О&кно запуска"
#: pysollib/tk/menubar.py:380 #: pysollib/tk/menubar.py:380
msgid "&Help" msgid "&Help"
@ -2809,7 +2809,7 @@ msgstr "Все фоновые изображения"
#: pysollib/tk/selecttile.py:158 #: pysollib/tk/selecttile.py:158
msgid "&Solid color..." msgid "&Solid color..."
msgstr "&Монотонный цвет..." msgstr "М&онотонный цвет..."
#: pysollib/tk/soundoptionsdialog.py:111 #: pysollib/tk/soundoptionsdialog.py:111
msgid "Sound enabled" msgid "Sound enabled"
@ -2837,7 +2837,7 @@ msgstr "&Применить"
#: pysollib/tk/soundoptionsdialog.py:169 pysollib/tk/soundoptionsdialog.py:171 #: pysollib/tk/soundoptionsdialog.py:169 pysollib/tk/soundoptionsdialog.py:171
msgid "&Mixer..." msgid "&Mixer..."
msgstr "&Миксер..." msgstr "Ми&ксер..."
#: pysollib/tk/soundoptionsdialog.py:220 #: pysollib/tk/soundoptionsdialog.py:220
msgid "Sound preferences info" msgid "Sound preferences info"

View file

@ -130,6 +130,7 @@ class PysolMenubarActions:
statusbar = BooleanVar(), statusbar = BooleanVar(),
num_cards = BooleanVar(), num_cards = BooleanVar(),
helpbar = BooleanVar(), helpbar = BooleanVar(),
save_games_geometry = BooleanVar(),
splashscreen = BooleanVar(), splashscreen = BooleanVar(),
demo_logo = BooleanVar(), demo_logo = BooleanVar(),
sticky_mouse = BooleanVar(), sticky_mouse = BooleanVar(),
@ -180,6 +181,7 @@ class PysolMenubarActions:
tkopt.statusbar.set(opt.statusbar) tkopt.statusbar.set(opt.statusbar)
tkopt.num_cards.set(opt.num_cards) tkopt.num_cards.set(opt.num_cards)
tkopt.helpbar.set(opt.helpbar) tkopt.helpbar.set(opt.helpbar)
tkopt.save_games_geometry.set(opt.save_games_geometry)
tkopt.demo_logo.set(opt.demo_logo) tkopt.demo_logo.set(opt.demo_logo)
tkopt.splashscreen.set(opt.splashscreen) tkopt.splashscreen.set(opt.splashscreen)
tkopt.sticky_mouse.set(opt.sticky_mouse) tkopt.sticky_mouse.set(opt.sticky_mouse)
@ -743,19 +745,19 @@ class PysolMenubarActions:
if self._cancelDrag(): return if self._cancelDrag(): return
if self.app.opt.hint: if self.app.opt.hint:
if self.game.showHint(0, self.app.opt.hint_sleep): if self.game.showHint(0, self.app.opt.hint_sleep):
self.game.stats.hints = self.game.stats.hints + 1 self.game.stats.hints += 1
def mHint1(self, *args): def mHint1(self, *args):
if self._cancelDrag(): return if self._cancelDrag(): return
if self.app.opt.hint: if self.app.opt.hint:
if self.game.showHint(1, self.app.opt.hint_sleep): if self.game.showHint(1, self.app.opt.hint_sleep):
self.game.stats.hints = self.game.stats.hints + 1 self.game.stats.hints += 1
def mHighlightPiles(self, *args): def mHighlightPiles(self, *args):
if self._cancelDrag(): return if self._cancelDrag(): return
if self.app.opt.highlight_piles: if self.app.opt.highlight_piles:
if self.game.highlightPiles(self.app.opt.highlight_piles_sleep): if self.game.highlightPiles(self.app.opt.highlight_piles_sleep):
self.game.stats.highlight_piles = self.game.stats.highlight_piles + 1 self.game.stats.highlight_piles += 1
def mDemo(self, *args): def mDemo(self, *args):
if self._cancelDrag(): return if self._cancelDrag(): return

View file

@ -129,14 +129,14 @@ class Options:
'autopilotlost' : True, 'autopilotlost' : True,
'autopilotwon' : True, 'autopilotwon' : True,
'deal' : True, 'deal' : True,
'deal01' : True, #'deal01' : True,
'deal02' : True, #'deal02' : True,
'deal04' : True, #'deal04' : True,
'deal08' : True, #'deal08' : True,
'dealwaste' : True, 'dealwaste' : True,
'droppair' : True, 'droppair' : True,
'drop' : True, 'drop' : True,
'extra' : True, #'extra' : True,
'flip' : True, 'flip' : True,
'move' : True, 'move' : True,
'nomove' : True, 'nomove' : True,
@ -184,6 +184,7 @@ class Options:
self.highlight_cards_sleep = 1.0 self.highlight_cards_sleep = 1.0
self.highlight_samerank_sleep = 1.0 self.highlight_samerank_sleep = 1.0
# additional startup information # additional startup information
self.num_recent_games = 15
self.recent_gameid = [] self.recent_gameid = []
self.favorite_gameid = [] self.favorite_gameid = []
self.last_gameid = 0 # last game played self.last_gameid = 0 # last game played
@ -191,6 +192,8 @@ class Options:
#self.last_save_dir = None # last directory for load/save #self.last_save_dir = None # last directory for load/save
self.game_holded = 0 self.game_holded = 0
self.wm_maximized = 0 self.wm_maximized = 0
self.save_games_geometry = False
self.games_geometry = {} # saved games geometry (gameid: (width, height))
# #
self.splashscreen = True self.splashscreen = True
self.sticky_mouse = False self.sticky_mouse = False
@ -668,7 +671,13 @@ class Application:
self.game._saveGame(self.fn.holdgame) self.game._saveGame(self.fn.holdgame)
self.opt.game_holded = self.game.id self.opt.game_holded = self.game.id
except: except:
traceback.print_exc()
pass pass
# save game geometry
self.wm_save_state()
if self.opt.save_games_geometry and not self.opt.wm_maximized:
geom = (self.canvas.winfo_width(), self.canvas.winfo_height())
self.opt.games_geometry[self.game.id] = geom
self.freeGame() self.freeGame()
# #
if self.nextgame.id <= 0: if self.nextgame.id <= 0:
@ -681,35 +690,25 @@ class Application:
finally: finally:
# update options # update options
self.opt.last_gameid = id self.opt.last_gameid = id
## if self.debug:
## self.wm_save_state()
## # save options
## self.saveOptions()
## # save statistics
## self.saveStatistics()
## # save comments
## self.saveComments()
## # shut down audio
## self.audio.destroy()
## else:
try: self.wm_save_state()
except:
pass
# save options # save options
try: self.saveOptions() try: self.saveOptions()
except: except:
traceback.print_exc()
pass pass
# save statistics # save statistics
try: self.saveStatistics() try: self.saveStatistics()
except: except:
traceback.print_exc()
pass pass
# save comments # save comments
try: self.saveComments() try: self.saveComments()
except: except:
traceback.print_exc()
pass pass
# shut down audio # shut down audio
try: self.audio.destroy() try: self.audio.destroy()
except: except:
traceback.print_exc()
pass pass
@ -741,7 +740,7 @@ class Application:
if id in self.opt.recent_gameid: if id in self.opt.recent_gameid:
self.opt.recent_gameid.remove(id) self.opt.recent_gameid.remove(id)
self.opt.recent_gameid.insert(0, id) self.opt.recent_gameid.insert(0, id)
del self.opt.recent_gameid[15:] del self.opt.recent_gameid[self.opt.num_recent_games:]
self.menubar.updateRecentGamesMenu(self.opt.recent_gameid) self.menubar.updateRecentGamesMenu(self.opt.recent_gameid)
self.menubar.updateFavoriteGamesMenu() self.menubar.updateFavoriteGamesMenu()
# delete intro progress bar # delete intro progress bar
@ -789,7 +788,6 @@ class Application:
self.toolbar.connectGame(None, None) self.toolbar.connectGame(None, None)
self.menubar.connectGame(None) self.menubar.connectGame(None)
# clean up the canvas # clean up the canvas
unbind_destroy(self.canvas)
self.canvas.deleteAllItems() self.canvas.deleteAllItems()
self.canvas.update_idletasks() self.canvas.update_idletasks()
# destruct the game # destruct the game
@ -808,7 +806,7 @@ class Application:
if self.top: if self.top:
s = self.top.wm_state() s = self.top.wm_state()
##print "wm_save_state", s ##print "wm_save_state", s
if s == "zoomed": if s == "zoomed": # Windows only
self.opt.wm_maximized = 1 self.opt.wm_maximized = 1
elif s == "normal": elif s == "normal":
self.opt.wm_maximized = 0 self.opt.wm_maximized = 0
@ -842,7 +840,7 @@ class Application:
for f in ("demo01", "demo02", "demo03", "demo04", "demo05",): for f in ("demo01", "demo02", "demo03", "demo04", "demo05",):
self.gimages.demo.append(self.dataloader.findImage(f, dir)) self.gimages.demo.append(self.dataloader.findImage(f, dir))
dir = os.path.join("images", "pause") dir = os.path.join("images", "pause")
for f in ("pause01", "pause02",): for f in ("pause01", "pause02", "pause03",):
self.gimages.pause.append(self.dataloader.findImage(f, dir)) self.gimages.pause.append(self.dataloader.findImage(f, dir))
##dir = os.path.join("images", "stats") ##dir = os.path.join("images", "stats")
##for f in ("barchart",): ##for f in ("barchart",):
@ -950,8 +948,7 @@ class Application:
self.opt.cardset[gi.category] = (cs.name, cs.backname) self.opt.cardset[gi.category] = (cs.name, cs.backname)
if update & 8: if update & 8:
self.opt.cardset[(1, gi.id)] = (cs.name, cs.backname) self.opt.cardset[(1, gi.id)] = (cs.name, cs.backname)
#from pprint import pprint #from pprint import pprint; pprint(self.opt.cardset)
#pprint(self.opt.cardset)
def loadCardset(self, cs, id=0, update=7, progress=None): def loadCardset(self, cs, id=0, update=7, progress=None):
#print 'loadCardset', cs.ident #print 'loadCardset', cs.ident
@ -1146,8 +1143,7 @@ Please select a %s type %s.
return return
opt = unpickle(self.fn.opt) opt = unpickle(self.fn.opt)
if opt: if opt:
##import pprint ##import pprint; pprint.pprint(opt.__dict__)
##pprint.pprint(opt.__dict__)
#cardset = self.opt.cardset #cardset = self.opt.cardset
#cardset.update(opt.cardset) #cardset.update(opt.cardset)
self.opt.__dict__.update(opt.__dict__) self.opt.__dict__.update(opt.__dict__)

View file

@ -184,12 +184,18 @@ class Game:
if not self.cards: if not self.cards:
self.cards = self.createCards(progress=self.app.intro.progress) self.cards = self.createCards(progress=self.app.intro.progress)
self.initBindings() self.initBindings()
self.top.bind('<ButtonPress>', self.top._sleepEvent) ##self.top.bind('<ButtonPress>', self.top._sleepEvent)
self.top.bind('<3>', self.top._sleepEvent) ##self.top.bind('<3>', self.top._sleepEvent)
##print timer ##print timer
# update display properties # update display properties
self.top.wm_geometry("") # cancel user-specified geometry self.top.wm_geometry("") # cancel user-specified geometry
self.canvas.setInitialSize(self.width, self.height) self.canvas.setInitialSize(self.width, self.height)
# restore game geometry
if self.app.opt.save_games_geometry:
w, h = self.app.opt.games_geometry.get(self.id, (0, 0))
w, h = max(w, self.width), max(h, self.height)
self.canvas.config(width=w, height=h)
#
self.stats.update_time = time.time() self.stats.update_time = time.time()
self.busy = old_busy self.busy = old_busy
##print timer ##print timer
@ -784,7 +790,8 @@ class Game:
# #
def playSample(self, name, priority=0, loop=0): def playSample(self, name, priority=0, loop=0):
if not self.app.opt.sound_samples[name]: if self.app.opt.sound_samples.has_key(name) and \
not self.app.opt.sound_samples[name]:
return 0 return 0
##print "playSample:", name, priority, loop ##print "playSample:", name, priority, loop
if self.app.audio: if self.app.audio:

View file

@ -57,3 +57,4 @@ import unionsquare
import wavemotion import wavemotion
import windmill import windmill
import yukon import yukon
import zodiac

View file

@ -187,22 +187,25 @@ class Dover_RowStack(RK_RowStack):
class Dover(Bristol): class Dover(Bristol):
Talon_Class = Bristol_Talon Talon_Class = Bristol_Talon
Foundation_Class = SS_FoundationStack Foundation_Class = StackWrapper(SS_FoundationStack, max_move=0)
RowStack_Class = Dover_RowStack RowStack_Class = StackWrapper(Dover_RowStack, base_rank=NO_RANK, max_move=1)
ReserveStack_Class = StackWrapper(ReserveStack, max_accept=0, max_cards=UNLIMITED_CARDS) ReserveStack_Class = StackWrapper(ReserveStack, max_accept=0, max_cards=UNLIMITED_CARDS)
def createGame(self, text=False): def createGame(self, rows=8, text=False):
# create layout # create layout
l, s = Layout(self), self.s l, s = Layout(self), self.s
# set window # set window
self.setSize(2*l.XM+9*l.XS, l.YM+20+5*l.YS) max_rows = max(rows, self.gameinfo.decks*4)
w, h = 2*l.XM+l.XS+max_rows*l.XS, l.YM+20+5*l.YS
self.setSize(w, h)
# create stacks # create stacks
x, y, = l.XM+l.XM+l.XS, l.YM x, y, = 2*l.XM+l.XS+l.XS*(max_rows-self.gameinfo.decks*4), l.YM
for i in range(8): for j in range(self.gameinfo.decks):
s.foundations.append(self.Foundation_Class(x, y, self, suit=i/2, max_move=0)) for i in range(4):
x += l.XS s.foundations.append(self.Foundation_Class(x, y, self, suit=i))
x += l.XS
if text: if text:
x, y = l.XM+8*l.XS, l.YM x, y = l.XM+8*l.XS, l.YM
tx, ty, ta, tf = l.getTextAttr(None, "s") tx, ty, ta, tf = l.getTextAttr(None, "s")
@ -210,12 +213,12 @@ class Dover(Bristol):
font = self.app.getFont("canvas_default") font = self.app.getFont("canvas_default")
self.texts.info = MfxCanvasText(self.canvas, tx, ty, anchor=ta, font=font) self.texts.info = MfxCanvasText(self.canvas, tx, ty, anchor=ta, font=font)
x, y = l.XM+l.XM, l.YM+l.YS x, y = 2*l.XM+(max_rows-rows)*l.XS, l.YM+l.YS
if text: if text:
y += 20 y += 20
for i in range(8): for i in range(rows):
x += l.XS x += l.XS
stack = self.RowStack_Class(x, y, self, base_rank=NO_RANK, max_move=1) stack = self.RowStack_Class(x, y, self)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, l.YOFFSET stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, l.YOFFSET
s.rows.append(stack) s.rows.append(stack)
x, y, = l.XM, l.YM x, y, = l.XM, l.YM
@ -262,9 +265,9 @@ class NewYork_RowStack(AC_RowStack):
class NewYork(Dover): class NewYork(Dover):
Foundation_Class = StackWrapper(SS_FoundationStack, mod=13) Foundation_Class = StackWrapper(SS_FoundationStack, mod=13, max_move=0)
Talon_Class = NewYork_Talon Talon_Class = NewYork_Talon
RowStack_Class = StackWrapper(NewYork_RowStack, base_rank=ANY_RANK, mod=13) RowStack_Class = StackWrapper(NewYork_RowStack, base_rank=ANY_RANK, mod=13, max_move=1)
ReserveStack_Class = StackWrapper(NewYork_ReserveStack, max_accept=1, max_cards=UNLIMITED_CARDS, mod=13) ReserveStack_Class = StackWrapper(NewYork_ReserveStack, max_accept=1, max_cards=UNLIMITED_CARDS, mod=13)
def createGame(self): def createGame(self):
@ -315,6 +318,30 @@ class NewYork(Dover):
p.dump(self.base_card.id) p.dump(self.base_card.id)
# /***********************************************************************
# // Spike
# ************************************************************************/
class Spike(Dover):
Foundation_Class = SS_FoundationStack
RowStack_Class = KingAC_RowStack
def createGame(self):
Dover.createGame(self, rows=7)
def startGame(self):
for i in range(1, 7):
self.s.talon.dealRow(rows=self.s.rows[i:], flip=0, frames=0)
self.startDealSample()
self.s.talon.dealRow()
self.s.talon.dealCards()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.color != card2.color and
abs(card1.rank-card2.rank) == 1)
# register the game # register the game
registerGame(GameInfo(42, Bristol, "Bristol", registerGame(GameInfo(42, Bristol, "Bristol",
GI.GT_FAN_TYPE, 1, 0)) GI.GT_FAN_TYPE, 1, 0))
@ -324,4 +351,6 @@ registerGame(GameInfo(266, Dover, "Dover",
GI.GT_FAN_TYPE, 2, 0)) GI.GT_FAN_TYPE, 2, 0))
registerGame(GameInfo(425, NewYork, "New York", registerGame(GameInfo(425, NewYork, "New York",
GI.GT_FAN_TYPE, 2, 0)) GI.GT_FAN_TYPE, 2, 0))
registerGame(GameInfo(468, Spike, "Spike",
GI.GT_KLONDIKE, 1, 0))

View file

@ -325,6 +325,8 @@ class LexingtonHarp(MilliganHarp):
GAME_VERSION = 2 GAME_VERSION = 2
RowStack_Class = Yukon_AC_RowStack RowStack_Class = Yukon_AC_RowStack
Hint_Class = YukonType_Hint Hint_Class = YukonType_Hint
def getHighlightPilesStacks(self):
return ()
class Brunswick(LexingtonHarp): class Brunswick(LexingtonHarp):
@ -344,6 +346,7 @@ class Griffon(Mississippi):
# /*********************************************************************** # /***********************************************************************
# // Blockade # // Blockade
# // Phantom Blockade
# ************************************************************************/ # ************************************************************************/
class Blockade(Gypsy): class Blockade(Gypsy):
@ -364,6 +367,24 @@ class Blockade(Gypsy):
self.s.talon.moveMove(1, stack) self.s.talon.moveMove(1, stack)
self.leaveState(old_state) self.leaveState(old_state)
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and
abs(card1.rank-card2.rank) == 1)
class PhantomBlockade(Gypsy):
Layout_Method = Layout.klondikeLayout
RowStack_Class = KingAC_RowStack
def createGame(self):
Gypsy.createGame(self, rows=13, playcards=24)
def startGame(self):
self.s.talon.dealRow(frames=0)
self.s.talon.dealRow(frames=0)
self.startDealSample()
self.s.talon.dealRow()
# /*********************************************************************** # /***********************************************************************
# // Cone # // Cone
@ -507,4 +528,6 @@ registerGame(GameInfo(412, Cone, "Cone",
GI.GT_GYPSY, 2, 0)) GI.GT_GYPSY, 2, 0))
registerGame(GameInfo(463, Surprise, "Surprise", registerGame(GameInfo(463, Surprise, "Surprise",
GI.GT_GYPSY, 2, 0)) GI.GT_GYPSY, 2, 0))
registerGame(GameInfo(469, PhantomBlockade, "Phantom Blockade",
GI.GT_GYPSY, 2, 0))

View file

@ -950,6 +950,27 @@ class SevenDevils(Klondike):
self.s.talon.dealRow(rows=self.s.reserves) self.s.talon.dealRow(rows=self.s.reserves)
# /***********************************************************************
# // Moving Left
# ************************************************************************/
class MovingLeft(Klondike):
def createGame(self):
Klondike.createGame(self, max_rounds=1, rows=10, playcards=24)
def fillStack(self, stack):
if not stack.cards:
old_state = self.enterState(self.S_FILL)
if stack in self.s.rows:
i = list(self.s.rows).index(stack)
if i < 9:
from_stack = self.s.rows[i+1]
pile = from_stack.getPile()
if pile:
from_stack.moveMove(len(pile), stack)
self.leaveState(old_state)
# register the game # register the game
registerGame(GameInfo(2, Klondike, "Klondike", registerGame(GameInfo(2, Klondike, "Klondike",
@ -1042,4 +1063,6 @@ registerGame(GameInfo(452, DoubleEasthaven, "Double Easthaven",
GI.GT_GYPSY, 2, 0)) GI.GT_GYPSY, 2, 0))
registerGame(GameInfo(453, TripleEasthaven, "Triple Easthaven", registerGame(GameInfo(453, TripleEasthaven, "Triple Easthaven",
GI.GT_GYPSY, 3, 0)) GI.GT_GYPSY, 3, 0))
registerGame(GameInfo(470, MovingLeft, "Moving Left",
GI.GT_KLONDIKE, 2, 0))

View file

@ -640,6 +640,9 @@ class Chelicera(Game):
for i in range(3): for i in range(3):
self.s.talon.dealRow(rows=self.s.rows[4:]) self.s.talon.dealRow(rows=self.s.rows[4:])
def getHighlightPilesStacks(self):
return ()
def shallHighlightMatch(self, stack1, card1, stack2, card2): def shallHighlightMatch(self, stack1, card1, stack2, card2):
return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1 return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1
@ -793,6 +796,9 @@ class Applegate(Game):
return False return False
return True return True
def getHighlightPilesStacks(self):
return ()
def shallHighlightMatch(self, stack1, card1, stack2, card2): def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and return (card1.suit == card2.suit and
((card1.rank + 1) % stack1.cap.mod == card2.rank or ((card1.rank + 1) % stack1.cap.mod == card2.rank or

View file

@ -347,21 +347,31 @@ Diamond: 4 8 Q 3 7 J 2 6 T A 5 9 K'''))
# /*********************************************************************** # /***********************************************************************
# // Double Yukon # // Double Yukon
# // Double Russian Solitaire
# ************************************************************************/ # ************************************************************************/
class DoubleYukon(Yukon): class DoubleYukon(Yukon):
def createGame(self): def createGame(self):
Yukon.createGame(self, rows=10) Yukon.createGame(self, rows=10)
def startGame(self): def startGame(self):
for i in range(1, len(self.s.rows)): for i in range(1, len(self.s.rows)-1):
self.s.talon.dealRow(rows=self.s.rows[i:], flip=0, frames=0) self.s.talon.dealRow(rows=self.s.rows[i:], flip=0, frames=0)
#self.s.talon.dealRow(rows=self.s.rows, flip=0, frames=0)
for i in range(5): for i in range(5):
self.s.talon.dealRow(rows=self.s.rows, flip=1, frames=0) self.s.talon.dealRow(flip=1, frames=0)
self.startDealSample() self.startDealSample()
self.s.talon.dealRow(rows=self.s.rows[:-1]) self.s.talon.dealRow()
assert len(self.s.talon.cards) == 0 assert len(self.s.talon.cards) == 0
class DoubleRussianSolitaire(DoubleYukon):
RowStack_Class = StackWrapper(Yukon_SS_RowStack, base_rank=KING)
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return (card1.suit == card2.suit and
(card1.rank + 1 == card2.rank or card2.rank + 1 == card1.rank))
# /*********************************************************************** # /***********************************************************************
# // Triple Yukon # // Triple Yukon
# ************************************************************************/ # ************************************************************************/
@ -543,3 +553,5 @@ registerGame(GameInfo(450, RawPrawn, "Raw Prawn",
GI.GT_YUKON, 1, 0)) GI.GT_YUKON, 1, 0))
registerGame(GameInfo(456, BimBom, "Bim Bom", registerGame(GameInfo(456, BimBom, "Bim Bom",
GI.GT_YUKON | GI.GT_ORIGINAL, 2, 0)) GI.GT_YUKON | GI.GT_ORIGINAL, 2, 0))
registerGame(GameInfo(466, DoubleRussianSolitaire, "Double Russian Solitaire",
GI.GT_YUKON | GI.GT_ORIGINAL, 2, 0))

126
pysollib/games/zodiac.py Normal file
View file

@ -0,0 +1,126 @@
##---------------------------------------------------------------------------##
##
## PySol -- a Python Solitaire game
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; see the file COPYING.
## If not, write to the Free Software Foundation, Inc.,
## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
##
##---------------------------------------------------------------------------##
__all__ = []
# imports
import sys
# PySol imports
from pysollib.gamedb import registerGame, GameInfo, GI
from pysollib.util import *
from pysollib.mfxutil import kwdefault
from pysollib.stack import *
from pysollib.game import Game
from pysollib.layout import Layout
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
# /***********************************************************************
# // Zodiac
# ************************************************************************/
class Zodiac_Foundation(SS_FoundationStack):
def acceptsCards(self, from_stack, cards):
if not SS_FoundationStack.acceptsCards(self, from_stack, cards):
return False
if self.game.s.waste.cards or self.game.s.talon.cards:
return False
return True
class Zodiac_RowStack(UD_SS_RowStack):
def acceptsCards(self, from_stack, cards):
if not UD_SS_RowStack.acceptsCards(self, from_stack, cards):
return False
if from_stack in self.game.s.rows:
return False
return True
class Zodiac_ReserveStack(ReserveStack):
def acceptsCards(self, from_stack, cards):
if not ReserveStack.acceptsCards(self, from_stack, cards):
return False
if from_stack in self.game.s.rows:
return False
return True
class Zodiac(Game):
def createGame(self):
# create layout
l, s = Layout(self), self.s
# set window
w, h = l.XM+12*l.XS, l.YM+5*l.YS
self.setSize(w, h)
# create stacks
x = l.XM
for i in range(12):
for y in (l.YM, l.YM+4*l.YS):
stack = Zodiac_RowStack(x, y, self, base_rank=NO_RANK)
s.rows.append(stack)
stack.CARD_XOFFSET, stack.CARD_YOFFSET = 0, 0
x += l.XS
x = l.XM+4*l.XS
for i in range(4):
y = l.YM+l.YS
s.foundations.append(Zodiac_Foundation(x, y, self, suit=i))
y += 2*l.YS
s.foundations.append(Zodiac_Foundation(x, y, self, suit=i,
base_rank=KING, dir=-1))
x += l.XS
x, y = l.XM+2*l.XS, l.YM+2*l.YS
for i in range(8):
s.reserves.append(Zodiac_ReserveStack(x, y, self))
x += l.XS
x, y = l.XM+l.XS, l.YM+l.YS
s.talon = WasteTalonStack(x, y, self,
max_rounds=UNLIMITED_REDEALS)
l.createText(s.talon, 'sw')
x += l.XS
s.waste = WasteStack(x, y, self)
l.createText(s.waste, 'se')
# define stack-groups
l.defaultStackGroups()
def startGame(self):
self.startDealSample()
self.s.talon.dealRow(rows=self.s.reserves)
self.s.talon.dealRow()
self.s.talon.dealCards()
def shallHighlightMatch(self, stack1, card1, stack2, card2):
return card1.suit == card2.suit and abs(card1.rank-card2.rank) == 1
# register the game
registerGame(GameInfo(467, Zodiac, "Zodiac",
GI.GT_2DECK_TYPE, 2, -1))

View file

@ -338,7 +338,7 @@ class PysolMenubar(PysolMenubarActions):
submenu.add_checkbutton(label=n_("Show removed tiles (in Mahjongg games)"), variable=self.tkopt.mahjongg_show_removed, command=self.mOptMahjonggShowRemoved) submenu.add_checkbutton(label=n_("Show removed tiles (in Mahjongg games)"), variable=self.tkopt.mahjongg_show_removed, command=self.mOptMahjonggShowRemoved)
submenu.add_checkbutton(label=n_("Show hint arrow (in Shisen-Sho games)"), variable=self.tkopt.shisen_show_hint, command=self.mOptShisenShowHint) submenu.add_checkbutton(label=n_("Show hint arrow (in Shisen-Sho games)"), variable=self.tkopt.shisen_show_hint, command=self.mOptShisenShowHint)
menu.add_separator() menu.add_separator()
label = n_("&Sound") label = n_("&Sound...")
if self.app.audio.audiodev is None: if self.app.audio.audiodev is None:
menu.add_checkbutton(label=label, variable=self.tkopt.sound, command=self.mOptSoundDialog, state=Tkinter.DISABLED) menu.add_checkbutton(label=label, variable=self.tkopt.sound, command=self.mOptSoundDialog, state=Tkinter.DISABLED)
else: else:
@ -372,6 +372,7 @@ class PysolMenubar(PysolMenubarActions):
submenu.add_checkbutton(label=n_("Show &statusbar"), variable=self.tkopt.statusbar, command=self.mOptStatusbar) submenu.add_checkbutton(label=n_("Show &statusbar"), variable=self.tkopt.statusbar, command=self.mOptStatusbar)
submenu.add_checkbutton(label=n_("Show &number of cards"), variable=self.tkopt.num_cards, command=self.mOptNumCards) submenu.add_checkbutton(label=n_("Show &number of cards"), variable=self.tkopt.num_cards, command=self.mOptNumCards)
submenu.add_checkbutton(label=n_("Show &help bar"), variable=self.tkopt.helpbar, command=self.mOptHelpbar) submenu.add_checkbutton(label=n_("Show &help bar"), variable=self.tkopt.helpbar, command=self.mOptHelpbar)
menu.add_checkbutton(label=n_("Save games &geometry"), variable=self.tkopt.save_games_geometry, command=self.mOptSaveGamesGeometry)
menu.add_checkbutton(label=n_("&Demo logo"), variable=self.tkopt.demo_logo, command=self.mOptDemoLogo) menu.add_checkbutton(label=n_("&Demo logo"), variable=self.tkopt.demo_logo, command=self.mOptDemoLogo)
menu.add_checkbutton(label=n_("Startup splash sc&reen"), variable=self.tkopt.splashscreen, command=self.mOptSplashscreen) menu.add_checkbutton(label=n_("Startup splash sc&reen"), variable=self.tkopt.splashscreen, command=self.mOptSplashscreen)
### menu.add_separator() ### menu.add_separator()
@ -866,6 +867,7 @@ class PysolMenubar(PysolMenubarActions):
self._cancelDrag() self._cancelDrag()
self.game.endGame(bookmark=1) self.game.endGame(bookmark=1)
self.game.quitGame(bookmark=1) self.game.quitGame(bookmark=1)
self.app.opt.games_geometry = {} # clear saved games geometry
def _mOptCardback(self, index): def _mOptCardback(self, index):
if self._cancelDrag(break_pause=False): return if self._cancelDrag(break_pause=False): return
@ -958,7 +960,8 @@ class PysolMenubar(PysolMenubarActions):
if not self.app.statusbar: return if not self.app.statusbar: return
side = self.tkopt.statusbar.get() side = self.tkopt.statusbar.get()
self.app.opt.statusbar = side self.app.opt.statusbar = side
if self.app.statusbar.show(side): resize = not self.app.opt.save_games_geometry
if self.app.statusbar.show(side, resize=resize):
self.top.update_idletasks() self.top.update_idletasks()
def mOptNumCards(self, *event): def mOptNumCards(self, *event):
@ -970,9 +973,14 @@ class PysolMenubar(PysolMenubarActions):
if not self.app.helpbar: return if not self.app.helpbar: return
show = self.tkopt.helpbar.get() show = self.tkopt.helpbar.get()
self.app.opt.helpbar = show self.app.opt.helpbar = show
if self.app.helpbar.show(show): resize = not self.app.opt.save_games_geometry
if self.app.helpbar.show(show, resize=resize):
self.top.update_idletasks() self.top.update_idletasks()
def mOptSaveGamesGeometry(self, *event):
if self._cancelDrag(break_pause=False): return
self.app.opt.save_games_geometry = self.tkopt.save_games_geometry.get()
def mOptDemoLogo(self, *event): def mOptDemoLogo(self, *event):
if self._cancelDrag(break_pause=False): return if self._cancelDrag(break_pause=False): return
self.app.opt.demo_logo = self.tkopt.demo_logo.get() self.app.opt.demo_logo = self.tkopt.demo_logo.get()
@ -1002,7 +1010,8 @@ class PysolMenubar(PysolMenubarActions):
if self._cancelDrag(break_pause=False): return if self._cancelDrag(break_pause=False): return
self.app.opt.toolbar = side self.app.opt.toolbar = side
self.tkopt.toolbar.set(side) # update radiobutton self.tkopt.toolbar.set(side) # update radiobutton
if self.app.toolbar.show(side): resize = not self.app.opt.save_games_geometry
if self.app.toolbar.show(side, resize=resize):
self.top.update_idletasks() self.top.update_idletasks()
def setToolbarSize(self, size): def setToolbarSize(self, size):

View file

@ -74,31 +74,33 @@ class SoundOptionsDialog(MfxDialog):
self.music_volume = IntVar() self.music_volume = IntVar()
self.music_volume.set(app.opt.sound_music_volume) self.music_volume.set(app.opt.sound_music_volume)
self.samples = [ self.samples = [
('areyousure', 'AreYouSure', BooleanVar()), ('areyousure', _('Are You Sure'), BooleanVar()),
('autodrop', 'AutoDrop', BooleanVar()),
('autoflip', 'AutoFlip', BooleanVar()), ('deal', _('Deal'), BooleanVar()),
('autopilotlost', 'AutopilotLost', BooleanVar()), ('dealwaste', _('Deal waste'), BooleanVar()),
('autopilotwon', 'AutopilotWon', BooleanVar()),
('deal', 'Deal', BooleanVar()), ('turnwaste', _('Turn waste'), BooleanVar()),
#('deal01', 'Deal01', BooleanVar()), ('startdrag', _('Start drag'), BooleanVar()),
#('deal02', 'Deal02', BooleanVar()),
#('deal04', 'Deal04', BooleanVar()), ('drop', _('Drop'), BooleanVar()),
#('deal08', 'Deal08', BooleanVar()), ('droppair', _('Drop pair'), BooleanVar()),
('dealwaste', 'DealWaste', BooleanVar()), ('autodrop', _('Auto drop'), BooleanVar()),
('droppair', 'DropPair', BooleanVar()),
('drop', 'Drop', BooleanVar()), ('flip', _('Flip'), BooleanVar()),
#('extra', 'Extra', BooleanVar()), ('autoflip', _('Auto flip'), BooleanVar()),
('flip', 'Flip', BooleanVar()), ('move', _('Move'), BooleanVar()),
('move', 'Move', BooleanVar()), ('nomove', _('No move'), BooleanVar()),
('nomove', 'NoMove', BooleanVar()),
('redo', 'Redo', BooleanVar()), ('undo', _('Undo'), BooleanVar()),
('startdrag', 'StartDrag', BooleanVar()), ('redo', _('Redo'), BooleanVar()),
('turnwaste', 'TurnWaste', BooleanVar()),
('undo', 'Undo', BooleanVar()), ('autopilotlost', _('Autopilot lost'), BooleanVar()),
('gamefinished', 'GameFinished', BooleanVar()), ('autopilotwon', _('Autopilot won'), BooleanVar()),
('gamelost', 'GameLost', BooleanVar()),
('gameperfect', 'GamePerfect', BooleanVar()), ('gamefinished', _('Game finished'), BooleanVar()),
('gamewon', 'GameWon', BooleanVar()), ('gamelost', _('Game lost'), BooleanVar()),
('gamewon', _('Game won'), BooleanVar()),
('gameperfect', _('Perfect game'), BooleanVar()),
] ]
# #

View file

@ -125,15 +125,15 @@ class tkHTMLWriter(formatter.DumbWriter):
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)
self.text.tag_config(tag, foreground="blue", underline=1) fg = 'blue'
u = self.viewer.normurl(url, with_protocol=False)
if u in self.viewer.visited_urls:
fg = '#303080'
self.text.tag_config(tag, foreground=fg, underline=1)
self.anchor = None self.anchor = None
def anchor_enter(self, url): def anchor_enter(self, url):
for p in REMOTE_PROTOCOLS: url = self.viewer.normurl(url)
if url.startswith(p):
break
else:
url = 'file://'+self.viewer.basejoin(url)
self.viewer.statusbar.updateText(url=url) self.viewer.statusbar.updateText(url=url)
self.text.config(cursor=self.viewer.handcursor) self.text.config(cursor=self.viewer.handcursor)
@ -219,6 +219,7 @@ class tkHTMLViewer:
list = [], list = [],
index = 0, index = 0,
) )
self.visited_urls = []
self.images = {} # need to keep a reference because of garbage collection self.images = {} # need to keep a reference because of garbage collection
self.defcursor = parent["cursor"] self.defcursor = parent["cursor"]
##self.defcursor = 'xterm' ##self.defcursor = 'xterm'
@ -247,7 +248,8 @@ class tkHTMLViewer:
text_frame = Tkinter.Frame(parent) text_frame = Tkinter.Frame(parent)
text_frame.grid(row=1, column=0, columnspan=4, sticky='nsew') text_frame.grid(row=1, column=0, columnspan=4, sticky='nsew')
self.text = Tkinter.Text(text_frame, self.text = Tkinter.Text(text_frame,
fg='black', bg='white', bd=0, fg='black', bg='white',
bd=1, relief='sunken',
cursor=self.defcursor, cursor=self.defcursor,
wrap='word', padx=20, pady=20) wrap='word', padx=20, pady=20)
self.text.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) self.text.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
@ -287,24 +289,22 @@ class tkHTMLViewer:
except: pass except: pass
self.parent = None self.parent = None
def _yview(self, *args):
apply(self.text.yview, args, {})
return 'break'
def page_up(self, *event): def page_up(self, *event):
self.text.yview_scroll(-1, "page") return self._yview('scroll', -1, 'page')
return "break"
def page_down(self, *event): def page_down(self, *event):
self.text.yview_scroll(1, "page") return self._yview('scroll', 1, 'page')
return "break"
def unit_up(self, *event): def unit_up(self, *event):
self.text.yview_scroll(-1, "unit") return self._yview('scroll', -1, 'unit')
return "break"
def unit_down(self, *event): def unit_down(self, *event):
self.text.yview_scroll(1, "unit") return self._yview('scroll', 1, 'unit')
return "break"
def scroll_top(self, *event): def scroll_top(self, *event):
self.text.yview_moveto(0) return self._yview('moveto', 0)
return "break"
def scroll_bottom(self, *event): def scroll_bottom(self, *event):
self.text.yview_moveto(1) return self._yview('moveto', 1)
return "break"
# locate a file relative to the current self.url # locate a file relative to the current self.url
def basejoin(self, url, baseurl=None, relpath=1): def basejoin(self, url, baseurl=None, relpath=1):
@ -325,6 +325,18 @@ class tkHTMLViewer:
url = os.path.normpath(url) url = os.path.normpath(url)
return url return url
def normurl(self, url, with_protocol=True):
for p in REMOTE_PROTOCOLS:
if url.startswith(p):
break
else:
url = self.basejoin(url)
if with_protocol:
if os.name == 'nt':
url = url.replace('\\', '/')
url = 'file://'+url
return url
def openfile(self, url): def openfile(self, url):
if url[-1:] == "/" or os.path.isdir(url): if url[-1:] == "/" or os.path.isdir(url):
url = os.path.join(url, "index.html") url = os.path.join(url, "index.html")
@ -338,6 +350,7 @@ class tkHTMLViewer:
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
# 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...
@ -418,6 +431,8 @@ to open the following URL:
##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 not url in self.visited_urls:
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 cmp(u, url) == 0:

View file

@ -38,7 +38,7 @@ import os, string, types
import Tkinter import Tkinter
# Toolkit imports # Toolkit imports
from tkutil import bind, unbind_destroy from tkutil import bind
from tkwidget import MfxScrolledCanvas from tkwidget import MfxScrolledCanvas
@ -244,6 +244,7 @@ class MfxTreeInCanvas(MfxScrolledCanvas):
def __init__(self, parent, rootnodes, **kw): def __init__(self, parent, rootnodes, **kw):
bg = kw["bg"] = kw.get("bg") or parent.cget("bg") bg = kw["bg"] = kw.get("bg") or parent.cget("bg")
kw['bd'] = 0
apply(MfxScrolledCanvas.__init__, (self, parent,), kw) apply(MfxScrolledCanvas.__init__, (self, parent,), kw)
# #
self.rootnodes = rootnodes self.rootnodes = rootnodes

View file

@ -420,7 +420,7 @@ class MfxTooltip:
class MfxScrolledCanvas: class MfxScrolledCanvas:
def __init__(self, parent, hbar=2, vbar=2, **kw): def __init__(self, parent, hbar=2, vbar=2, **kw):
bg = kw.get("bg", parent.cget("bg")) bg = kw.get("bg", parent.cget("bg"))
kwdefault(kw, bg=bg, highlightthickness=0) kwdefault(kw, bg=bg, highlightthickness=0, bd=1, relief='sunken')
self.parent = parent self.parent = parent
self.createFrame(kw) self.createFrame(kw)
self.canvas = None self.canvas = None
@ -629,41 +629,36 @@ class MfxScrolledCanvas:
self.vbar_show = show self.vbar_show = show
return 1 return 1
def _xview(self, *args):
if self.hbar_show: apply(self.canvas.xview, args, {})
return 'break'
def _yview(self, *args):
if self.vbar_show: apply(self.canvas.yview, args, {})
return 'break'
def page_up(self, *event): def page_up(self, *event):
self.canvas.yview_scroll(-1, "page") return self._yview('scroll', -1, 'page')
return "break"
def page_down(self, *event): def page_down(self, *event):
self.canvas.yview_scroll(1, "page") return self._yview('scroll', 1, 'page')
return "break"
def unit_up(self, *event): def unit_up(self, *event):
self.canvas.yview_scroll(-1, "unit") return self._yview('scroll', -1, 'unit')
return "break"
def unit_down(self, *event): def unit_down(self, *event):
self.canvas.yview_scroll(1, "unit") return self._yview('scroll', 1, 'unit')
return "break"
def mouse_wheel_up(self, *event): def mouse_wheel_up(self, *event):
self.canvas.yview_scroll(-5, "unit") return self._yview('scroll', -5, 'unit')
return "break"
def mouse_wheel_down(self, *event): def mouse_wheel_down(self, *event):
self.canvas.yview_scroll(5, "unit") return self._yview('scroll', 5, 'unit')
return "break"
def page_left(self, *event): def page_left(self, *event):
self.canvas.xview_scroll(-1, "page") return self._xview('scroll', -1, 'page')
return "break"
def page_right(self, *event): def page_right(self, *event):
self.canvas.xview_scroll(1, "page") return self._xview('scroll', 1, 'page')
return "break"
def unit_left(self, *event): def unit_left(self, *event):
self.canvas.xview_scroll(-1, "unit") return self._xview('scroll', -1, 'unit')
return "break"
def unit_right(self, *event): def unit_right(self, *event):
self.canvas.xview_scroll(1, "unit") return self._xview('scroll', 1, 'unit')
return "break"
def scroll_top(self, *event): def scroll_top(self, *event):
self.canvas.yview_moveto(0) return self._yview('moveto', 0)
return "break"
def scroll_bottom(self, *event): def scroll_bottom(self, *event):
self.canvas.yview_moveto(1) return self._yview('moveto', 1)
return "break"