1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00
PySolFC/pysollib/kivy/toolbar.py
lufebe16 c3ffbff146 Kivy Version
- refactorings & some clean up
2023-11-23 17:49:38 +01:00

455 lines
15 KiB
Python

#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------#
# Copyright (C) 2016-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/>.
#
# ---------------------------------------------------------------------------#
# imports
import os
from kivy.cache import Cache
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.properties import BooleanProperty
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image as KivyImage
# PySol kivy imports
from pysollib.kivy.LBase import LBase
from pysollib.kivy.LImage import LImage
from pysollib.kivy.toast import Toast
# PySol imports
from pysollib.mygettext import _, n_ # noqa
from pysollib.util import IMAGE_EXTENSIONS
from pysollib.winsystems import TkSettings
# ************************************************************************
class MyButtonBase(ButtonBehavior, KivyImage, LBase):
shown = BooleanProperty(True)
enabled = BooleanProperty(True)
config = BooleanProperty(True)
def __init__(self, **kwargs):
super(MyButtonBase, self).__init__(**kwargs)
self.src = None
if ('image' in kwargs):
self.src = kwargs['image'].source
self.command = None
if ('command' in kwargs):
self.command = kwargs['command']
self.name = ""
if ('name' in kwargs):
self.name = kwargs['name']
self.source = self.src
self.allow_stretch = True
def set_shown(self, instance, value):
# print ('** set shown (',self.name ,') called', value)
self.shown = value
def set_enabled(self, instance, value):
# print ('** set enabled (',self.name ,') called', value)
self.enabled = value
def set_config(self, instance, value):
# print ('** set config (',self.name ,') called', value)
self.config = value
class MyButton(MyButtonBase):
def __init__(self, **kwargs):
super(MyButton, self).__init__(**kwargs)
def on_press(self):
self.allow_stretch = False
def on_release(self):
self.allow_stretch = True
if (self.command is not None):
self.command()
class MyCheckButton(MyButtonBase):
def __init__(self, **kwargs):
super(MyCheckButton, self).__init__(**kwargs)
self.variable = None
if ('variable' in kwargs):
self.variable = kwargs['variable']
self.win = None
if ('win' in kwargs):
self.win = kwargs['win']
self.checked = False
# self.variable = self.win.app.menubar.tkopt.pause
if self.variable:
self.variable.bind(value=self.updateState)
def updateState(self, obj, val):
if (val):
self.allow_stretch = False
else:
self.allow_stretch = True
def isChecked(self):
return self.checked
def on_press(self):
if self.win is None:
return
if self.win.app is None:
return
if self.win.app.game is None:
return
game = self.win.app.game
if game.finished:
return
if game.demo:
return
# if self.win.app.menubar == None: return
# mb = self.win.app.menubar
if game.pause:
self.allow_stretch = True
self.checked = False
if (self.command is not None):
self.command()
else:
self.allow_stretch = False
self.checked = True
if (self.command is not None):
self.command()
def on_release(self):
pass
class MyToastButton(MyButtonBase):
def __init__(self, **kwargs):
super(MyToastButton, self).__init__(**kwargs)
self.timeout = 2.0
if ('timeout' in kwargs):
self.timeout = kwargs['timeout']
def exec_command(self):
if (self.command is not None):
self.command()
def on_press(self):
self.allow_stretch = False
text = ""
if self.name == "new":
text = _("New game")
if self.name == "restart":
text = _("Restart game")
toast = Toast(text=text+" ?")
toast.show(parent=Cache.get('LAppCache', 'mainApp').baseWindow,
duration=self.timeout,
hook=self.exec_command)
def on_release(self):
self.allow_stretch = True
class MyWaitButton(MyButtonBase):
def __init__(self, **kwargs):
super(MyWaitButton, self).__init__(**kwargs)
self.timeout = 1.0
if ('timeout' in kwargs):
self.timeout = kwargs['timeout']
self.eventId = None
self.wait_toast = None
self.ok = False
def make_toast(self, text):
mainApp = Cache.get('LAppCache', 'mainApp')
self.wait_toast = Toast(text=text)
self.wait_toast.popup(mainApp.baseWindow, offset=(0,-0.2)) # noqa
def clear_toast(self):
if self.wait_toast is not None:
self.wait_toast.stop()
self.wait_toast = None
def okstart(self, *args):
self.make_toast(_("ok to release"))
def holdend(self, *args):
self.clear_toast()
self.eventId = None
self.ok = True
Clock.schedule_once(self.okstart, 0.1)
def on_press(self):
self.allow_stretch = False
self.eventId = Clock.schedule_once(self.holdend, self.timeout)
self.make_toast(_("hold on ..."))
def on_release(self):
self.allow_stretch = True
if self.eventId is not None:
Clock.unschedule(self.eventId)
self.clear_toast()
if self.ok:
if (self.command is not None):
self.command()
self.ok = False
# ************************************************************************
# * Note: Applications should call show/hide after constructor.
# ************************************************************************
class PysolToolbarTk(BoxLayout):
def __init__(
self,
top,
menubar,
dir,
size=0,
relief='flat',
compound='none'):
super(PysolToolbarTk, self).__init__(orientation='vertical')
self.size_hint = (0.06, 1.0)
# self.size_hint=(None, 1.0)
# self.width = 50
self.win = top
self.menubar = menubar
self.dir = dir
self.win.setTool(self, 3)
self.buttons = []
self.buttond = {}
# This is called only once after program start. Configurations
# have to take place elsewhere.
bl = []
bl.append((n_("New"), self.mNewGame, _("New game")))
bl.append((n_("Restart"), self.mRestart, _("Restart the\ncurrent game"))) # noqa
bl.append((n_("Undo"), self.mUndo, _("Undo last move"))) # noqa
bl.append((n_("Redo"), self.mRedo, _("Redo last move")))
bl.append((n_("Autodrop"), self.mDrop, _("Auto drop cards")))
bl.append((n_("Shuffle"), self.mShuffle, _("Shuffle tiles")))
bl.append((n_("Hint"), self.mHint, _("Hint")))
bl.append((n_("Pause"), self.mPause, _("Pause game")))
bl.append((n_("Rules"), self.mHelpRules, _("Rules for this game")))
'''
for label, f, t in [
(n_("New"), self.mNewGame, _("New game")),
(n_("Restart"), self.mRestart, _("Restart the\ncurrent game")),
(None, None, None),
# (n_("Open"), self.mOpen, _("Open a\nsaved game")),
# (n_("Save"), self.mSave, _("Save game")),
(None, None, None),
(n_("Undo"), self.mUndo, _("Undo last move")),
(n_("Redo"), self.mRedo, _("Redo last move")),
(n_("Autodrop"), self.mDrop, _("Auto drop cards")),
(n_("Shuffle"), self.mShuffle, _("Shuffle tiles")),
(n_("Hint"), self.mHint, _("Hint")),
(n_("Pause"), self.mPause, _("Pause game")),
(None, None, None),
# (n_("Statistics"), self.mPlayerStats, _("View statistics")),
(n_("Rules"), self.mHelpRules, _("Rules for this game")),
(None, None, None),
(n_("Quit"), self.mHoldAndQuit, _("Quit %s") % TITLE),
]:
'''
# Build all the buttions.
for label, f, t in bl:
if label is None:
button = None
# We dont have separators in kivy version.
pass
elif label == 'Pause':
button = self._createButton(label, f, check=True, tooltip=t)
self.buttons.append(button)
elif label in ["New", "Restart"]:
button = self._createButton(label, f, check=False, tooltip=t, timeout=3.0) # noqa
self.buttons.append(button)
else:
button = self._createButton(label, f, check=False, tooltip=t)
self.buttons.append(button)
if button is not None:
# print('button name: ', button.name)
self.buttond[button.name] = button
# check buttons if configurated or opted out.
# (could ev. be integrated into _createButton)
toolbar_opt = getattr(self.menubar.tkopt, 'toolbar_vars')
for k in toolbar_opt.keys():
opt = toolbar_opt[k]
if k in self.buttond.keys():
b = self.buttond[k]
b.config = opt.get()
opt.bind(value=b.set_config)
self.redraw()
Window.bind(size=self.doResize)
def doResize(self, *args):
self.show(True)
def show(self, on, **kw):
side = self.menubar.tkopt.toolbar.get()
self.win.setTool(None, side)
# size_hint dependent on screen orientation:
asp = Window.width/Window.height
if side in [1, 2]:
self.orientation = "horizontal"
if asp > 1.0:
self.size_hint = (1.0, 0.09)
else:
self.size_hint = (1.0, 0.06)
else:
self.orientation = "vertical"
if asp > 1.0:
self.size_hint = (0.06, 1.0)
else:
self.size_hint = (0.09, 1.0)
return False
def mHoldAndQuit(self, *args):
if not self._busy():
self.menubar.mHoldAndQuit()
return 1
def getSize(self):
return 0
def updateText(self, **kw):
pass
def redraw(self):
self.clear_widgets()
for b in self.buttons:
# print(b.name,b.config,b.shown,b.enabled)
if b.shown and b.enabled and b.config:
self.add_widget(b)
def changed_state(self, instance, value):
self.redraw()
def config(self, w, v):
if w == 'shuffle':
self.buttond['shuffle'].shown = v
self.buttond['autodrop'].shown = not v
# Lokale.
def _loadImage(self, name):
file = os.path.join(self.dir, name)
image = None
for ext in IMAGE_EXTENSIONS:
file = os.path.join(self.dir, name + ext)
if os.path.isfile(file):
image = LImage(source=file)
# print('_loadImage: file=%s' % file)
break
return image
def _createButton(self, label, command, check=False, tooltip=None, timeout=0.0): # noqa
name = label.lower()
image = self._loadImage(name)
# position = len(self._widgets)
button_relief = TkSettings.toolbar_button_relief
bd = TkSettings.toolbar_button_borderwidth
padx, pady = TkSettings.toolbar_button_padding
kw = {
'toolbar': self,
'toolbar_name': name,
'command': command,
'takefocus': 0,
'text': _(label),
'bd': bd,
'relief': button_relief,
'padx': padx,
'pady': pady,
'overrelief': 'raised',
'timeout': timeout
}
# print ('toolbar: print %s' % self.win)
# print ('toolbar: print %s' % self.win.app)
kw['win'] = self.win
if image:
kw['image'] = image
if name:
kw['name'] = name
if check:
kw['offrelief'] = button_relief
kw['indicatoron'] = False
kw['selectcolor'] = ''
button = MyCheckButton(**kw)
elif timeout > 0.0:
button = MyToastButton(**kw)
else:
button = MyButton(**kw)
try:
oname = name
# redo is handled same way as undo, there is no separate option.
if name == 'redo':
oname = 'undo'
opt = getattr(self.menubar.tkopt, oname)
# specialisation (differently used options):
# - autodrop button has no own option. option 'autodrop' is used
# for the different effect of fully automatic dropping!
# - pause button sets and clears the pause option, not vice versa!
# it is an option that only exists internaly (not saved). (same
# applies also to the tk and tile implementations)
if oname not in ['autodrop', 'pause']:
button.enabled = opt.get()
# print('** ', oname, '(enabled) = ', opt.get())
opt.bind(value=button.set_enabled)
button.bind(enabled=self.changed_state)
button.bind(shown=self.changed_state)
except: # noqa
pass
button.bind(config=self.changed_state)
# TBD: tooltip ev. auf basis einer statuszeile implementieren
# if tooltip:
# b = MfxTooltip(button)
# self._tooltips.append(b)
# b.setText(tooltip)
return button
def _busy(self):
# if not self.side or not self.game or not self.menubar:
# return 1
if not self.game or not self.menubar:
return 1
# print('_busy:')
self.game.stopDemo()
self.game.interruptSleep()
return self.game.busy