diff --git a/pysollib/kivy/toast.py b/pysollib/kivy/toast.py index 76ac0372..b19876ad 100644 --- a/pysollib/kivy/toast.py +++ b/pysollib/kivy/toast.py @@ -1,72 +1,103 @@ # ================================================================ -# flake8: noqa # Toast implementation -# LB230919 +# LB230919-22 from kivy.animation import Animation from kivy.clock import Clock -from kivy.uix.label import Label from kivy.graphics import Color from kivy.graphics.vertex_instructions import RoundedRectangle +from kivy.uix.label import Label +from kivy.uix.widget import Widget + +from pysollib.kivy.LApp import LBase # ================================================================ -class Toast(Label): + +class Toast(Label, LBase): def __init__(self, **kw): - super().__init__(opacity=0, **kw) + super().__init__(**kw) self.duration = 4.0 self.tsize = self.size - self.rsize = [20,] + self.rsize = [2,] + self.hook = None with self.canvas.before: - Color(0.2, 0.2, 0.2, 0.8) + Color(0.2, 0.2, 0.2, 0.85) self.rect = RoundedRectangle() + self.bind(texture_size=self.eval_size) self.bind(size=self._update_rect) - def eval_size(self,instance,size): + def eval_size(self, instance, size): width, height = size - if width > self.parent.width: - instance.text_size = (self.parent.width, None) - instance.texture_update() - width, height = instance.texture_size + if self.parent is not None: + if width > self.parent.width: + instance.text_size = (self.parent.width, None) + instance.texture_update() + width, height = instance.texture_size ads = height * 1.7 - self.tsize = (width + ads, height + ads) self.rsize = [(ads+height)/2.0,] - # print(self.tsize, self.rsize) + self.tsize = (width + ads, height + ads) + # print('eval_size:',self.tsize,self.rsize) def _update_rect(self, instance, value): self.rect.size = self.tsize - # print(self.top) - # print(self.pos_hint) - self.rect.pos = (self.center_x-self.tsize[0]/2.0,self.center_y-self.tsize[1]/2.0) + self.rect.pos = (instance.center_x-self.tsize[0]/2.0, + instance.center_y-self.tsize[1]/2.0) self.rect.radius = self.rsize + # print('update_rect:',self.tsize,self.rsize,self.size) + + def start(self, *args): + Clock.schedule_once(self.extro, self.duration) def stop(self, *args): - self.unbind(texture_size=self.eval_size) - self.parent.remove_widget(self) + if self.parent is not None: + self.parent.remove_widget(self) - def hide(self, *args): - anim = Animation(opacity=0, duration=0.4) + def intro(self, *args): + anim = Animation(opacity=1, duration=0.55) + anim.bind(on_complete=self.start) + anim.start(self) + + def extro(self, *args): + anim = Animation(opacity=0, duration=0.45) anim.bind(on_complete=self.stop) anim.start(self) - # Timed display with fadein/-out - def show(self, parent=None, duration=2.0): + # Timed display with fadein/-out, click also works + def show(self, parent=None, duration=2.0, offset=(0.0, -0.25), hook=None): if parent is None: return - self.duration = duration + self.hook = hook + duration = duration - 1.0 + if duration > 0.0: self.duration = duration # noqa + else: self.duration = 0.0 # noqa + self.opacity = 0 + self.pos = [parent.width*offset[0], parent.height*offset[1]] parent.add_widget(self) - self.bind(texture_size=self.eval_size) - anim = Animation(opacity=1, duration=0.4) - anim.start(self) - Clock.schedule_once(self.hide,self.duration) + self.intro() - # Popup display - use 'stop' to terminate. - def start(self,parent=None): + # Popup (needs call to stop to terminate or click on it) + def popup(self, parent=None, offset=(0.0, -0.25), hook=None): if parent is None: return + self.hook = hook self.opacity = 1 + self.pos = [parent.width*offset[0], parent.height*offset[1]] parent.add_widget(self) - self.bind(texture_size=self.eval_size) + + # dismiss popup by clicking on it. + def on_touch_down(self, touch): + if super().on_touch_down(touch): + return True + pos = [self.pos[0]+(self.width-self.rect.size[0])/2.0, + self.pos[1]+(self.height-self.rect.size[1])/2.0] + w = Widget(size=self.rect.size, pos=pos) + if w.collide_point(*touch.pos): + self.stop() + if self.hook is not None: + self.hook() + return True + return False # ================================================================ diff --git a/pysollib/kivy/toolbar.py b/pysollib/kivy/toolbar.py index 3e19cd3b..06305acd 100644 --- a/pysollib/kivy/toolbar.py +++ b/pysollib/kivy/toolbar.py @@ -20,7 +20,6 @@ # imports import os -from time import time from kivy.cache import Cache from kivy.clock import Clock @@ -146,63 +145,73 @@ class MyCheckButton(MyButtonBase): class MyToastButton(MyButtonBase): def __init__(self, **kwargs): super(MyToastButton, self).__init__(**kwargs) - self.timeout = 0.0 + self.timeout = 2.0 if ('timeout' in kwargs): self.timeout = kwargs['timeout'] - self.start_time = 0.0 + + def exec_command(self): + if (self.command is not None): + self.command() def on_press(self): self.allow_stretch = False - self.start_time = time() + 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 - delta = time()-self.start_time - if (self.command is not None): - if delta > self.timeout: - self.command() - else: - mainApp = Cache.get('LAppCache', 'mainApp') - toast = Toast(text=_("button released too early")) - # toast = Toast(text=_("button released too early"),pos_hint={'top': 0.8}) # noqa - # pos hint wirkt nur auf den text, nicht auf die box !!! - toast.show(parent=mainApp.baseWindow, duration=2.0) - # print('too early released') class MyWaitButton(MyButtonBase): def __init__(self, **kwargs): super(MyWaitButton, self).__init__(**kwargs) - self.timeout = 0.0 + self.timeout = 1.0 if ('timeout' in kwargs): self.timeout = kwargs['timeout'] - self.start_time = 0.0 self.eventId = None self.wait_toast = None + self.ok = False - def time_out(self, *args): - self.wait_toast.stop() - self.wait_toast = None + 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 - if (self.command is not None): - self.command() - # print ('timeout') + self.ok = True + Clock.schedule_once(self.okstart, 0.1) def on_press(self): self.allow_stretch = False - self.eventId = Clock.schedule_once(self.time_out, 1.0) - mainApp = Cache.get('LAppCache', 'mainApp') - self.wait_toast = Toast(text=_("hold on ...")) - self.wait_toast.start(mainApp.baseWindow) + 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) - # print ('unscheduled') - if self.wait_toast is not None: - self.wait_toast.stop() - self.wait_toast = None + 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. @@ -277,7 +286,7 @@ class PysolToolbarTk(BoxLayout): 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=1.0) # noqa + 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) @@ -381,8 +390,7 @@ class PysolToolbarTk(BoxLayout): button = MyCheckButton(**kw) elif timeout > 0.0: - # button = MyToastButton(**kw) - button = MyWaitButton(**kw) + button = MyToastButton(**kw) else: button = MyButton(**kw)