From dc038c8dc9e12ac46253968ae367700382a1bde9 Mon Sep 17 00:00:00 2001 From: skomoroh Date: Mon, 21 Aug 2006 21:17:19 +0000 Subject: [PATCH] * improved GTK bindings; menu, stats-dialog, colors-dialog, timeouts-dialog git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@53 efabe8c0-fbe8-4139-b769-b5e6d273206e --- po/ru_pysol.po | 4 +- pysollib/actions.py | 155 ++--------- pysollib/app.py | 38 +-- pysollib/game.py | 34 ++- pysollib/games/mahjongg/shisensho.py | 4 +- pysollib/main.py | 4 +- pysollib/pysolgtk/colorsdialog.py | 110 +++++++- pysollib/pysolgtk/fontsdialog.py | 15 +- pysollib/pysolgtk/menubar.py | 274 +++++++++++++++---- pysollib/pysolgtk/selecttile.py | 6 +- pysollib/pysolgtk/timeoutsdialog.py | 83 +++++- pysollib/pysolgtk/tkcanvas.py | 102 ++++--- pysollib/pysolgtk/tkstats.py | 385 ++++++++++++++++++++------- pysollib/pysolgtk/tkutil.py | 8 +- pysollib/stack.py | 54 ++-- pysollib/tk/colorsdialog.py | 82 +++--- pysollib/tk/findcarddialog.py | 2 +- pysollib/tk/menubar.py | 122 ++++++++- pysollib/tk/selecttile.py | 2 +- pysollib/tk/timeoutsdialog.py | 24 +- pysollib/tk/tkcanvas.py | 32 ++- pysollib/tk/tkstats.py | 6 +- pysollib/tk/tkwidget.py | 9 +- 23 files changed, 1066 insertions(+), 489 deletions(-) diff --git a/po/ru_pysol.po b/po/ru_pysol.po index 9b9773f1..c0e251e9 100644 --- a/po/ru_pysol.po +++ b/po/ru_pysol.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PySol 0.0.1\n" "POT-Creation-Date: Fri Aug 11 02:14:56 2006\n" -"PO-Revision-Date: 2006-08-11 02:13+0400\n" +"PO-Revision-Date: 2006-08-20 17:42+0400\n" "Last-Translator: Скоморох \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" @@ -2386,7 +2386,7 @@ msgstr "Разрешить показывать карты &одного дос #: pysollib/tk/menubar.py:353 msgid "Highlight &no matching" -msgstr "Подсветка отсутствия &совпадения:" +msgstr "Подсветка отсутствия &совпадения" #: pysollib/tk/menubar.py:355 msgid "&Show removed tiles (in Mahjongg games)" diff --git a/pysollib/actions.py b/pysollib/actions.py index 04df3482..5a0b06c1 100644 --- a/pysollib/actions.py +++ b/pysollib/actions.py @@ -378,12 +378,6 @@ class PysolMenubarActions: self.game.endGame() self.game.quitGame(id, random=random) - def mSelectGame(self, *args): - self._mSelectGame(self.tkopt.gameid.get()) - - def mSelectGamePopular(self, *args): - self._mSelectGame(self.tkopt.gameid_popular.get()) - def _mNewGameBySeed(self, seed, origin): try: random = constructRandom(seed) @@ -762,19 +756,19 @@ class PysolMenubarActions: def mHint(self, *args): if self._cancelDrag(): return if self.app.opt.hint: - if self.game.showHint(0, self.app.opt.hint_sleep): + if self.game.showHint(0, self.app.opt.timeouts['hint']): self.game.stats.hints += 1 def mHint1(self, *args): if self._cancelDrag(): return if self.app.opt.hint: - if self.game.showHint(1, self.app.opt.hint_sleep): + if self.game.showHint(1, self.app.opt.timeouts['hint']): self.game.stats.hints += 1 def mHighlightPiles(self, *args): if self._cancelDrag(): return if self.app.opt.highlight_piles: - if self.game.highlightPiles(self.app.opt.highlight_piles_sleep): + if self.game.highlightPiles(self.app.opt.timeouts['highlight_piles']): self.game.stats.highlight_piles += 1 def mDemo(self, *args): @@ -787,7 +781,6 @@ class PysolMenubarActions: self._mDemo(mixed=1) def _mDemo(self, mixed): - if self._cancelDrag(): return if self.changed(): # only ask if there have been no demo moves or hints yet if self.game.stats.demo_moves == 0 and self.game.stats.hints == 0: @@ -814,134 +807,36 @@ class PysolMenubarActions: self.game.updateStatus(player=self.app.opt.player) self.game.updateStatus(stats=self.app.stats.getStats(self.app.opt.player, self.game.id)) - def mOptAutoFaceUp(self, *args): - if self._cancelDrag(): return - self.app.opt.autofaceup = self.tkopt.autofaceup.get() - if self.app.opt.autofaceup: - self.game.autoPlay() - - def mOptAutoDrop(self, *args): - if self._cancelDrag(): return - self.app.opt.autodrop = self.tkopt.autodrop.get() - if self.app.opt.autodrop: - self.game.autoPlay() - - def mOptAutoDeal(self, *args): - if self._cancelDrag(): return - self.app.opt.autodeal = self.tkopt.autodeal.get() - if self.app.opt.autodeal: - self.game.autoPlay() - - def mOptQuickPlay(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.quickplay = self.tkopt.quickplay.get() - - def mOptEnableUndo(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.undo = self.tkopt.undo.get() - self.game.updateMenus() - - def mOptEnableBookmarks(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.bookmarks = self.tkopt.bookmarks.get() - self.game.updateMenus() - - def mOptEnableHint(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.hint = self.tkopt.hint.get() - self.game.updateMenus() - - def mOptEnableHighlightPiles(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.highlight_piles = self.tkopt.highlight_piles.get() - self.game.updateMenus() - - def mOptEnableHighlightCards(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.highlight_cards = self.tkopt.highlight_cards.get() - self.game.updateMenus() - - def mOptEnableHighlightSameRank(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.highlight_samerank = self.tkopt.highlight_samerank.get() - ##self.game.updateMenus() - - def mOptEnableHighlightNotMatching(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.highlight_not_matching = self.tkopt.highlight_not_matching.get() - ##self.game.updateMenus() - - def mOptShrinkFaceDown(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.shrink_face_down = self.tkopt.shrink_face_down.get() - self.game.endGame(bookmark=1) - self.game.quitGame(bookmark=1) - - def mOptShadeFilledStacks(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.shade_filled_stacks = self.tkopt.shade_filled_stacks.get() - self.game.endGame(bookmark=1) - self.game.quitGame(bookmark=1) - - def mOptMahjonggShowRemoved(self, *args): - if self._cancelDrag(): return - self.app.opt.mahjongg_show_removed = self.tkopt.mahjongg_show_removed.get() - ##self.game.updateMenus() - self.game.endGame(bookmark=1) - self.game.quitGame(bookmark=1) - - def mOptShisenShowHint(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.shisen_show_hint = self.tkopt.shisen_show_hint.get() - ##self.game.updateMenus() - -## def mOptSound(self, *args): -## if self._cancelDrag(break_pause=False): return -## self.app.opt.sound = self.tkopt.sound.get() -## if not self.app.opt.sound: -## self.app.audio.stopAll() - def mOptSoundDialog(self, *args): if self._cancelDrag(break_pause=False): return d = SoundOptionsDialog(self.top, _("Sound settings"), self.app) self.tkopt.sound.set(self.app.opt.sound) - def mOptAnimations(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.animations = self.tkopt.animations.get() - - def mOptShadow(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.shadow = self.tkopt.shadow.get() - - def mOptShade(self, *args): - if self._cancelDrag(break_pause=False): return - self.app.opt.shade = self.tkopt.shade.get() - ## def mOptIrregularPiles(self, *args): ## if self._cancelDrag(): return ## self.app.opt.irregular_piles = self.tkopt.irregular_piles.get() - def mOptColorsOptions(self, *args): + def mOptColors(self, *args): if self._cancelDrag(break_pause=False): return d = ColorsDialog(self.top, _("Set colors"), self.app) - table_text_color = self.app.opt.table_text_color - table_text_color_value = self.app.opt.table_text_color_value + text_color = self.app.opt.colors['text'] + use_default_text_color = self.app.opt.use_default_text_color if d.status == 0 and d.button == 0: - self.app.opt.table_text_color = d.table_text_color - self.app.opt.table_text_color_value = d.table_text_color_value - ##self.app.opt.table_color = d.table_color - self.app.opt.highlight_piles_colors = d.highlight_piles_colors - self.app.opt.highlight_cards_colors = d.highlight_cards_colors - self.app.opt.highlight_samerank_colors = d.highlight_samerank_colors - self.app.opt.hintarrow_color = d.hintarrow_color - self.app.opt.highlight_not_matching_color = d.highlight_not_matching_color + self.app.opt.use_default_text_color = d.use_default_color + self.app.opt.colors['text'] = d.text_color + self.app.opt.colors['piles'] = d.piles_color + self.app.opt.colors['cards_1'] = d.cards_1_color + self.app.opt.colors['cards_2'] = d.cards_2_color + self.app.opt.colors['samerank_1'] = d.samerank_1_color + self.app.opt.colors['samerank_2'] = d.samerank_2_color + self.app.opt.colors['hintarrow'] = d.hintarrow_color + self.app.opt.colors['not_matching'] = d.not_matching_color # - if table_text_color != self.app.opt.table_text_color \ - or table_text_color_value != self.app.opt.table_text_color_value: + if (text_color != self.app.opt.colors['text'] or + use_default_text_color != self.app.opt.use_default_text_color): self.app.setTile(self.tkopt.tabletile.get(), 1) - def mOptFontsOptions(self, *args): + def mOptFonts(self, *args): if self._cancelDrag(break_pause=False): return d = FontsDialog(self.top, _("Set fonts"), self.app) if d.status == 0 and d.button == 0: @@ -950,16 +845,16 @@ class PysolMenubarActions: self.game.endGame(bookmark=1) self.game.quitGame(bookmark=1) - def mOptTimeoutsOptions(self, *args): + def mOptTimeouts(self, *args): if self._cancelDrag(break_pause=False): return d = TimeoutsDialog(self.top, _("Set timeouts"), self.app) if d.status == 0 and d.button == 0: - self.app.opt.demo_sleep = d.demo_sleep - self.app.opt.hint_sleep = d.hint_sleep - self.app.opt.raise_card_sleep = d.raise_card_sleep - self.app.opt.highlight_piles_sleep = d.highlight_piles_sleep - self.app.opt.highlight_cards_sleep = d.highlight_cards_sleep - self.app.opt.highlight_samerank_sleep = d.highlight_samerank_sleep + self.app.opt.timeouts['demo'] = d.demo_timeout + self.app.opt.timeouts['hint'] = d.hint_timeout + self.app.opt.timeouts['raise_card'] = d.raise_card_timeout + self.app.opt.timeouts['highlight_piles'] = d.highlight_piles_timeout + self.app.opt.timeouts['highlight_cards'] = d.highlight_cards_timeout + self.app.opt.timeouts['highlight_samerank'] = d.highlight_samerank_timeout ## def mOptSave(self, *args): ## if self._cancelDrag(break_pause=False): return diff --git a/pysollib/app.py b/pysollib/app.py index cb8d6771..0ebdd5eb 100644 --- a/pysollib/app.py +++ b/pysollib/app.py @@ -167,21 +167,27 @@ class Options: self.fonts["sans"] = ("times new roman", 12) self.fonts["fixed"] = ("courier new", 10) # colors - self.table_color = "#008200" - self.highlight_piles_colors = (None, "#ffc000") - self.highlight_cards_colors = (None, "#ffc000", None, "#0000ff") - self.highlight_samerank_colors = (None, "#ffc000", None, "#0000ff") - self.hintarrow_color = "#303030" - self.highlight_not_matching_color = '#ff0000' - self.table_text_color = False # `False' is mean use default - self.table_text_color_value = '#ffffff' + self.colors = { + 'table': '#008200', + 'text': '#ffffff', + 'piles': '#ffc000', + 'cards_1': '#ffc000', + 'cards_2': '#0000ff', + 'samerank_1': '#ffc000', + 'samerank_2': '#0000ff', + 'hintarrow': '#303030', + 'not_matching': '#ff0000', + } + self.use_default_text_color = True # delays - self.hint_sleep = 1.0 - self.demo_sleep = 1.0 - self.raise_card_sleep = 1.0 - self.highlight_piles_sleep = 1.0 - self.highlight_cards_sleep = 1.0 - self.highlight_samerank_sleep = 1.0 + self.timeouts = { + 'hint': 1.0, + 'demo': 1.0, + 'raise_card': 1.0, + 'highlight_piles': 1.0, + 'highlight_cards': 1.0, + 'highlight_samerank': 1.0, + } # additional startup information self.num_recent_games = 15 self.recent_gameid = [] @@ -935,7 +941,7 @@ class Application: if self.scrolled_canvas.setTile(self, i, force): tile = self.tabletile_manager.get(i) if i == 0: - self.opt.table_color = tile.color + self.opt.colors['table'] = tile.color self.opt.tabletile_name = None else: self.opt.tabletile_name = tile.basename @@ -1005,7 +1011,7 @@ class Application: self.wm_save_state() self.wm_withdraw() title = _("Loading %s %s...") % (CARDSET, cs.name) - color = self.opt.table_color + color = self.opt.colors['table'] if self.tabletile_index > 0: color = "#008200" progress = PysolProgressBar(self, self.top, title=title, diff --git a/pysollib/game.py b/pysollib/game.py index 7555d1d9..3a1d7508 100644 --- a/pysollib/game.py +++ b/pysollib/game.py @@ -1470,7 +1470,7 @@ for %d moves. def highlightCard(self, suit, rank): if not self.app: return None - col = self.app.opt.highlight_samerank_colors[1] + col = self.app.opt.colors['samerank_1'] info = [] for s in self.allstacks: for c in s.cards: @@ -1546,10 +1546,19 @@ for %d moves. y2 = y2 + self.app.images.CARDH tkraise = True ##print c1, c2, x1, y1, x2, y2 - r = MfxCanvasRectangle(self.canvas, x1-1, y1-1, x2+1, y2+1, - width=4, fill=None, outline=color) - if tkraise: - r.tkraise(c2.item) + if TOOLKIT == 'tk': + r = MfxCanvasRectangle(self.canvas, x1-1, y1-1, x2+1, y2+1, + width=4, fill=None, outline=color) + if tkraise: + r.tkraise(c2.item) + elif TOOLKIT == 'gtk': + r = MfxCanvasRectangle(self.canvas, x1-1, y1-1, x2+1, y2+1, + width=4, fill=None, outline=color, + group=s.group) + if tkraise: + i = s.cards.index(c2) + for c in s.cards[i+1:]: + c.tkraise(1) items.append(r) if not items: return 0 @@ -1575,14 +1584,14 @@ for %d moves. y = int(int(self.canvas.cget('height'))*(self.canvas.yview()[0])) w, h = self.canvas.winfo_width(), self.canvas.winfo_height() # - color = self.app.opt.highlight_not_matching_color + color = self.app.opt.colors['not_matching'] width = 6 x0, y0 = x+width/2-self.canvas.xmargin, y+width/2-self.canvas.ymargin x1, y1 = x+w-width-self.canvas.xmargin, y+h-width-self.canvas.ymargin r = MfxCanvasRectangle(self.canvas, x0, y0, x1, y1, width=width, fill=None, outline=color) self.canvas.update_idletasks() - self.sleep(self.app.opt.highlight_cards_sleep) + self.sleep(self.app.opt.timeouts['highlight_cards']) r.delete() self.canvas.update_idletasks() @@ -1591,7 +1600,7 @@ for %d moves. if not stackinfo: self.highlightNotMatching() return 0 - col = self.app.opt.highlight_piles_colors + col = self.app.opt.colors['piles'] hi = [] for si in stackinfo: for s in si[0]: @@ -1771,7 +1780,7 @@ for %d moves. y2 = y2 + images.CARDH / 2 # draw the hint arrow = MfxCanvasLine(self.canvas, x1, y1, x2, y2, width=7, - fill=self.app.opt.hintarrow_color, + fill=self.app.opt.colors['hintarrow'], arrow="last", arrowshape=(30,30,10)) self.canvas.update_idletasks() # wait @@ -1794,7 +1803,7 @@ for %d moves. self.demo = Struct( level = level, mixed = mixed, - sleep = self.app.opt.demo_sleep, + sleep = self.app.opt.timeouts['demo'], last_deal = [], hint = None, keypress = None, @@ -1979,8 +1988,9 @@ for %d moves. ta = self.getDemoInfoTextAttr(tinfo) if ta: font = self.app.getFont("canvas_large") - self.demo.info_text = MfxCanvasText(self.canvas, ta[1], ta[2], anchor=ta[0], - font=font, text=self.getDemoInfoText()) + self.demo.info_text = MfxCanvasText(self.canvas, ta[1], ta[2], + anchor=ta[0], font=font, + text=self.getDemoInfoText()) def getDemoInfoText(self): return self.gameinfo.short_name diff --git a/pysollib/games/mahjongg/shisensho.py b/pysollib/games/mahjongg/shisensho.py index 58c05b69..32e9b9da 100644 --- a/pysollib/games/mahjongg/shisensho.py +++ b/pysollib/games/mahjongg/shisensho.py @@ -228,7 +228,7 @@ class Shisen_RowStack(Mahjongg_RowStack): game.updateStackMove(game.s.talon, 2|16) # for undo if not game.demo: if game.app.opt.shisen_show_hint: - self.drawArrow(other_stack, game.app.opt.hint_sleep) + self.drawArrow(other_stack, game.app.opt.timeouts['hint']) game.playSample("droppair", priority=200) # game.moveMove(n, self, f, frames=frames, shadow=shadow) @@ -275,7 +275,7 @@ class Shisen_RowStack(Mahjongg_RowStack): arrow = MfxCanvasLine(game.canvas, coords, {'width': w, - 'fill': game.app.opt.hintarrow_color, + 'fill': game.app.opt.colors['hintarrow'], ##'arrow': 'last', ##'arrowshape': (s1, s1, s2) } diff --git a/pysollib/main.py b/pysollib/main.py index afdc65ae..6f1dab6f 100644 --- a/pysollib/main.py +++ b/pysollib/main.py @@ -374,7 +374,7 @@ Please check your %s installation. # init tiles manager = app.tabletile_manager tile = Tile() - tile.color = app.opt.table_color + tile.color = app.opt.colors['table'] tile.name = "None" tile.filename = None manager.register(tile) @@ -449,7 +449,7 @@ Sounds and background music will be disabled.'''), # create the progress bar title = _("Welcome to ") + PACKAGE - color = app.opt.table_color + color = app.opt.colors['table'] if app.tabletile_index > 0: color = "#008200" app.intro.progress = PysolProgressBar(app, top, title=title, color=color, diff --git a/pysollib/pysolgtk/colorsdialog.py b/pysollib/pysolgtk/colorsdialog.py index 8c9ce661..d7fefbbc 100644 --- a/pysollib/pysolgtk/colorsdialog.py +++ b/pysollib/pysolgtk/colorsdialog.py @@ -21,25 +21,115 @@ __all__ = ['ColorsDialog'] -## # imports +# imports ## import os, sys -## import Tkinter -## from tkColorChooser import askcolor +import gtk, gobject, pango +import gtk.glade +from gtk import gdk -## # PySol imports -## from pysollib.mfxutil import destruct, kwdefault, KwStruct, Struct +# PySol imports -## # Toolkit imports -## from tkconst import EVENT_HANDLED, EVENT_PROPAGATE +# Toolkit imports -from tkwidget import MfxDialog + +gettext = _ # /*********************************************************************** # // # ************************************************************************/ -class ColorsDialog(MfxDialog): - pass +class ColorsDialog: + +## self.app.opt.table_text_color = d.table_text_color +## self.app.opt.table_text_color_value = d.table_text_color_value +## ##self.app.opt.table_color = d.table_color +## self.app.opt.highlight_piles_colors = d.highlight_piles_colors +## self.app.opt.highlight_cards_colors = d.highlight_cards_colors +## self.app.opt.highlight_samerank_colors = d.highlight_samerank_colors +## self.app.opt.hintarrow_color = d.hintarrow_color +## self.app.opt.highlight_not_matching_color = d.highlight_not_matching_color + + def __init__(self, parent, title, app, **kw): + + glade_file = app.dataloader.findFile('pysolfc.glade') + self.widgets_tree = gtk.glade.XML(glade_file) + + keys = ( + 'text', + 'piles', + 'cards_1', + 'cards_2', + 'samerank_1', + 'samerank_2', + 'hintarrow', + 'not_matching', + ) + for n in keys: + label = self.widgets_tree.get_widget(n+'_label') + self._setColor(label, app.opt.colors[n]) + button = self.widgets_tree.get_widget(n+'_button') + button.connect('clicked', self._changeColor, n, label) + checkbutton = self.widgets_tree.get_widget('use_default_checkbutton') + checkbutton.set_active(not app.opt.use_default_text_color) + + self._translateLabels() + + dialog = self.widgets_tree.get_widget('colors_dialog') + self.dialog = dialog + dialog.set_title(title) + dialog.set_transient_for(parent) + dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + + self.status = -1 + self.button = -1 + response = dialog.run() + if response == gtk.RESPONSE_OK: + self.status = 0 + self.button = 0 + for n in keys: + w = self.widgets_tree.get_widget(n+'_label') + c = w.get_data('user_data') + setattr(self, n+'_color', c) + self.use_default_color = not checkbutton.get_active() + + dialog.destroy() + def _setColor(self, label, color): + c = gdk.color_parse(color) + al = pango.AttrList() + al.insert(pango.AttrBackground(c.red, c.green, c.blue, 0, 10)) + label.set_attributes(al) + label.set_data('user_data', color) + + + def _changeColor(self, w, name, label): + print '_changeColor', name + color = label.get_data('user_data') + dialog = gtk.ColorSelectionDialog(_('Select color')) + dialog.help_button.destroy() + dialog.set_transient_for(self.dialog) + dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + dialog.colorsel.set_current_color(gdk.color_parse(color)) + response = dialog.run() + if response == gtk.RESPONSE_OK: + c = dialog.colorsel.get_current_color() + c = '#%02x%02x%02x' % (c.red/256, c.green/256, c.blue/256) + self._setColor(label, c) + dialog.destroy() + + + def _translateLabels(self): + for n in ( + 'label31', + 'label32', + 'label33', + 'label34', + 'label35', + 'label36', + 'label37', + ): + w = self.widgets_tree.get_widget(n) + w.set_text(gettext(w.get_text())) + diff --git a/pysollib/pysolgtk/fontsdialog.py b/pysollib/pysolgtk/fontsdialog.py index d2cb80ab..d99e4853 100644 --- a/pysollib/pysolgtk/fontsdialog.py +++ b/pysollib/pysolgtk/fontsdialog.py @@ -21,28 +21,29 @@ __all__ = ['FontsDialog'] -## # imports +# imports ## import os, sys ## import types ## import Tkinter ## import tkFont +import gtk, gobject, pango +import gtk.glade -## # PySol imports +# PySol imports ## from pysollib.mfxutil import destruct, kwdefault, KwStruct, Struct -## # Toolkit imports +# Toolkit imports ## from tkconst import EVENT_HANDLED, EVENT_PROPAGATE ## from tkutil import bind -from tkwidget import MfxDialog # /*********************************************************************** # // # ************************************************************************/ -class FontsDialog(MfxDialog): - pass - +class FontsDialog: + def __init__(self, parent, title, app, **kw): + pass diff --git a/pysollib/pysolgtk/menubar.py b/pysollib/pysolgtk/menubar.py index 068bc18b..ced06062 100644 --- a/pysollib/pysolgtk/menubar.py +++ b/pysollib/pysolgtk/menubar.py @@ -51,7 +51,6 @@ from selectgame import SelectGameDialogWithPreview gettext = _ - def ltk2gtk(s): # label tk to gtk return gettext(s).replace('&', '_') @@ -67,6 +66,7 @@ class PysolMenubar(PysolMenubarActions): def __init__(self, app, top, progress=None): PysolMenubarActions.__init__(self, app, top) self.progress = progress + self._cb_max = gdk.screen_height()/24 # create menus menubar = self.createMenubar() self.top.table.attach(menubar, @@ -89,10 +89,10 @@ class PysolMenubar(PysolMenubarActions): entries = ( ### toolbar - ('newgame', gtk.STOCK_NEW, - ltk2gtk('&New game'), 'N', - ltk2gtk('New game'), - self.mNewGame), + ('newgame', gtk.STOCK_NEW, # action name, stock + ltk2gtk('&New game'), 'N', # label, accelerator + ltk2gtk('New game'), # tooltip + self.mNewGame), # callback ('open', gtk.STOCK_OPEN, ltk2gtk('&Open...'), 'O', ltk2gtk('Open a\nsaved game'), @@ -118,11 +118,11 @@ class PysolMenubar(PysolMenubarActions): ltk2gtk('Auto drop'), self.mDrop), ('stats', gtk.STOCK_INDEX, - ltk2gtk('Stats'), None, + ltk2gtk('&Statistics'), None, ltk2gtk('Statistics'), lambda w, self=self: self.mPlayerStats(mode=101)), ('rules', gtk.STOCK_HELP, - ltk2gtk('Rules'), 'F1', + ltk2gtk('&Rules'), 'F1', ltk2gtk('Rules'), self.mHelpRules), ('quit', gtk.STOCK_QUIT, @@ -131,19 +131,21 @@ class PysolMenubar(PysolMenubarActions): self.mQuit), ### menus - ('file', None, ltk2gtk('&File')), - ('selectgame', None, ltk2gtk('Select &game')), - ('edit', None, ltk2gtk('&Edit')), - ('game', None, ltk2gtk('&Game')), - ('assist', None, ltk2gtk('&Assist')), - ('options', None, ltk2gtk('&Options')), - ('assistlevel', None, ltk2gtk('Assist &level')), - ('automaticplay', None, ltk2gtk('&Automatic play')), - ('animations', None, ltk2gtk('A&nimations')), - ('cardview', None, ltk2gtk('Card &view')), - ('toolbar', None, ltk2gtk('&Toolbar')), - ('statusbar', None, ltk2gtk('Stat&usbar')), - ('help', None, ltk2gtk('&Help')), + ('file', None, ltk2gtk('&File')), + ('recentgames', None, ltk2gtk('R&ecent games')), + ('favoritegames', None, ltk2gtk('Fa&vorite games')), + ('select', None, ltk2gtk('&Select')), + ('edit', None, ltk2gtk('&Edit')), + ('game', None, ltk2gtk('&Game')), + ('assist', None, ltk2gtk('&Assist')), + ('options', None, ltk2gtk('&Options')), + ('assistlevel', None, ltk2gtk('Assist &level')), + ('automaticplay', None, ltk2gtk('&Automatic play')), + ('animations', None, ltk2gtk('A&nimations')), + ('cardview', None, ltk2gtk('Card &view')), + ('toolbar', None, ltk2gtk('&Toolbar')), + ('statusbar', None, ltk2gtk('Stat&usbar')), + ('help', None, ltk2gtk('&Help')), ### menuitems ('playablepreview', None, @@ -152,6 +154,12 @@ class PysolMenubar(PysolMenubarActions): ('selectgamebynumber', None, ltk2gtk('Select game by nu&mber...'), None, None, self.mSelectGameById), + ('addtofavorites', None, + ltk2gtk('A&dd to favorites'), None, + None, self.mAddFavor), + ('removefromfavorites', None, + ltk2gtk('R&emove from favorites'), None, + None, self.mDelFavor), ('saveas', None, ltk2gtk('Save &as...'), None, None, self.mSaveAs), @@ -188,6 +196,12 @@ class PysolMenubar(PysolMenubarActions): ('cardset', None, ltk2gtk('Cards&et...'), 'E', None, self.mSelectCardsetDialog), + ('timeouts', None, + ltk2gtk('Time&outs...'), None, + None, self.mOptTimeouts), + ('colors', None, + ltk2gtk('&Colors...'), None, + None, self.mOptColors), ('contents', None, ltk2gtk('&Contents'), 'F1', None, self.mHelp), @@ -274,8 +288,10 @@ class PysolMenubar(PysolMenubarActions): - - + + + + @@ -283,6 +299,12 @@ class PysolMenubar(PysolMenubarActions): + + + + + + @@ -353,6 +375,9 @@ class PysolMenubar(PysolMenubarActions): + + + @@ -394,19 +419,28 @@ class PysolMenubar(PysolMenubarActions): ui_manager.insert_action_group(action_group, 0) self.top.add_accel_group(ui_manager.get_accel_group()) self.top.ui_manager = ui_manager - menubar = ui_manager.get_widget('/menubar') + + #ui_manager.get_widget('/menubar/file/recentgames').show() + #ui_manager.get_widget('/menubar/file/favoritegames').show() games = map(self.app.gdb.get, self.app.gdb.getGamesIdSortedByName()) + menu = ui_manager.get_widget('/menubar/select').get_submenu() + self._createSelectMenu(games, menu) - menu_item = ui_manager.get_widget('/menubar/file/selectgame') - menu_item.show() - menu = gtk.Menu() - menu_item.set_submenu(menu) - self._addSelectAllGameSubMenu(games, menu, self.mSelectGame) - + menubar = ui_manager.get_widget('/menubar') return menubar + # + # Select Game menu creation + # + + def _getNumGames(self, games, select_data): + ngames = 0 + for label, select_func in select_data: + ngames += len(filter(select_func, games)) + return ngames + def _createSubMenu(self, menu, label): menu_item = gtk.MenuItem(label) menu.add(menu_item) @@ -415,21 +449,26 @@ class PysolMenubar(PysolMenubarActions): menu_item.set_submenu(submenu) return submenu - def _addSelectGameSubMenu(self, games, menu, command, group): - for g in games: - label = g.name - label = gettext(label) - menu_item = gtk.RadioMenuItem(group, label) - group = menu_item - menu.add(menu_item) - menu_item.show() - menu_item.connect('toggled', command, g.id) + def _addGamesMenuItem(self, menu, gi, short_name=False): + if short_name: + label = gi.short_name + else: + label = gi.name + label = gettext(label) + menu_item = gtk.MenuItem(label) + menu_item.set_data('user_data', gi.id) + menu_item.connect('activate', self.mSelectGame) + menu.add(menu_item) + menu_item.show() - def _addSelectAllGameSubMenu(self, games, menu, command): - cb_max = gdk.screen_height()/24 - n, d = 0, cb_max + def _addGamesSubMenu(self, games, menu, short_name=False): + for gi in games: + self._addGamesMenuItem(menu, gi, short_name=short_name) + + def _addAllGamesMenu(self, games, menu): + menu = self._createSubMenu(menu, label=ltk2gtk('&All games by name')) + n, d = 0, self._cb_max i = 0 - group = None while True: if self.progress: self.progress.update(step=1) i += 1 @@ -440,16 +479,88 @@ class PysolMenubar(PysolMenubarActions): n1, n2 = gettext(n1), gettext(n2) label = n1[:3]+' - '+n2[:3] submenu = self._createSubMenu(menu, label=label) - group = self._addSelectGameSubMenu(games[n:n+d], submenu, - command, group) + self._addGamesSubMenu(games[n:n+d], submenu) n += d + def _addSelectedGamesSubMenu(self, games, menu, select_data): + for label, select_func in select_data: + g = filter(select_func, games) + if not g: + continue + submenu = self._createSubMenu(menu, label=label) + self._addGamesSubMenu(g, submenu) + + def _addPopularGamesMenu(self, games, menu): + select_func = lambda gi: gi.si.game_flags & GI.GT_POPULAR + if len(filter(select_func, games)) == 0: + return + data = (ltk2gtk('&Popular games'), select_func) + self._addSelectedGamesSubMenu(games, menu, (data, )) + + def _addGamesByType(self, games, menu, label, data): + if self._getNumGames(games, data) == 0: + return + submenu = self._createSubMenu(menu, label=label) + self._addSelectedGamesSubMenu(games, submenu, data) + + def _addMahjonggGamesMenu(self, games, menu): + select_func = lambda gi: gi.si.game_type == GI.GT_MAHJONGG + mahjongg_games = filter(select_func, games) + if len(mahjongg_games) == 0: + return + menu = self._createSubMenu(menu, label=ltk2gtk('&Mahjongg games')) + # + def add_menu(games, c0, c1, menu=menu): + if not games: + return + label = c0 + ' - ' + c1 + if c0 == c1: + label = c0 + submenu = self._createSubMenu(menu, label=label) + self._addGamesSubMenu(games, submenu, short_name=True) + # + games = {} + for gi in mahjongg_games: + c = gettext(gi.short_name).strip()[0] + if games.has_key(c): + games[c].append(gi) + else: + games[c] = [gi] + games = games.items() + games.sort() + # + g0 = [] + c0 = c1 = games[0][0] + for c, g1 in games: + if len(g0)+len(g1) >= self._cb_max: + add_menu(g0, c0, c1) + g0 = g1 + c0 = c1 = c + else: + g0 += g1 + c1 = c + add_menu(g0, c0, c1) + + + def _createSelectMenu(self, games, menu): + assert isinstance(menu, gtk.Menu) + self._addPopularGamesMenu(games, menu) + for l, d in ( + (ltk2gtk('&French games'), GI.SELECT_GAME_BY_TYPE), + (ltk2gtk('&Oriental games'), GI.SELECT_ORIENTAL_GAME_BY_TYPE), + (ltk2gtk('&Special games'), GI.SELECT_SPECIAL_GAME_BY_TYPE), + ): + self._addGamesByType(games, menu, l, d) + self._addMahjonggGamesMenu(games, menu) + sep = gtk.SeparatorMenuItem() + menu.add(sep) + self._addAllGamesMenu(games, menu) + # # menu updates # -## WARNING: setMenuState: not found: /menubar/file/holdandquit ## WARNING: setMenuState: not found: /menubar/assist/findcard def setMenuState(self, state, path): path_map = { @@ -467,7 +578,6 @@ class PysolMenubar(PysolMenubarActions): menuitem.set_sensitive(state) - def setToolbarState(self, state, path): path = '/toolbar/'+path button = self.top.ui_manager.get_widget(path) @@ -481,9 +591,59 @@ class PysolMenubar(PysolMenubarActions): # menu actions # - def _createFileChooser(self, title, action, idir, ifile): + def mAddFavor(self, w): + gameid = self.app.game.id + if gameid not in self.app.opt.favorite_gameid: + self.app.opt.favorite_gameid.append(gameid) + self.updateFavoriteGamesMenu() + + def mDelFavor(self, w): + gameid = self.app.game.id + if gameid in self.app.opt.favorite_gameid: + self.app.opt.favorite_gameid.remove(gameid) + self.updateFavoriteGamesMenu() + + def updateFavoriteGamesMenu(self): + games = self.app.opt.favorite_gameid + self._updateGamesMenu('/menubar/file/favoritegames', games) + in_favor = self.app.game.id in games + item = self.top.ui_manager.get_widget('/menubar/file/addtofavorites') + item.set_sensitive(not in_favor) + item = self.top.ui_manager.get_widget('/menubar/file/removefromfavorites') + item.set_sensitive(in_favor) + + def updateRecentGamesMenu(self, games): + self._updateGamesMenu('/menubar/file/recentgames', games) + + def _updateGamesMenu(self, path, games): + item = self.top.ui_manager.get_widget(path) + item.show() + menu = item.get_submenu() + menu.show() + # + menu_games = [] + def checkFavor(item): + gameid = item.get_data('user_data') + if gameid in games: + menu_games.append(gameid) + else: + menu.remove(item) + menu.foreach(checkFavor) + # + for gameid in games: + if gameid not in menu_games: + gi = self.app.getGameInfo(gameid) + self._addGamesMenuItem(menu, gi) + if not games: + item = gtk.MenuItem(_('Empty')) + item.show() + item.set_sensitive(False) + menu.add(item) + + + def _createFileChooser(self, title, action, idir, ifile, stock): d = gtk.FileChooserDialog(title, self.top, action, - (gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT, + (stock, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) d.set_current_folder(idir) if ifile: @@ -519,7 +679,8 @@ class PysolMenubar(PysolMenubarActions): idir = self.app.dn.savegames filename = self._createFileChooser(_('Open Game'), gtk.FILE_CHOOSER_ACTION_OPEN, - idir, '') + idir, '', + gtk.STOCK_OPEN) if filename: ##filename = os.path.normpath(filename) ##filename = os.path.normcase(filename) @@ -547,7 +708,8 @@ class PysolMenubar(PysolMenubarActions): ##print self.game.filename, ifile filename = self._createFileChooser(_('Save Game'), gtk.FILE_CHOOSER_ACTION_SAVE, - idir, ifile) + idir, ifile, + gtk.STOCK_SAVE) if filename: ##filename = os.path.normpath(filename) ##filename = os.path.normcase(filename) @@ -555,14 +717,10 @@ class PysolMenubar(PysolMenubarActions): self.updateMenus() + def mSelectGame(self, menu_item): + game_id = menu_item.get_data('user_data') + self._mSelectGame(game_id) - def updateFavoriteGamesMenu(self, *args): - pass - - - def mSelectGame(self, menu_item, game_id): - if menu_item.get_active(): - self._mSelectGame(game_id) def mSelectGameDialogWithPreview(self, *event): if self._cancelDrag(break_pause=False): return @@ -593,7 +751,7 @@ class PysolMenubar(PysolMenubarActions): if self._cancelDrag(break_pause=False): return key = self.app.tabletile_index if key <= 0: - key = self.app.opt.table_color.lower() + key = self.app.opt.colors['table'] d = SelectTileDialogWithPreview(self.top, app=self.app, title=_('Select table background'), manager=self.app.tabletile_manager, diff --git a/pysollib/pysolgtk/selecttile.py b/pysollib/pysolgtk/selecttile.py index 91fd3e8b..08c52d6b 100644 --- a/pysollib/pysolgtk/selecttile.py +++ b/pysollib/pysolgtk/selecttile.py @@ -54,7 +54,7 @@ class SelectTileDialogWithPreview(MfxDialog): self.key = key self.preview_key = -1 self.all_keys = [] - self.table_color = app.opt.table_color + self.table_color = app.opt.colors['table'] # paned hpaned = gtk.HPaned() self.hpaned = hpaned @@ -150,7 +150,7 @@ class SelectTileDialogWithPreview(MfxDialog): canvas.setBackgroundImage(None) canvas.setTextColor(None) self.preview_key = key - self.table_color = key + self.colors['table'] = key else: # image tile = self.manager.get(key) @@ -186,7 +186,7 @@ class SelectTileDialogWithPreview(MfxDialog): if type(self.preview_key) is str: color = self.preview_key else: - color = self.app.opt.table_color + color = self.app.opt.colors['table'] win.colorsel.set_current_color(gdk.color_parse(color)) win.connect('delete_event', lambda w, e: win.destroy()) win.ok_button.connect('clicked', self._colorselOkClicked, win) diff --git a/pysollib/pysolgtk/timeoutsdialog.py b/pysollib/pysolgtk/timeoutsdialog.py index 13283977..4d98ef31 100644 --- a/pysollib/pysolgtk/timeoutsdialog.py +++ b/pysollib/pysolgtk/timeoutsdialog.py @@ -21,22 +21,87 @@ __all__ = ['TimeoutsDialog'] -## # imports +# imports ## import os, sys -## import Tkinter +import gtk, gobject, pango +import gtk.glade -## # PySol imports -## from pysollib.mfxutil import destruct, kwdefault, KwStruct, Struct +# PySol imports -## # Toolkit imports -## from tkconst import EVENT_HANDLED, EVENT_PROPAGATE +# Toolkit imports -from tkwidget import MfxDialog + +gettext = _ # /*********************************************************************** # // # ************************************************************************/ -class TimeoutsDialog(MfxDialog): - pass +class TimeoutsDialog: + + def __init__(self, parent, title, app, **kw): + + glade_file = app.dataloader.findFile('pysolfc.glade') + self.widgets_tree = gtk.glade.XML(glade_file) + + keys = ( + 'demo', + 'hint', + 'raise_card', + 'highlight_piles', + 'highlight_cards', + 'highlight_samerank', + ) + + dic = {} + for n in keys: + def callback(w, n=n): + sp = self.widgets_tree.get_widget(n+'_spinbutton') + sc = self.widgets_tree.get_widget(n+'_scale') + sp.set_value(sc.get_value()) + dic[n+'_scale_value_changed'] = callback + def callback(w, n=n): + sp = self.widgets_tree.get_widget(n+'_spinbutton') + sc = self.widgets_tree.get_widget(n+'_scale') + sc.set_value(sp.get_value()) + dic[n+'_spinbutton_value_changed'] = callback + self.widgets_tree.signal_autoconnect(dic) + + for n in keys: + v = app.opt.timeouts[n] + w = self.widgets_tree.get_widget(n+'_spinbutton') + w.set_value(v) + w = self.widgets_tree.get_widget(n+'_scale') + w.set_value(v) + + self._translateLabels() + + dialog = self.widgets_tree.get_widget('timeouts_dialog') + dialog.set_title(title) + dialog.set_transient_for(parent) + dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + + self.status = -1 + self.button = -1 + response = dialog.run() + if response == gtk.RESPONSE_OK: + self.status = 0 + self.button = 0 + for n in keys: + w = self.widgets_tree.get_widget(n+'_spinbutton') + setattr(self, n+'_timeout', w.get_value()) + + dialog.destroy() + + def _translateLabels(self): + for n in ( + 'label25', + 'label26', + 'label27', + 'label28', + 'label29', + 'label30', + ): + w = self.widgets_tree.get_widget(n) + w.set_text(gettext(w.get_text())) diff --git a/pysollib/pysolgtk/tkcanvas.py b/pysollib/pysolgtk/tkcanvas.py index 1570974d..43ff8751 100644 --- a/pysollib/pysolgtk/tkcanvas.py +++ b/pysollib/pysolgtk/tkcanvas.py @@ -77,11 +77,16 @@ class _CanvasItem: self.canvas = canvas canvas._all_items.append(self) self._is_hidden = False + self._x, self._y = 0, 0 + self._group = None def addtag(self, group): ##print self, 'addtag' ##~ assert isinstance(group._item, CanvasGroup) self._item.reparent(group._item) + if self._group == group: + print 'addtag: new_group == old_group' + self._group = group def dtag(self, group): ##print self, 'dtag' @@ -102,11 +107,14 @@ class _CanvasItem: self._item = None def lower(self, positions=None): - return # used for reordered shadow; don't need? + print 'lower', self, positions + return # don't need? ## if positions is None: -## self._item.lower_to_bottom() -## self._item.get_property('parent').raise_to_top() +## pass +## ##self._item.lower_to_bottom() +## ##self._item.get_property('parent').lower_to_bottom() ## else: +## print self, positions ## ##~ assert type(positions) is types.IntType and positions > 0 ## self._item.lower(positions) @@ -116,13 +124,18 @@ class _CanvasItem: self._item.raise_to_top() self._item.get_property('parent').raise_to_top() else: - print self, 'tkraise', positions # don't used? + #print self, 'tkraise', positions + #self._item.raise_to_top() ##~ assert type(positions) is types.IntType and positions > 0 - self._item.raise_(positions) + self._item.raise_to_top() #positions) def move(self, x, y): self._item.move(x, y) - moveTo = move + self._x, self._y = self._x+x, self._y+y + + def moveTo(self, x, y): + self._item.move(x-self._x, y-self._y) + self._x, self._y = x, y def show(self): if self._item: @@ -146,16 +159,22 @@ class MfxCanvasGroup(_CanvasItem): class MfxCanvasImage(_CanvasItem): - def __init__(self, canvas, x, y, image, anchor=gtk.ANCHOR_NW): + def __init__(self, canvas, x, y, image, anchor=gtk.ANCHOR_NW, group=None): _CanvasItem.__init__(self, canvas) + self._x, self._y = x, y if type(anchor) is str: anchor = anchor_tk2gtk(anchor) - self._item = canvas.root().add(gnome.canvas.CanvasPixbuf, - x=x, y=y, - pixbuf=image.pixbuf, - width=image.width(), - height=image.height(), - anchor=anchor) + if group: + self._group = group + group = group._item + else: + group = canvas.root() + self._item = group.add(gnome.canvas.CanvasPixbuf, + x=x, y=y, + pixbuf=image.pixbuf, + width=image.width(), + height=image.height(), + anchor=anchor) self._item.show() def config(self, image): @@ -183,35 +202,52 @@ class MfxCanvasLine(_CanvasItem): kwargs['arrow_shape_a'] = kw['arrowshape'][0] kwargs['arrow_shape_b'] = kw['arrowshape'][1] kwargs['arrow_shape_c'] = kw['arrowshape'][2] - self._item = canvas.root().add(gnome.canvas.CanvasLine, - points=points, **kwargs) + if kw.has_key('group'): + self._group = kw['group'] + group = kw['group']._item + else: + group = canvas.root() + self._item = group.add(gnome.canvas.CanvasLine, + points=points, **kwargs) self._item.show() - #canvas.show_all() class MfxCanvasRectangle(_CanvasItem): def __init__(self, canvas, x1, y1, x2, y2, - width=0, fill=None, outline=None): + width=0, fill=None, outline=None, group=None): _CanvasItem.__init__(self, canvas) + self._x, self._y = x1, y1 kw = {'x1': x1, 'x2': x2, 'y1': y1, 'y2': y2} if width: kw['width_pixels'] = width if fill: kw['fill_color'] = fill if outline: kw['outline_color'] = outline - self._item = canvas.root().add(gnome.canvas.CanvasRect, **kw) + if group: + self._group = group + group = group._item + else: + group = canvas.root() + self._item = group.add(gnome.canvas.CanvasRect, **kw) self._item.show() class MfxCanvasText(_CanvasItem): def __init__(self, canvas, x, y, anchor=gtk.ANCHOR_NW, preview=-1, **kw): _CanvasItem.__init__(self, canvas) + self._x, self._y = x, y if preview < 0: preview = canvas.preview if preview > 1: self._item = None return anchor = anchor_tk2gtk(anchor) - self._item = canvas.root().add(gnome.canvas.CanvasText, - x=x, y=y, anchor=anchor) + if kw.has_key('group'): + self._group = kw['group'] + group = kw['group']._item + del kw['group'] + else: + group = canvas.root() + self._item = group.add(gnome.canvas.CanvasText, + x=x, y=y, anchor=anchor) if not kw.has_key('fill'): kw['fill'] = canvas._text_color for k, v in kw.items(): @@ -236,7 +272,6 @@ class MfxCanvasText(_CanvasItem): def __getitem__(self, key): if key == 'text': - # FIXME return self._item.get_property('text') else: raise AttributeError, key @@ -295,7 +330,7 @@ class MfxCanvas(gnome.canvas.Canvas): def bind(self, sequence=None, func=None, add=None): assert add is None # FIXME - print "TkCanvas bind:", sequence + print 'TkCanvas bind:', sequence return def cget(self, attr): @@ -307,7 +342,7 @@ class MfxCanvas(gnome.canvas.Canvas): return self.get_size()[0] elif attr == 'height': return self.get_size()[1] - print "TkCanvas cget:", attr + print 'TkCanvas cget:', attr raise AttributeError, attr def xview(self): @@ -327,20 +362,20 @@ class MfxCanvas(gnome.canvas.Canvas): def configure(self, **kw): height, width = -1, -1 for k, v in kw.items(): - if k in ("background", "bg"): + if k in ('background', 'bg'): ##print 'configure: bg:', v c = self.get_colormap().alloc_color(v) self.style.bg[gtk.STATE_NORMAL] = c - elif k == "cursor": + elif k == 'cursor': if not self.window: self.realize() self.window.set_cursor(gdk.Cursor(v)) - elif k == "height": + elif k == 'height': height = v - elif k == "width": + elif k == 'width': width = v else: - print "TkCanvas", k, v + print 'TkCanvas', k, v raise AttributeError, k if height > 0 and width > 0: self.set_size_request(width, height) @@ -386,7 +421,7 @@ class MfxCanvas(gnome.canvas.Canvas): if self._text_color != color: self._text_color = color for item in self._text_items: - item.set(fill_color=_self.text_color) + item._item.set(fill_color=self._text_color) # PySol extension - set a tiled background image def setTile(self, app, i, force=False): @@ -402,7 +437,8 @@ class MfxCanvas(gnome.canvas.Canvas): assert tile.filename assert tile.basename if not force: - if i == app.tabletile_index and tile.color == app.opt.table_color: + if (i == app.tabletile_index and + tile.color == app.opt.colors['table']): return False if self._tile is tile: return False @@ -420,10 +456,10 @@ class MfxCanvas(gnome.canvas.Canvas): self.configure(bg=self.top_bg) color = tile.text_color - if app.opt.table_text_color: - self.setTextColor(app.opt.table_text_color_value) - else: + if app.opt.use_default_text_color: self.setTextColor(color) + else: + self.setTextColor(app.opt.colors['text']) return True diff --git a/pysollib/pysolgtk/tkstats.py b/pysollib/pysolgtk/tkstats.py index 70ccdafe..9e02ee7a 100644 --- a/pysollib/pysolgtk/tkstats.py +++ b/pysollib/pysolgtk/tkstats.py @@ -1,13 +1,7 @@ -## vim:ts=4:et:nowrap -## ##---------------------------------------------------------------------------## ## ## PySol -- a Python Solitaire game ## -## Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer -## Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer -## Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer -## ## 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 @@ -23,10 +17,6 @@ ## If not, write to the Free Software Foundation, Inc., ## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ## -## Markus F.X.J. Oberhumer -## -## http://wildsau.idv.uni-linz.ac.at/mfx/pysol.html -## ##---------------------------------------------------------------------------## @@ -37,16 +27,13 @@ import gtk.glade # PySol imports from pysollib.mfxutil import format_time -from pysollib.settings import TOP_TITLE +from pysollib.settings import TOP_TITLE, PACKAGE from pysollib.stats import PysolStatsFormatter # Toolkit imports from tkwidget import MfxDialog, MfxMessageDialog - -glade_file = os.path.join(sys.path[0], 'data', 'pysolfc.glade') - -open(glade_file) +gettext = _ # /*********************************************************************** @@ -54,6 +41,7 @@ open(glade_file) # ************************************************************************/ class StatsWriter(PysolStatsFormatter.StringWriter): + def __init__(self, store): self.store = store @@ -70,7 +58,7 @@ class StatsWriter(PysolStatsFormatter.StringWriter): return iter = self.store.append(None) self.store.set(iter, - 0, args[0], + 0, gettext(args[0]), 1, args[1], 2, args[2], 3, args[3], @@ -80,9 +68,12 @@ class StatsWriter(PysolStatsFormatter.StringWriter): 7, gameid) -class FullLogWriter(PysolStatsFormatter.StringWriter): +class LogWriter(PysolStatsFormatter.StringWriter): + MAX_ROWS = 10000 + def __init__(self, store): self.store = store + self._num_rows = 0 def p(self, s): pass @@ -94,13 +85,16 @@ class FullLogWriter(PysolStatsFormatter.StringWriter): if gameid < 0: # header return + if self._num_rows > self.MAX_ROWS: + return iter = self.store.append(None) self.store.set(iter, - 0, gamename, + 0, gettext(gamename), 1, gamenumber, 2, date, 3, status, 4, gameid) + self._num_rows += 1 class Game_StatsDialog: @@ -108,49 +102,153 @@ class Game_StatsDialog: def __init__(self, parent, header, app, player, gameid): # self.app = app - + self.player = player + self.gameid = gameid + self.games = {} + self.games_id = [] # sorted by name + # formatter = PysolStatsFormatter(self.app) + glade_file = app.dataloader.findFile('pysolfc.glade') + # + games = app.gdb.getGamesIdSortedByName() + n = 0 + current = 0 + for id in games: + won, lost = self.app.stats.getStats(self.player, id) + if won+lost > 0 or id == gameid: + gi = app.gdb.get(id) + if id == gameid: + current = n + self.games[n] = gi + self.games_id.append(id) + n += 1 # self.widgets_tree = gtk.glade.XML(glade_file) - #game_name_combo = self.widgets_tree.get_widget('game_name_combo') - #model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT) - #game_name_combo.set_model(model) - #game_name_combo.set_text_column(0) - stats_dialog = self.widgets_tree.get_widget('stats_dialog') - stats_dialog.set_title('Game Statistics') - stats_dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) - # total - won, lost = app.stats.getStats(player, gameid) - self._createText('total', won, lost) - drawing = self.widgets_tree.get_widget('total_drawingarea') - drawing.connect('expose_event', self._createChart, won, lost) - # current session - won, lost = app.stats.getSessionStats(player, gameid) - self._createText('current', won, lost) - drawing = self.widgets_tree.get_widget('session_drawingarea') - drawing.connect('expose_event', self._createChart, won, lost) # + table = self.widgets_tree.get_widget('current_game_table') + combo = self._createGameCombo(table, 1, 0, self._currentComboChanged) + # total + self._createText('total') + drawing = self.widgets_tree.get_widget('total_drawingarea') + drawing.connect('expose_event', self._drawingExposeEvent, 'total') + # current session + self._createText('session') + drawing = self.widgets_tree.get_widget('session_drawingarea') + drawing.connect('expose_event', self._drawingExposeEvent, 'session') + # top 10 + table = self.widgets_tree.get_widget('top_10_table') + combo = self._createGameCombo(table, 1, 0, self._top10ComboChanged) + self._createTop() + self._updateTop(gameid) + # all games stat store = self._createStatsList() writer = StatsWriter(store) formatter.writeStats(writer, player, header, sort_by='name') - # + # full log store = self._createLogList('full_log_treeview') - writer = FullLogWriter(store) + writer = LogWriter(store) formatter.writeFullLog(writer, player, header) - # + # session log store = self._createLogList('session_log_treeview') - writer = FullLogWriter(store) + writer = LogWriter(store) formatter.writeSessionLog(writer, player, header) # - stats_dialog.set_transient_for(parent) - stats_dialog.resize(400, 300) - - stats_dialog.run() + self._translateLabels() + dialog = self.widgets_tree.get_widget('stats_dialog') + dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + dialog.set_transient_for(parent) + dialog.resize(500, 340) + dialog.set_title(PACKAGE+' - '+_("Statistics")) + # + dialog.run() self.status = -1 - stats_dialog.destroy() + dialog.destroy() - def _createText(self, name, won, lost): + def _translateLabels(self): + # mnemonic + for n in ( + 'label1', + 'label2', + 'label3', + 'label4', + 'label15', + 'label16', + 'label17', + 'label18', + ): + w = self.widgets_tree.get_widget(n) + w.set_text_with_mnemonic(gettext(w.get_label())) + # simple + for n in ( + 'label5', + 'label6', + 'label7', + 'label14' + ): + w = self.widgets_tree.get_widget(n) + w.set_text(gettext(w.get_text())) + # markup + for n in ( + 'label8', + 'label9', + 'label10', + 'label11', + 'label12', + 'label13', + 'label19', + 'label20', + 'label21', + 'label22', + 'label23', + 'label24', + ): + w = self.widgets_tree.get_widget(n) + s = gettext(w.get_label()) + w.set_markup('%s' % s) + + + def _createGameCombo(self, table, x, y, callback): + combo = gtk.combo_box_new_text() + combo.show() + table.attach(combo, + x, x+1, y, y+1, + gtk.FILL|gtk.EXPAND, 0, + 4, 4) + # + n = 0 + current = 0 + for id in self.games_id: + gi = self.app.gdb.get(id) + combo.append_text(gettext(gi.name)) + if id == self.gameid: + current = n + n += 1 + combo.set_active(current) + combo.connect('changed', callback) #self._comboChanged) + + + def _currentComboChanged(self, w): + gi = self.games[w.get_active()] + self.gameid = gi.id + self._createText('total') + drawing = self.widgets_tree.get_widget('total_drawingarea') + self._createChart(drawing, 'total') + self._createText('session') + drawing = self.widgets_tree.get_widget('session_drawingarea') + self._createChart(drawing, 'session') + + + def _top10ComboChanged(self, w): + gi = self.games[w.get_active()] + self._updateTop(gi.id) + + + def _createText(self, name): + if name == 'total': + won, lost = self.app.stats.getStats(self.player, self.gameid) + else: + won, lost = self.app.stats.getSessionStats(self.player, self.gameid) pwon, plost = self._getPwon(won, lost) label = self.widgets_tree.get_widget(name+'_num_won_label') label.set_text(str(won)) @@ -164,7 +262,15 @@ class Game_StatsDialog: label.set_text(str(won+lost)) - def _createChart(self, drawing, e, won, lost): + def _drawingExposeEvent(self, drawing, e, frame): + self._createChart(drawing, frame) + + + def _createChart(self, drawing, frame): + if frame == 'total': + won, lost = self.app.stats.getStats(self.player, self.gameid) + else: + won, lost = self.app.stats.getSessionStats(self.player, self.gameid) pwon, plost = self._getPwon(won, lost) s, ewon, elost = 0, int(360.0*pwon), int(360.0*plost) @@ -182,34 +288,128 @@ class Game_StatsDialog: y = y-dy/2 if won+lost > 0: - gc.set_rgb_fg_color(colormap.alloc_color('#007f00')) + gc.set_foreground(colormap.alloc_color('#008000')) win.draw_arc(gc, True, x, y+dy, w, h, s*64, ewon*64) - gc.set_rgb_fg_color(colormap.alloc_color('#7f0000')) + gc.set_foreground(colormap.alloc_color('black')) + win.draw_arc(gc, False, x, y+dy, w, h, s*64, ewon*64) + gc.set_foreground(colormap.alloc_color('#800000')) win.draw_arc(gc, True, x, y+dy, w, h, (s+ewon)*64, elost*64) - gc.set_rgb_fg_color(colormap.alloc_color('#00ff00')) + gc.set_foreground(colormap.alloc_color('black')) + win.draw_arc(gc, False, x, y+dy, w, h, (s+ewon)*64, elost*64) + gc.set_foreground(colormap.alloc_color('#00ff00')) win.draw_arc(gc, True, x, y, w, h, s*64, ewon*64) - gc.set_rgb_fg_color(colormap.alloc_color('#ff0000')) + gc.set_foreground(colormap.alloc_color('black')) + win.draw_arc(gc, False, x, y, w, h, s*64, ewon*64) + gc.set_foreground(colormap.alloc_color('#ff0000')) win.draw_arc(gc, True, x, y, w, h, (s+ewon)*64, elost*64) + gc.set_foreground(colormap.alloc_color('black')) + win.draw_arc(gc, False, x, y, w, h, (s+ewon)*64, elost*64) else: - gc.set_rgb_fg_color(colormap.alloc_color('#7f7f7f')) + gc.set_foreground(colormap.alloc_color('#808080')) win.draw_arc(gc, True, x, y+dy, w, h, 0, 360*64) - gc.set_rgb_fg_color(colormap.alloc_color('#f0f0f0')) + gc.set_foreground(colormap.alloc_color('black')) + win.draw_arc(gc, False, x, y+dy, w, h, 0, 360*64) + gc.set_foreground(colormap.alloc_color('#f0f0f0')) win.draw_arc(gc, True, x, y, w, h, 0, 360*64) - gc.set_rgb_fg_color(colormap.alloc_color('#bfbfbf')) - pangolayout = drawing.create_pango_layout('No games') + gc.set_foreground(colormap.alloc_color('black')) + win.draw_arc(gc, False, x, y, w, h, 0, 360*64) + gc.set_foreground(colormap.alloc_color('#a0a0a0')) + pangolayout = drawing.create_pango_layout(_('No games')) ext = pangolayout.get_extents() tw, th = ext[1][2]/pango.SCALE, ext[1][3]/pango.SCALE - win.draw_layout( - gc, - x+w/2-tw/2, y+h/2-th/2, - pangolayout) + win.draw_layout(gc, x+w/2-tw/2, y+h/2-th/2, pangolayout) + + + def _createTop(self): + for n in ('top_10_time_treeview', + 'top_10_moves_treeview', + 'top_10_total_moves_treeview'): + self._createTopList(n) + + + def _updateTop(self, gameid): + if (not self.app.stats.games_stats.has_key(self.player) or + not self.app.stats.games_stats[self.player].has_key(gameid) or + not self.app.stats.games_stats[self.player][gameid].time_result.top): + return + + s = self.app.stats.games_stats[self.player][gameid] + + label = self.widgets_tree.get_widget('playing_time_minimum_label') + label.set_text(format_time(s.time_result.min)) + label = self.widgets_tree.get_widget('playing_time_maximum_label') + label.set_text(format_time(s.time_result.max)) + label = self.widgets_tree.get_widget('playing_time_average_label') + label.set_text(format_time(s.time_result.average)) + + label = self.widgets_tree.get_widget('moves_minimum_label') + label.set_text(str(s.moves_result.min)) + label = self.widgets_tree.get_widget('moves_maximum_label') + label.set_text(str(s.moves_result.max)) + label = self.widgets_tree.get_widget('moves_average_label') + label.set_text(str(round(s.moves_result.average, 2))) + + label = self.widgets_tree.get_widget('total_moves_minimum_label') + label.set_text(str(s.total_moves_result.min)) + label = self.widgets_tree.get_widget('total_moves_maximum_label') + label.set_text(str(s.total_moves_result.max)) + label = self.widgets_tree.get_widget('total_moves_average_label') + label.set_text(str(round(s.total_moves_result.average, 2))) + + for n, ss in ( + ('top_10_time_treeview', s.time_result.top), + ('top_10_moves_treeview', s.moves_result.top), + ('top_10_total_moves_treeview', s.total_moves_result.top)): + self._updateTopList(n, ss) + + + def _createTopList(self, tv_name): + treeview = self.widgets_tree.get_widget(tv_name) + store = gtk.ListStore(gobject.TYPE_INT, # N + gobject.TYPE_STRING, # number + gobject.TYPE_STRING, # started at + gobject.TYPE_STRING, # result + gobject.TYPE_STRING, # result + ) + treeview.set_model(store) + n = 0 + for label in ( + _('N'), + _('Game number'), + _('Started at'), + _('Result'), + ): + column = gtk.TreeViewColumn(label, gtk.CellRendererText(), text=n) + column.set_resizable(True) + ##column.set_sort_column_id(n) + treeview.append_column(column) + n += 1 + + + def _updateTopList(self, tv_name, top): + treeview = self.widgets_tree.get_widget(tv_name) + store = treeview.get_model() + store.clear() + row = 1 + for i in top: + t = time.strftime('%Y-%m-%d %H:%M', + time.localtime(i.game_start_time)) + if isinstance(i.value, float): + # time + r = format_time(i.value) + else: + # moves + r = str(i.value) + iter = store.append(None) + store.set(iter, 0, row, 1, i.game_number, 2, t, 3, r) + row += 1 def _createStatsList(self): treeview = self.widgets_tree.get_widget('all_games_treeview') n = 0 for label in ( - '', + _('Game'), _('Played'), _('Won'), _('Lost'), @@ -234,10 +434,11 @@ class Game_StatsDialog: gobject.TYPE_INT, # gameid ) sortable = gtk.TreeModelSort(store) - treeview.set_model(sortable) sortable.set_sort_func(4, self._cmpPlayingTime) sortable.set_sort_func(5, self._cmpMoves) sortable.set_sort_func(6, self._cmpPercent) + treeview.set_model(sortable) + treeview.set_rules_hint(True) return store @@ -265,6 +466,7 @@ class Game_StatsDialog: gobject.TYPE_INT, # gameid ) treeview.set_model(store) + treeview.set_rules_hint(True) return store @@ -300,15 +502,10 @@ class Game_StatsDialog: # ************************************************************************/ SingleGame_StatsDialog = Game_StatsDialog - -class AllGames_StatsDialog(MfxDialog): - pass - -class FullLog_StatsDialog(AllGames_StatsDialog): - pass - -class SessionLog_StatsDialog(FullLog_StatsDialog): - pass +AllGames_StatsDialog = Game_StatsDialog +FullLog_StatsDialog = Game_StatsDialog +SessionLog_StatsDialog = Game_StatsDialog +Top_StatsDialog = Game_StatsDialog # /*********************************************************************** @@ -334,32 +531,32 @@ class Status_StatsDialog(MfxMessageDialog): #MfxDialog if game.s.foundations: w2 = w2 + _('\nCards in Foundations: ') + str(n) # - date = time.strftime('%Y-%m-%d %H:%M', time.localtime(game.gstats.start_time)) - MfxMessageDialog.__init__(self, parent, title=_('Game status'), - text=game.getTitleName() + '\n' + - game.getGameNumber(format=1) + '\n' + - _('Playing time: ') + game.getTime() + '\n' + - _('Started at: ') + date + '\n\n'+ - _('Moves: ') + str(game.moves.index) + '\n' + - _('Undo moves: ') + str(stats.undo_moves) + '\n' + - _('Bookmark moves: ') + str(gstats.goto_bookmark_moves) + '\n' + - _('Demo moves: ') + str(stats.demo_moves) + '\n' + - _('Total player moves: ') + str(stats.player_moves) + '\n' + - _('Total moves in this game: ') + str(stats.total_moves) + '\n' + - _('Hints: ') + str(stats.hints) + '\n' + - '\n' + - w1 + w2, - strings=(_('&OK'), - (_('&Statistics...'), 101), - (TOP_TITLE+'...', 105), ), - image=game.app.gimages.logos[3], - image_side='left', image_padx=20, - padx=20, - ) + date = time.strftime('%Y-%m-%d %H:%M', + time.localtime(game.gstats.start_time)) + MfxMessageDialog.__init__( + self, parent, title=_('Game status'), + text=game.getTitleName() + '\n' + + game.getGameNumber(format=1) + '\n' + + _('Playing time: ') + game.getTime() + '\n' + + _('Started at: ') + date + '\n\n'+ + _('Moves: ') + str(game.moves.index) + '\n' + + _('Undo moves: ') + str(stats.undo_moves) + '\n' + + _('Bookmark moves: ') + str(gstats.goto_bookmark_moves) + '\n' + + _('Demo moves: ') + str(stats.demo_moves) + '\n' + + _('Total player moves: ') + str(stats.player_moves) + '\n' + + _('Total moves in this game: ') + str(stats.total_moves) + '\n' + + _('Hints: ') + str(stats.hints) + '\n' + + '\n' + + w1 + w2, + strings=(_('&OK'), + (_('&Statistics...'), 101), ), + image=game.app.gimages.logos[3], + image_side='left', image_padx=20, + padx=20, + ) + -class Top_StatsDialog(MfxDialog): - pass diff --git a/pysollib/pysolgtk/tkutil.py b/pysollib/pysolgtk/tkutil.py index f19d28dd..9f8fbc95 100644 --- a/pysollib/pysolgtk/tkutil.py +++ b/pysollib/pysolgtk/tkutil.py @@ -164,7 +164,9 @@ def createImage(width, height, fill, outline=None): # ************************************************************************/ def _wrap_b1_press(e): - return e.type == gdk.BUTTON_PRESS and e.button == 1 + return (e.type == gdk.BUTTON_PRESS and e.button == 1 and + not (e.state & gdk.CONTROL_MASK) and + not (e.state & gdk.SHIFT_MASK)) def _wrap_b1_double(e): return e.type == gdk._2BUTTON_PRESS and e.button == 1 @@ -179,7 +181,9 @@ def _wrap_b2_press(e): return e.type == gdk.BUTTON_PRESS and e.button == 2 def _wrap_b3_press(e): - return e.type == gdk.BUTTON_PRESS and e.button == 3 + return (e.type == gdk.BUTTON_PRESS and e.button == 3 and + not (e.state & gdk.CONTROL_MASK) and + not (e.state & gdk.SHIFT_MASK)) def _wrap_b3_control(e): return e.type == gdk.BUTTON_PRESS and e.button == 3 and (e.state & gdk.CONTROL_MASK) diff --git a/pysollib/stack.py b/pysollib/stack.py index 72d06e79..a43db16f 100644 --- a/pysollib/stack.py +++ b/pysollib/stack.py @@ -396,9 +396,9 @@ class Stack: assert self.is_visible and self.images.bottom is None img = self.getBottomImage() if img is not None: - self.images.bottom = MfxCanvasImage(self.canvas, self.x, self.y, - image=img, anchor=ANCHOR_NW) - self.images.bottom.addtag(self.group) + self.images.bottom = MfxCanvasImage(self.canvas,self.x, self.y, + image=img,anchor=ANCHOR_NW, + group=self.group) self.top_bottom = self.images.bottom # invisible stack bottom @@ -410,8 +410,8 @@ class Stack: self.items.bottom = MfxCanvasRectangle(self.canvas, self.x, self.y, self.x + images.CARDW, self.y + images.CARDH, - fill="", outline="", width=0) - self.items.bottom.addtag(self.group) + fill="", outline="", width=0, + group=self.group) self.top_bottom = self.items.bottom # sanity checks @@ -815,8 +815,9 @@ class Stack: card = self.cards[i] if not self.basicShallHighlightSameRank(card): return 0 - col = self.game.app.opt.highlight_samerank_colors - info = [ (self, card, card, col[1]) ] + col_1 = self.game.app.opt.colors['samerank_1'] + col_2 = self.game.app.opt.colors['samerank_2'] + info = [ (self, card, card, col_1) ] for s in self.game.allstacks: for c in s.cards: if c is card: continue @@ -824,9 +825,9 @@ class Stack: if c.rank != card.rank: continue # ask the target stack if s.basicShallHighlightSameRank(c): - info.append((s, c, c, col[3])) + info.append((s, c, c, col_2)) self.game.stats.highlight_samerank = self.game.stats.highlight_samerank + 1 - return self.game._highlightCards(info, self.game.app.opt.highlight_samerank_sleep) + return self.game._highlightCards(info, self.game.app.opt.timeouts['highlight_samerank']) def highlightMatchingCards(self, event): i = self._findCard(event) @@ -835,7 +836,8 @@ class Stack: card = self.cards[i] if not self.basicShallHighlightMatch(card): return 0 - col = self.game.app.opt.highlight_cards_colors + col_1 = self.game.app.opt.colors['cards_1'] + col_2 = self.game.app.opt.colors['cards_2'] c1 = c2 = card info = [] found = 0 @@ -857,12 +859,12 @@ class Stack: j = self.cards.index(c) if i - 1 == j: c1 = c; continue if i + 1 == j: c2 = c; continue - info.append((s, c, c, col[3])) + info.append((s, c, c, col_1)) if found: if info: self.game.stats.highlight_cards = self.game.stats.highlight_cards + 1 - info.append((self, c1, c2, col[1])) - return self.game._highlightCards(info, self.game.app.opt.highlight_cards_sleep) + info.append((self, c1, c2, col_2)) + return self.game._highlightCards(info, self.game.app.opt.timeouts['highlight_cards']) if not self.basicIsBlocked(): self.game.highlightNotMatching() return 0 @@ -886,7 +888,7 @@ class Stack: ##print self.cards[i] self.cards[i].item.tkraise() self.game.canvas.update_idletasks() - self.game.sleep(self.game.app.opt.raise_card_sleep) + self.game.sleep(self.game.app.opt.timeouts['raise_card']) if TOOLKIT == 'tk': self.cards[i].item.lower(self.cards[i+1].item) elif TOOLKIT == 'gtk': @@ -1064,8 +1066,8 @@ class Stack: drag.noshade_stacks = [ self ] drag.cards = self.getDragCards(i) drag.index = i - if TOOLKIT == 'gtk': - drag.stack.group.tkraise() + ##if TOOLKIT == 'gtk': + ## drag.stack.group.tkraise() images = game.app.images drag.shadows = self.createShadows(drag.cards) ##sx, sy = 0, 0 @@ -1227,7 +1229,8 @@ class Stack: if drag.shade_img: drag.shade_img.moveTo(sx, sy) else: - img = MfxCanvasImage(game.canvas, sx, sy, image=img, anchor=ANCHOR_NW) + img = MfxCanvasImage(game.canvas, sx, sy, + image=img, anchor=ANCHOR_NW) drag.shade_img = img # raise/lower the shade image to the correct stacking order if TOOLKIT == 'tk': @@ -1258,9 +1261,9 @@ class Stack: #self.game.canvas.update_idletasks() card = self.cards[-1] item = MfxCanvasImage(self.game.canvas, card.x, card.y, - image=img, anchor=ANCHOR_NW) + image=img, anchor=ANCHOR_NW, + group=self.group) #item.tkraise() - item.addtag(self.group) self.items.shade_item = item def _unshadeStack(self): @@ -1566,15 +1569,16 @@ class TalonStack(Stack, # add a redeal image above the bottom image img = (self.getRedealImages())[self.max_rounds != 1] if img is not None: - self.images.redeal = MfxCanvasImage(self.game.canvas, cx, cy, - image=img, anchor="center") self.images.redeal_img = img + self.images.redeal = MfxCanvasImage(self.game.canvas, + cx, cy, image=img, + anchor="center", + group=self.group) if TOOLKIT == 'tk': self.images.redeal.tkraise(self.top_bottom) elif TOOLKIT == 'gtk': ### FIXME pass - self.images.redeal.addtag(self.group) self.top_bottom = self.images.redeal if images.CARDH >= 90: cy, ca = self.y + images.CARDH - 4, "s" @@ -1585,16 +1589,16 @@ class TalonStack(Stack, if images.CARDW >= text_width+4 and ca: # add a redeal text above the bottom image if self.max_rounds != 1: + self.texts.redeal_str = "" images = self.game.app.images self.texts.redeal = MfxCanvasText(self.game.canvas, cx, cy, - anchor=ca, font=font) - self.texts.redeal_str = "" + anchor=ca, font=font, + group=self.group) if TOOLKIT == 'tk': self.texts.redeal.tkraise(self.top_bottom) elif TOOLKIT == 'gtk': ### FIXME pass - self.texts.redeal.addtag(self.group) self.top_bottom = self.texts.redeal def getBottomImage(self): diff --git a/pysollib/tk/colorsdialog.py b/pysollib/tk/colorsdialog.py index 9810c02c..e01f74ee 100644 --- a/pysollib/tk/colorsdialog.py +++ b/pysollib/tk/colorsdialog.py @@ -48,47 +48,43 @@ class ColorsDialog(MfxDialog): frame.pack(expand=True, fill='both', padx=5, pady=10) frame.columnconfigure(0, weight=1) - self.table_text_color_var = Tkinter.BooleanVar() - self.table_text_color_var.set(app.opt.table_text_color) - self.table_text_color_value_var = Tkinter.StringVar() - self.table_text_color_value_var.set(app.opt.table_text_color_value) - ##self.table_color_var = StringVar() - ##self.table_color_var.set(app.opt.table_color) - self.highlight_piles_colors_var = Tkinter.StringVar() - self.highlight_piles_colors_var.set(app.opt.highlight_piles_colors[1]) - self.highlight_cards_colors_1_var = Tkinter.StringVar() - self.highlight_cards_colors_1_var.set(app.opt.highlight_cards_colors[1]) - self.highlight_cards_colors_2_var = Tkinter.StringVar() - self.highlight_cards_colors_2_var.set(app.opt.highlight_cards_colors[3]) - self.highlight_samerank_colors_1_var = Tkinter.StringVar() - self.highlight_samerank_colors_1_var.set(app.opt.highlight_samerank_colors[1]) - self.highlight_samerank_colors_2_var = Tkinter.StringVar() - self.highlight_samerank_colors_2_var.set(app.opt.highlight_samerank_colors[3]) - self.hintarrow_color_var = Tkinter.StringVar() - self.hintarrow_color_var.set(app.opt.hintarrow_color) - self.highlight_not_matching_color_var = Tkinter.StringVar() - self.highlight_not_matching_color_var.set(app.opt.highlight_not_matching_color) + self.use_default_var = Tkinter.BooleanVar() + self.use_default_var.set(not app.opt.use_default_text_color) + self.text_var = Tkinter.StringVar() + self.text_var.set(app.opt.colors['text']) + self.piles_var = Tkinter.StringVar() + self.piles_var.set(app.opt.colors['piles']) + self.cards_1_var = Tkinter.StringVar() + self.cards_1_var.set(app.opt.colors['cards_1']) + self.cards_2_var = Tkinter.StringVar() + self.cards_2_var.set(app.opt.colors['cards_2']) + self.samerank_1_var = Tkinter.StringVar() + self.samerank_1_var.set(app.opt.colors['samerank_1']) + self.samerank_2_var = Tkinter.StringVar() + self.samerank_2_var.set(app.opt.colors['samerank_2']) + self.hintarrow_var = Tkinter.StringVar() + self.hintarrow_var.set(app.opt.colors['hintarrow']) + self.not_matching_var = Tkinter.StringVar() + self.not_matching_var.set(app.opt.colors['not_matching']) # - c = Tkinter.Checkbutton(frame, variable=self.table_text_color_var, + c = Tkinter.Checkbutton(frame, variable=self.use_default_var, text=_("Text foreground:"), anchor='w') c.grid(row=0, column=0, sticky='we') l = Tkinter.Label(frame, width=10, height=2, - bg=self.table_text_color_value_var.get(), - textvariable=self.table_text_color_value_var) + bg=self.text_var.get(), textvariable=self.text_var) l.grid(row=0, column=1, padx=5) b = Tkinter.Button(frame, text=_('Change...'), width=10, command=lambda l=l: self.selectColor(l)) b.grid(row=0, column=2) row = 1 for title, var in ( - ##('Table:', self.table_color_var), - (_('Highlight piles:'), self.highlight_piles_colors_var), - (_('Highlight cards 1:'), self.highlight_cards_colors_1_var), - (_('Highlight cards 2:'), self.highlight_cards_colors_2_var), - (_('Highlight same rank 1:'), self.highlight_samerank_colors_1_var), - (_('Highlight same rank 2:'), self.highlight_samerank_colors_2_var), - (_('Hint arrow:'), self.hintarrow_color_var), - (_('Highlight not matching:'), self.highlight_not_matching_color_var), + (_('Highlight piles:'), self.piles_var), + (_('Highlight cards 1:'), self.cards_1_var), + (_('Highlight cards 2:'), self.cards_2_var), + (_('Highlight same rank 1:'), self.samerank_1_var), + (_('Highlight same rank 2:'), self.samerank_2_var), + (_('Hint arrow:'), self.hintarrow_var), + (_('Highlight not matching:'), self.not_matching_var), ): Tkinter.Label(frame, text=title, anchor='w' ).grid(row=row, column=0, sticky='we') @@ -103,21 +99,15 @@ class ColorsDialog(MfxDialog): focus = self.createButtons(bottom_frame, kw) self.mainloop(focus, kw.timeout) # - self.table_text_color = self.table_text_color_var.get() - self.table_text_color_value = self.table_text_color_value_var.get() - ##self.table_color = self.table_color_var.get() - self.highlight_piles_colors = (None, - self.highlight_piles_colors_var.get()) - self.highlight_cards_colors = (None, - self.highlight_cards_colors_1_var.get(), - None, - self.highlight_cards_colors_2_var.get()) - self.highlight_samerank_colors = (None, - self.highlight_samerank_colors_1_var.get(), - None, - self.highlight_samerank_colors_2_var.get()) - self.hintarrow_color = self.hintarrow_color_var.get() - self.highlight_not_matching_color = self.highlight_not_matching_color_var.get() + self.use_default_color = not self.use_default_var.get() + self.text_color = self.text_var.get() + self.piles_color = self.piles_var.get() + self.cards_1_color = self.cards_1_var.get() + self.cards_2_color = self.cards_2_var.get() + self.samerank_1_color = self.samerank_1_var.get() + self.samerank_2_color = self.samerank_2_var.get() + self.hintarrow_color = self.hintarrow_var.get() + self.not_matching_color = self.not_matching_var.get() def selectColor(self, label): c = askcolor(master=self.top, initialcolor=label.cget('bg'), diff --git a/pysollib/tk/findcarddialog.py b/pysollib/tk/findcarddialog.py index fc2465b2..0ae5ad91 100644 --- a/pysollib/tk/findcarddialog.py +++ b/pysollib/tk/findcarddialog.py @@ -72,7 +72,7 @@ class FindCardDialog(Tkinter.Toplevel): bind(self, "", self.destroy) # ##self.normal_timeout = 400 # in milliseconds - self.normal_timeout = int(1000*game.app.opt.highlight_samerank_sleep) + self.normal_timeout = int(1000*game.app.opt.timeouts['highlight_samerank']) self.hidden_timeout = 200 self.timer = None diff --git a/pysollib/tk/menubar.py b/pysollib/tk/menubar.py index 8357442e..bc8c951f 100644 --- a/pysollib/tk/menubar.py +++ b/pysollib/tk/menubar.py @@ -382,9 +382,9 @@ class PysolMenubar(PysolMenubarActions): menu.add_checkbutton(label=n_("Stick&y mouse"), variable=self.tkopt.sticky_mouse, command=self.mOptStickyMouse) menu.add_checkbutton(label=n_("Use mouse for undo/redo"), variable=self.tkopt.mouse_undo, command=self.mOptMouseUndo) menu.add_separator() - menu.add_command(label=n_("&Fonts..."), command=self.mOptFontsOptions) - menu.add_command(label=n_("&Colors..."), command=self.mOptColorsOptions) - menu.add_command(label=n_("Time&outs..."), command=self.mOptTimeoutsOptions) + menu.add_command(label=n_("&Fonts..."), command=self.mOptFonts) + menu.add_command(label=n_("&Colors..."), command=self.mOptColors) + menu.add_command(label=n_("Time&outs..."), command=self.mOptTimeouts) menu.add_separator() submenu = MfxMenu(menu, label=n_("&Toolbar")) createToolbarMenu(self, submenu) @@ -637,7 +637,7 @@ class PysolMenubar(PysolMenubarActions): self.mSelectGame, self.tkopt.gameid) def _addSelectAllGameSubMenu(self, games, menu, command, variable): - menu = MfxMenu(menu, label=n_("All games by name")) + menu = MfxMenu(menu, label=n_("&All games by name")) n, d = 0, self.__cb_max i = 0 while True: @@ -676,6 +676,12 @@ class PysolMenubar(PysolMenubarActions): # Select Game menu actions # + def mSelectGame(self, *args): + self._mSelectGame(self.tkopt.gameid.get()) + + def mSelectGamePopular(self, *args): + self._mSelectGame(self.tkopt.gameid_popular.get()) + def _mSelectGameDialog(self, d): if d.status == 0 and d.button == 0 and d.gameid != self.game.id: self.tkopt.gameid.set(d.gameid) @@ -890,6 +896,105 @@ class PysolMenubar(PysolMenubarActions): self.game.saveGame(filename) self.updateMenus() + def mOptAutoFaceUp(self, *args): + if self._cancelDrag(): return + self.app.opt.autofaceup = self.tkopt.autofaceup.get() + if self.app.opt.autofaceup: + self.game.autoPlay() + + def mOptAutoDrop(self, *args): + if self._cancelDrag(): return + self.app.opt.autodrop = self.tkopt.autodrop.get() + if self.app.opt.autodrop: + self.game.autoPlay() + + def mOptAutoDeal(self, *args): + if self._cancelDrag(): return + self.app.opt.autodeal = self.tkopt.autodeal.get() + if self.app.opt.autodeal: + self.game.autoPlay() + + def mOptQuickPlay(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.quickplay = self.tkopt.quickplay.get() + + def mOptEnableUndo(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.undo = self.tkopt.undo.get() + self.game.updateMenus() + + def mOptEnableBookmarks(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.bookmarks = self.tkopt.bookmarks.get() + self.game.updateMenus() + + def mOptEnableHint(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.hint = self.tkopt.hint.get() + self.game.updateMenus() + + def mOptEnableHighlightPiles(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.highlight_piles = self.tkopt.highlight_piles.get() + self.game.updateMenus() + + def mOptEnableHighlightCards(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.highlight_cards = self.tkopt.highlight_cards.get() + self.game.updateMenus() + + def mOptEnableHighlightSameRank(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.highlight_samerank = self.tkopt.highlight_samerank.get() + ##self.game.updateMenus() + + def mOptEnableHighlightNotMatching(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.highlight_not_matching = self.tkopt.highlight_not_matching.get() + ##self.game.updateMenus() + + def mOptAnimations(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.animations = self.tkopt.animations.get() + + def mOptShadow(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.shadow = self.tkopt.shadow.get() + + def mOptShade(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.shade = self.tkopt.shade.get() + + def mOptShrinkFaceDown(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.shrink_face_down = self.tkopt.shrink_face_down.get() + self.game.endGame(bookmark=1) + self.game.quitGame(bookmark=1) + + def mOptShadeFilledStacks(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.shade_filled_stacks = self.tkopt.shade_filled_stacks.get() + self.game.endGame(bookmark=1) + self.game.quitGame(bookmark=1) + + def mOptMahjonggShowRemoved(self, *args): + if self._cancelDrag(): return + self.app.opt.mahjongg_show_removed = self.tkopt.mahjongg_show_removed.get() + ##self.game.updateMenus() + self.game.endGame(bookmark=1) + self.game.quitGame(bookmark=1) + + def mOptShisenShowHint(self, *args): + if self._cancelDrag(break_pause=False): return + self.app.opt.shisen_show_hint = self.tkopt.shisen_show_hint.get() + ##self.game.updateMenus() + +## def mOptSound(self, *args): +## if self._cancelDrag(break_pause=False): return +## self.app.opt.sound = self.tkopt.sound.get() +## if not self.app.opt.sound: +## self.app.audio.stopAll() + def mSelectCardsetDialog(self, *event): if self._cancelDrag(break_pause=False): return ##strings, default = ("&OK", "&Load", "&Cancel"), 0 @@ -957,7 +1062,7 @@ class PysolMenubar(PysolMenubarActions): if self._cancelDrag(break_pause=False): return key = self.app.tabletile_index if key <= 0: - key = self.app.opt.table_color.lower() + key = self.app.opt.colors['table'] ##.lower() d = SelectTileDialogWithPreview(self.top, app=self.app, title=_("Select table background"), manager=self.app.tabletile_manager, @@ -968,13 +1073,6 @@ class PysolMenubar(PysolMenubarActions): elif d.key > 0 and d.key != self.app.tabletile_index: self._mOptTableTile(d.key) -## def mOptTableColor(self, *event): -## if self._cancelDrag(break_pause=False): return -## c = tkColorChooser.askcolor(initialcolor=self.app.opt.table_color, -## title=_("Select table color")) -## if c and c[1]: -## self._mOptTableColor(c[1]) - def mOptToolbar(self, *event): ##if self._cancelDrag(break_pause=False): return self.setToolbarSide(self.tkopt.toolbar.get()) diff --git a/pysollib/tk/selecttile.py b/pysollib/tk/selecttile.py index d1aa55e3..e2982604 100644 --- a/pysollib/tk/selecttile.py +++ b/pysollib/tk/selecttile.py @@ -121,7 +121,7 @@ class SelectTileDialogWithPreview(MfxDialog): self.app = app self.manager = manager self.key = key - self.table_color = app.opt.table_color + self.table_color = app.opt.colors['table'] if self.TreeDataHolder_Class.data is None: self.TreeDataHolder_Class.data = self.TreeData_Class(manager, key) # diff --git a/pysollib/tk/timeoutsdialog.py b/pysollib/tk/timeoutsdialog.py index a2294147..bdb56b08 100644 --- a/pysollib/tk/timeoutsdialog.py +++ b/pysollib/tk/timeoutsdialog.py @@ -48,17 +48,17 @@ class TimeoutsDialog(MfxDialog): frame.columnconfigure(0, weight=1) self.demo_sleep_var = Tkinter.DoubleVar() - self.demo_sleep_var.set(app.opt.demo_sleep) + self.demo_sleep_var.set(app.opt.timeouts['demo']) self.hint_sleep_var = Tkinter.DoubleVar() - self.hint_sleep_var.set(app.opt.hint_sleep) + self.hint_sleep_var.set(app.opt.timeouts['hint']) self.raise_card_sleep_var = Tkinter.DoubleVar() - self.raise_card_sleep_var.set(app.opt.raise_card_sleep) + self.raise_card_sleep_var.set(app.opt.timeouts['raise_card']) self.highlight_piles_sleep_var = Tkinter.DoubleVar() - self.highlight_piles_sleep_var.set(app.opt.highlight_piles_sleep) + self.highlight_piles_sleep_var.set(app.opt.timeouts['highlight_piles']) self.highlight_cards_sleep_var = Tkinter.DoubleVar() - self.highlight_cards_sleep_var.set(app.opt.highlight_cards_sleep) + self.highlight_cards_sleep_var.set(app.opt.timeouts['highlight_cards']) self.highlight_samerank_sleep_var = Tkinter.DoubleVar() - self.highlight_samerank_sleep_var.set(app.opt.highlight_samerank_sleep) + self.highlight_samerank_sleep_var.set(app.opt.timeouts['highlight_samerank']) # #Tkinter.Label(frame, text='Set delays in seconds').grid(row=0, column=0, columnspan=2) row = 0 @@ -80,12 +80,12 @@ class TimeoutsDialog(MfxDialog): focus = self.createButtons(bottom_frame, kw) self.mainloop(focus, kw.timeout) # - self.demo_sleep = self.demo_sleep_var.get() - self.hint_sleep = self.hint_sleep_var.get() - self.raise_card_sleep = self.raise_card_sleep_var.get() - self.highlight_piles_sleep = self.highlight_piles_sleep_var.get() - self.highlight_cards_sleep = self.highlight_cards_sleep_var.get() - self.highlight_samerank_sleep = self.highlight_samerank_sleep_var.get() + self.demo_timeout = self.demo_sleep_var.get() + self.hint_timeout = self.hint_sleep_var.get() + self.raise_card_timeout = self.raise_card_sleep_var.get() + self.highlight_piles_timeout = self.highlight_piles_sleep_var.get() + self.highlight_cards_timeout = self.highlight_cards_sleep_var.get() + self.highlight_samerank_timeout = self.highlight_samerank_sleep_var.get() def initKw(self, kw): kw = KwStruct(kw, diff --git a/pysollib/tk/tkcanvas.py b/pysollib/tk/tkcanvas.py index c97a73c7..1b149a4e 100644 --- a/pysollib/tk/tkcanvas.py +++ b/pysollib/tk/tkcanvas.py @@ -77,6 +77,14 @@ class MfxCanvasGroup(Canvas.Group): return self.canvas.tk.splitlist(self._do("gettags")) class MfxCanvasImage(Canvas.ImageItem): + def __init__(self, canvas, *args, **kwargs): + group = None + if kwargs.has_key('group'): + group = kwargs['group'] + del kwargs['group'] + Canvas.ImageItem.__init__(self, canvas, *args, **kwargs) + if group: + self.addtag(group) def moveTo(self, x, y): c = self.coords() self.move(x - int(c[0]), y - int(c[1])) @@ -87,19 +95,33 @@ class MfxCanvasImage(Canvas.ImageItem): MfxCanvasLine = Canvas.Line -MfxCanvasRectangle = Canvas.Rectangle +class MfxCanvasRectangle(Canvas.Rectangle): + def __init__(self, canvas, *args, **kwargs): + group = None + if kwargs.has_key('group'): + group = kwargs['group'] + del kwargs['group'] + Canvas.Rectangle.__init__(self, canvas, *args, **kwargs) + if group: + self.addtag(group) class MfxCanvasText(Canvas.CanvasText): - def __init__(self, canvas, x, y, preview=-1, **kw): + def __init__(self, canvas, x, y, preview=-1, **kwargs): if preview < 0: preview = canvas.preview if preview > 1: return - if not kw.has_key("fill"): - kw["fill"] = canvas._text_color - apply(Canvas.CanvasText.__init__, (self, canvas, x, y), kw) + if not kwargs.has_key("fill"): + kwargs["fill"] = canvas._text_color + group = None + if kwargs.has_key('group'): + group = kwargs['group'] + del kwargs['group'] + Canvas.CanvasText.__init__(self, canvas, x, y, **kwargs) self.text_format = None canvas._text_items.append(self) + if group: + self.addtag(group) # /*********************************************************************** diff --git a/pysollib/tk/tkstats.py b/pysollib/tk/tkstats.py index 6bb4f433..0c699e56 100644 --- a/pysollib/tk/tkstats.py +++ b/pysollib/tk/tkstats.py @@ -790,9 +790,9 @@ class Top_StatsDialog(MfxDialog): frame.pack(expand=Tkinter.YES, fill=Tkinter.BOTH, padx=5, pady=10) frame.columnconfigure(0, weight=1) - if app.stats.games_stats.has_key(player) \ - and app.stats.games_stats[player].has_key(gameid) \ - and app.stats.games_stats[player][gameid].time_result.top: + if (app.stats.games_stats.has_key(player) and + app.stats.games_stats[player].has_key(gameid) and + app.stats.games_stats[player][gameid].time_result.top): Tkinter.Label(frame, text=_('Minimum')).grid(row=0, column=1) Tkinter.Label(frame, text=_('Maximum')).grid(row=0, column=2) diff --git a/pysollib/tk/tkwidget.py b/pysollib/tk/tkwidget.py index 9ac6b9e4..a0f6a3c8 100644 --- a/pysollib/tk/tkwidget.py +++ b/pysollib/tk/tkwidget.py @@ -501,7 +501,8 @@ class MfxScrolledCanvas: assert tile.filename assert tile.basename if not force: - if i == app.tabletile_index and tile.color == app.opt.table_color: + if (i == app.tabletile_index and + tile.color == app.opt.colors['table']): return False # if not self.canvas.setTile(tile.filename, tile.stretch): @@ -517,10 +518,10 @@ class MfxScrolledCanvas: ##app.top.config(bg=app.top_bg) color = tile.text_color - if app.opt.table_text_color: - self.canvas.setTextColor(app.opt.table_text_color_value) - else: + if app.opt.use_default_text_color: self.canvas.setTextColor(color) + else: + self.canvas.setTextColor(app.opt.colors['text']) return True