mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
- Added new menu option to adjust font size in general. - Fixed a bug with doubleclick moves addressed in #117.
2631 lines
93 KiB
Python
2631 lines
93 KiB
Python
#!/usr/bin/env python
|
|
# -*- mode: python; coding: utf-8; -*-
|
|
# ---------------------------------------------------------------------------#
|
|
#
|
|
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
|
|
# Copyright (C) 2003 Mt. Hood Playing Card Co.
|
|
# Copyright (C) 2005-2009 Skomoroh
|
|
# Copyright (C) 2017 LB
|
|
#
|
|
# 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 3 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. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# ---------------------------------------------------------------------------#
|
|
|
|
import math
|
|
import os
|
|
import re
|
|
|
|
from kivy.cache import Cache
|
|
from kivy.clock import Clock
|
|
from kivy.core.window import Window
|
|
|
|
from pysollib.gamedb import GI
|
|
from pysollib.kivy.LApp import LMenu
|
|
from pysollib.kivy.LApp import LMenuItem
|
|
from pysollib.kivy.LApp import LScrollView
|
|
from pysollib.kivy.LApp import LTopLevel
|
|
from pysollib.kivy.LApp import LTreeNode
|
|
from pysollib.kivy.LApp import LTreeRoot
|
|
from pysollib.kivy.LApp import LTreeSliderNode
|
|
from pysollib.kivy.LObjWrap import LBoolWrap
|
|
from pysollib.kivy.LObjWrap import LListWrap
|
|
from pysollib.kivy.LObjWrap import LNumWrap
|
|
from pysollib.kivy.LObjWrap import LStringWrap
|
|
from pysollib.kivy.androidrot import AndroidScreenRotation
|
|
from pysollib.kivy.findcarddialog import destroy_find_card_dialog
|
|
from pysollib.kivy.fullpicturedialog import destroy_full_picture_dialog
|
|
from pysollib.kivy.selectcardset import SelectCardsetDialogWithPreview
|
|
from pysollib.kivy.selectgame import SelectGameDialog
|
|
from pysollib.kivy.solverdialog import connect_game_solver_dialog
|
|
from pysollib.kivy.tkconst import CURSOR_WATCH, EVENT_HANDLED, EVENT_PROPAGATE
|
|
from pysollib.kivy.tkconst import TOOLBAR_BUTTONS
|
|
from pysollib.kivy.tkutil import after_idle
|
|
from pysollib.kivy.tkutil import bind
|
|
from pysollib.kivy.toast import Toast
|
|
from pysollib.mfxutil import Struct
|
|
from pysollib.mygettext import _
|
|
from pysollib.pysoltk import MfxMessageDialog
|
|
from pysollib.pysoltk import connect_game_find_card_dialog
|
|
from pysollib.pysoltk import connect_game_full_picture_dialog
|
|
from pysollib.settings import SELECT_GAME_MENU
|
|
from pysollib.settings import TITLE
|
|
|
|
# ************************************************************************
|
|
# * Common base
|
|
# ************************************************************************
|
|
|
|
|
|
class LMenuBase(object):
|
|
def __init__(self, menubar, parent, title, app):
|
|
self.menubar = menubar
|
|
self.parent = parent
|
|
self.app = app
|
|
self.title = title
|
|
|
|
def make_pop_command(self, parent, title):
|
|
def pop_command(event):
|
|
parent.popWork(title)
|
|
return pop_command
|
|
|
|
def closeWindow(self, event):
|
|
self.parent.popWork(self.title)
|
|
|
|
def auto_close(self, command):
|
|
def auto_close_command():
|
|
if command is not None:
|
|
command()
|
|
self.closeWindow(0)
|
|
return auto_close_command
|
|
|
|
def make_toggle_command(self, variable, command):
|
|
def auto_command():
|
|
variable.value = not variable.value
|
|
if command is not None:
|
|
command()
|
|
return auto_command
|
|
|
|
def make_val_command(self, variable, value, command):
|
|
def val_command():
|
|
variable.value = value
|
|
if command is not None:
|
|
command()
|
|
return val_command
|
|
|
|
def make_vars_command(self, command, key):
|
|
def vars_command():
|
|
command(key)
|
|
return vars_command
|
|
|
|
def make_game_command(self, key, command):
|
|
def game_command():
|
|
self.closeWindow(0)
|
|
command(key)
|
|
return game_command
|
|
|
|
def make_command(self, command):
|
|
def _command():
|
|
self.closeWindow(0)
|
|
if command is not None:
|
|
command()
|
|
return _command
|
|
|
|
def addCheckNode(self, tv, rg, title, auto_var, auto_com):
|
|
command = self.make_toggle_command(auto_var, auto_com)
|
|
rg1 = tv.add_node(
|
|
LTreeNode(text=title, command=command, variable=auto_var), rg)
|
|
return rg1
|
|
|
|
def addRadioNode(self, tv, rg, title, auto_var, auto_val, auto_com):
|
|
command = self.make_val_command(auto_var, auto_val, auto_com)
|
|
rg1 = tv.add_node(
|
|
LTreeNode(text=title,
|
|
command=command,
|
|
variable=auto_var, value=auto_val), rg)
|
|
return rg1
|
|
|
|
def addSliderNode(self, tv, rg, auto_var, auto_setup):
|
|
rg1 = tv.add_node(
|
|
LTreeSliderNode(variable=auto_var, setup=auto_setup), rg)
|
|
return rg1
|
|
|
|
# ************************************************************************
|
|
# * Tree Generators
|
|
# ************************************************************************
|
|
|
|
|
|
class LTreeGenerator(LMenuBase):
|
|
def __init__(self, menubar, parent, title, app):
|
|
super(LTreeGenerator, self).__init__(menubar, parent, title, app)
|
|
|
|
def generate(self):
|
|
tv = LTreeRoot(root_options=dict(text='EditTree'))
|
|
tv.hide_root = True
|
|
tv.size_hint = 1, None
|
|
tv.bind(minimum_height=tv.setter('height'))
|
|
|
|
gen = self.buildTree(tv, None)
|
|
|
|
def process(dt):
|
|
try:
|
|
gen.send(None)
|
|
Clock.schedule_once(process, 0.2)
|
|
except StopIteration:
|
|
print('generator: all jobs done')
|
|
pass
|
|
|
|
Clock.schedule_once(process, 0.2)
|
|
return tv
|
|
|
|
def buildTree(self, tv, node):
|
|
print('buildTree generator function not implemented')
|
|
# needs at least on 'yield' statement
|
|
# not reentrant: do not recurse !
|
|
# implement it in a dervied class
|
|
yield
|
|
|
|
# ************************************************************************
|
|
# * Menu Dialogs
|
|
# ************************************************************************
|
|
|
|
|
|
class LMenuDialog(LMenuBase):
|
|
|
|
dialogCache = {}
|
|
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
super(LMenuDialog, self).__init__(menubar, parent, title, app)
|
|
|
|
self.window = None
|
|
self.running = False
|
|
self.persist = False
|
|
if 'persist' in kw:
|
|
self.persist = kw['persist']
|
|
self.tvroot = None
|
|
if 'tv' in kw:
|
|
self.tvroot = kw['tv']
|
|
|
|
# prüfen ob noch aktiv - toggle.
|
|
|
|
if parent.workStack.peek(title) is not None:
|
|
parent.popWork(title)
|
|
return
|
|
|
|
if self.persist and title in self.dialogCache:
|
|
parent.pushWork(title, self.dialogCache[title])
|
|
return
|
|
|
|
pc = self.closeWindow = self.make_pop_command(parent, title)
|
|
|
|
# neuen Dialog aufbauen.
|
|
|
|
window = LTopLevel(parent, title, **kw)
|
|
window.titleline.bind(on_press=pc)
|
|
self.parent.pushWork(title, window)
|
|
self.window = window
|
|
self.running = True
|
|
|
|
from pysollib.kivy.LApp import get_menu_size_hint
|
|
|
|
def updrule(obj, val):
|
|
self.window.size_hint = get_menu_size_hint()
|
|
updrule(0, 0)
|
|
self.parent.bind(size=updrule)
|
|
|
|
if self.persist:
|
|
self.dialogCache[title] = window
|
|
|
|
# Tree construct or assign.
|
|
|
|
if self.tvroot is None:
|
|
tv = self.initTree()
|
|
self.buildTree(tv, None)
|
|
else:
|
|
tv = self.tvroot
|
|
|
|
# show the tree in a scroll window
|
|
|
|
root = LScrollView(pos=(0, 0))
|
|
root.add_widget(tv)
|
|
self.window.content.add_widget(root)
|
|
|
|
def initTree(self):
|
|
tv = self.tvroot = LTreeRoot(root_options=dict(text='EditTree'))
|
|
tv.hide_root = True
|
|
tv.size_hint = 1, None
|
|
tv.bind(minimum_height=tv.setter('height'))
|
|
return tv
|
|
|
|
def buildTree(self, tree, node):
|
|
# to implement in dervied class if needed
|
|
pass
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class MainMenuDialog(LMenuDialog):
|
|
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
kw['persist'] = True
|
|
super(MainMenuDialog, self).__init__(
|
|
menubar, parent, title, app, **kw)
|
|
|
|
# print('MainMenuDialog starting')
|
|
|
|
def buildTree(self, tv, node):
|
|
rg = tv.add_node(
|
|
LTreeNode(
|
|
text=_("File"),
|
|
command=self.auto_close(self.menubar.mFileMenuDialog)))
|
|
rg = tv.add_node(
|
|
LTreeNode(
|
|
text=_("Games"),
|
|
command=self.auto_close(
|
|
self.menubar.mSelectGameDialog)))
|
|
rg = tv.add_node(
|
|
LTreeNode(
|
|
text=_("Tools"),
|
|
command=self.auto_close(self.menubar.mEditMenuDialog)))
|
|
rg = tv.add_node(
|
|
LTreeNode(
|
|
text=_("Statistics"),
|
|
command=self.auto_close(self.menubar.mGameMenuDialog)))
|
|
rg = tv.add_node(
|
|
LTreeNode(
|
|
text=_("Assist"),
|
|
command=self.auto_close(
|
|
self.menubar.mAssistMenuDialog)))
|
|
rg = tv.add_node(
|
|
LTreeNode(
|
|
text=_("Options"),
|
|
command=self.auto_close(
|
|
self.menubar.mOptionsMenuDialog)))
|
|
rg = tv.add_node(
|
|
LTreeNode(
|
|
text=_("Help"),
|
|
command=self.auto_close(self.menubar.mHelpMenuDialog)))
|
|
del rg
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class FileMenuDialog(LMenuDialog):
|
|
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
super(FileMenuDialog, self).__init__(
|
|
menubar, parent, title, app, **kw)
|
|
|
|
def make_favid_list(self, tv, rg):
|
|
favids = self.app.opt.favorite_gameid
|
|
for fid in favids:
|
|
gi = self.app.getGameInfo(fid)
|
|
if gi:
|
|
command = self.make_game_command(
|
|
fid, self.menubar._mSelectGame)
|
|
tv.add_node(
|
|
LTreeNode(text=gi.name, command=command), rg)
|
|
|
|
def remove_favid_list(self, tv, rg):
|
|
delist = []
|
|
for n in rg.nodes:
|
|
if n.text not in [_('<Add>'), _('<Remove>')]:
|
|
delist.append(n)
|
|
for m in delist:
|
|
tv.remove_node(m)
|
|
|
|
def change_favid_list(self, command, *args):
|
|
def doit():
|
|
command()
|
|
self.remove_favid_list(args[0], args[1])
|
|
self.make_favid_list(args[0], args[1])
|
|
return doit
|
|
|
|
def buildTree(self, tv, node):
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Recent games')))
|
|
recids = self.app.opt.recent_gameid
|
|
for rid in recids:
|
|
gi = self.app.getGameInfo(rid)
|
|
if gi:
|
|
command = self.make_game_command(
|
|
rid, self.menubar._mSelectGame)
|
|
tv.add_node(
|
|
LTreeNode(text=gi.name, command=command), rg)
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Favorite games')))
|
|
if rg:
|
|
tv.add_node(LTreeNode(
|
|
text=_('<Add>'),
|
|
command=self.change_favid_list(
|
|
self.menubar.mAddFavor, tv, rg)), rg)
|
|
tv.add_node(LTreeNode(
|
|
text=_('<Remove>'),
|
|
command=self.change_favid_list(
|
|
self.menubar.mDelFavor, tv, rg)), rg)
|
|
|
|
self.make_favid_list(tv, rg)
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Load'), command=self.make_command(self.menubar.mOpen)))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Save'), command=self.make_command(self.menubar.mSaveAs)))
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Quit'), command=self.menubar.mHoldAndQuit))
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class EditMenuDialog(LMenuDialog): # Tools
|
|
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
kw['persist'] = True
|
|
super(EditMenuDialog, self).__init__(
|
|
menubar, parent, title, app, **kw)
|
|
|
|
def buildTree(self, tv, node):
|
|
tv.add_node(LTreeNode(
|
|
text=_('New game'), command=self.menubar.mNewGame))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Restart game'), command=self.menubar.mRestart))
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Undo'), command=self.menubar.mUndo))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Redo'), command=self.menubar.mRedo))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Redo all'), command=self.menubar.mRedoAll))
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Auto drop'), command=self.menubar.mDrop))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Shuffle tiles'), command=self.menubar.mShuffle))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Deal cards'), command=self.menubar.mDeal))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Reset zoom'),
|
|
command=self.auto_close(self.menubar.mResetZoom)))
|
|
|
|
self.addCheckNode(tv, None,
|
|
_('Pause'),
|
|
self.menubar.tkopt.pause,
|
|
self.menubar.mPause)
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Load game'), command=self.menubar.mOpen))
|
|
tv.add_node(LTreeNode(
|
|
text=_('Save game'), command=self.menubar.mSaveAs))
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Help'), command=self.menubar.mHelpRules))
|
|
|
|
# -------------------------------------------
|
|
# TBD ?
|
|
'''
|
|
menu.add_separator()
|
|
submenu = MfxMenu(menu, label=n_("&Set bookmark"))
|
|
for i in range(9):
|
|
label = _("Bookmark %d") % (i + 1)
|
|
submenu.add_command(
|
|
label=label, command=lambda i=i: self.mSetBookmark(i))
|
|
submenu = MfxMenu(menu, label=n_("Go&to bookmark"))
|
|
for i in range(9):
|
|
label = _("Bookmark %d") % (i + 1)
|
|
acc = m + "%d" % (i + 1)
|
|
submenu.add_command(
|
|
label=label,
|
|
command=lambda i=i: self.mGotoBookmark(i),
|
|
accelerator=acc)
|
|
menu.add_command(
|
|
label=n_("&Clear bookmarks"), command=self.mClearBookmarks)
|
|
menu.add_separator()
|
|
'''
|
|
# und solitär wizard (-> custom games).
|
|
'''
|
|
tv.add_node(LTreeNode(
|
|
text='Solitaire &Wizard...', command=self.menubar.mWizard))
|
|
tv.add_node(LTreeNode(
|
|
text='Edit current game', command=self.menubar.mWizardEdit))
|
|
'''
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class GameMenuDialog(LMenuDialog):
|
|
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
kw['persist'] = True
|
|
super(GameMenuDialog, self).__init__(
|
|
menubar, parent, title, app, **kw)
|
|
|
|
def make_command(self, key, command):
|
|
def stats_command():
|
|
kw = {}
|
|
kw['mode'] = key
|
|
command(**kw)
|
|
return stats_command
|
|
|
|
def buildTree(self, tv, node):
|
|
tv.add_node(LTreeNode(
|
|
text=_('Current game...'),
|
|
command=self.auto_close(
|
|
self.make_command(101, self.menubar.mPlayerStats))), None)
|
|
|
|
# tv.add_node(LTreeNode(
|
|
# text='All games ...',
|
|
# command=self.make_command(102, self.menubar.mPlayerStats)), None)
|
|
|
|
# -------------------------------------------
|
|
# TBD ? - just to remember original tk code.
|
|
'''
|
|
menu.add_command(
|
|
label=n_("S&tatus..."),
|
|
command=lambda x: self.mPlayerStats(mode=100), accelerator=m+"Y")
|
|
menu.add_checkbutton(
|
|
label=n_("&Comments..."), variable=self.tkopt.comment,
|
|
command=self.mEditGameComment)
|
|
'''
|
|
'''
|
|
menu.add_separator()
|
|
submenu = MfxMenu(menu, label=n_("&Statistics"))
|
|
submenu.add_command(
|
|
label=n_("Current game..."),
|
|
command=lambda x: self.mPlayerStats(mode=101))
|
|
submenu.add_command(
|
|
label=n_("All games..."),
|
|
command=lambda x: self.mPlayerStats(mode=102))
|
|
submenu.add_separator()
|
|
submenu.add_command(
|
|
label=n_("Session log..."),
|
|
command=lambda x: self.mPlayerStats(mode=104))
|
|
submenu.add_command(
|
|
label=n_("Full log..."),
|
|
command=lambda x: self.mPlayerStats(mode=103))
|
|
submenu.add_separator()
|
|
submenu.add_command(
|
|
label=TOP_TITLE+"...",
|
|
command=lambda x: self.mPlayerStats(mode=105),
|
|
accelerator=m+"T")
|
|
submenu.add_command(
|
|
label=n_("Progression..."),
|
|
command=lambda x: self.mPlayerStats(mode=107))
|
|
submenu = MfxMenu(menu, label=n_("D&emo statistics..."))
|
|
submenu.add_command(
|
|
label=n_("Current game..."),
|
|
command=lambda x: self.mPlayerStats(mode=1101))
|
|
submenu.add_command(
|
|
label=n_("All games..."),
|
|
command=lambda x: self.mPlayerStats(mode=1102))
|
|
'''
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class AssistMenuDialog(LMenuDialog):
|
|
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
kw['persist'] = True
|
|
super(AssistMenuDialog, self).__init__(
|
|
menubar, parent, title, app, **kw)
|
|
|
|
def buildTree(self, tv, node):
|
|
tv.add_node(LTreeNode(
|
|
text=_('Hint'), command=self.menubar.mHint))
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Highlight piles'), command=self.menubar.mHighlightPiles))
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Show full picture...'),
|
|
command=self.auto_close(self.menubar.mFullPicture)))
|
|
|
|
# tv.add_node(LTreeNode(
|
|
# text='Find Card', command=self.menubar.mFindCard))
|
|
|
|
tv.add_node(LTreeNode(
|
|
text=_('Demo'), command=self.auto_close(self.menubar.mDemo)))
|
|
|
|
# -------------------------------------------
|
|
# TBD. How ?
|
|
|
|
'''
|
|
menu.add_command(
|
|
label=n_("Demo (&all games)"), command=self.mMixedDemo)
|
|
if USE_FREECELL_SOLVER:
|
|
menu.add_command(label=n_("&Solver..."), command=self.mSolver)
|
|
else:
|
|
menu.add_command(label=n_("&Solver..."), state='disabled')
|
|
menu.add_separator()
|
|
menu.add_command(
|
|
label=n_("&Piles description"),
|
|
command=self.mStackDesk, accelerator="F2")
|
|
'''
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class LOptionsMenuGenerator(LTreeGenerator):
|
|
def __init__(self, menubar, parent, title, app):
|
|
super(LOptionsMenuGenerator, self).__init__(
|
|
menubar, parent, title, app)
|
|
|
|
def buildTree(self, tv, node):
|
|
# -------------------------------------------
|
|
# Automatic play settings
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Automatic play')))
|
|
if rg:
|
|
self.addCheckNode(tv, rg,
|
|
_('Auto face up'),
|
|
self.menubar.tkopt.autofaceup,
|
|
self.menubar.mOptAutoFaceUp)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Auto drop'),
|
|
self.menubar.tkopt.autodrop,
|
|
self.menubar.mOptAutoDrop)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Auto deal'),
|
|
self.menubar.tkopt.autodeal,
|
|
self.menubar.mOptAutoDeal)
|
|
|
|
# submenu.add_separator()
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Quick play'),
|
|
self.menubar.tkopt.quickplay,
|
|
self.menubar.mOptQuickPlay)
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Player assistance
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Assist level')))
|
|
if rg:
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable undo'),
|
|
self.menubar.tkopt.undo,
|
|
self.menubar.mOptEnableUndo)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable bookmarks'),
|
|
self.menubar.tkopt.bookmarks,
|
|
self.menubar.mOptEnableBookmarks)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable hint'),
|
|
self.menubar.tkopt.hint,
|
|
self.menubar.mOptEnableHint)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable shuffle'),
|
|
self.menubar.tkopt.shuffle,
|
|
self.menubar.mOptEnableShuffle)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Free hints'),
|
|
self.menubar.tkopt.free_hint,
|
|
self.menubar.mOptFreeHints)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable highlight piles'),
|
|
self.menubar.tkopt.highlight_piles,
|
|
self.menubar.mOptEnableHighlightPiles)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable highlight cards'),
|
|
self.menubar.tkopt.highlight_cards,
|
|
self.menubar.mOptEnableHighlightCards)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable highlight same rank'),
|
|
self.menubar.tkopt.highlight_samerank,
|
|
self.menubar.mOptEnableHighlightSameRank)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable face-down peek'),
|
|
self.menubar.tkopt.peek_facedown,
|
|
self.menubar.mOptEnablePeekFacedown)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Highlight no matching'),
|
|
self.menubar.tkopt.highlight_not_matching,
|
|
self.menubar.mOptEnableHighlightNotMatching)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Stuck notification'),
|
|
self.menubar.tkopt.stuck_notification,
|
|
self.menubar.mOptEnableStuckNotification)
|
|
|
|
# submenu.add_separator()
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Show removed tiles (in Mahjongg games)'),
|
|
self.menubar.tkopt.mahjongg_show_removed,
|
|
self.menubar.mOptMahjonggShowRemoved)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Show hint arrow (in Shisen-Sho games)'),
|
|
self.menubar.tkopt.shisen_show_hint,
|
|
self.menubar.mOptShisenShowHint)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Deal all cards (in Accordion type games)'),
|
|
self.menubar.tkopt.accordion_deal_all,
|
|
self.menubar.mOptAccordionDealAll)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Auto-remove first card (in Pegged games)'),
|
|
self.menubar.tkopt.accordion_deal_all,
|
|
self.menubar.mOptPeggedAutoRemove)
|
|
|
|
# submenu.add_separator()
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Language options
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Language')))
|
|
if rg:
|
|
self.addRadioNode(tv, rg,
|
|
_('Default'),
|
|
self.menubar.tkopt.language, '',
|
|
self.menubar.mOptLanguage)
|
|
self.addRadioNode(tv, rg,
|
|
_('English'),
|
|
self.menubar.tkopt.language, 'en',
|
|
self.menubar.mOptLanguage)
|
|
self.addRadioNode(tv, rg,
|
|
_('German'),
|
|
self.menubar.tkopt.language, 'de',
|
|
self.menubar.mOptLanguage)
|
|
self.addRadioNode(tv, rg,
|
|
_('Italian'),
|
|
self.menubar.tkopt.language, 'it',
|
|
self.menubar.mOptLanguage)
|
|
self.addRadioNode(tv, rg,
|
|
_('Polish'),
|
|
self.menubar.tkopt.language, 'pl',
|
|
self.menubar.mOptLanguage)
|
|
self.addRadioNode(tv, rg,
|
|
_('Russian'),
|
|
self.menubar.tkopt.language, 'ru',
|
|
self.menubar.mOptLanguage)
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Sound options
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Sound')))
|
|
if rg:
|
|
self.addCheckNode(tv, rg,
|
|
_('Enable'),
|
|
self.menubar.tkopt.sound, None)
|
|
|
|
rg1 = tv.add_node(
|
|
LTreeNode(text=_('Volume')), rg)
|
|
if rg1:
|
|
self.addRadioNode(tv, rg1,
|
|
_('100%'),
|
|
self.menubar.tkopt.sound_sample_volume, 100,
|
|
None)
|
|
self.addRadioNode(tv, rg1,
|
|
_('75%'),
|
|
self.menubar.tkopt.sound_sample_volume, 75,
|
|
None)
|
|
self.addRadioNode(tv, rg1,
|
|
_('50%'),
|
|
self.menubar.tkopt.sound_sample_volume, 50,
|
|
None)
|
|
self.addRadioNode(tv, rg1,
|
|
_('25%'),
|
|
self.menubar.tkopt.sound_sample_volume, 25,
|
|
None)
|
|
|
|
rg1 = tv.add_node(
|
|
LTreeNode(text=_('Samples')), rg)
|
|
if rg1:
|
|
key = 'areyousure'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('are you sure'),
|
|
self.menubar.tkopt.sound_areyousure, None)
|
|
key = 'autodrop'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('auto drop'),
|
|
self.menubar.tkopt.sound_autodrop, None)
|
|
key = 'autoflip'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('auto flip'),
|
|
self.menubar.tkopt.sound_autoflip, None)
|
|
key = 'autopilotlost'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('auto pilot lost'),
|
|
self.menubar.tkopt.sound_autopilotlost, None)
|
|
key = 'autopilotwon'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('auto pilot won'),
|
|
self.menubar.tkopt.sound_autopilotwon, None)
|
|
key = 'deal'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('deal'),
|
|
self.menubar.tkopt.sound_deal, None)
|
|
key = 'dealwaste'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('deal waste'),
|
|
self.menubar.tkopt.sound_dealwaste, None)
|
|
key = 'droppair'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('drop pair'),
|
|
self.menubar.tkopt.sound_droppair, None)
|
|
key = 'drop'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('drop'),
|
|
self.menubar.tkopt.sound_drop, None)
|
|
key = 'flip'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('flip'),
|
|
self.menubar.tkopt.sound_flip, None)
|
|
key = 'move'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('move'),
|
|
self.menubar.tkopt.sound_move, None)
|
|
key = 'nomove'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('no move'),
|
|
self.menubar.tkopt.sound_nomove, None)
|
|
key = 'redo'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('redo'),
|
|
self.menubar.tkopt.sound_redo, None)
|
|
key = 'startdrag'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('start drag'),
|
|
self.menubar.tkopt.sound_startdrag, None)
|
|
key = 'turnwaste'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('turn waste'),
|
|
self.menubar.tkopt.sound_turnwaste, None)
|
|
key = 'undo'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('undo'),
|
|
self.menubar.tkopt.sound_undo, None)
|
|
key = 'gamefinished'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('game finished'),
|
|
self.menubar.tkopt.sound_gamefinished, None)
|
|
key = 'gamelost'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('game lost'),
|
|
self.menubar.tkopt.sound_gamelost, None)
|
|
key = 'gameperfect'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('game perfect'),
|
|
self.menubar.tkopt.sound_gameperfect, None)
|
|
key = 'gamewon'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('game won'),
|
|
self.menubar.tkopt.sound_gamewon, None)
|
|
key = 'extra'
|
|
self.addCheckNode(
|
|
tv, rg1,
|
|
_('Other'),
|
|
self.menubar.tkopt.sound_extra, None)
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Cardsets and card backside options
|
|
|
|
from pysollib.resource import CSI
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Cardsets')))
|
|
if rg:
|
|
self.menubar.tkopt.cardset.value = self.app.cardset.index
|
|
|
|
csm = self.app.cardset_manager
|
|
cdict = {}
|
|
i = 0
|
|
while 1:
|
|
cardset = csm.get(i)
|
|
if cardset is None: break # noqa
|
|
t = cardset.type
|
|
if t not in cdict.keys(): cdict[t] = [] # noqa
|
|
cdict[t].append((i, cardset))
|
|
i += 1
|
|
|
|
for k in sorted(cdict.keys()):
|
|
name = CSI.TYPE_NAME[k]
|
|
csl = cdict[k]
|
|
rg1 = tv.add_node(LTreeNode(text=name), rg)
|
|
|
|
for cst in csl:
|
|
i = cst[0]
|
|
cs = cst[1]
|
|
rg2 = self.addRadioNode(
|
|
tv,rg1,cs.name,self.menubar.tkopt.cardset, # noqa
|
|
i,self.menubar.mOptCardset) # noqa
|
|
|
|
if rg2:
|
|
cbs = cs.backnames
|
|
self.menubar.tkopt.cardbacks[i] = LNumWrap(None)
|
|
self.menubar.tkopt.cardbacks[i].value = cs.backindex
|
|
|
|
bcnt = len(cbs)
|
|
bi = 0
|
|
while 1:
|
|
if bi == bcnt: break # noqa
|
|
cb = cbs[bi]
|
|
self.addRadioNode(tv,rg2,cb, # noqa
|
|
self.menubar.tkopt.cardbacks[i],bi, # noqa
|
|
self.make_vars_command( # noqa
|
|
self.menubar.mOptSetCardback, i))
|
|
bi += 1
|
|
yield
|
|
# -------------------------------------------
|
|
# Table background settings
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Table')))
|
|
if rg:
|
|
rg1 = tv.add_node(
|
|
LTreeNode(text=_('Solid colors')), rg)
|
|
if rg1:
|
|
key = 'table'
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Azure'),
|
|
self.menubar.tkopt.color_vars[key], '#0082df',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Black'),
|
|
self.menubar.tkopt.color_vars[key], '#000000',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Blue'),
|
|
self.menubar.tkopt.color_vars[key], '#0000ff',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Bright Green'),
|
|
self.menubar.tkopt.color_vars[key], '#00ff00',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Brown'),
|
|
self.menubar.tkopt.color_vars[key], '#684700',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Cyan'),
|
|
self.menubar.tkopt.color_vars[key], '#00ffff',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Grey'),
|
|
self.menubar.tkopt.color_vars[key], '#888888',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Green'),
|
|
self.menubar.tkopt.color_vars[key], '#008200',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Magenta'),
|
|
self.menubar.tkopt.color_vars[key], '#ff00ff',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Navy'),
|
|
self.menubar.tkopt.color_vars[key], '#000086',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Olive'),
|
|
self.menubar.tkopt.color_vars[key], '#868200',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Orange'),
|
|
self.menubar.tkopt.color_vars[key], '#f79600',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Pink'),
|
|
self.menubar.tkopt.color_vars[key], '#ff92fc',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Purple'),
|
|
self.menubar.tkopt.color_vars[key], '#8300ff',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Red'),
|
|
self.menubar.tkopt.color_vars[key], '#ff0000',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Teal'),
|
|
self.menubar.tkopt.color_vars[key], '#008286',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('White'),
|
|
self.menubar.tkopt.color_vars[key], '#ffffff',
|
|
self.menubar.mOptTableColor)
|
|
self.addRadioNode(
|
|
tv, rg1,
|
|
_('Yellow'),
|
|
self.menubar.tkopt.color_vars[key], '#ffff00',
|
|
self.menubar.mOptTableColor)
|
|
|
|
rg1 = tv.add_node(
|
|
LTreeNode(text=_('Tiles')), rg)
|
|
rg2 = tv.add_node(
|
|
LTreeNode(text=_('Images')), rg)
|
|
|
|
if rg1 or rg2:
|
|
tm = self.app.tabletile_manager
|
|
# cnt = tm.len()
|
|
i = 1
|
|
while True:
|
|
ti = tm.get(i)
|
|
|
|
if ti is None:
|
|
break
|
|
if ti.save_aspect == 0 and ti.stretch == 0 and rg1:
|
|
self.addRadioNode(tv, rg1,
|
|
ti.name,
|
|
self.menubar.tkopt.tabletile, i,
|
|
self.menubar.mOptTileSet)
|
|
if (ti.save_aspect == 1 or ti.stretch == 1) and rg2:
|
|
self.addRadioNode(tv, rg2,
|
|
ti.name,
|
|
self.menubar.tkopt.tabletile, i,
|
|
self.menubar.mOptTileSet)
|
|
i += 1
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Card view options
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Card view')))
|
|
if rg:
|
|
self.addCheckNode(tv, rg,
|
|
_('Card shadow'),
|
|
self.menubar.tkopt.shadow,
|
|
self.menubar.mOptShadow)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Shade legal moves'),
|
|
self.menubar.tkopt.shade,
|
|
self.menubar.mOptShade)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Negative cards bottom'),
|
|
self.menubar.tkopt.negative_bottom,
|
|
self.menubar.mOptNegativeBottom)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Shrink face-down cards'),
|
|
self.menubar.tkopt.shrink_face_down,
|
|
self.menubar.mOptShrinkFaceDown)
|
|
|
|
self.addCheckNode(tv, rg,
|
|
_('Shade filled stacks'),
|
|
self.menubar.tkopt.shade_filled_stacks,
|
|
self.menubar.mOptShadeFilledStacks)
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Animation settins
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Animations')))
|
|
if rg:
|
|
self.addRadioNode(tv, rg,
|
|
_('None'),
|
|
self.menubar.tkopt.animations, 0,
|
|
self.menubar.mOptAnimations)
|
|
|
|
self.addRadioNode(tv, rg,
|
|
_('Very fast'),
|
|
self.menubar.tkopt.animations, 1,
|
|
self.menubar.mOptAnimations)
|
|
|
|
self.addRadioNode(tv, rg,
|
|
_('Fast'),
|
|
self.menubar.tkopt.animations, 2,
|
|
self.menubar.mOptAnimations)
|
|
|
|
self.addRadioNode(tv, rg,
|
|
_('Medium'),
|
|
self.menubar.tkopt.animations, 3,
|
|
self.menubar.mOptAnimations)
|
|
|
|
self.addRadioNode(tv, rg,
|
|
_('Slow'),
|
|
self.menubar.tkopt.animations, 4,
|
|
self.menubar.mOptAnimations)
|
|
|
|
self.addRadioNode(tv, rg,
|
|
_('Very slow'),
|
|
self.menubar.tkopt.animations, 5,
|
|
self.menubar.mOptAnimations)
|
|
|
|
# NOTE: All the following animation features only work on the
|
|
# desktop and only if pillow is installed. So its useless to
|
|
# present them here.
|
|
'''
|
|
self.addCheckNode(tv, rg,
|
|
_('Redeal animation'),
|
|
self.menubar.tkopt.redeal_animation,
|
|
self.menubar.mRedealAnimation)
|
|
self.addCheckNode(tv, rg,
|
|
_('Winning animation'),
|
|
self.menubar.tkopt.win_animation,
|
|
self.menubar.mWinAnimation)
|
|
self.addCheckNode(tv, rg,
|
|
_('Flip animation'),
|
|
self.menubar.tkopt.flip_animation,
|
|
None)
|
|
'''
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Touch mode settings
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Touch mode')))
|
|
if rg:
|
|
self.addRadioNode(tv, rg,
|
|
_('Drag-and-Drop'),
|
|
self.menubar.tkopt.mouse_type, 'drag-n-drop',
|
|
None)
|
|
|
|
self.addRadioNode(tv, rg,
|
|
_('Point-and-Click'),
|
|
self.menubar.tkopt.mouse_type, 'point-n-click',
|
|
None)
|
|
|
|
# sinnlos mit touch-device:
|
|
# self.addRadioNode(tv, rg,
|
|
# 'Sticky mouse',
|
|
# self.menubar.tkopt.mouse_type, u'sticky-mouse',
|
|
# self.menubar.mOptMouseType)
|
|
|
|
# submenu.add_separator()
|
|
|
|
# sinnlos mit touch-device:
|
|
# self.addCheckNode(tv, rg,
|
|
# 'Use mouse for undo/redo',
|
|
# self.menubar.tkopt.mouse_undo,
|
|
# self.menubar.mOptMouseUndo)
|
|
|
|
# submenu.add_separator()
|
|
|
|
# -------------------------------------------
|
|
# TBD ?
|
|
|
|
'''
|
|
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()
|
|
'''
|
|
|
|
yield
|
|
# -------------------------------------------
|
|
# Toolbar options
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Toolbar')))
|
|
if rg:
|
|
self.addRadioNode(tv, rg,
|
|
_('Hide'),
|
|
self.menubar.tkopt.toolbar, 0,
|
|
self.menubar.setToolbarPos)
|
|
|
|
self.addRadioNode(tv, rg,
|
|
_('Top'),
|
|
self.menubar.tkopt.toolbar, 1,
|
|
self.menubar.setToolbarPos)
|
|
self.addRadioNode(tv, rg,
|
|
_('Bottom'),
|
|
self.menubar.tkopt.toolbar, 2,
|
|
self.menubar.setToolbarPos)
|
|
self.addRadioNode(tv, rg,
|
|
_('Left'),
|
|
self.menubar.tkopt.toolbar, 3,
|
|
self.menubar.setToolbarPos)
|
|
self.addRadioNode(tv, rg,
|
|
_('Right'),
|
|
self.menubar.tkopt.toolbar, 4,
|
|
self.menubar.setToolbarPos)
|
|
|
|
rg1 = tv.add_node(
|
|
LTreeNode(text=_('Visible buttons')), rg)
|
|
if rg1:
|
|
for w in TOOLBAR_BUTTONS:
|
|
w0 = w[0].upper()
|
|
ww = w[1:]
|
|
self.addCheckNode(tv, rg1,
|
|
_(w0+ww), # noqa
|
|
self.menubar.tkopt.toolbar_vars[w],
|
|
self.make_vars_command(self.menubar.mOptToolbarConfig, w)) # noqa
|
|
|
|
# -------------------------------------------
|
|
# Statusbar - not implemented
|
|
|
|
'''
|
|
submenu = MfxMenu(menu, label=n_("Stat&usbar"))
|
|
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 &help bar"),
|
|
variable=self.tkopt.helpbar,
|
|
command=self.mOptHelpbar)
|
|
'''
|
|
# -------------------------------------------
|
|
# Other graphics settings
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Other graphics')))
|
|
data_dir = os.path.join(self.app.dataloader.dir, 'images', 'demo')
|
|
dl = tv.add_node(
|
|
LTreeNode(text=_('Demo logo')), rg)
|
|
styledirs = os.listdir(data_dir)
|
|
styledirs.append("none")
|
|
styledirs.sort()
|
|
for f in styledirs:
|
|
d = os.path.join(data_dir, f)
|
|
if (os.path.isdir(d) and os.path.exists(os.path.join(d))) \
|
|
or f == "none":
|
|
name = f.replace('_', ' ').capitalize()
|
|
self.addRadioNode(tv, dl,
|
|
_(name),
|
|
self.menubar.tkopt.demo_logo_style, f,
|
|
self.menubar.mOptDemoLogoStyle)
|
|
|
|
data_dir = os.path.join(self.app.dataloader.dir, 'images', 'pause')
|
|
dl = tv.add_node(
|
|
LTreeNode(text=_('Pause text')), rg)
|
|
styledirs = os.listdir(data_dir)
|
|
styledirs.sort()
|
|
for f in styledirs:
|
|
d = os.path.join(data_dir, f)
|
|
if os.path.isdir(d) and os.path.exists(os.path.join(d)):
|
|
name = f.replace('_', ' ').capitalize()
|
|
self.addRadioNode(tv, dl,
|
|
_(name),
|
|
self.menubar.tkopt.pause_text_style, f,
|
|
self.menubar.mOptPauseTextStyle)
|
|
|
|
data_dir = os.path.join(self.app.dataloader.dir, 'images',
|
|
'redealicons')
|
|
dl = tv.add_node(
|
|
LTreeNode(text=_('Redeal icons')), rg)
|
|
styledirs = os.listdir(data_dir)
|
|
styledirs.sort()
|
|
for f in styledirs:
|
|
d = os.path.join(data_dir, f)
|
|
if os.path.isdir(d) and os.path.exists(os.path.join(d)):
|
|
name = f.replace('_', ' ').capitalize()
|
|
self.addRadioNode(tv, dl,
|
|
_(name),
|
|
self.menubar.tkopt.redeal_icon_style, f,
|
|
self.menubar.mOptRedealIconStyle)
|
|
|
|
# -------------------------------------------
|
|
# general options
|
|
|
|
rg = tv.add_node(
|
|
LTreeNode(text=_('Font size')))
|
|
if rg:
|
|
self.addRadioNode(tv, rg,
|
|
_('default'),
|
|
self.menubar.tkopt.fontscale, 'default',
|
|
None)
|
|
self.addRadioNode(tv, rg,
|
|
_('tiny'),
|
|
self.menubar.tkopt.fontscale, 'tiny',
|
|
None)
|
|
self.addRadioNode(tv, rg,
|
|
_('small'),
|
|
self.menubar.tkopt.fontscale, 'small',
|
|
None)
|
|
self.addRadioNode(tv, rg,
|
|
_('normal'),
|
|
self.menubar.tkopt.fontscale, 'normal',
|
|
None)
|
|
self.addRadioNode(tv, rg,
|
|
_('large'),
|
|
self.menubar.tkopt.fontscale, 'large',
|
|
None)
|
|
self.addRadioNode(tv, rg,
|
|
_('huge'),
|
|
self.menubar.tkopt.fontscale, 'huge',
|
|
None)
|
|
'''
|
|
self.addSliderNode(tv, rg, self.menubar.tkopt.fontsizefactor,
|
|
(0.7, 2.0, 0.1))
|
|
'''
|
|
|
|
# self.addCheckNode(tv, None,
|
|
# 'Save games geometry',
|
|
# self.menubar.tkopt.save_games_geometry,
|
|
# self.menubar.mOptSaveGamesGeometry)
|
|
|
|
# self.addCheckNode(tv, None,
|
|
# 'Demo logo',
|
|
# self.menubar.tkopt.demo_logo,
|
|
# self.menubar.mOptDemoLogo)
|
|
|
|
self.addCheckNode(tv, None,
|
|
_('Startup splash screen'),
|
|
self.menubar.tkopt.splashscreen,
|
|
None)
|
|
|
|
self.addCheckNode(tv, None,
|
|
_('Winning splash'),
|
|
self.menubar.tkopt.display_win_message,
|
|
None)
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class OptionsMenuDialog(LMenuDialog):
|
|
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
kw['persist'] = True
|
|
super(OptionsMenuDialog, self).__init__(
|
|
menubar, parent, title, app, **kw)
|
|
|
|
def initTree(self):
|
|
og = LOptionsMenuGenerator(
|
|
self.menubar, self.parent, title=_("Options"), app=self.app)
|
|
tv = og.generate()
|
|
return tv
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class HelpMenuDialog(LMenuDialog):
|
|
def __init__(self, menubar, parent, title, app, **kw):
|
|
kw['persist'] = True
|
|
super(HelpMenuDialog, self).__init__(menubar, parent, title, app, **kw)
|
|
|
|
def buildTree(self, tv, node):
|
|
tv.add_node(
|
|
LTreeNode(
|
|
text=_('Contents'),
|
|
command=self.auto_close(self.menubar.mHelp)))
|
|
tv.add_node(
|
|
LTreeNode(
|
|
text=_('How to use PySol'),
|
|
command=self.auto_close(self.menubar.mHelpHowToPlay)))
|
|
tv.add_node(
|
|
LTreeNode(
|
|
text=_('Rules for this game'),
|
|
command=self.auto_close(self.menubar.mHelpRules)))
|
|
tv.add_node(
|
|
LTreeNode(
|
|
text=_('License terms'),
|
|
command=self.auto_close(self.menubar.mHelpLicense)))
|
|
tv.add_node(
|
|
LTreeNode(
|
|
text=_('About %s...') % TITLE,
|
|
command=self.auto_close(self.menubar.mHelpAbout)))
|
|
|
|
# tv.add_node(LTreeNode(
|
|
# text='AboutKivy ...',
|
|
# command=self.makeHtmlCommand(self.menubar, "kivy.html")))
|
|
'''
|
|
def makeHtmlCommand(self, bar, htmlfile):
|
|
def htmlCommand():
|
|
bar.mHelpHtml(htmlfile)
|
|
return htmlCommand
|
|
'''
|
|
|
|
# ************************************************************************
|
|
# *
|
|
# ************************************************************************
|
|
|
|
|
|
class EmulTkMenu(object):
|
|
|
|
def __init__(self, master, **kw):
|
|
|
|
self.name = kw["name"]
|
|
self.n = 0
|
|
self._w = None
|
|
if (self.name):
|
|
if master._w == '.':
|
|
self._w = '.' + self.name
|
|
else:
|
|
self._w = master._w + '.' + self.name
|
|
else:
|
|
self.name = "<>"
|
|
|
|
def labeltoname(self, label):
|
|
name = re.sub(r"[^0-9a-zA-Z]", "", label).lower()
|
|
label = _(label)
|
|
underline = label.find('&')
|
|
if underline >= 0:
|
|
label = label.replace('&', '')
|
|
return name, label, underline
|
|
|
|
def add_cascade(self, cnf={}, **kw):
|
|
self.add('cascade', cnf or kw)
|
|
pass
|
|
|
|
def add(self, itemType, cnf={}):
|
|
label = cnf.get("label")
|
|
if label:
|
|
name = cnf.get('name')
|
|
if name:
|
|
name, label, underline = self.labeltoname(label)
|
|
cnf["underline"] = cnf.get("underline", underline)
|
|
cnf["label"] = label
|
|
if name and self.addPath:
|
|
path = str(self._w) + "." + name
|
|
self.addPath(path, self, self.n, cnf.get("menu"))
|
|
|
|
def cget(self, key):
|
|
return key
|
|
|
|
# ************************************************************************
|
|
|
|
|
|
class MfxMenubar(EmulTkMenu):
|
|
addPath = None
|
|
|
|
def __init__(self, master, **kw):
|
|
super(MfxMenubar, self).__init__(master, **kw)
|
|
topmenu = self.name == 'menubar'
|
|
|
|
self.menu = LMenu(not topmenu, text=self.name)
|
|
if topmenu:
|
|
master.setMenu(self.menu)
|
|
|
|
# ************************************************************************
|
|
# * - create menubar
|
|
# * - update menubar
|
|
# * - menu actions
|
|
# ************************************************************************
|
|
|
|
|
|
class DictObjMap(object):
|
|
def __init__(self, val):
|
|
self.__dict__ = val
|
|
|
|
|
|
class PysolMenubarTk:
|
|
def __init__(self, app, top, progress=None):
|
|
print('PysolMenubarTk: __init__()')
|
|
self.top = top
|
|
self.app = app
|
|
|
|
self._createTkOpt()
|
|
self._setOptions()
|
|
|
|
self.__cb_max = 8
|
|
self.progress = progress
|
|
|
|
# create menus
|
|
self.__menubar = None
|
|
self.__menupath = {}
|
|
self.__keybindings = {}
|
|
self._createMenubar()
|
|
|
|
if self.progress:
|
|
self.progress.update(step=1)
|
|
|
|
def unlockScreenRotation(self, obj, val):
|
|
AndroidScreenRotation.unlock(toaster=False)
|
|
print('unlock screen rotation')
|
|
|
|
def setFontScale(self, obj, val):
|
|
from kivy.metrics import Metrics
|
|
vals = {
|
|
'tiny': 0.833,
|
|
'small': 1.0,
|
|
'normal': 1.2,
|
|
'large': 1.44,
|
|
'huge': 1.728
|
|
}
|
|
if val == 'default':
|
|
Metrics.reset_metrics()
|
|
else:
|
|
Metrics.fontscale = vals[val]
|
|
'''
|
|
def setFontSize(self, obj, val):
|
|
from kivy.metrics import Metrics
|
|
Metrics.fontscale = val
|
|
'''
|
|
|
|
def _createTkOpt(self):
|
|
opt = self.app.opt
|
|
|
|
# fake options
|
|
self.tabletile_index = self.app.tabletile_index
|
|
self.cardback = self.app.cardset.backindex
|
|
self.cardset = self.app.cardset_manager.getSelected()
|
|
self.pause = False
|
|
if self.game:
|
|
self.pause = self.game.pause
|
|
self.gameid = 0
|
|
self.gameid_popular = 0
|
|
|
|
# map dicts to Obj
|
|
self.sound_samples = DictObjMap(opt.sound_samples)
|
|
self.tbv = DictObjMap(opt.toolbar_vars)
|
|
self.cvo = DictObjMap(opt.colors)
|
|
|
|
# option mappings.
|
|
self.tkopt = Struct(
|
|
# automation
|
|
autofaceup=LBoolWrap(opt, "autofaceup"),
|
|
autodrop=LBoolWrap(opt, "autodrop"),
|
|
autodeal=LBoolWrap(opt, "autodeal"),
|
|
quickplay=LBoolWrap(opt, "quickplay"),
|
|
# support
|
|
undo=LBoolWrap(opt, "undo"),
|
|
hint=LBoolWrap(opt, "hint"),
|
|
free_hint=LBoolWrap(opt, "free_hint"),
|
|
shuffle=LBoolWrap(opt, "shuffle"),
|
|
bookmarks=LBoolWrap(opt, "bookmarks"),
|
|
highlight_piles=LBoolWrap(opt, "highlight_piles"),
|
|
highlight_cards=LBoolWrap(opt, "highlight_cards"),
|
|
highlight_samerank=LBoolWrap(opt, "highlight_samerank"),
|
|
peek_facedown=LBoolWrap(opt, "peek_facedown"),
|
|
highlight_not_matching=LBoolWrap(opt, "highlight_not_matching"),
|
|
stuck_notification=LBoolWrap(opt, "stuck_notification"),
|
|
mahjongg_show_removed=LBoolWrap(opt, "mahjongg_show_removed"),
|
|
shisen_show_hint=LBoolWrap(opt, "shisen_show_hint"),
|
|
accordion_deal_all=LBoolWrap(opt, "accordion_deal_all"),
|
|
pegged_auto_remove=LBoolWrap(opt, "pegged_auto_remove"),
|
|
# sound
|
|
sound=LBoolWrap(opt, "sound"),
|
|
sound_sample_volume=LNumWrap(opt, "sound_sample_volume"),
|
|
sound_music_volume=LNumWrap(opt, "sound_music_volume"),
|
|
# sound samples
|
|
sound_areyousure=LBoolWrap(self.sound_samples, 'areyousure'),
|
|
sound_autodrop=LBoolWrap(self.sound_samples, 'autodrop'),
|
|
sound_autoflip=LBoolWrap(self.sound_samples, 'autoflip'),
|
|
sound_autopilotlost=LBoolWrap(self.sound_samples, 'autopilotlost'),
|
|
sound_autopilotwon=LBoolWrap(self.sound_samples, 'autopilotwon'),
|
|
sound_deal=LBoolWrap(self.sound_samples, 'deal'),
|
|
sound_dealwaste=LBoolWrap(self.sound_samples, 'dealwaste'),
|
|
sound_droppair=LBoolWrap(self.sound_samples, 'droppair'),
|
|
sound_drop=LBoolWrap(self.sound_samples, 'drop'),
|
|
sound_extra=LBoolWrap(self.sound_samples, 'extra'),
|
|
sound_flip=LBoolWrap(self.sound_samples, 'flip'),
|
|
sound_move=LBoolWrap(self.sound_samples, 'move'),
|
|
sound_nomove=LBoolWrap(self.sound_samples, 'nomove'),
|
|
sound_redo=LBoolWrap(self.sound_samples, 'redo'),
|
|
sound_startdrag=LBoolWrap(self.sound_samples, 'startdrag'),
|
|
sound_turnwaste=LBoolWrap(self.sound_samples, 'turnwaste'),
|
|
sound_undo=LBoolWrap(self.sound_samples, 'undo'),
|
|
sound_gamefinished=LBoolWrap(self.sound_samples, 'gamefinished'),
|
|
sound_gamelost=LBoolWrap(self.sound_samples, 'gamelost'),
|
|
sound_gameperfect=LBoolWrap(self.sound_samples, 'gameperfect'),
|
|
sound_gamewon=LBoolWrap(self.sound_samples, 'gamewon'),
|
|
# animation
|
|
animations=LNumWrap(opt, "animations"),
|
|
redeal_animation=LBoolWrap(opt, "redeal_animation"),
|
|
win_animation=LBoolWrap(opt, "win_animation"),
|
|
flip_animation=LBoolWrap(opt, "flip_animation"),
|
|
# toolbar
|
|
toolbar=LNumWrap(opt, "toolbar"),
|
|
toolbar_land=LNumWrap(opt, "toolbar_land", self.mOptToolbar),
|
|
toolbar_port=LNumWrap(opt, "toolbar_port", self.mOptToolbar),
|
|
toolbar_style=LStringWrap(opt, "toolbar_style"),
|
|
toolbar_relief=LStringWrap(opt, "toolbar_relief"),
|
|
toolbar_compound=LStringWrap(opt, "toolbar_compound"),
|
|
toolbar_size=LNumWrap(opt, "toolbar_size"),
|
|
toolbar_vars={},
|
|
# card dsiplay and text style settings
|
|
demo_logo=LBoolWrap(opt, "demo_logo"),
|
|
demo_logo_style=LStringWrap(opt, "demo_logo_style"),
|
|
pause_text_style=LStringWrap(opt, "pause_text_style"),
|
|
redeal_icon_style=LStringWrap(opt, "redeal_icon_style"),
|
|
mouse_type=LStringWrap(opt, "mouse_type"),
|
|
mouse_undo=LBoolWrap(opt, "mouse_undo"),
|
|
shade_filled_stacks=LBoolWrap(opt, "shade_filled_stacks"),
|
|
shrink_face_down=LBoolWrap(opt, "shrink_face_down"),
|
|
negative_bottom=LBoolWrap(opt, "negative_bottom"),
|
|
shadow=LBoolWrap(opt, "shadow"),
|
|
shade=LBoolWrap(opt, "shade"),
|
|
# colors
|
|
color_vars={},
|
|
tabletile=LNumWrap(self, "tabletile_index"),
|
|
# other
|
|
splashscreen=LBoolWrap(opt, "splashscreen"),
|
|
display_win_message=LBoolWrap(opt, "display_win_message"),
|
|
language=LStringWrap(opt, "language"),
|
|
save_games_geometry=LBoolWrap(opt, "save_games_geometry"),
|
|
pause=LBoolWrap(self, "pause"),
|
|
table_zoom=LListWrap(opt, "table_zoom"),
|
|
fontscale=LStringWrap(opt, "fontscale", self.setFontScale),
|
|
# fontsizefactor=LNumWrap(opt, "fontsizefactor", self.setFontSize),
|
|
# cards
|
|
cardset=LNumWrap(self, "cardset"),
|
|
cardback=LNumWrap(self, "cardback"),
|
|
cardbacks={},
|
|
# statusbar (not implemented)
|
|
statusbar=LBoolWrap(opt, "statusbar"),
|
|
# num_cards=BooleanVar(),
|
|
# helpbar=BooleanVar(),
|
|
# game
|
|
gameid=LNumWrap(self, "gameid", self.unlockScreenRotation),
|
|
gameid_popular=LNumWrap(self, "gameid_popular"),
|
|
)
|
|
for w in TOOLBAR_BUTTONS:
|
|
self.tkopt.toolbar_vars[w] = LBoolWrap(self.tbv, w)
|
|
for k in self.app.opt.colors:
|
|
self.tkopt.color_vars[k] = LStringWrap(self.cvo, k)
|
|
|
|
def _setOptions(self):
|
|
self.tkopt.save_games_geometry.value = False
|
|
self.getToolbarPos(None, Window.size)
|
|
self.setFontScale(None, self.tkopt.fontscale.value)
|
|
# self.setFontSize(None, self.tkopt.fontsizefactor.value)
|
|
Window.bind(size=self.getToolbarPos)
|
|
|
|
def getToolbarPos(self, obj, size):
|
|
if (size[0] > size[1]):
|
|
self.tkopt.toolbar.value = self.tkopt.toolbar_land.value
|
|
else:
|
|
self.tkopt.toolbar.value = self.tkopt.toolbar_port.value
|
|
|
|
def setToolbarPos(self, *args):
|
|
if (Window.size[0] > Window.size[1]):
|
|
self.tkopt.toolbar_land.value = self.tkopt.toolbar.value
|
|
else:
|
|
self.tkopt.toolbar_port.value = self.tkopt.toolbar.value
|
|
|
|
def connectGame(self, game):
|
|
self.game = game
|
|
if game is None:
|
|
return
|
|
assert self.app is game.app
|
|
tkopt = self.tkopt
|
|
# opt = self.app.opt
|
|
tkopt.gameid.value = game.id
|
|
tkopt.gameid_popular.value = game.id
|
|
tkopt.pause.value = self.game.pause
|
|
if game.canFindCard():
|
|
connect_game_find_card_dialog(game)
|
|
else:
|
|
destroy_find_card_dialog()
|
|
if game.canShowFullPicture():
|
|
connect_game_full_picture_dialog(game)
|
|
else:
|
|
destroy_full_picture_dialog()
|
|
connect_game_solver_dialog(game)
|
|
|
|
# create a GTK-like path
|
|
def _addPath(self, path, menu, index, submenu):
|
|
# print ('MfxMenubar: _addPath %s, %s' % (path, menu))
|
|
# y = self.yy
|
|
if path not in self.__menupath:
|
|
# print path, menu, index, submenu
|
|
self.__menupath[path] = (menu, index, submenu)
|
|
|
|
def _getEnabledState(self, enabled):
|
|
print('_getEnabledState: %s' % enabled)
|
|
if enabled:
|
|
return "normal"
|
|
return "disabled"
|
|
|
|
def updateProgress(self):
|
|
if self.progress:
|
|
self.progress.update(step=1)
|
|
|
|
#
|
|
# create the menubar
|
|
#
|
|
|
|
def _createMenubar(self):
|
|
MfxMenubar.addPath = self._addPath
|
|
kw = {"name": "menubar"}
|
|
self.__menubar = MfxMenubar(self.top, **kw)
|
|
|
|
# init keybindings
|
|
bind(self.top, "<KeyPress>", self._keyPressHandler)
|
|
|
|
# LMainMenuDialog()
|
|
LMenuItem(self.__menubar.menu,
|
|
text=_("Menu"), command=self.mMainMenuDialog)
|
|
|
|
MfxMenubar.addPath = None
|
|
|
|
#
|
|
# key binding utility
|
|
#
|
|
|
|
def _bindKey(self, modifier, key, func):
|
|
# if 0 and not modifier and len(key) == 1:
|
|
# self.__keybindings[key.lower()] = func
|
|
# self.__keybindings[key.upper()] = func
|
|
# return
|
|
if not modifier and len(key) == 1:
|
|
# ignore Ctrl/Shift/Alt
|
|
# but don't ignore NumLock (state == 16)
|
|
def lfunc(e, func=func):
|
|
return e.state in (0, 16) and func(e)
|
|
func = lfunc
|
|
# func = lambda e, func=func: e.state in (0, 16) and func(e)
|
|
sequence = "<" + modifier + "KeyPress-" + key + ">"
|
|
bind(self.top, sequence, func)
|
|
if len(key) == 1 and key != key.upper():
|
|
key = key.upper()
|
|
sequence = "<" + modifier + "KeyPress-" + key + ">"
|
|
bind(self.top, sequence, func)
|
|
|
|
def _keyPressHandler(self, event):
|
|
r = EVENT_PROPAGATE
|
|
if event and self.game:
|
|
# print event.__dict__
|
|
if self.game.demo:
|
|
# stop the demo by setting self.game.demo.keypress
|
|
if event.char: # ignore Ctrl/Shift/etc.
|
|
self.game.demo.keypress = event.char
|
|
r = EVENT_HANDLED
|
|
# func = self.__keybindings.get(event.char)
|
|
# if func and (event.state & ~2) == 0:
|
|
# func(event)
|
|
# r = EVENT_HANDLED
|
|
return r
|
|
|
|
#
|
|
# Select Game menu creation
|
|
#
|
|
'''
|
|
def _addSelectGameMenu(self, menu):
|
|
games = map(self.app.gdb.get, self.app.gdb.getGamesIdSortedByName())
|
|
m = "Ctrl-"
|
|
if sys.platform == "darwin":
|
|
m = "Cmd-"
|
|
menu.add_command(label=n_("All &games..."), accelerator=m + "W",
|
|
command=self.mSelectGameDialog)
|
|
|
|
def _addSelectGameSubMenu(self, games, menu, select_data,
|
|
command, variable):
|
|
# print select_data
|
|
need_sep = 0
|
|
for label, select_func in select_data:
|
|
if label is None:
|
|
need_sep = 1
|
|
continue
|
|
g = filter(select_func, games)
|
|
if not g:
|
|
continue
|
|
if need_sep:
|
|
menu.add_separator()
|
|
need_sep = 0
|
|
submenu = MfxMenu(menu, label=label)
|
|
self._addSelectGameSubSubMenu(g, submenu, command, variable)
|
|
|
|
def _getNumGames(self, games, select_data):
|
|
ngames = 0
|
|
for label, select_func in select_data:
|
|
ngames += len(filter(select_func, games))
|
|
return ngames
|
|
|
|
def _addSelectMahjonggGameSubMenu(self, games, menu, command, variable):
|
|
def select_func(gi): return gi.si.game_type == GI.GT_MAHJONGG
|
|
mahjongg_games = filter(select_func, games)
|
|
if len(mahjongg_games) == 0:
|
|
return
|
|
#
|
|
menu = MfxMenu(menu, label=n_("&Mahjongg games"))
|
|
|
|
def add_menu(games, c0, c1, menu=menu,
|
|
variable=variable, command=command):
|
|
if not games:
|
|
return
|
|
label = c0 + ' - ' + c1
|
|
if c0 == c1:
|
|
label = c0
|
|
submenu = MfxMenu(menu, label=label, name=None)
|
|
self._addSelectGameSubSubMenu(games, submenu, command,
|
|
variable, short_name=True)
|
|
|
|
games = {}
|
|
for gi in mahjongg_games:
|
|
c = gi.short_name.strip()[0]
|
|
if c in games:
|
|
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 _addSelectPopularGameSubMenu(self, games, menu, command, variable):
|
|
def select_func(gi): return gi.si.game_flags & GI.GT_POPULAR
|
|
if len(filter(select_func, games)) == 0:
|
|
return
|
|
data = (n_("&Popular games"), select_func)
|
|
self._addSelectGameSubMenu(games, menu, (data, ),
|
|
self.mSelectGamePopular,
|
|
self.tkopt.gameid_popular)
|
|
|
|
def _addSelectFrenchGameSubMenu(self, games, menu, command, variable):
|
|
if self._getNumGames(games, GI.SELECT_GAME_BY_TYPE) == 0:
|
|
return
|
|
submenu = MfxMenu(menu, label=n_("&French games"))
|
|
self._addSelectGameSubMenu(games, submenu, GI.SELECT_GAME_BY_TYPE,
|
|
self.mSelectGame, self.tkopt.gameid)
|
|
|
|
def _addSelectOrientalGameSubMenu(self, games, menu, command, variable):
|
|
if self._getNumGames(games, GI.SELECT_ORIENTAL_GAME_BY_TYPE) == 0:
|
|
return
|
|
submenu = MfxMenu(menu, label=n_("&Oriental games"))
|
|
self._addSelectGameSubMenu(games, submenu,
|
|
GI.SELECT_ORIENTAL_GAME_BY_TYPE,
|
|
self.mSelectGame, self.tkopt.gameid)
|
|
|
|
def _addSelectSpecialGameSubMenu(self, games, menu, command, variable):
|
|
if self._getNumGames(games, GI.SELECT_ORIENTAL_GAME_BY_TYPE) == 0:
|
|
return
|
|
submenu = MfxMenu(menu, label=n_("&Special games"))
|
|
self._addSelectGameSubMenu(games, submenu,
|
|
GI.SELECT_SPECIAL_GAME_BY_TYPE,
|
|
self.mSelectGame, self.tkopt.gameid)
|
|
|
|
def _addSelectCustomGameSubMenu(self, games, menu, command, variable):
|
|
submenu = MfxMenu(menu, label=n_("&Custom games"))
|
|
|
|
def select_func(gi): return gi.si.game_type == GI.GT_CUSTOM
|
|
games = filter(select_func, games)
|
|
self.updateGamesMenu(submenu, games)
|
|
'''
|
|
|
|
def _addSelectAllGameSubMenu(self, games, menu, command, variable):
|
|
# LB
|
|
# herausgenommen: zu aufwendig !
|
|
return
|
|
'''
|
|
menu = MfxMenu(menu, label=n_("&All games by name"))
|
|
n, d = 0, self.__cb_max
|
|
i = 0
|
|
while True:
|
|
if self.progress:
|
|
self.progress.update(step=1)
|
|
columnbreak = i > 0 and (i % d) == 0
|
|
i += 1
|
|
if not games[n:n + d]:
|
|
break
|
|
m = min(n + d - 1, len(games) - 1)
|
|
label = games[n].name[:3] + ' - ' + games[m].name[:3]
|
|
|
|
submenu = MfxMenu(menu, label=label, name=None)
|
|
self._addSelectGameSubSubMenu(games[n:n + d], submenu,
|
|
command, variable)
|
|
n += d
|
|
# if columnbreak:
|
|
# menu.entryconfigure(i, columnbreak=columnbreak)
|
|
'''
|
|
|
|
# Eine 'closure' in Python? - voila!
|
|
def make_gamesetter(self, n, variable, command):
|
|
def gamesetter(x):
|
|
variable.value = n
|
|
command()
|
|
return gamesetter
|
|
|
|
def _addSelectGameSubSubMenu(self, games, menu, command, variable,
|
|
short_name=False):
|
|
|
|
# cb = self.__cb_max
|
|
for i in range(len(games)):
|
|
gi = games[i]
|
|
# columnbreak = i > 0 and (i % cb) == 0
|
|
if short_name:
|
|
label = gi.short_name
|
|
else:
|
|
label = gi.name
|
|
|
|
# optimized by inlining
|
|
|
|
# geht nicht mehr 'optimiert' mit kivy
|
|
# die Funktionalität des tk.calls kann mit hilfe
|
|
# einer 'closure' rekonstruiert werden (s.o).
|
|
# LB
|
|
|
|
gsetter = self.make_gamesetter(gi.id, variable, command)
|
|
menu.add_command(label=label, command=gsetter)
|
|
|
|
# menu.tk.call((menu._w, 'add', 'radiobutton') +
|
|
# menu._options({'command': command,
|
|
# 'variable': variable,
|
|
# 'columnbreak': columnbreak,
|
|
# 'value': gi.id,
|
|
# 'label': label}))
|
|
|
|
def updateGamesMenu(self, menu, games):
|
|
|
|
def cmp2(a, b):
|
|
"""python 3 replacement for python 2 cmp function"""
|
|
return (a > b) - (a < b)
|
|
|
|
menu.delete(0, 'last')
|
|
|
|
if len(games) == 0:
|
|
menu.add_radiobutton(label=_('<none>'), name=None,
|
|
state='disabled')
|
|
elif len(games) > self.__cb_max * 4:
|
|
games.sort(lambda a, b: cmp2(a.name, b.name))
|
|
self._addSelectAllGameSubMenu(games, menu,
|
|
command=self.mSelectGame,
|
|
variable=self.tkopt.gameid)
|
|
else:
|
|
self._addSelectGameSubSubMenu(games, menu,
|
|
command=self.mSelectGame,
|
|
variable=self.tkopt.gameid)
|
|
|
|
def mMainMenuDialog(self, *event):
|
|
MainMenuDialog(self, self.top, title=_("Main Menu"), app=self.app)
|
|
return EVENT_HANDLED
|
|
|
|
def mFileMenuDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.setCursor(cursor=CURSOR_WATCH)
|
|
after_idle(self.top, self.__restoreCursor)
|
|
FileMenuDialog(self, self.top, title=_("File Menu"), app=self.app)
|
|
return EVENT_HANDLED
|
|
|
|
def mEditMenuDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.setCursor(cursor=CURSOR_WATCH)
|
|
after_idle(self.top, self.__restoreCursor)
|
|
EditMenuDialog(self, self.top, title=_("Tools"), app=self.app)
|
|
return EVENT_HANDLED
|
|
|
|
def mGameMenuDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.setCursor(cursor=CURSOR_WATCH)
|
|
after_idle(self.top, self.__restoreCursor)
|
|
GameMenuDialog(self, self.top, title=_("Statistics"), app=self.app)
|
|
return EVENT_HANDLED
|
|
|
|
def mAssistMenuDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.setCursor(cursor=CURSOR_WATCH)
|
|
after_idle(self.top, self.__restoreCursor)
|
|
AssistMenuDialog(self, self.top, title=_("Assists"), app=self.app)
|
|
return EVENT_HANDLED
|
|
|
|
def mOptionsMenuDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.setCursor(cursor=CURSOR_WATCH)
|
|
after_idle(self.top, self.__restoreCursor)
|
|
|
|
OptionsMenuDialog(self, self.top, title=_("Options"), app=self.app)
|
|
return EVENT_HANDLED
|
|
|
|
def mHelpMenuDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.setCursor(cursor=CURSOR_WATCH)
|
|
after_idle(self.top, self.__restoreCursor)
|
|
HelpMenuDialog(self, self.top, title=_("Help"), app=self.app)
|
|
return EVENT_HANDLED
|
|
#
|
|
# Select Game menu actions
|
|
#
|
|
|
|
def mSelectGame(self, *args):
|
|
print('mSelectGame %s' % self)
|
|
self._mSelectGame(self.tkopt.gameid.value)
|
|
|
|
def mSelectGamePopular(self, *args):
|
|
self._mSelectGame(self.tkopt.gameid_popular.value)
|
|
|
|
def _mSelectGameDialog(self, d):
|
|
if d.gameid != self.game.id:
|
|
self.tkopt.gameid.value = d.gameid
|
|
self.tkopt.gameid_popular.value = d.gameid
|
|
self._cancelDrag()
|
|
self.game.endGame()
|
|
self.game.quitGame(d.gameid, random=d.random)
|
|
return EVENT_HANDLED
|
|
|
|
def __restoreCursor(self, *event):
|
|
self.game.setCursor(cursor=self.app.top_cursor)
|
|
|
|
def mSelectGameDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.setCursor(cursor=CURSOR_WATCH)
|
|
after_idle(self.top, self.__restoreCursor)
|
|
d = SelectGameDialog(self.top, title=_("Select game"),
|
|
app=self.app, gameid=self.game.id)
|
|
return self._mSelectGameDialog(d)
|
|
|
|
#
|
|
# menubar overrides
|
|
#
|
|
|
|
def updateFavoriteGamesMenu(self):
|
|
return
|
|
|
|
# TBD ?
|
|
'''
|
|
gameids = self.app.opt.favorite_gameid
|
|
|
|
print('favorite_gameids = %s' % gameids)
|
|
|
|
submenu = self.__menupath[".menubar.file.favoritegames"][2]
|
|
games = []
|
|
for id in gameids:
|
|
gi = self.app.getGameInfo(id)
|
|
if gi:
|
|
games.append(gi)
|
|
self.updateGamesMenu(submenu, games)
|
|
|
|
# das folgende ist nur das enable/disable des add/remove buttons.
|
|
# geht mit kivy nicht so.
|
|
|
|
# state = self._getEnabledState
|
|
# in_favor = self.app.game.id in gameids
|
|
|
|
# menu, index, submenu = self.__menupath[".menubar.file.addtofavorites"]
|
|
# menu.entryconfig(index, state=state(not in_favor))
|
|
|
|
# menu, index, submenu = self.__menupath[".menubar.file.removefromfavorites"]
|
|
# menu.entryconfig(index, state=state(in_favor))
|
|
'''
|
|
|
|
def updateRecentGamesMenu(self, gameids):
|
|
return
|
|
|
|
# TBD ?
|
|
'''
|
|
submenu = self.__menupath[".menubar.file.recentgames"][2]
|
|
games = []
|
|
for id in gameids:
|
|
gi = self.app.getGameInfo(id)
|
|
if gi:
|
|
games.append(gi)
|
|
self.updateGamesMenu(submenu, games)
|
|
'''
|
|
|
|
def updateBookmarkMenuState(self):
|
|
# LB:
|
|
# print('updateBookmarkMenuState - fake')
|
|
return
|
|
|
|
state = self._getEnabledState
|
|
mp1 = self.__menupath.get(".menubar.edit.setbookmark")
|
|
mp2 = self.__menupath.get(".menubar.edit.gotobookmark")
|
|
mp3 = self.__menupath.get(".menubar.edit.clearbookmarks")
|
|
if mp1 is None or mp2 is None or mp3 is None:
|
|
return
|
|
x = self.app.opt.bookmarks and self.game.canSetBookmark()
|
|
#
|
|
menu, index, submenu = mp1
|
|
for i in range(9):
|
|
submenu.entryconfig(i, state=state(x))
|
|
menu.entryconfig(index, state=state(x))
|
|
#
|
|
menu, index, submenu = mp2
|
|
ms = 0
|
|
for i in range(9):
|
|
s = self.game.gsaveinfo.bookmarks.get(i) is not None
|
|
submenu.entryconfig(i, state=state(s and x))
|
|
ms = ms or s
|
|
menu.entryconfig(index, state=state(ms and x))
|
|
#
|
|
menu, index, submenu = mp3
|
|
menu.entryconfig(index, state=state(ms and x))
|
|
|
|
def updateBackgroundImagesMenu(self):
|
|
# LB:
|
|
print('updateBackgroundImagesMenu - fake')
|
|
return
|
|
|
|
mp = self.__menupath.get(".menubar.options.cardbackground")
|
|
# delete all entries
|
|
submenu = mp[2]
|
|
submenu.delete(0, "last")
|
|
# insert new cardbacks
|
|
mbacks = self.app.images.getCardbacks()
|
|
cb = int(math.ceil(math.sqrt(len(mbacks))))
|
|
for i in range(len(mbacks)):
|
|
columnbreak = i > 0 and (i % cb) == 0
|
|
submenu.add_radiobutton(
|
|
label=mbacks[i].name,
|
|
image=mbacks[i].menu_image,
|
|
variable=self.tkopt.cardback,
|
|
value=i,
|
|
command=self.mOptCardback,
|
|
columnbreak=columnbreak,
|
|
indicatoron=0,
|
|
hidemargin=0)
|
|
#
|
|
# menu updates
|
|
#
|
|
|
|
def setMenuState(self, state, path):
|
|
# LB: not used
|
|
return
|
|
|
|
def setToolbarState(self, state, path):
|
|
# LB: not used
|
|
return
|
|
|
|
def _setPauseMenu(self, v):
|
|
self.tkopt.pause.value = v
|
|
|
|
#
|
|
# menu actions
|
|
#
|
|
|
|
DEFAULTEXTENSION = ".pso"
|
|
# TRANSLATORS: Usually, 'PySol files'
|
|
FILETYPES = ((_("%s files") % TITLE, "*" + DEFAULTEXTENSION),
|
|
(_("All files"), "*"))
|
|
|
|
def mAddFavor(self, *event):
|
|
gameid = self.app.game.id
|
|
if gameid not in self.app.opt.favorite_gameid:
|
|
self.app.opt.favorite_gameid.insert(0, gameid)
|
|
self.updateFavoriteGamesMenu()
|
|
|
|
def mDelFavor(self, *event):
|
|
gameid = self.app.game.id
|
|
if gameid in self.app.opt.favorite_gameid:
|
|
self.app.opt.favorite_gameid.remove(gameid)
|
|
self.updateFavoriteGamesMenu()
|
|
|
|
def mOpen(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# filename = self.game.filename
|
|
filename = "lastgame.pso"
|
|
if filename:
|
|
idir, ifile = os.path.split(os.path.normpath(filename))
|
|
else:
|
|
idir, ifile = "", ""
|
|
if not idir:
|
|
idir = self.app.dn.savegames
|
|
# d = tkinter.filedialog.Open()
|
|
# filename = d.show(filetypes=self.FILETYPES,
|
|
# defaultextension=self.DEFAULTEXTENSION,
|
|
# initialdir=idir, initialfile=ifile)
|
|
filename = idir + "/" + ifile
|
|
|
|
print('filename = %s' % filename)
|
|
if filename:
|
|
filename = os.path.normpath(filename)
|
|
if os.path.isfile(filename):
|
|
baseWindow = Cache.get('LAppCache', 'baseWindow')
|
|
text = _("loading game from:")+filename
|
|
toast = Toast(text=text)
|
|
toast.show(parent=baseWindow, duration=4.0)
|
|
Clock.schedule_once(lambda dt: self.game.loadGame(filename), 1.0) # noqa
|
|
|
|
def mSaveAs(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
if not self.menustate.save_as:
|
|
return
|
|
# filename = self.game.filename
|
|
filename = "lastgame.pso"
|
|
if not filename:
|
|
filename = self.app.getGameSaveName(self.game.id)
|
|
if os.name == "posix":
|
|
filename = filename + "-" + self.game.getGameNumber(format=0)
|
|
elif os.path.supports_unicode_filenames: # new in python 2.3
|
|
filename = filename + "-" + self.game.getGameNumber(format=0)
|
|
else:
|
|
filename = filename + "-01"
|
|
filename = filename + self.DEFAULTEXTENSION
|
|
idir, ifile = os.path.split(os.path.normpath(filename))
|
|
if not idir:
|
|
idir = self.app.dn.savegames
|
|
|
|
filename = idir + "/" + ifile
|
|
if filename:
|
|
filename = os.path.normpath(filename)
|
|
# filename = os.path.normcase(filename)
|
|
if self.game.saveGame(filename):
|
|
baseWindow = Cache.get('LAppCache', 'baseWindow')
|
|
text = _("game saved to:")+filename
|
|
toast = Toast(text=text)
|
|
toast.show(parent=baseWindow, duration=5.0)
|
|
self.updateMenus()
|
|
|
|
def mResetZoom(self, *args):
|
|
self.tkopt.table_zoom.value = [1.0, 0.0, 0.0]
|
|
|
|
def mPause(self, *args):
|
|
if not self.game:
|
|
return
|
|
if not self.game.pause:
|
|
if self._cancelDrag():
|
|
return
|
|
self.game.doPause()
|
|
self.tkopt.pause.value = self.game.pause
|
|
|
|
def mOptLanguage(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
MfxMessageDialog(
|
|
self.app.top, title=_("Note"),
|
|
text=_("""\
|
|
These settings will take effect
|
|
the next time you restart the %(app)s""") % {'app': TITLE})
|
|
|
|
def mAppSetTile(self, idx, force=False):
|
|
self.app.setTile(idx, force=force)
|
|
# setTile() may change option values (?):
|
|
# app.opt.tabletile_scale_method: not manaaged here -> o.k.
|
|
# app.opt.tabletile_name: not managed here -> o.k.
|
|
# app.tabletile_index: managed here, is set to idx, no change occurs. # noqa
|
|
# app.opt.colors['table']: managed as color_vars, complex, (proved: no change) # noqa
|
|
# print('**********', self.app.opt.colors['table'])
|
|
# print('**********', self.tkopt.color_vars['table'].value)
|
|
|
|
def mOptTableColor(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.tkopt.tabletile.value = 0 # (0 denotes color instead of a tile)
|
|
nv = self.tkopt.color_vars['table'].value
|
|
self.app.top_bg = nv
|
|
self.mAppSetTile(0, force=True)
|
|
|
|
def mOptTileSet(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
idx = self.tkopt.tabletile.value
|
|
if idx > 0 and idx != self.app.tabletile_index:
|
|
self.mAppSetTile(idx)
|
|
# set color out of known colors
|
|
# (its to remove the check flag from the menu):
|
|
self.tkopt.color_vars['table'].value = '#008285'
|
|
|
|
def mOptAutoFaceUp(self, *args):
|
|
if self._cancelDrag():
|
|
return
|
|
if self.app.opt.autofaceup:
|
|
self.game.autoPlay()
|
|
|
|
def mOptAutoDrop(self, *args):
|
|
if self._cancelDrag():
|
|
return
|
|
if self.app.opt.autodrop:
|
|
self.game.autoPlay()
|
|
|
|
def mOptAutoDeal(self, *args):
|
|
if self._cancelDrag():
|
|
return
|
|
if self.app.opt.autodeal:
|
|
self.game.autoPlay()
|
|
|
|
def mOptQuickPlay(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mOptEnableUndo(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.updateMenus()
|
|
|
|
def mOptEnableBookmarks(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.updateMenus()
|
|
|
|
def mOptEnableHint(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.updateMenus()
|
|
|
|
def mOptFreeHints(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.updateMenus()
|
|
|
|
def mOptEnableShuffle(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.updateMenus()
|
|
|
|
def mOptEnableHighlightPiles(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.updateMenus()
|
|
|
|
def mOptEnableHighlightCards(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.updateMenus()
|
|
|
|
def mOptEnableHighlightSameRank(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# self.game.updateMenus()
|
|
|
|
def mOptEnablePeekFacedown(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# self.game.updateMenus()
|
|
|
|
def mOptEnableHighlightNotMatching(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# self.game.updateMenus()
|
|
|
|
def mOptEnableStuckNotification(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# self.game.updateMenus()
|
|
|
|
def mOptAnimations(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mRedealAnimation(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mWinAnimation(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mOptShadow(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mOptShade(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mOptShrinkFaceDown(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.endGame(bookmark=1)
|
|
self.game.quitGame(bookmark=1)
|
|
|
|
def mOptShadeFilledStacks(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.game.endGame(bookmark=1)
|
|
self.game.quitGame(bookmark=1)
|
|
|
|
def mOptMahjonggShowRemoved(self, *args):
|
|
if self._cancelDrag():
|
|
return
|
|
# 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.game.updateMenus()
|
|
|
|
def mOptAccordionDealAll(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# self.game.updateMenus()
|
|
|
|
def mOptPeggedAutoRemove(self, *args):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# self.game.updateMenus()
|
|
|
|
def mOptCardset(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
idx = self.tkopt.cardset.value
|
|
cs = self.app.cardset_manager.get(idx)
|
|
if cs is None or idx == self.app.cardset.index:
|
|
return
|
|
if idx >= 0:
|
|
self.app.nextgame.cardset = cs
|
|
self._cancelDrag()
|
|
self.game.endGame(bookmark=1)
|
|
self.game.quitGame(bookmark=1)
|
|
|
|
def mSelectCardsetDialog(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
# strings, default = ("&OK", "&Load", "&Cancel"), 0
|
|
strings, default = (None, _("&Load"), _("&Cancel"), ), 1
|
|
# if os.name == "posix":
|
|
strings, default = (None, _("&Load"), _(
|
|
"&Cancel"), _("&Info..."), ), 1
|
|
key = self.app.nextgame.cardset.index
|
|
d = SelectCardsetDialogWithPreview(
|
|
self.top, title=_("Select cardset"),
|
|
app=self.app, manager=self.app.cardset_manager, key=key,
|
|
strings=strings, default=default)
|
|
|
|
cs = self.app.cardset_manager.get(d.key)
|
|
if cs is None or d.key == self.app.cardset.index:
|
|
return
|
|
if d.status == 0 and d.button in (0, 1) and d.key >= 0:
|
|
self.app.nextgame.cardset = cs
|
|
if d.button == 1:
|
|
self._cancelDrag()
|
|
self.game.endGame(bookmark=1)
|
|
self.game.quitGame(bookmark=1)
|
|
|
|
def mOptSetCardback(self, key, *event):
|
|
val = self.tkopt.cardbacks[key].value
|
|
cs = self.app.cardset_manager.get(key)
|
|
cs.updateCardback(backindex=val)
|
|
# ANM: wir können den Background nur für das aktuell
|
|
# selektierte Cardset wirklich ändern. Nur dieses wird
|
|
# wird in den Optionen gespeichert.
|
|
if (cs == self.app.cardset):
|
|
self.app.updateCardset(self.game.id)
|
|
self.app.cardset.backindex = val
|
|
image = self.app.images.getBack(update=True)
|
|
for card in self.game.cards:
|
|
card.updateCardBackground(image=image)
|
|
|
|
def _mOptCardback(self, index):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
cs = self.app.cardset
|
|
old_index = cs.backindex
|
|
cs.updateCardback(backindex=index)
|
|
if cs.backindex == old_index:
|
|
return
|
|
self.app.updateCardset(self.game.id)
|
|
image = self.app.images.getBack(update=True)
|
|
for card in self.game.cards:
|
|
card.updateCardBackground(image=image)
|
|
self.tkopt.cardback.value = cs.backindex
|
|
|
|
def mOptCardback(self, *event):
|
|
self._mOptCardback(self.tkopt.cardback.value)
|
|
|
|
def mOptChangeCardback(self, *event):
|
|
self._mOptCardback(self.app.cardset.backindex + 1)
|
|
|
|
def mOptToolbar(self, *event):
|
|
self.app.toolbar.show()
|
|
|
|
def mOptToolbarStyle(self, *event):
|
|
self.setToolbarStyle(self.tkopt.toolbar_style.value)
|
|
|
|
def mOptToolbarCompound(self, *event):
|
|
self.setToolbarCompound(self.tkopt.toolbar_compound.value)
|
|
|
|
def mOptToolbarSize(self, *event):
|
|
self.setToolbarSize(self.tkopt.toolbar_size.value)
|
|
|
|
def mOptToolbarRelief(self, *event):
|
|
self.setToolbarRelief(self.tkopt.toolbar_relief.value)
|
|
|
|
def mOptToolbarConfig(self, w):
|
|
self.toolbarConfig(w, self.tkopt.toolbar_vars[w].value)
|
|
|
|
def mOptDemoLogoStyle(self, *event):
|
|
self.setDemoLogoStyle()
|
|
|
|
def mOptPauseTextStyle(self, *event):
|
|
self.setPauseTextStyle()
|
|
|
|
def mOptRedealIconStyle(self, *event):
|
|
self.setRedealIconStyle()
|
|
|
|
def mOptStatusbar(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
if not self.app.statusbar:
|
|
return
|
|
side = self.tkopt.statusbar.value # noqa
|
|
resize = not self.app.opt.save_games_geometry # noqa
|
|
|
|
def mOptSaveGamesGeometry(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mOptDemoLogo(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
def mOptNegativeBottom(self, *event):
|
|
if self._cancelDrag():
|
|
return
|
|
self.app.updateCardset()
|
|
self.game.endGame(bookmark=1)
|
|
self.game.quitGame(bookmark=1)
|
|
|
|
#
|
|
# toolbar support
|
|
#
|
|
|
|
def setToolbarSize(self, size):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
dir = self.app.getToolbarImagesDir()
|
|
if self.app.toolbar.updateImages(dir, size):
|
|
self.game.updateStatus(player=self.app.opt.player)
|
|
|
|
def setToolbarStyle(self, style):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
dir = self.app.getToolbarImagesDir()
|
|
size = self.app.opt.toolbar_size
|
|
self.app.toolbar.updateImages(dir, size)
|
|
|
|
def setToolbarCompound(self, compound):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
if self.app.toolbar.setCompound(compound):
|
|
self.game.updateStatus(player=self.app.opt.player)
|
|
|
|
def setToolbarRelief(self, relief):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.app.toolbar.setRelief(relief)
|
|
|
|
def toolbarConfig(self, w, v):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
|
|
#
|
|
# other graphics
|
|
#
|
|
|
|
def setDemoLogoStyle(self, style=None):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
if self.tkopt.demo_logo_style.value == "none":
|
|
self.tkopt.demo_logo.value = False
|
|
else:
|
|
self.tkopt.demo_logo.value = True
|
|
self.app.loadImages2()
|
|
self.app.loadImages4()
|
|
|
|
def setDialogIconStyle(self, style):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.app.loadImages1()
|
|
self.app.loadImages4()
|
|
|
|
def setPauseTextStyle(self, style=None):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.app.loadImages2()
|
|
self.app.loadImages4()
|
|
if self.tkopt.pause.value:
|
|
self.app.game.displayPauseImage()
|
|
|
|
def setRedealIconStyle(self, style=None):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.app.loadImages2()
|
|
self.app.loadImages4()
|
|
try:
|
|
images = self.app.game.canvas.findImagesByType("redeal_image")
|
|
for i in images:
|
|
i.group.stack.updateRedealImage()
|
|
except: # noqa
|
|
pass
|
|
|
|
#
|
|
# stacks descriptions
|
|
#
|
|
|
|
def mStackDesk(self, *event):
|
|
if self.game.stackdesc_list:
|
|
self.game.deleteStackDesc()
|
|
else:
|
|
if self._cancelDrag(break_pause=True):
|
|
return
|
|
self.game.showStackDesc()
|
|
|
|
def wizardDialog(self, edit=False):
|
|
from pysollib.wizardutil import write_game, reset_wizard
|
|
from wizarddialog import WizardDialog
|
|
|
|
if edit:
|
|
reset_wizard(self.game)
|
|
else:
|
|
reset_wizard(None)
|
|
d = WizardDialog(self.top, _('Solitaire Wizard'), self.app)
|
|
if d.status == 0 and d.button == 0:
|
|
try:
|
|
if edit:
|
|
gameid = write_game(self.app, game=self.game)
|
|
else:
|
|
gameid = write_game(self.app)
|
|
except Exception:
|
|
return
|
|
if SELECT_GAME_MENU:
|
|
menu = self.__menupath[".menubar.select.customgames"][2]
|
|
|
|
def select_func(gi): return gi.si.game_type == GI.GT_CUSTOM
|
|
games = map(self.app.gdb.get,
|
|
self.app.gdb.getGamesIdSortedByName())
|
|
games = filter(select_func, games)
|
|
self.updateGamesMenu(menu, games)
|
|
|
|
self.tkopt.gameid.value = gameid
|
|
self._mSelectGame(gameid, force=True)
|
|
|
|
def mWizard(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.wizardDialog()
|
|
|
|
def mWizardEdit(self, *event):
|
|
if self._cancelDrag(break_pause=False):
|
|
return
|
|
self.wizardDialog(edit=True)
|
|
|
|
|
|
'''
|
|
'''
|