1#!/usr/bin/env python 2# -*- mode: python; coding: utf-8; -*- 3# ---------------------------------------------------------------------------# 4# 5# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer 6# Copyright (C) 2003 Mt. Hood Playing Card Co. 7# Copyright (C) 2005-2009 Skomoroh 8# Copyright (C) 2017 LB 9# 10# This program is free software: you can redistribute it and/or modify 11# it under the terms of the GNU General Public License as published by 12# the Free Software Foundation, either version 3 of the License, or 13# (at your option) any later version. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License 21# along with this program. If not, see <http://www.gnu.org/licenses/>. 22# 23# ---------------------------------------------------------------------------# 24 25import math 26import os 27import re 28 29from kivy.event import EventDispatcher 30from kivy.properties import BooleanProperty 31from kivy.properties import NumericProperty 32from kivy.properties import StringProperty 33 34from pysollib.gamedb import GI 35from pysollib.kivy.LApp import LMenu 36from pysollib.kivy.LApp import LMenuItem 37from pysollib.kivy.LApp import LScrollView 38from pysollib.kivy.LApp import LTopLevel 39from pysollib.kivy.LApp import LTreeNode 40from pysollib.kivy.LApp import LTreeRoot 41from pysollib.kivy.findcarddialog import destroy_find_card_dialog 42from pysollib.kivy.selectcardset import SelectCardsetDialogWithPreview 43from pysollib.kivy.selectgame import SelectGameDialog 44from pysollib.kivy.solverdialog import connect_game_solver_dialog 45from pysollib.kivy.tkconst import CURSOR_WATCH, EVENT_HANDLED, EVENT_PROPAGATE 46from pysollib.kivy.tkconst import TOOLBAR_BUTTONS 47from pysollib.kivy.tkutil import after_idle 48from pysollib.kivy.tkutil import bind 49from pysollib.mfxutil import Struct 50from pysollib.mygettext import _ 51from pysollib.pysoltk import MfxMessageDialog 52from pysollib.pysoltk import connect_game_find_card_dialog 53from pysollib.settings import SELECT_GAME_MENU 54from pysollib.settings import TITLE 55 56 57# ************************************************************************ 58# * tk emuls: 59# ************************************************************************ 60 61 62class TkVarObj(EventDispatcher): 63 def __init(self): 64 self.value = None 65 66 def set(self, v): 67 if v is None: 68 if type(self.value) is str: 69 v = '' 70 self.value = v 71 72 def get(self): 73 return self.value 74 75 76class BooleanVar(TkVarObj): 77 value = BooleanProperty(False) 78 79 80class IntVar(TkVarObj): 81 value = NumericProperty(0) 82 83 84class StringVar(TkVarObj): 85 value = StringProperty('') 86 87# ************************************************************************ 88# * Menu Dialogs 89# ************************************************************************ 90 91 92class LMenuDialog(object): 93 94 dialogCache = {} 95 96 def make_pop_command(self, parent, title): 97 def pop_command(event): 98 print('event = %s' % event) 99 parent.popWork(title) 100 return pop_command 101 102 def __init__(self, menubar, parent, title, app, **kw): 103 super(LMenuDialog, self).__init__() 104 105 self.menubar = menubar 106 self.parent = parent 107 self.app = app 108 self.title = title 109 self.window = None 110 self.running = False 111 self.persist = False 112 if 'persist' in kw: 113 self.persist = kw['persist'] 114 115 # prüfen ob noch aktiv - toggle. 116 117 if parent.workStack.peek(title) is not None: 118 parent.popWork(title) 119 return 120 121 if self.persist and title in self.dialogCache: 122 parent.pushWork(title, self.dialogCache[title]) 123 return 124 125 pc = self.closeWindow = self.make_pop_command(parent, title) 126 127 # neuen Dialog aufbauen. 128 129 window = LTopLevel(parent, title, **kw) 130 window.titleline.bind(on_press=pc) 131 self.parent.pushWork(title, window) 132 self.window = window 133 self.running = True 134 135 if self.persist: 136 self.dialogCache[title] = window 137 138 # Tree skelett. 139 140 tv = self.tvroot = LTreeRoot(root_options=dict(text='EditTree')) 141 tv.hide_root = True 142 tv.size_hint = 1, None 143 tv.bind(minimum_height=tv.setter('height')) 144 145 # menupunkte aufbauen. 146 147 self.buildTree(tv, None) 148 149 # tree in einem Scrollwindow präsentieren. 150 151 root = LScrollView(pos=(0, 0)) 152 root.add_widget(tv) 153 self.window.content.add_widget(root) 154 155 def buildTree(self, tree, node): 156 print('buildTree base') 157 # to implement in dervied class 158 pass 159 160# ************************************************************************ 161 162 163class MainMenuDialog(LMenuDialog): 164 165 def __init__(self, menubar, parent, title, app, **kw): 166 kw['size_hint'] = (0.2, 1) 167 kw['persist'] = True 168 super(MainMenuDialog, self).__init__( 169 menubar, parent, title, app, **kw) 170 171 def make_game_command(self, command): 172 def game_command(): 173 command() 174 self.closeWindow(0) 175 return game_command 176 177 def buildTree(self, tv, node): 178 rg = tv.add_node( 179 LTreeNode( 180 text=_("File"), 181 command=self.make_game_command(self.menubar.mFileMenuDialog))) 182 rg = tv.add_node( 183 LTreeNode( 184 text=_("Games"), 185 command=self.make_game_command( 186 self.menubar.mSelectGameDialog))) 187 rg = tv.add_node( 188 LTreeNode( 189 text=_("Tools"), 190 command=self.make_game_command(self.menubar.mEditMenuDialog))) 191 rg = tv.add_node( 192 LTreeNode( 193 text=_("Statistics"), 194 command=self.make_game_command(self.menubar.mGameMenuDialog))) 195 rg = tv.add_node( 196 LTreeNode( 197 text=_("Assist"), 198 command=self.make_game_command( 199 self.menubar.mAssistMenuDialog))) 200 rg = tv.add_node( 201 LTreeNode( 202 text=_("Options"), 203 command=self.make_game_command( 204 self.menubar.mOptionsMenuDialog))) 205 rg = tv.add_node( 206 LTreeNode( 207 text=_("Help"), 208 command=self.make_game_command(self.menubar.mHelpMenuDialog))) 209 del rg 210 211# ************************************************************************ 212 213 214class FileMenuDialog(LMenuDialog): 215 216 def __init__(self, menubar, parent, title, app, **kw): 217 kw['size_hint'] = (0.3, 1) 218 super(FileMenuDialog, self).__init__( 219 menubar, parent, title, app, **kw) 220 221 def make_game_command(self, key, command): 222 def game_command(): 223 command(key) 224 return game_command 225 226 def buildTree(self, tv, node): 227 rg = tv.add_node( 228 LTreeNode(text=_('Recent games'))) 229 # Recent Liste 230 recids = self.app.opt.recent_gameid 231 # recgames = [] 232 for rid in recids: 233 gi = self.app.getGameInfo(rid) 234 if gi: 235 command = self.make_game_command( 236 rid, self.menubar._mSelectGame) 237 tv.add_node( 238 LTreeNode(text=gi.name, command=command), rg) 239 240 rg = tv.add_node( 241 LTreeNode(text=_('Favorite games'))) 242 if rg: 243 tv.add_node(LTreeNode( 244 text=_('<Add>'), command=self.menubar.mAddFavor), rg) 245 tv.add_node(LTreeNode( 246 text=_('<Remove>'), command=self.menubar.mDelFavor), rg) 247 248 # Recent Liste 249 favids = self.app.opt.favorite_gameid 250 # favgames = [] 251 for fid in favids: 252 gi = self.app.getGameInfo(fid) 253 if gi: 254 command = self.make_game_command( 255 fid, self.menubar._mSelectGame) 256 tv.add_node( 257 LTreeNode(text=gi.name, command=command), rg) 258 259 tv.add_node(LTreeNode( 260 text=_('Load'), command=self.menubar.mOpen)) 261 tv.add_node(LTreeNode( 262 text=_('Save'), command=self.menubar.mSaveAs)) 263 264 tv.add_node(LTreeNode( 265 text=_('Quit'), command=self.menubar.mHoldAndQuit)) 266 267# ************************************************************************ 268 269 270class EditMenuDialog(LMenuDialog): # Tools 271 272 def __init__(self, menubar, parent, title, app, **kw): 273 kw['size_hint'] = (0.2, 1) 274 kw['persist'] = True 275 super(EditMenuDialog, self).__init__( 276 menubar, parent, title, app, **kw) 277 278 def make_auto_command(self, variable, command): 279 def auto_command(): 280 variable.set(not variable.get()) 281 command() 282 return auto_command 283 284 def addCheckNode(self, tv, rg, title, auto_var, auto_com): 285 command = self.make_auto_command(auto_var, auto_com) 286 rg1 = tv.add_node( 287 LTreeNode(text=title, command=command, variable=auto_var), rg) 288 return rg1 289 290 def buildTree(self, tv, node): 291 tv.add_node(LTreeNode( 292 text=_('New game'), command=self.menubar.mNewGame)) 293 tv.add_node(LTreeNode( 294 text=_('Restart game'), command=self.menubar.mRestart)) 295 296 tv.add_node(LTreeNode( 297 text=_('Undo'), command=self.menubar.mUndo)) 298 tv.add_node(LTreeNode( 299 text=_('Redo'), command=self.menubar.mRedo)) 300 tv.add_node(LTreeNode( 301 text=_('Redo all'), command=self.menubar.mRedoAll)) 302 303 tv.add_node(LTreeNode( 304 text=_('Auto drop'), command=self.menubar.mDrop)) 305 tv.add_node(LTreeNode( 306 text=_('Shuffle tiles'), command=self.menubar.mShuffle)) 307 tv.add_node(LTreeNode( 308 text=_('Deal cards'), command=self.menubar.mDeal)) 309 310 self.addCheckNode(tv, None, 311 _('Pause'), 312 self.menubar.tkopt.pause, 313 self.menubar.mPause) 314 315 tv.add_node(LTreeNode( 316 text=_('Load game'), command=self.menubar.mOpen)) 317 tv.add_node(LTreeNode( 318 text=_('Save game'), command=self.menubar.mSaveAs)) 319 320 tv.add_node(LTreeNode( 321 text=_('Help'), command=self.menubar.mHelpRules)) 322 323 # ------------------------------------------- 324 # TBD ? 325 ''' 326 menu.add_separator() 327 submenu = MfxMenu(menu, label=n_("&Set bookmark")) 328 for i in range(9): 329 label = _("Bookmark %d") % (i + 1) 330 submenu.add_command( 331 label=label, command=lambda i=i: self.mSetBookmark(i)) 332 submenu = MfxMenu(menu, label=n_("Go&to bookmark")) 333 for i in range(9): 334 label = _("Bookmark %d") % (i + 1) 335 acc = m + "%d" % (i + 1) 336 submenu.add_command( 337 label=label, 338 command=lambda i=i: self.mGotoBookmark(i), 339 accelerator=acc) 340 menu.add_command( 341 label=n_("&Clear bookmarks"), command=self.mClearBookmarks) 342 menu.add_separator() 343 ''' 344 # und solitär wizard (-> custom games). 345 ''' 346 tv.add_node(LTreeNode( 347 text='Solitaire &Wizard', command=self.menubar.mWizard)) 348 tv.add_node(LTreeNode( 349 text='Edit current game', command=self.menubar.mWizardEdit)) 350 ''' 351 352# ************************************************************************ 353 354 355class GameMenuDialog(LMenuDialog): 356 357 def __init__(self, menubar, parent, title, app, **kw): 358 kw['size_hint'] = (0.2, 1) 359 kw['persist'] = True 360 super(GameMenuDialog, self).__init__( 361 menubar, parent, title, app, **kw) 362 363 def make_command(self, key, command): 364 def stats_command(): 365 kw = {} 366 kw['mode'] = key 367 command(**kw) 368 return stats_command 369 370 def buildTree(self, tv, node): 371 tv.add_node(LTreeNode( 372 text=_('Current game...'), 373 command=self.make_command(101, self.menubar.mPlayerStats)), None) 374 375 # tv.add_node(LTreeNode( 376 # text='All games ...', 377 # command=self.make_command(102, self.menubar.mPlayerStats)), None) 378 379 # ------------------------------------------- 380 # TBD ? - just to remember original tk code. 381 ''' 382 menu.add_command( 383 label=n_("S&tatus..."), 384 command=lambda x: self.mPlayerStats(mode=100), accelerator=m+"Y") 385 menu.add_checkbutton( 386 label=n_("&Comments..."), variable=self.tkopt.comment, 387 command=self.mEditGameComment) 388 ''' 389 ''' 390 menu.add_separator() 391 submenu = MfxMenu(menu, label=n_("&Statistics")) 392 submenu.add_command( 393 label=n_("Current game..."), 394 command=lambda x: self.mPlayerStats(mode=101)) 395 submenu.add_command( 396 label=n_("All games..."), 397 command=lambda x: self.mPlayerStats(mode=102)) 398 submenu.add_separator() 399 submenu.add_command( 400 label=n_("Session log..."), 401 command=lambda x: self.mPlayerStats(mode=104)) 402 submenu.add_command( 403 label=n_("Full log..."), 404 command=lambda x: self.mPlayerStats(mode=103)) 405 submenu.add_separator() 406 submenu.add_command( 407 label=TOP_TITLE+"...", 408 command=lambda x: self.mPlayerStats(mode=105), 409 accelerator=m+"T") 410 submenu.add_command( 411 label=n_("Progression..."), 412 command=lambda x: self.mPlayerStats(mode=107)) 413 submenu = MfxMenu(menu, label=n_("D&emo statistics")) 414 submenu.add_command( 415 label=n_("Current game..."), 416 command=lambda x: self.mPlayerStats(mode=1101)) 417 submenu.add_command( 418 label=n_("All games..."), 419 command=lambda x: self.mPlayerStats(mode=1102)) 420 ''' 421 422# ************************************************************************ 423 424 425class AssistMenuDialog(LMenuDialog): 426 427 def __init__(self, menubar, parent, title, app, **kw): 428 kw['size_hint'] = (0.2, 1) 429 kw['persist'] = True 430 super(AssistMenuDialog, self).__init__( 431 menubar, parent, title, app, **kw) 432 433 def buildTree(self, tv, node): 434 tv.add_node(LTreeNode( 435 text=_('Hint'), command=self.menubar.mHint)) 436 437 tv.add_node(LTreeNode( 438 text=_('Highlight piles'), command=self.menubar.mHighlightPiles)) 439 440 # tv.add_node(LTreeNode( 441 # text='Find Card', command=self.menubar.mFindCard)) 442 443 tv.add_node(LTreeNode( 444 text=_('Demo'), command=self.menubar.mDemo)) 445 446 # ------------------------------------------- 447 # TBD. How ? 448 449 ''' 450 menu.add_command( 451 label=n_("Demo (&all games)"), command=self.mMixedDemo) 452 if USE_FREECELL_SOLVER: 453 menu.add_command(label=n_("&Solver"), command=self.mSolver) 454 else: 455 menu.add_command(label=n_("&Solver"), state='disabled') 456 menu.add_separator() 457 menu.add_command( 458 label=n_("&Piles description"), 459 command=self.mStackDesk, accelerator="F2") 460 ''' 461 462# ************************************************************************ 463 464 465class OptionsMenuDialog(LMenuDialog): 466 467 def __init__(self, menubar, parent, title, app, **kw): 468 kw['size_hint'] = (0.5, 1) 469 kw['persist'] = True 470 super(OptionsMenuDialog, self).__init__( 471 menubar, parent, title, app, **kw) 472 473 def make_auto_command(self, variable, command): 474 def auto_command(): 475 variable.set(not variable.get()) 476 command() 477 return auto_command 478 479 def addCheckNode(self, tv, rg, title, auto_var, auto_com): 480 command = self.make_auto_command(auto_var, auto_com) 481 rg1 = tv.add_node( 482 LTreeNode(text=title, command=command, variable=auto_var), rg) 483 return rg1 484 485 def make_val_command(self, variable, value, command): 486 def val_command(): 487 variable.set(value) 488 command() 489 return val_command 490 491 def make_vars_command(self, command, key): 492 def vars_command(): 493 command(key) 494 return vars_command 495 496 def addRadioNode(self, tv, rg, title, auto_var, auto_val, auto_com): 497 command = self.make_val_command(auto_var, auto_val, auto_com) 498 rg1 = tv.add_node( 499 LTreeNode(text=title, 500 command=command, 501 variable=auto_var, value=auto_val), rg) 502 return rg1 503 504 def buildTree(self, tv, node): 505 506 # ------------------------------------------- 507 # Automatic play settings 508 509 rg = tv.add_node( 510 LTreeNode(text=_('Automatic play'))) 511 if rg: 512 self.addCheckNode(tv, rg, 513 _('Auto face up'), 514 self.menubar.tkopt.autofaceup, 515 self.menubar.mOptAutoFaceUp) 516 517 self.addCheckNode(tv, rg, 518 _('Auto drop'), 519 self.menubar.tkopt.autodrop, 520 self.menubar.mOptAutoDrop) 521 522 self.addCheckNode(tv, rg, 523 _('Auto deal'), 524 self.menubar.tkopt.autodeal, 525 self.menubar.mOptAutoDeal) 526 527 # submenu.add_separator() 528 529 self.addCheckNode(tv, rg, 530 _('Quick play'), 531 self.menubar.tkopt.quickplay, 532 self.menubar.mOptQuickPlay) 533 534 # ------------------------------------------- 535 # Player assistance 536 537 rg = tv.add_node( 538 LTreeNode(text=_('Assist level'))) 539 if rg: 540 self.addCheckNode(tv, rg, 541 _('Enable undo'), 542 self.menubar.tkopt.undo, 543 self.menubar.mOptEnableUndo) 544 545 self.addCheckNode(tv, rg, 546 _('Enable bookmarks'), 547 self.menubar.tkopt.bookmarks, 548 self.menubar.mOptEnableBookmarks) 549 550 self.addCheckNode(tv, rg, 551 _('Enable hint'), 552 self.menubar.tkopt.hint, 553 self.menubar.mOptEnableHint) 554 555 self.addCheckNode(tv, rg, 556 _('Enable shuffle'), 557 self.menubar.tkopt.shuffle, 558 self.menubar.mOptEnableShuffle) 559 560 self.addCheckNode(tv, rg, 561 _('Enable highlight piles'), 562 self.menubar.tkopt.highlight_piles, 563 self.menubar.mOptEnableHighlightPiles) 564 565 self.addCheckNode(tv, rg, 566 _('Enable highlight cards'), 567 self.menubar.tkopt.highlight_cards, 568 self.menubar.mOptEnableHighlightCards) 569 570 self.addCheckNode(tv, rg, 571 _('Enable highlight same rank'), 572 self.menubar.tkopt.highlight_samerank, 573 self.menubar.mOptEnableHighlightSameRank) 574 575 self.addCheckNode(tv, rg, 576 _('Highlight no matching'), 577 self.menubar.tkopt.highlight_not_matching, 578 self.menubar.mOptEnableHighlightNotMatching) 579 580 # submenu.add_separator() 581 582 self.addCheckNode(tv, rg, 583 _('Show removed tiles (in Mahjongg games)'), 584 self.menubar.tkopt.mahjongg_show_removed, 585 self.menubar.mOptMahjonggShowRemoved) 586 587 self.addCheckNode(tv, rg, 588 _('Show hint arrow (in Shisen-Sho games)'), 589 self.menubar.tkopt.shisen_show_hint, 590 self.menubar.mOptShisenShowHint) 591 592 self.addCheckNode(tv, rg, 593 _('Deal all cards (in Accordion type games)'), 594 self.menubar.tkopt.accordion_deal_all, 595 self.menubar.mOptAccordionDealAll) 596 597 # submenu.add_separator() 598 599 # ------------------------------------------- 600 # Language options 601 602 rg = tv.add_node( 603 LTreeNode(text=_('Language'))) 604 if rg: 605 self.addRadioNode(tv, rg, 606 _('Default'), 607 self.menubar.tkopt.language, '', 608 self.menubar.mOptLanguage) 609 self.addRadioNode(tv, rg, 610 _('English'), 611 self.menubar.tkopt.language, 'en', 612 self.menubar.mOptLanguage) 613 self.addRadioNode(tv, rg, 614 _('German'), 615 self.menubar.tkopt.language, 'de', 616 self.menubar.mOptLanguage) 617 self.addRadioNode(tv, rg, 618 _('Italian'), 619 self.menubar.tkopt.language, 'it', 620 self.menubar.mOptLanguage) 621 self.addRadioNode(tv, rg, 622 _('Polish'), 623 self.menubar.tkopt.language, 'pl', 624 self.menubar.mOptLanguage) 625 self.addRadioNode(tv, rg, 626 _('Russian'), 627 self.menubar.tkopt.language, 'ru', 628 self.menubar.mOptLanguage) 629 630 # ------------------------------------------- 631 # Sound options 632 633 rg = tv.add_node( 634 LTreeNode(text=_('Sound'))) 635 if rg: 636 self.addCheckNode(tv, rg, 637 _('Enable'), 638 self.menubar.tkopt.sound, 639 self.menubar.mOptSoundDialog) 640 641 rg1 = tv.add_node( 642 LTreeNode(text=_('Volume')), rg) 643 if rg1: 644 self.addRadioNode(tv, rg1, 645 _('100%'), 646 self.menubar.tkopt.sound_sample_volume, 100, 647 self.menubar.mOptSoundSampleVol) 648 self.addRadioNode(tv, rg1, 649 _('75%'), 650 self.menubar.tkopt.sound_sample_volume, 75, 651 self.menubar.mOptSoundSampleVol) 652 self.addRadioNode(tv, rg1, 653 _('50%'), 654 self.menubar.tkopt.sound_sample_volume, 50, 655 self.menubar.mOptSoundSampleVol) 656 self.addRadioNode(tv, rg1, 657 _('25%'), 658 self.menubar.tkopt.sound_sample_volume, 25, 659 self.menubar.mOptSoundSampleVol) 660 661 rg1 = tv.add_node( 662 LTreeNode(text=_('Samples')), rg) 663 if rg1: 664 key = 'areyousure' 665 self.addCheckNode( 666 tv, rg1, 667 _('are you sure'), 668 self.menubar.tkopt.sound_sample_vars[key], 669 self.make_vars_command(self.menubar.mOptSoundSample, key)) 670 key = 'autodrop' 671 self.addCheckNode( 672 tv, rg1, 673 _('auto drop'), 674 self.menubar.tkopt.sound_sample_vars[key], 675 self.make_vars_command(self.menubar.mOptSoundSample, key)) 676 key = 'autoflip' 677 self.addCheckNode( 678 tv, rg1, 679 _('auto flip'), 680 self.menubar.tkopt.sound_sample_vars[key], 681 self.make_vars_command(self.menubar.mOptSoundSample, key)) 682 key = 'autopilotlost' 683 self.addCheckNode( 684 tv, rg1, 685 _('auto pilot lost'), 686 self.menubar.tkopt.sound_sample_vars[key], 687 self.make_vars_command(self.menubar.mOptSoundSample, key)) 688 key = 'autopilotwon' 689 self.addCheckNode( 690 tv, rg1, 691 _('auto pilot won'), 692 self.menubar.tkopt.sound_sample_vars[key], 693 self.make_vars_command(self.menubar.mOptSoundSample, key)) 694 key = 'deal' 695 self.addCheckNode( 696 tv, rg1, 697 _('deal'), 698 self.menubar.tkopt.sound_sample_vars[key], 699 self.make_vars_command(self.menubar.mOptSoundSample, key)) 700 key = 'dealwaste' 701 self.addCheckNode( 702 tv, rg1, 703 _('deal waste'), 704 self.menubar.tkopt.sound_sample_vars[key], 705 self.make_vars_command(self.menubar.mOptSoundSample, key)) 706 key = 'droppair' 707 self.addCheckNode( 708 tv, rg1, 709 _('drop pair'), 710 self.menubar.tkopt.sound_sample_vars[key], 711 self.make_vars_command(self.menubar.mOptSoundSample, key)) 712 key = 'drop' 713 self.addCheckNode( 714 tv, rg1, 715 _('drop'), 716 self.menubar.tkopt.sound_sample_vars[key], 717 self.make_vars_command(self.menubar.mOptSoundSample, key)) 718 key = 'flip' 719 self.addCheckNode( 720 tv, rg1, 721 _('flip'), 722 self.menubar.tkopt.sound_sample_vars[key], 723 self.make_vars_command(self.menubar.mOptSoundSample, key)) 724 key = 'move' 725 self.addCheckNode( 726 tv, rg1, 727 _('move'), 728 self.menubar.tkopt.sound_sample_vars[key], 729 self.make_vars_command(self.menubar.mOptSoundSample, key)) 730 key = 'nomove' 731 self.addCheckNode( 732 tv, rg1, 733 _('no move'), 734 self.menubar.tkopt.sound_sample_vars[key], 735 self.make_vars_command(self.menubar.mOptSoundSample, key)) 736 key = 'redo' 737 self.addCheckNode( 738 tv, rg1, 739 _('redo'), 740 self.menubar.tkopt.sound_sample_vars[key], 741 self.make_vars_command(self.menubar.mOptSoundSample, key)) 742 key = 'startdrag' 743 self.addCheckNode( 744 tv, rg1, 745 _('start drag'), 746 self.menubar.tkopt.sound_sample_vars[key], 747 self.make_vars_command(self.menubar.mOptSoundSample, key)) 748 key = 'turnwaste' 749 self.addCheckNode( 750 tv, rg1, 751 _('turn waste'), 752 self.menubar.tkopt.sound_sample_vars[key], 753 self.make_vars_command(self.menubar.mOptSoundSample, key)) 754 key = 'undo' 755 self.addCheckNode( 756 tv, rg1, 757 _('undo'), 758 self.menubar.tkopt.sound_sample_vars[key], 759 self.make_vars_command(self.menubar.mOptSoundSample, key)) 760 key = 'gamefinished' 761 self.addCheckNode( 762 tv, rg1, 763 _('game finished'), 764 self.menubar.tkopt.sound_sample_vars[key], 765 self.make_vars_command(self.menubar.mOptSoundSample, key)) 766 key = 'gamelost' 767 self.addCheckNode( 768 tv, rg1, 769 _('game lost'), 770 self.menubar.tkopt.sound_sample_vars[key], 771 self.make_vars_command(self.menubar.mOptSoundSample, key)) 772 key = 'gameperfect' 773 self.addCheckNode( 774 tv, rg1, 775 _('game perfect'), 776 self.menubar.tkopt.sound_sample_vars[key], 777 self.make_vars_command(self.menubar.mOptSoundSample, key)) 778 key = 'gamewon' 779 self.addCheckNode( 780 tv, rg1, 781 _('game won'), 782 self.menubar.tkopt.sound_sample_vars[key], 783 self.make_vars_command(self.menubar.mOptSoundSample, key)) 784 key = 'extra' 785 self.addCheckNode( 786 tv, rg1, 787 _('Other'), 788 self.menubar.tkopt.sound_sample_vars[key], 789 self.make_vars_command(self.menubar.mOptSoundSample, key)) 790 791 # ------------------------------------------- 792 # Cardsets and card backside options 793 794 rg = tv.add_node( 795 LTreeNode(text=_('Cardsets'))) 796 if rg: 797 self.menubar.tkopt.cardset.set(self.app.cardset.index) 798 799 csm = self.app.cardset_manager 800 # cnt = csm.len() 801 i = 0 802 while 1: 803 cs = csm.get(i) 804 if cs is None: 805 break 806 rg1 = self.addRadioNode(tv, rg, 807 cs.name, 808 self.menubar.tkopt.cardset, i, 809 self.menubar.mOptCardset) 810 if rg1: 811 cbs = cs.backnames 812 self.menubar.tkopt.cardbacks[i] = IntVar() 813 self.menubar.tkopt.cardbacks[i].set(cs.backindex) 814 815 bcnt = len(cbs) 816 bi = 0 817 while 1: 818 if bi == bcnt: 819 break 820 cb = cbs[bi] 821 self.addRadioNode( 822 tv, rg1, 823 cb, 824 self.menubar.tkopt.cardbacks[i], bi, 825 self.make_vars_command( 826 self.menubar.mOptSetCardback, i)) 827 bi += 1 828 829 i += 1 830 831 # ------------------------------------------- 832 # Table background settings 833 834 rg = tv.add_node( 835 LTreeNode(text=_('Table'))) 836 if rg: 837 rg1 = tv.add_node( 838 LTreeNode(text=_('Solid colors')), rg) 839 if rg1: 840 key = 'table' 841 self.addRadioNode( 842 tv, rg1, 843 _('Blue'), 844 self.menubar.tkopt.color_vars[key], '#0082df', 845 self.menubar.mOptTableColor) 846 self.addRadioNode( 847 tv, rg1, 848 _('Green'), 849 self.menubar.tkopt.color_vars[key], '#008200', 850 self.menubar.mOptTableColor) 851 self.addRadioNode( 852 tv, rg1, 853 _('Navy'), 854 self.menubar.tkopt.color_vars[key], '#000086', 855 self.menubar.mOptTableColor) 856 self.addRadioNode( 857 tv, rg1, 858 _('Olive'), 859 self.menubar.tkopt.color_vars[key], '#868200', 860 self.menubar.mOptTableColor) 861 self.addRadioNode( 862 tv, rg1, 863 _('Orange'), 864 self.menubar.tkopt.color_vars[key], '#f79600', 865 self.menubar.mOptTableColor) 866 self.addRadioNode( 867 tv, rg1, 868 _('Teal'), 869 self.menubar.tkopt.color_vars[key], '#008286', 870 self.menubar.mOptTableColor) 871 872 rg1 = tv.add_node( 873 LTreeNode(text=_('Textures')), rg) 874 rg2 = tv.add_node( 875 LTreeNode(text=_('Images')), rg) 876 877 if rg1 or rg2: 878 tm = self.app.tabletile_manager 879 # cnt = tm.len() 880 i = 1 881 while True: 882 ti = tm.get(i) 883 884 if ti is None: 885 break 886 if ti.save_aspect == 0 and ti.stretch == 0 and rg1: 887 self.addRadioNode(tv, rg1, 888 ti.name, 889 self.menubar.tkopt.tabletile, i, 890 self.menubar.mOptTileSet) 891 if (ti.save_aspect == 1 or ti.stretch == 1) and rg2: 892 self.addRadioNode(tv, rg2, 893 ti.name, 894 self.menubar.tkopt.tabletile, i, 895 self.menubar.mOptTileSet) 896 i += 1 897 898 # ------------------------------------------- 899 # Card view options 900 901 rg = tv.add_node( 902 LTreeNode(text=_('Card view'))) 903 if rg: 904 self.addCheckNode(tv, rg, 905 _('Card shadow'), 906 self.menubar.tkopt.shadow, 907 self.menubar.mOptShadow) 908 909 self.addCheckNode(tv, rg, 910 _('Shade legal moves'), 911 self.menubar.tkopt.shade, 912 self.menubar.mOptShade) 913 914 self.addCheckNode(tv, rg, 915 _('Negative cards bottom'), 916 self.menubar.tkopt.negative_bottom, 917 self.menubar.mOptNegativeBottom) 918 919 self.addCheckNode(tv, rg, 920 _('Shrink face-down cards'), 921 self.menubar.tkopt.shrink_face_down, 922 self.menubar.mOptShrinkFaceDown) 923 924 self.addCheckNode(tv, rg, 925 _('Shade filled stacks'), 926 self.menubar.tkopt.shade_filled_stacks, 927 self.menubar.mOptShadeFilledStacks) 928 929 # ------------------------------------------- 930 # Animation settins 931 932 rg = tv.add_node( 933 LTreeNode(text=_('Animations'))) 934 if rg: 935 self.addRadioNode(tv, rg, 936 _('None'), 937 self.menubar.tkopt.animations, 0, 938 self.menubar.mOptAnimations) 939 940 self.addRadioNode(tv, rg, 941 _('Very fast'), 942 self.menubar.tkopt.animations, 1, 943 self.menubar.mOptAnimations) 944 945 self.addRadioNode(tv, rg, 946 _('Fast'), 947 self.menubar.tkopt.animations, 2, 948 self.menubar.mOptAnimations) 949 950 self.addRadioNode(tv, rg, 951 _('Medium'), 952 self.menubar.tkopt.animations, 3, 953 self.menubar.mOptAnimations) 954 955 self.addRadioNode(tv, rg, 956 _('Slow'), 957 self.menubar.tkopt.animations, 4, 958 self.menubar.mOptAnimations) 959 960 self.addRadioNode(tv, rg, 961 _('Very slow'), 962 self.menubar.tkopt.animations, 5, 963 self.menubar.mOptAnimations) 964 965 # submenu.add_separator() 966 967 self.addCheckNode(tv, rg, 968 _('Redeal animation'), 969 self.menubar.tkopt.redeal_animation, 970 self.menubar.mRedealAnimation) 971 972 self.addCheckNode(tv, rg, 973 _('Winning animation'), 974 self.menubar.tkopt.win_animation, 975 self.menubar.mWinAnimation) 976 977 # ------------------------------------------- 978 # Touch mode settings 979 980 rg = tv.add_node( 981 LTreeNode(text=_('Touch mode'))) 982 if rg: 983 self.addRadioNode(tv, rg, 984 _('Drag-and-Drop'), 985 self.menubar.tkopt.mouse_type, 'drag-n-drop', 986 self.menubar.mOptMouseType) 987 988 self.addRadioNode(tv, rg, 989 _('Point-and-Click'), 990 self.menubar.tkopt.mouse_type, 'point-n-click', 991 self.menubar.mOptMouseType) 992 993 # sinnlos mit touch-device: 994 # self.addRadioNode(tv, rg, 995 # 'Sticky mouse', 996 # self.menubar.tkopt.mouse_type, u'sticky-mouse', 997 # self.menubar.mOptMouseType) 998 999 # submenu.add_separator() 1000 1001 # sinnlos mit touch-device: 1002 # self.addCheckNode(tv, rg, 1003 # 'Use mouse for undo/redo', 1004 # self.menubar.tkopt.mouse_undo, 1005 # self.menubar.mOptMouseUndo) 1006 1007 # submenu.add_separator() 1008 1009 # ------------------------------------------- 1010 # TBD ? 1011 1012 ''' 1013 menu.add_command(label=n_("&Fonts..."), command=self.mOptFonts) 1014 menu.add_command(label=n_("&Colors..."), command=self.mOptColors) 1015 menu.add_command(label=n_("Time&outs..."), command=self.mOptTimeouts) 1016 menu.add_separator() 1017 ''' 1018 1019 # ------------------------------------------- 1020 # Toolbar options 1021 1022 rg = tv.add_node( 1023 LTreeNode(text=_('Toolbar'))) 1024 if rg: 1025 self.addRadioNode(tv, rg, 1026 _('Hide'), 1027 self.menubar.tkopt.toolbar, 0, 1028 self.menubar.mOptToolbar) 1029 1030 # not supported: Top, Bottom 1031 # self.addRadioNode(tv, rg, 1032 # 'Top', 1033 # self.menubar.tkopt.toolbar, 1, 1034 # self.menubar.mOptToolbar) 1035 # self.addRadioNode(tv, rg, 1036 # 'Bottom', 1037 # self.menubar.tkopt.toolbar, 2, 1038 # self.menubar.mOptToolbar) 1039 1040 self.addRadioNode(tv, rg, 1041 _('Left'), 1042 self.menubar.tkopt.toolbar, 3, 1043 self.menubar.mOptToolbar) 1044 self.addRadioNode(tv, rg, 1045 _('Right'), 1046 self.menubar.tkopt.toolbar, 4, 1047 self.menubar.mOptToolbar) 1048 1049 # ------------------------------------------- 1050 # Statusbar - not implemented 1051 1052 ''' 1053 submenu = MfxMenu(menu, label=n_("Stat&usbar")) 1054 submenu.add_checkbutton( 1055 label=n_("Show &statusbar"), 1056 variable=self.tkopt.statusbar, 1057 command=self.mOptStatusbar) 1058 submenu.add_checkbutton( 1059 label=n_("Show &number of cards"), 1060 variable=self.tkopt.num_cards, 1061 command=self.mOptNumCards) 1062 submenu.add_checkbutton( 1063 label=n_("Show &help bar"), 1064 variable=self.tkopt.helpbar, 1065 command=self.mOptHelpbar) 1066 ''' 1067 1068 # ------------------------------------------- 1069 # general options 1070 1071 # self.addCheckNode(tv, None, 1072 # 'Save games geometry', 1073 # self.menubar.tkopt.save_games_geometry, 1074 # self.menubar.mOptSaveGamesGeometry) 1075 1076 # self.addCheckNode(tv, None, 1077 # 'Demo logo', 1078 # self.menubar.tkopt.demo_logo, 1079 # self.menubar.mOptDemoLogo) 1080 1081 self.addCheckNode(tv, None, 1082 _('Startup splash screen'), 1083 self.menubar.tkopt.splashscreen, 1084 self.menubar.mOptSplashscreen) 1085 1086 self.addCheckNode(tv, None, 1087 _('Winning splash'), 1088 self.menubar.tkopt.display_win_message, 1089 self.menubar.mWinDialog) 1090 1091 1092# ************************************************************************ 1093 1094 1095class HelpMenuDialog(LMenuDialog): 1096 def __init__(self, menubar, parent, title, app, **kw): 1097 kw['size_hint'] = (0.3, 1) 1098 kw['persist'] = True 1099 super(HelpMenuDialog, self).__init__(menubar, parent, title, app, **kw) 1100 1101 def make_help_command(self, command): 1102 def help_command(): 1103 command() 1104 self.closeWindow(0) 1105 return help_command 1106 1107 def buildTree(self, tv, node): 1108 tv.add_node( 1109 LTreeNode( 1110 text=_('Contents'), 1111 command=self.make_help_command(self.menubar.mHelp))) 1112 tv.add_node( 1113 LTreeNode( 1114 text=_('How to use PySol'), 1115 command=self.make_help_command(self.menubar.mHelpHowToPlay))) 1116 tv.add_node( 1117 LTreeNode( 1118 text=_('Rules for this game'), 1119 command=self.make_help_command(self.menubar.mHelpRules))) 1120 tv.add_node( 1121 LTreeNode( 1122 text=_('License terms'), 1123 command=self.make_help_command(self.menubar.mHelpLicense))) 1124 tv.add_node( 1125 LTreeNode( 1126 text=_('About %s...') % TITLE, 1127 command=self.make_help_command(self.menubar.mHelpAbout))) 1128 1129 # tv.add_node(LTreeNode( 1130 # text='AboutKivy ...', 1131 # command=self.makeHtmlCommand(self.menubar, "kivy.html"))) 1132 1133 def makeHtmlCommand(self, bar, htmlfile): 1134 def htmlCommand(): 1135 bar.mHelpHtml(htmlfile) 1136 1137 return htmlCommand 1138 1139 1140# ************************************************************************ 1141# * 1142# ************************************************************************ 1143 1144 1145class EmulTkMenu(object): 1146 1147 def __init__(self, master, **kw): 1148 1149 self.name = kw["name"] 1150 self.n = 0 1151 self._w = None 1152 if (self.name): 1153 if master._w == '.': 1154 self._w = '.' + self.name 1155 else: 1156 self._w = master._w + '.' + self.name 1157 else: 1158 self.name = "<>" 1159 1160 def labeltoname(self, label): 1161 name = re.sub(r"[^0-9a-zA-Z]", "", label).lower() 1162 label = _(label) 1163 underline = label.find('&') 1164 if underline >= 0: 1165 label = label.replace('&', '') 1166 return name, label, underline 1167 1168 def add_cascade(self, cnf={}, **kw): 1169 self.add('cascade', cnf or kw) 1170 pass 1171 1172 def add(self, itemType, cnf={}): 1173 label = cnf.get("label") 1174 if label: 1175 name = cnf.get('name') 1176 if name: 1177 name, label, underline = self.labeltoname(label) 1178 cnf["underline"] = cnf.get("underline", underline) 1179 cnf["label"] = label 1180 if name and self.addPath: 1181 path = str(self._w) + "." + name 1182 self.addPath(path, self, self.n, cnf.get("menu")) 1183 1184 def cget(self, key): 1185 return key 1186 1187# ************************************************************************ 1188 1189 1190class MfxMenubar(EmulTkMenu): 1191 addPath = None 1192 1193 def __init__(self, master, **kw): 1194 super(MfxMenubar, self).__init__(master, **kw) 1195 topmenu = self.name == 'menubar' 1196 1197 self.menu = LMenu(not topmenu, text=self.name) 1198 if topmenu: 1199 master.setMenu(self.menu) 1200 1201# ************************************************************************ 1202# * - create menubar 1203# * - update menubar 1204# * - menu actions 1205# ************************************************************************ 1206 1207 1208class PysolMenubarTk: 1209 def __init__(self, app, top, progress=None): 1210 self._createTkOpt() 1211 self._setOptions() 1212 # init columnbreak 1213# self.__cb_max = int(self.top.winfo_screenheight()/23) 1214 self.__cb_max = 8 1215# sh = self.top.winfo_screenheight() 1216# self.__cb_max = 22 1217# if sh >= 600: self.__cb_max = 27 1218# if sh >= 768: self.__cb_max = 32 1219# if sh >= 1024: self.__cb_max = 40 1220 self.progress = progress 1221 # create menus 1222 self.__menubar = None 1223 self.__menupath = {} 1224 self.__keybindings = {} 1225 self._createMenubar() 1226 self.top = top 1227 1228 if self.progress: 1229 self.progress.update(step=1) 1230 1231 # set the menubar 1232 # self.updateBackgroundImagesMenu() 1233 # self.top.config(menu=self.__menubar) 1234 1235 def _createTkOpt(self): 1236 # structure to convert menu-options to Toolkit variables 1237 self.tkopt = Struct( 1238 gameid=IntVar(), 1239 gameid_popular=IntVar(), 1240 comment=BooleanVar(), 1241 autofaceup=BooleanVar(), 1242 autodrop=BooleanVar(), 1243 autodeal=BooleanVar(), 1244 quickplay=BooleanVar(), 1245 undo=BooleanVar(), 1246 bookmarks=BooleanVar(), 1247 hint=BooleanVar(), 1248 shuffle=BooleanVar(), 1249 highlight_piles=BooleanVar(), 1250 highlight_cards=BooleanVar(), 1251 highlight_samerank=BooleanVar(), 1252 highlight_not_matching=BooleanVar(), 1253 mahjongg_show_removed=BooleanVar(), 1254 shisen_show_hint=BooleanVar(), 1255 accordion_deal_all=BooleanVar(), 1256 sound=BooleanVar(), 1257 sound_sample_volume=IntVar(), 1258 sound_music_volume=IntVar(), 1259 cardback=IntVar(), 1260 tabletile=IntVar(), 1261 animations=IntVar(), 1262 redeal_animation=BooleanVar(), 1263 win_animation=BooleanVar(), 1264 shadow=BooleanVar(), 1265 shade=BooleanVar(), 1266 shade_filled_stacks=BooleanVar(), 1267 shrink_face_down=BooleanVar(), 1268 toolbar=IntVar(), 1269 toolbar_style=StringVar(), 1270 toolbar_relief=StringVar(), 1271 toolbar_compound=StringVar(), 1272 toolbar_size=IntVar(), 1273 statusbar=BooleanVar(), 1274 num_cards=BooleanVar(), 1275 helpbar=BooleanVar(), 1276 save_games_geometry=BooleanVar(), 1277 splashscreen=BooleanVar(), 1278 demo_logo=BooleanVar(), 1279 mouse_type=StringVar(), 1280 mouse_undo=BooleanVar(), 1281 negative_bottom=BooleanVar(), 1282 display_win_message=BooleanVar(), 1283 pause=BooleanVar(), 1284 cardset=IntVar(), 1285 cardbacks={}, 1286 toolbar_vars={}, 1287 sound_sample_vars={}, 1288 color_vars={}, 1289 language=StringVar(), 1290 ) 1291 for w in TOOLBAR_BUTTONS: 1292 self.tkopt.toolbar_vars[w] = BooleanVar() 1293 for k in self.app.opt.sound_samples: 1294 self.tkopt.sound_sample_vars[k] = BooleanVar() 1295 for k in self.app.opt.colors: 1296 self.tkopt.color_vars[k] = StringVar() 1297 1298 def _setOptions(self): 1299 tkopt, opt = self.tkopt, self.app.opt 1300 # set state of the menu items 1301 tkopt.autofaceup.set(opt.autofaceup) 1302 tkopt.autodrop.set(opt.autodrop) 1303 tkopt.autodeal.set(opt.autodeal) 1304 tkopt.quickplay.set(opt.quickplay) 1305 tkopt.undo.set(opt.undo) 1306 tkopt.hint.set(opt.hint) 1307 tkopt.shuffle.set(opt.shuffle) 1308 tkopt.bookmarks.set(opt.bookmarks) 1309 tkopt.highlight_piles.set(opt.highlight_piles) 1310 tkopt.highlight_cards.set(opt.highlight_cards) 1311 tkopt.highlight_samerank.set(opt.highlight_samerank) 1312 tkopt.highlight_not_matching.set(opt.highlight_not_matching) 1313 tkopt.shrink_face_down.set(opt.shrink_face_down) 1314 tkopt.shade_filled_stacks.set(opt.shade_filled_stacks) 1315 tkopt.mahjongg_show_removed.set(opt.mahjongg_show_removed) 1316 tkopt.shisen_show_hint.set(opt.shisen_show_hint) 1317 tkopt.accordion_deal_all.set(opt.accordion_deal_all) 1318 tkopt.sound.set(opt.sound) 1319 tkopt.sound_sample_volume.set(opt.sound_sample_volume) 1320 tkopt.sound_music_volume.set(opt.sound_music_volume) 1321 tkopt.cardback.set(self.app.cardset.backindex) 1322 tkopt.tabletile.set(self.app.tabletile_index) 1323 tkopt.animations.set(opt.animations) 1324 tkopt.redeal_animation.set(opt.redeal_animation) 1325 tkopt.win_animation.set(opt.win_animation) 1326 tkopt.shadow.set(opt.shadow) 1327 tkopt.shade.set(opt.shade) 1328 tkopt.toolbar.set(opt.toolbar) 1329 tkopt.toolbar_style.set(opt.toolbar_style) 1330 tkopt.toolbar_relief.set(opt.toolbar_relief) 1331 tkopt.toolbar_compound.set(opt.toolbar_compound) 1332 tkopt.toolbar_size.set(opt.toolbar_size) 1333 tkopt.toolbar_relief.set(opt.toolbar_relief) 1334 tkopt.statusbar.set(opt.statusbar) 1335 tkopt.num_cards.set(opt.num_cards) 1336 tkopt.helpbar.set(opt.helpbar) 1337 tkopt.save_games_geometry.set(opt.save_games_geometry) 1338 tkopt.demo_logo.set(opt.demo_logo) 1339 tkopt.splashscreen.set(opt.splashscreen) 1340 tkopt.mouse_type.set(opt.mouse_type) 1341 tkopt.mouse_undo.set(opt.mouse_undo) 1342 tkopt.negative_bottom.set(opt.negative_bottom) 1343 tkopt.display_win_message.set(opt.display_win_message) 1344 tkopt.cardset.set(self.app.cardset_manager.getSelected()) 1345 tkopt.language.set(opt.language) 1346 1347 for w in TOOLBAR_BUTTONS: 1348 tkopt.toolbar_vars[w].set(opt.toolbar_vars.get(w, False)) 1349 for k in self.app.opt.sound_samples: 1350 self.tkopt.sound_sample_vars[k].set( 1351 opt.sound_samples.get(k, False)) 1352 for k in self.app.opt.colors: 1353 self.tkopt.color_vars[k].set(opt.colors.get(k, '#000000')) 1354 1355 def connectGame(self, game): 1356 self.game = game 1357 if game is None: 1358 return 1359 assert self.app is game.app 1360 tkopt = self.tkopt 1361 # opt = self.app.opt 1362 tkopt.gameid.set(game.id) 1363 tkopt.gameid_popular.set(game.id) 1364 tkopt.comment.set(bool(game.gsaveinfo.comment)) 1365 tkopt.pause.set(self.game.pause) 1366 if game.canFindCard(): 1367 connect_game_find_card_dialog(game) 1368 else: 1369 destroy_find_card_dialog() 1370 connect_game_solver_dialog(game) 1371 1372 # create a GTK-like path 1373 def _addPath(self, path, menu, index, submenu): 1374 # print ('MfxMenubar: _addPath %s, %s' % (path, menu)) 1375 # y = self.yy 1376 if path not in self.__menupath: 1377 # print path, menu, index, submenu 1378 self.__menupath[path] = (menu, index, submenu) 1379 1380 def _getEnabledState(self, enabled): 1381 print('_getEnabledState: %s' % enabled) 1382 if enabled: 1383 return "normal" 1384 return "disabled" 1385 1386 def updateProgress(self): 1387 if self.progress: 1388 self.progress.update(step=1) 1389 1390 # 1391 # create the menubar 1392 # 1393 1394 def _createMenubar(self): 1395 MfxMenubar.addPath = self._addPath 1396 kw = {"name": "menubar"} 1397 self.__menubar = MfxMenubar(self.top, **kw) 1398 1399 # init keybindings 1400 bind(self.top, "<KeyPress>", self._keyPressHandler) 1401 1402 # LMainMenuDialog() 1403 LMenuItem(self.__menubar.menu, 1404 text=_("Menu"), command=self.mMainMenuDialog) 1405 1406 MfxMenubar.addPath = None 1407 1408 # 1409 # key binding utility 1410 # 1411 1412 def _bindKey(self, modifier, key, func): 1413 # if 0 and not modifier and len(key) == 1: 1414 # self.__keybindings[key.lower()] = func 1415 # self.__keybindings[key.upper()] = func 1416 # return 1417 if not modifier and len(key) == 1: 1418 # ignore Ctrl/Shift/Alt 1419 # but don't ignore NumLock (state == 16) 1420 def lfunc(e, func=func): 1421 return e.state in (0, 16) and func(e) 1422 func = lfunc 1423 # func = lambda e, func=func: e.state in (0, 16) and func(e) 1424 sequence = "<" + modifier + "KeyPress-" + key + ">" 1425 bind(self.top, sequence, func) 1426 if len(key) == 1 and key != key.upper(): 1427 key = key.upper() 1428 sequence = "<" + modifier + "KeyPress-" + key + ">" 1429 bind(self.top, sequence, func) 1430 1431 def _keyPressHandler(self, event): 1432 r = EVENT_PROPAGATE 1433 if event and self.game: 1434 # print event.__dict__ 1435 if self.game.demo: 1436 # stop the demo by setting self.game.demo.keypress 1437 if event.char: # ignore Ctrl/Shift/etc. 1438 self.game.demo.keypress = event.char 1439 r = EVENT_HANDLED 1440# func = self.__keybindings.get(event.char) 1441# if func and (event.state & ~2) == 0: 1442# func(event) 1443# r = EVENT_HANDLED 1444 return r 1445 1446 # 1447 # Select Game menu creation 1448 # 1449 ''' 1450 def _addSelectGameMenu(self, menu): 1451 games = map(self.app.gdb.get, self.app.gdb.getGamesIdSortedByName()) 1452 m = "Ctrl-" 1453 if sys.platform == "darwin": 1454 m = "Cmd-" 1455 menu.add_command(label=n_("All &games..."), accelerator=m + "W", 1456 command=self.mSelectGameDialog) 1457 1458 def _addSelectGameSubMenu(self, games, menu, select_data, 1459 command, variable): 1460 # print select_data 1461 need_sep = 0 1462 for label, select_func in select_data: 1463 if label is None: 1464 need_sep = 1 1465 continue 1466 g = filter(select_func, games) 1467 if not g: 1468 continue 1469 if need_sep: 1470 menu.add_separator() 1471 need_sep = 0 1472 submenu = MfxMenu(menu, label=label) 1473 self._addSelectGameSubSubMenu(g, submenu, command, variable) 1474 1475 def _getNumGames(self, games, select_data): 1476 ngames = 0 1477 for label, select_func in select_data: 1478 ngames += len(filter(select_func, games)) 1479 return ngames 1480 1481 def _addSelectMahjonggGameSubMenu(self, games, menu, command, variable): 1482 def select_func(gi): return gi.si.game_type == GI.GT_MAHJONGG 1483 mahjongg_games = filter(select_func, games) 1484 if len(mahjongg_games) == 0: 1485 return 1486 # 1487 menu = MfxMenu(menu, label=n_("&Mahjongg games")) 1488 1489 def add_menu(games, c0, c1, menu=menu, 1490 variable=variable, command=command): 1491 if not games: 1492 return 1493 label = c0 + ' - ' + c1 1494 if c0 == c1: 1495 label = c0 1496 submenu = MfxMenu(menu, label=label, name=None) 1497 self._addSelectGameSubSubMenu(games, submenu, command, 1498 variable, short_name=True) 1499 1500 games = {} 1501 for gi in mahjongg_games: 1502 c = gi.short_name.strip()[0] 1503 if c in games: 1504 games[c].append(gi) 1505 else: 1506 games[c] = [gi] 1507 games = games.items() 1508 games.sort() 1509 g0 = [] 1510 c0 = c1 = games[0][0] 1511 for c, g1 in games: 1512 if len(g0) + len(g1) >= self.__cb_max: 1513 add_menu(g0, c0, c1) 1514 g0 = g1 1515 c0 = c1 = c 1516 else: 1517 g0 += g1 1518 c1 = c 1519 add_menu(g0, c0, c1) 1520 1521 def _addSelectPopularGameSubMenu(self, games, menu, command, variable): 1522 def select_func(gi): return gi.si.game_flags & GI.GT_POPULAR 1523 if len(filter(select_func, games)) == 0: 1524 return 1525 data = (n_("&Popular games"), select_func) 1526 self._addSelectGameSubMenu(games, menu, (data, ), 1527 self.mSelectGamePopular, 1528 self.tkopt.gameid_popular) 1529 1530 def _addSelectFrenchGameSubMenu(self, games, menu, command, variable): 1531 if self._getNumGames(games, GI.SELECT_GAME_BY_TYPE) == 0: 1532 return 1533 submenu = MfxMenu(menu, label=n_("&French games")) 1534 self._addSelectGameSubMenu(games, submenu, GI.SELECT_GAME_BY_TYPE, 1535 self.mSelectGame, self.tkopt.gameid) 1536 1537 def _addSelectOrientalGameSubMenu(self, games, menu, command, variable): 1538 if self._getNumGames(games, GI.SELECT_ORIENTAL_GAME_BY_TYPE) == 0: 1539 return 1540 submenu = MfxMenu(menu, label=n_("&Oriental games")) 1541 self._addSelectGameSubMenu(games, submenu, 1542 GI.SELECT_ORIENTAL_GAME_BY_TYPE, 1543 self.mSelectGame, self.tkopt.gameid) 1544 1545 def _addSelectSpecialGameSubMenu(self, games, menu, command, variable): 1546 if self._getNumGames(games, GI.SELECT_ORIENTAL_GAME_BY_TYPE) == 0: 1547 return 1548 submenu = MfxMenu(menu, label=n_("&Special games")) 1549 self._addSelectGameSubMenu(games, submenu, 1550 GI.SELECT_SPECIAL_GAME_BY_TYPE, 1551 self.mSelectGame, self.tkopt.gameid) 1552 1553 def _addSelectCustomGameSubMenu(self, games, menu, command, variable): 1554 submenu = MfxMenu(menu, label=n_("&Custom games")) 1555 1556 def select_func(gi): return gi.si.game_type == GI.GT_CUSTOM 1557 games = filter(select_func, games) 1558 self.updateGamesMenu(submenu, games) 1559 ''' 1560 1561 def _addSelectAllGameSubMenu(self, games, menu, command, variable): 1562 # LB 1563 # herausgenommen: zu aufwendig ! 1564 return 1565 ''' 1566 menu = MfxMenu(menu, label=n_("&All games by name")) 1567 n, d = 0, self.__cb_max 1568 i = 0 1569 while True: 1570 if self.progress: 1571 self.progress.update(step=1) 1572 columnbreak = i > 0 and (i % d) == 0 1573 i += 1 1574 if not games[n:n + d]: 1575 break 1576 m = min(n + d - 1, len(games) - 1) 1577 label = games[n].name[:3] + ' - ' + games[m].name[:3] 1578 1579 submenu = MfxMenu(menu, label=label, name=None) 1580 self._addSelectGameSubSubMenu(games[n:n + d], submenu, 1581 command, variable) 1582 n += d 1583 # if columnbreak: 1584 # menu.entryconfigure(i, columnbreak=columnbreak) 1585 ''' 1586 1587 # Eine 'closure' in Python? - voila! 1588 def make_gamesetter(self, n, variable, command): 1589 def gamesetter(x): 1590 variable.set(n) 1591 command() 1592 return gamesetter 1593 1594 def _addSelectGameSubSubMenu(self, games, menu, command, variable, 1595 short_name=False): 1596 1597 # cb = self.__cb_max 1598 for i in range(len(games)): 1599 gi = games[i] 1600 # columnbreak = i > 0 and (i % cb) == 0 1601 if short_name: 1602 label = gi.short_name 1603 else: 1604 label = gi.name 1605 1606 # optimized by inlining 1607 1608 # geht nicht mehr 'optimiert' mit kivy 1609 # die Funktionalität des tk.calls kann mit hilfe 1610 # einer 'closure' rekonstruiert werden (s.o). 1611 # LB 1612 1613 gsetter = self.make_gamesetter(gi.id, variable, command) 1614 menu.add_command(label=label, command=gsetter) 1615 1616 # menu.tk.call((menu._w, 'add', 'radiobutton') + 1617 # menu._options({'command': command, 1618 # 'variable': variable, 1619 # 'columnbreak': columnbreak, 1620 # 'value': gi.id, 1621 # 'label': label})) 1622 1623 def updateGamesMenu(self, menu, games): 1624 1625 def cmp2(a, b): 1626 """python 3 replacement for python 2 cmp function""" 1627 return (a > b) - (a < b) 1628 1629 menu.delete(0, 'last') 1630 1631 if len(games) == 0: 1632 menu.add_radiobutton(label=_('<none>'), name=None, 1633 state='disabled') 1634 elif len(games) > self.__cb_max * 4: 1635 games.sort(lambda a, b: cmp2(a.name, b.name)) 1636 self._addSelectAllGameSubMenu(games, menu, 1637 command=self.mSelectGame, 1638 variable=self.tkopt.gameid) 1639 else: 1640 self._addSelectGameSubSubMenu(games, menu, 1641 command=self.mSelectGame, 1642 variable=self.tkopt.gameid) 1643 1644 def mMainMenuDialog(self, *event): 1645 MainMenuDialog(self, self.top, title=_("Main Menu"), app=self.app) 1646 return EVENT_HANDLED 1647 1648 def mFileMenuDialog(self, *event): 1649 if self._cancelDrag(break_pause=False): 1650 return 1651 self.game.setCursor(cursor=CURSOR_WATCH) 1652 after_idle(self.top, self.__restoreCursor) 1653 FileMenuDialog(self, self.top, title=_("File Menu"), app=self.app) 1654 return EVENT_HANDLED 1655 1656 def mEditMenuDialog(self, *event): 1657 if self._cancelDrag(break_pause=False): 1658 return 1659 self.game.setCursor(cursor=CURSOR_WATCH) 1660 after_idle(self.top, self.__restoreCursor) 1661 EditMenuDialog(self, self.top, title=_("Tools"), app=self.app) 1662 return EVENT_HANDLED 1663 1664 def mGameMenuDialog(self, *event): 1665 if self._cancelDrag(break_pause=False): 1666 return 1667 self.game.setCursor(cursor=CURSOR_WATCH) 1668 after_idle(self.top, self.__restoreCursor) 1669 GameMenuDialog(self, self.top, title=_("Statistics"), app=self.app) 1670 return EVENT_HANDLED 1671 1672 def mAssistMenuDialog(self, *event): 1673 if self._cancelDrag(break_pause=False): 1674 return 1675 self.game.setCursor(cursor=CURSOR_WATCH) 1676 after_idle(self.top, self.__restoreCursor) 1677 AssistMenuDialog(self, self.top, title=_("Assists"), app=self.app) 1678 return EVENT_HANDLED 1679 1680 def mOptionsMenuDialog(self, *event): 1681 if self._cancelDrag(break_pause=False): 1682 return 1683 self.game.setCursor(cursor=CURSOR_WATCH) 1684 after_idle(self.top, self.__restoreCursor) 1685 OptionsMenuDialog(self, self.top, title=_("Options"), app=self.app) 1686 return EVENT_HANDLED 1687 1688 def mHelpMenuDialog(self, *event): 1689 if self._cancelDrag(break_pause=False): 1690 return 1691 self.game.setCursor(cursor=CURSOR_WATCH) 1692 after_idle(self.top, self.__restoreCursor) 1693 HelpMenuDialog(self, self.top, title=_("Help"), app=self.app) 1694 return EVENT_HANDLED 1695 # 1696 # Select Game menu actions 1697 # 1698 1699 def mSelectGame(self, *args): 1700 print('mSelectGame %s' % self) 1701 self._mSelectGame(self.tkopt.gameid.get()) 1702 1703 def mSelectGamePopular(self, *args): 1704 self._mSelectGame(self.tkopt.gameid_popular.get()) 1705 1706 def _mSelectGameDialog(self, d): 1707 if d.gameid != self.game.id: 1708 self.tkopt.gameid.set(d.gameid) 1709 self.tkopt.gameid_popular.set(d.gameid) 1710 self._cancelDrag() 1711 self.game.endGame() 1712 self.game.quitGame(d.gameid, random=d.random) 1713 return EVENT_HANDLED 1714 1715 def __restoreCursor(self, *event): 1716 self.game.setCursor(cursor=self.app.top_cursor) 1717 1718 def mSelectGameDialog(self, *event): 1719 if self._cancelDrag(break_pause=False): 1720 return 1721 self.game.setCursor(cursor=CURSOR_WATCH) 1722 after_idle(self.top, self.__restoreCursor) 1723 d = SelectGameDialog(self.top, title=_("Select game"), 1724 app=self.app, gameid=self.game.id) 1725 return self._mSelectGameDialog(d) 1726 1727 # 1728 # menubar overrides 1729 # 1730 1731 def updateFavoriteGamesMenu(self): 1732 return 1733 1734 # TBD ? 1735 ''' 1736 gameids = self.app.opt.favorite_gameid 1737 1738 print('favorite_gameids = %s' % gameids) 1739 1740 submenu = self.__menupath[".menubar.file.favoritegames"][2] 1741 games = [] 1742 for id in gameids: 1743 gi = self.app.getGameInfo(id) 1744 if gi: 1745 games.append(gi) 1746 self.updateGamesMenu(submenu, games) 1747 1748 # das folgende ist nur das enable/disable des add/remove buttons. 1749 # geht mit kivy nicht so. 1750 1751# state = self._getEnabledState 1752# in_favor = self.app.game.id in gameids 1753 1754# menu, index, submenu = self.__menupath[".menubar.file.addtofavorites"] 1755# menu.entryconfig(index, state=state(not in_favor)) 1756 1757# menu, index, submenu = self.__menupath[".menubar.file.removefromfavorites"] 1758# menu.entryconfig(index, state=state(in_favor)) 1759 ''' 1760 1761 def updateRecentGamesMenu(self, gameids): 1762 return 1763 1764 # TBD ? 1765 ''' 1766 submenu = self.__menupath[".menubar.file.recentgames"][2] 1767 games = [] 1768 for id in gameids: 1769 gi = self.app.getGameInfo(id) 1770 if gi: 1771 games.append(gi) 1772 self.updateGamesMenu(submenu, games) 1773 ''' 1774 1775 def updateBookmarkMenuState(self): 1776 # LB: 1777 print('updateBookmarkMenuState - fake') 1778 return 1779 1780 state = self._getEnabledState 1781 mp1 = self.__menupath.get(".menubar.edit.setbookmark") 1782 mp2 = self.__menupath.get(".menubar.edit.gotobookmark") 1783 mp3 = self.__menupath.get(".menubar.edit.clearbookmarks") 1784 if mp1 is None or mp2 is None or mp3 is None: 1785 return 1786 x = self.app.opt.bookmarks and self.game.canSetBookmark() 1787 # 1788 menu, index, submenu = mp1 1789 for i in range(9): 1790 submenu.entryconfig(i, state=state(x)) 1791 menu.entryconfig(index, state=state(x)) 1792 # 1793 menu, index, submenu = mp2 1794 ms = 0 1795 for i in range(9): 1796 s = self.game.gsaveinfo.bookmarks.get(i) is not None 1797 submenu.entryconfig(i, state=state(s and x)) 1798 ms = ms or s 1799 menu.entryconfig(index, state=state(ms and x)) 1800 # 1801 menu, index, submenu = mp3 1802 menu.entryconfig(index, state=state(ms and x)) 1803 1804 def updateBackgroundImagesMenu(self): 1805 # LB: 1806 print('updateBackgroundImagesMenu - fake') 1807 return 1808 1809 mp = self.__menupath.get(".menubar.options.cardbackground") 1810 # delete all entries 1811 submenu = mp[2] 1812 submenu.delete(0, "last") 1813 # insert new cardbacks 1814 mbacks = self.app.images.getCardbacks() 1815 cb = int(math.ceil(math.sqrt(len(mbacks)))) 1816 for i in range(len(mbacks)): 1817 columnbreak = i > 0 and (i % cb) == 0 1818 submenu.add_radiobutton( 1819 label=mbacks[i].name, 1820 image=mbacks[i].menu_image, 1821 variable=self.tkopt.cardback, 1822 value=i, 1823 command=self.mOptCardback, 1824 columnbreak=columnbreak, 1825 indicatoron=0, 1826 hidemargin=0) 1827 # 1828 # menu updates 1829 # 1830 1831 def setMenuState(self, state, path): 1832 # LB: not used 1833 return 1834 1835 def setToolbarState(self, state, path): 1836 # LB: not used 1837 return 1838 1839 def _setCommentMenu(self, v): 1840 self.tkopt.comment.set(v) 1841 1842 def _setPauseMenu(self, v): 1843 self.tkopt.pause.set(v) 1844 1845 # 1846 # menu actions 1847 # 1848 1849 DEFAULTEXTENSION = ".pso" 1850 # TRANSLATORS: Usually, 'PySol files' 1851 FILETYPES = ((_("%s files") % TITLE, "*" + DEFAULTEXTENSION), 1852 (_("All files"), "*")) 1853 1854 def mAddFavor(self, *event): 1855 gameid = self.app.game.id 1856 if gameid not in self.app.opt.favorite_gameid: 1857 self.app.opt.favorite_gameid.append(gameid) 1858 self.updateFavoriteGamesMenu() 1859 1860 def mDelFavor(self, *event): 1861 gameid = self.app.game.id 1862 if gameid in self.app.opt.favorite_gameid: 1863 self.app.opt.favorite_gameid.remove(gameid) 1864 self.updateFavoriteGamesMenu() 1865 1866 def mOpen(self, *event): 1867 if self._cancelDrag(break_pause=False): 1868 return 1869 # filename = self.game.filename 1870 filename = "lastgame.pso" 1871 if filename: 1872 idir, ifile = os.path.split(os.path.normpath(filename)) 1873 else: 1874 idir, ifile = "", "" 1875 if not idir: 1876 idir = self.app.dn.savegames 1877# d = tkFileDialog.Open() 1878# filename = d.show(filetypes=self.FILETYPES, 1879# defaultextension=self.DEFAULTEXTENSION, 1880# initialdir=idir, initialfile=ifile) 1881 filename = idir + "/" + ifile 1882 1883 print('filename = %s' % filename) 1884 if filename: 1885 filename = os.path.normpath(filename) 1886 # filename = os.path.normcase(filename) 1887 if os.path.isfile(filename): 1888 self.game.loadGame(filename) 1889 1890 def mSaveAs(self, *event): 1891 if self._cancelDrag(break_pause=False): 1892 return 1893 if not self.menustate.save_as: 1894 return 1895 # filename = self.game.filename 1896 filename = "lastgame.pso" 1897 if not filename: 1898 filename = self.app.getGameSaveName(self.game.id) 1899 if os.name == "posix": 1900 filename = filename + "-" + self.game.getGameNumber(format=0) 1901 elif os.path.supports_unicode_filenames: # new in python 2.3 1902 filename = filename + "-" + self.game.getGameNumber(format=0) 1903 else: 1904 filename = filename + "-01" 1905 filename = filename + self.DEFAULTEXTENSION 1906 idir, ifile = os.path.split(os.path.normpath(filename)) 1907 if not idir: 1908 idir = self.app.dn.savegames 1909 # print self.game.filename, ifile 1910 # d = tkFileDialog.SaveAs() 1911 # filename = d.show(filetypes=self.FILETYPES, 1912 # defaultextension=self.DEFAULTEXTENSION, 1913 # initialdir=idir, initialfile=ifile) 1914 filename = idir + "/" + ifile 1915 if filename: 1916 filename = os.path.normpath(filename) 1917 # filename = os.path.normcase(filename) 1918 self.game.saveGame(filename) 1919 self.updateMenus() 1920 1921 def mPause(self, *args): 1922 if not self.game: 1923 return 1924 if not self.game.pause: 1925 if self._cancelDrag(): 1926 return 1927 self.game.doPause() 1928 self.tkopt.pause.set(self.game.pause) 1929 1930 def mOptLanguage(self, *args): 1931 if self._cancelDrag(break_pause=False): 1932 return 1933 self.app.opt.language = self.tkopt.language.get() 1934 MfxMessageDialog( 1935 self.app.top, title=_("Note"), 1936 text=_("""\ 1937These settings will take effect 1938the next time you restart the %(app)s""") % {'app': TITLE}) 1939 1940 def mOptSoundDialog(self, *args): 1941 if self._cancelDrag(break_pause=False): 1942 return 1943 self.app.opt.sound = self.tkopt.sound.get() 1944 1945 def mOptSoundSampleVol(self, *args): 1946 if self._cancelDrag(break_pause=False): 1947 return 1948 self.app.opt.sound_sample_volume = self.tkopt.sound_sample_volume.get() 1949 1950 def mOptSoundMusicVol(self, *args): 1951 if self._cancelDrag(break_pause=False): 1952 return 1953 self.app.opt.sound_music_volume = self.tkopt.sound_music_volume.get() 1954 1955 def mOptSoundSample(self, key, *args): 1956 if self._cancelDrag(break_pause=False): 1957 return 1958 self.app.opt.sound_samples[key] = \ 1959 self.tkopt.sound_sample_vars[key].get() 1960 1961 def mOptTableColor(self, *args): 1962 if self._cancelDrag(break_pause=False): 1963 return 1964 nv = self.tkopt.color_vars['table'].get() 1965 ov = self.app.opt.colors['table'] 1966 self.app.opt.colors['table'] = nv 1967 if ov != nv: 1968 self.app.top_bg = nv 1969 self.app.tabletile_index = 0 1970 self.app.setTile(0, force=True) 1971 self.tkopt.tabletile.set(0) 1972 1973 def mOptTileSet(self, *args): 1974 if self._cancelDrag(break_pause=False): 1975 return 1976 idx = self.tkopt.tabletile.get() 1977 if idx > 0 and idx != self.app.tabletile_index: 1978 self.app.setTile(idx) 1979 self.tkopt.color_vars['table'].set('#008285') 1980 1981 def mOptAutoFaceUp(self, *args): 1982 if self._cancelDrag(): 1983 return 1984 self.app.opt.autofaceup = self.tkopt.autofaceup.get() 1985 if self.app.opt.autofaceup: 1986 self.game.autoPlay() 1987 1988 def mOptAutoDrop(self, *args): 1989 if self._cancelDrag(): 1990 return 1991 self.app.opt.autodrop = self.tkopt.autodrop.get() 1992 if self.app.opt.autodrop: 1993 self.game.autoPlay() 1994 1995 def mOptAutoDeal(self, *args): 1996 if self._cancelDrag(): 1997 return 1998 self.app.opt.autodeal = self.tkopt.autodeal.get() 1999 if self.app.opt.autodeal: 2000 self.game.autoPlay() 2001 2002 def mOptQuickPlay(self, *args): 2003 if self._cancelDrag(break_pause=False): 2004 return 2005 self.app.opt.quickplay = self.tkopt.quickplay.get() 2006 2007 def mOptEnableUndo(self, *args): 2008 if self._cancelDrag(break_pause=False): 2009 return 2010 self.app.opt.undo = self.tkopt.undo.get() 2011 self.game.updateMenus() 2012 2013 def mOptEnableBookmarks(self, *args): 2014 if self._cancelDrag(break_pause=False): 2015 return 2016 self.app.opt.bookmarks = self.tkopt.bookmarks.get() 2017 self.game.updateMenus() 2018 2019 def mOptEnableHint(self, *args): 2020 if self._cancelDrag(break_pause=False): 2021 return 2022 self.app.opt.hint = self.tkopt.hint.get() 2023 self.game.updateMenus() 2024 2025 def mOptEnableShuffle(self, *args): 2026 if self._cancelDrag(break_pause=False): 2027 return 2028 self.app.opt.shuffle = self.tkopt.shuffle.get() 2029 self.game.updateMenus() 2030 2031 def mOptEnableHighlightPiles(self, *args): 2032 if self._cancelDrag(break_pause=False): 2033 return 2034 self.app.opt.highlight_piles = self.tkopt.highlight_piles.get() 2035 self.game.updateMenus() 2036 2037 def mOptEnableHighlightCards(self, *args): 2038 if self._cancelDrag(break_pause=False): 2039 return 2040 self.app.opt.highlight_cards = self.tkopt.highlight_cards.get() 2041 self.game.updateMenus() 2042 2043 def mOptEnableHighlightSameRank(self, *args): 2044 if self._cancelDrag(break_pause=False): 2045 return 2046 self.app.opt.highlight_samerank = self.tkopt.highlight_samerank.get() 2047 # self.game.updateMenus() 2048 2049 def mOptEnableHighlightNotMatching(self, *args): 2050 if self._cancelDrag(break_pause=False): 2051 return 2052 self.app.opt.highlight_not_matching = \ 2053 self.tkopt.highlight_not_matching.get() 2054 # self.game.updateMenus() 2055 2056 def mOptAnimations(self, *args): 2057 if self._cancelDrag(break_pause=False): 2058 return 2059 self.app.opt.animations = self.tkopt.animations.get() 2060 2061 def mRedealAnimation(self, *args): 2062 if self._cancelDrag(break_pause=False): 2063 return 2064 self.app.opt.redeal_animation = self.tkopt.redeal_animation.get() 2065 2066 def mWinAnimation(self, *args): 2067 if self._cancelDrag(break_pause=False): 2068 return 2069 self.app.opt.win_animation = self.tkopt.win_animation.get() 2070 2071 def mWinDialog(self, *args): 2072 if self._cancelDrag(break_pause=False): 2073 return 2074 self.app.opt.display_win_message = self.tkopt.display_win_message.get() 2075 2076 def mOptShadow(self, *args): 2077 if self._cancelDrag(break_pause=False): 2078 return 2079 self.app.opt.shadow = self.tkopt.shadow.get() 2080 2081 def mOptShade(self, *args): 2082 if self._cancelDrag(break_pause=False): 2083 return 2084 self.app.opt.shade = self.tkopt.shade.get() 2085 2086 def mOptShrinkFaceDown(self, *args): 2087 if self._cancelDrag(break_pause=False): 2088 return 2089 self.app.opt.shrink_face_down = self.tkopt.shrink_face_down.get() 2090 self.game.endGame(bookmark=1) 2091 self.game.quitGame(bookmark=1) 2092 2093 def mOptShadeFilledStacks(self, *args): 2094 if self._cancelDrag(break_pause=False): 2095 return 2096 self.app.opt.shade_filled_stacks = self.tkopt.shade_filled_stacks.get() 2097 self.game.endGame(bookmark=1) 2098 self.game.quitGame(bookmark=1) 2099 2100 def mOptMahjonggShowRemoved(self, *args): 2101 if self._cancelDrag(): 2102 return 2103 self.app.opt.mahjongg_show_removed = \ 2104 self.tkopt.mahjongg_show_removed.get() 2105 # self.game.updateMenus() 2106 self.game.endGame(bookmark=1) 2107 self.game.quitGame(bookmark=1) 2108 2109 def mOptShisenShowHint(self, *args): 2110 if self._cancelDrag(break_pause=False): 2111 return 2112 self.app.opt.shisen_show_hint = self.tkopt.shisen_show_hint.get() 2113 # self.game.updateMenus() 2114 2115 def mOptAccordionDealAll(self, *args): 2116 if self._cancelDrag(break_pause=False): 2117 return 2118 self.app.opt.accordion_deal_all = self.tkopt.accordion_deal_all.get() 2119 # self.game.updateMenus() 2120 2121 def mOptCardset(self, *event): 2122 if self._cancelDrag(break_pause=False): 2123 return 2124 idx = self.tkopt.cardset.get() 2125 cs = self.app.cardset_manager.get(idx) 2126 if cs is None or idx == self.app.cardset.index: 2127 return 2128 if idx >= 0: 2129 self.app.nextgame.cardset = cs 2130 self._cancelDrag() 2131 self.game.endGame(bookmark=1) 2132 self.game.quitGame(bookmark=1) 2133 2134 def mSelectCardsetDialog(self, *event): 2135 if self._cancelDrag(break_pause=False): 2136 return 2137 # strings, default = ("&OK", "&Load", "&Cancel"), 0 2138 strings, default = (None, _("&Load"), _("&Cancel"), ), 1 2139 # if os.name == "posix": 2140 strings, default = (None, _("&Load"), _( 2141 "&Cancel"), _("&Info..."), ), 1 2142 key = self.app.nextgame.cardset.index 2143 d = SelectCardsetDialogWithPreview( 2144 self.top, title=_("Select cardset"), 2145 app=self.app, manager=self.app.cardset_manager, key=key, 2146 strings=strings, default=default) 2147 2148 cs = self.app.cardset_manager.get(d.key) 2149 if cs is None or d.key == self.app.cardset.index: 2150 return 2151 if d.status == 0 and d.button in (0, 1) and d.key >= 0: 2152 self.app.nextgame.cardset = cs 2153 if d.button == 1: 2154 self._cancelDrag() 2155 self.game.endGame(bookmark=1) 2156 self.game.quitGame(bookmark=1) 2157 2158 def mOptSetCardback(self, key, *event): 2159 val = self.tkopt.cardbacks[key].get() 2160 cs = self.app.cardset_manager.get(key) 2161 cs.updateCardback(backindex=val) 2162 # ANM: wir können den Background nur für das aktuell 2163 # selektierte Cardset wirklich ändern. Nur dieses wird 2164 # wird in den Optionen gespeichert. 2165 if (cs == self.app.cardset): 2166 self.app.updateCardset(self.game.id) 2167 self.app.cardset.backindex = val 2168 image = self.app.images.getBack(update=True) 2169 for card in self.game.cards: 2170 card.updateCardBackground(image=image) 2171 self.app.canvas.update_idletasks() 2172 2173 def _mOptCardback(self, index): 2174 if self._cancelDrag(break_pause=False): 2175 return 2176 cs = self.app.cardset 2177 old_index = cs.backindex 2178 cs.updateCardback(backindex=index) 2179 if cs.backindex == old_index: 2180 return 2181 self.app.updateCardset(self.game.id) 2182 image = self.app.images.getBack(update=True) 2183 for card in self.game.cards: 2184 card.updateCardBackground(image=image) 2185 self.app.canvas.update_idletasks() 2186 self.tkopt.cardback.set(cs.backindex) 2187 2188 def mOptCardback(self, *event): 2189 self._mOptCardback(self.tkopt.cardback.get()) 2190 2191 def mOptChangeCardback(self, *event): 2192 self._mOptCardback(self.app.cardset.backindex + 1) 2193 2194 def mOptToolbar(self, *event): 2195 # if self._cancelDrag(break_pause=False): return 2196 self.setToolbarSide(self.tkopt.toolbar.get()) 2197 2198 def mOptToolbarStyle(self, *event): 2199 # if self._cancelDrag(break_pause=False): return 2200 self.setToolbarStyle(self.tkopt.toolbar_style.get()) 2201 2202 def mOptToolbarCompound(self, *event): 2203 # if self._cancelDrag(break_pause=False): return 2204 self.setToolbarCompound(self.tkopt.toolbar_compound.get()) 2205 2206 def mOptToolbarSize(self, *event): 2207 # if self._cancelDrag(break_pause=False): return 2208 self.setToolbarSize(self.tkopt.toolbar_size.get()) 2209 2210 def mOptToolbarRelief(self, *event): 2211 # if self._cancelDrag(break_pause=False): return 2212 self.setToolbarRelief(self.tkopt.toolbar_relief.get()) 2213 2214 def mOptToolbarConfig(self, w): 2215 self.toolbarConfig(w, self.tkopt.toolbar_vars[w].get()) 2216 2217 def mOptStatusbar(self, *event): 2218 if self._cancelDrag(break_pause=False): 2219 return 2220 if not self.app.statusbar: 2221 return 2222 side = self.tkopt.statusbar.get() 2223 self.app.opt.statusbar = side 2224 resize = not self.app.opt.save_games_geometry 2225 if self.app.statusbar.show(side, resize=resize): 2226 self.top.update_idletasks() 2227 2228 def mOptNumCards(self, *event): 2229 if self._cancelDrag(break_pause=False): 2230 return 2231 self.app.opt.num_cards = self.tkopt.num_cards.get() 2232 2233 def mOptHelpbar(self, *event): 2234 if self._cancelDrag(break_pause=False): 2235 return 2236 if not self.app.helpbar: 2237 return 2238 show = self.tkopt.helpbar.get() 2239 self.app.opt.helpbar = show 2240 resize = not self.app.opt.save_games_geometry 2241 if self.app.helpbar.show(show, resize=resize): 2242 self.top.update_idletasks() 2243 2244 def mOptSaveGamesGeometry(self, *event): 2245 if self._cancelDrag(break_pause=False): 2246 return 2247 self.app.opt.save_games_geometry = self.tkopt.save_games_geometry.get() 2248 2249 def mOptDemoLogo(self, *event): 2250 if self._cancelDrag(break_pause=False): 2251 return 2252 self.app.opt.demo_logo = self.tkopt.demo_logo.get() 2253 2254 def mOptSplashscreen(self, *event): 2255 if self._cancelDrag(break_pause=False): 2256 return 2257 self.app.opt.splashscreen = self.tkopt.splashscreen.get() 2258 2259 def mOptMouseType(self, *event): 2260 if self._cancelDrag(break_pause=False): 2261 return 2262 self.app.opt.mouse_type = self.tkopt.mouse_type.get() 2263 2264 def mOptMouseUndo(self, *event): 2265 if self._cancelDrag(break_pause=False): 2266 return 2267 self.app.opt.mouse_undo = self.tkopt.mouse_undo.get() 2268 2269 def mOptNegativeBottom(self, *event): 2270 if self._cancelDrag(): 2271 return 2272 self.app.opt.negative_bottom = self.tkopt.negative_bottom.get() 2273 self.app.updateCardset() 2274 self.game.endGame(bookmark=1) 2275 self.game.quitGame(bookmark=1) 2276 2277 # 2278 # toolbar support 2279 # 2280 2281 def setToolbarSide(self, side): 2282 if self._cancelDrag(break_pause=False): 2283 return 2284 self.app.opt.toolbar = side 2285 self.tkopt.toolbar.set(side) # update radiobutton 2286 resize = not self.app.opt.save_games_geometry 2287 if self.app.toolbar.show(side, resize=resize): 2288 self.top.update_idletasks() 2289 2290 def setToolbarSize(self, size): 2291 if self._cancelDrag(break_pause=False): 2292 return 2293 self.app.opt.toolbar_size = size 2294 self.tkopt.toolbar_size.set(size) # update radiobutton 2295 dir = self.app.getToolbarImagesDir() 2296 if self.app.toolbar.updateImages(dir, size): 2297 self.game.updateStatus(player=self.app.opt.player) 2298 self.top.update_idletasks() 2299 2300 def setToolbarStyle(self, style): 2301 if self._cancelDrag(break_pause=False): 2302 return 2303 self.app.opt.toolbar_style = style 2304 # update radiobutton 2305 self.tkopt.toolbar_style.set(style) 2306 dir = self.app.getToolbarImagesDir() 2307 size = self.app.opt.toolbar_size 2308 if self.app.toolbar.updateImages(dir, size): 2309 # self.game.updateStatus(player=self.app.opt.player) 2310 self.top.update_idletasks() 2311 2312 def setToolbarCompound(self, compound): 2313 if self._cancelDrag(break_pause=False): 2314 return 2315 self.app.opt.toolbar_compound = compound 2316 self.tkopt.toolbar_compound.set( 2317 compound) # update radiobutton 2318 if self.app.toolbar.setCompound(compound): 2319 self.game.updateStatus(player=self.app.opt.player) 2320 self.top.update_idletasks() 2321 2322 def setToolbarRelief(self, relief): 2323 if self._cancelDrag(break_pause=False): 2324 return 2325 self.app.opt.toolbar_relief = relief 2326 self.tkopt.toolbar_relief.set(relief) # update radiobutton 2327 self.app.toolbar.setRelief(relief) 2328 self.top.update_idletasks() 2329 2330 def toolbarConfig(self, w, v): 2331 if self._cancelDrag(break_pause=False): 2332 return 2333 self.app.opt.toolbar_vars[w] = v 2334 self.app.toolbar.config(w, v) 2335 self.top.update_idletasks() 2336 2337 # 2338 # stacks descriptions 2339 # 2340 2341 def mStackDesk(self, *event): 2342 if self.game.stackdesc_list: 2343 self.game.deleteStackDesc() 2344 else: 2345 if self._cancelDrag(break_pause=True): 2346 return 2347 self.game.showStackDesc() 2348 2349 def wizardDialog(self, edit=False): 2350 from pysollib.wizardutil import write_game, reset_wizard 2351 from wizarddialog import WizardDialog 2352 2353 if edit: 2354 reset_wizard(self.game) 2355 else: 2356 reset_wizard(None) 2357 d = WizardDialog(self.top, _('Solitaire Wizard'), self.app) 2358 if d.status == 0 and d.button == 0: 2359 try: 2360 if edit: 2361 gameid = write_game(self.app, game=self.game) 2362 else: 2363 gameid = write_game(self.app) 2364 except Exception: 2365 return 2366 if SELECT_GAME_MENU: 2367 menu = self.__menupath[".menubar.select.customgames"][2] 2368 2369 def select_func(gi): return gi.si.game_type == GI.GT_CUSTOM 2370 games = map(self.app.gdb.get, 2371 self.app.gdb.getGamesIdSortedByName()) 2372 games = filter(select_func, games) 2373 self.updateGamesMenu(menu, games) 2374 2375 self.tkopt.gameid.set(gameid) 2376 self._mSelectGame(gameid, force=True) 2377 2378 def mWizard(self, *event): 2379 if self._cancelDrag(break_pause=False): 2380 return 2381 self.wizardDialog() 2382 2383 def mWizardEdit(self, *event): 2384 if self._cancelDrag(break_pause=False): 2385 return 2386 self.wizardDialog(edit=True) 2387 2388 2389''' 2390''' 2391