diff --git a/fastlane/metadata/android/en-US/changelogs/102122100.txt b/fastlane/metadata/android/en-US/changelogs/102122100.txt
index ddbe1a1a..a9c36c12 100644
--- a/fastlane/metadata/android/en-US/changelogs/102122100.txt
+++ b/fastlane/metadata/android/en-US/changelogs/102122100.txt
@@ -1,7 +1,9 @@
Android specific:
-- Temporary screen orientation lock added. Long tap (3 seconds) to the
- playground locks screen rotation, pause unlocks.
-- Toolbar: configuration of displayed toolbar buttons added to the options menu.
+- Temporary screen orientation lock added. While playing a game screen
+ rotation is locked with the first card move, unlocked when selecting
+ menu or pause.
+- Toolbar: configuration of displayed toolbar buttons added to the options
+ menu.
- Toolbar: dynamic updates on Toolbar and Options settings.
- Toolbar buttons for 'new deal' and 'restart' now display a
toast. Tap to it to accept.
diff --git a/pysollib/game/__init__.py b/pysollib/game/__init__.py
index e06dd28a..774e5b99 100644
--- a/pysollib/game/__init__.py
+++ b/pysollib/game/__init__.py
@@ -1452,16 +1452,14 @@ class Game(object):
return
if TOOLKIT == 'kivy':
- if tkraise:
- for card in cards:
- card.tkraise()
c0 = cards[0]
dx, dy = (x - c0.x), (y - c0.y)
base = float(self.app.opt.animations)
- duration = base*base/5.0/10.0
+ duration = base*base/40.0 + 0.05
for card in cards:
card.animatedMove(dx, dy, duration)
- self.top.waitAnimation(swallow=True, pickup=True)
+ # self.top.waitAnimation(swallow=True, pickup=True)
+ # synchronise: ev. per option ?
return
# init timer - need a high resolution for this to work
diff --git a/pysollib/kivy/LApp.py b/pysollib/kivy/LApp.py
index 01a483d4..55449b06 100644
--- a/pysollib/kivy/LApp.py
+++ b/pysollib/kivy/LApp.py
@@ -54,6 +54,7 @@ from kivy.uix.widget import Widget
from kivy.utils import platform
from pysollib.kivy.LBase import LBase
+from pysollib.kivy.LTask import LTask, LTaskQ
from pysollib.kivy.androidperms import requestStoragePerm
from pysollib.kivy.androidrot import AndroidScreenRotation
from pysollib.resource import CSI
@@ -113,38 +114,51 @@ class LPopCommander(LBase):
# =============================================================================
+class LAnimationTask(LTask, LBase):
+ def __init__(self, anim, spos, widget, delay):
+ super(LAnimationTask, self).__init__(widget.card)
+ self.anim = anim
+ self.spos = spos
+ self.widget = widget
+ print(self.widget.card)
+ self.delay = delay
+
+ def start(self):
+ super(LAnimationTask, self).start()
+ self.widget.pos = self.spos
+ self.anim.bind(on_complete=self.stop)
+ self.anim.start(self.widget)
+
+# =============================================================================
+
+
class LAnimationMgr(object):
def __init__(self, **kw):
super(LAnimationMgr, self).__init__()
self.animations = []
self.widgets = {}
+ self.callbacks = []
+ self.taskQ = LTaskQ()
+
+ def checkRunning(self):
+ return len(self.animations) > 0
+
+ def addEndCallback(self, cb):
+ self.callbacks.append(cb)
+ # print('len of callbacks', len(self.callbacks))
def animEnd(self, anim, widget):
# print('LAnimationMgr: animEnd = %s.%s' % (anim, widget))
- self.widgets[widget] = self.widgets[widget][1:]
self.animations.remove(anim)
- if len(self.widgets[widget]) > 0:
- # start next animation on widget
- nanim = self.widgets[widget][0]
- self.animations.append(nanim)
- print('LAnimationMgr: animEnd, append = %s' % (nanim))
- nanim.start(widget)
- else:
- # no further animations for widget so stop
- del self.widgets[widget]
+ if not self.checkRunning():
+ # print('LAnimationMgr: animEnd -> do callbacks')
+ for cb in self.callbacks:
+ cb()
+ print('LAnimationMgr: animEnd -> callbacks done')
+ self.callbacks = []
- # print('Clock.get_fps() ->', Clock.get_fps())
-
- def makeAnimStart(self, anim, spos, widget):
- def animStart(dt):
- widget.pos = spos
- # print('LAnimationMgr: animStart = %s ... %s' % (anim, dt))
- anim.start(widget)
- return animStart
-
- def checkRunning(self):
- return len(self.animations) > 0
+ print('Clock.get_fps() ->', Clock.get_fps())
def create(self, spos, widget, **kw):
x = 0.0
@@ -166,22 +180,11 @@ class LAnimationMgr(object):
anim.bind(on_complete=kw['bindE'])
if 'bindS' in kw:
anim.bind(on_start=kw['bindS'])
+ self.animations.append(anim)
offset = duration / 3.0
- # offset = duration*1.2
- timedelay = offset * len(self.animations)
- # print('offset = %s'% offset)
- # print('LAnimationMgr: timedelay = %s' % timedelay)
-
- if widget in self.widgets:
- # append additional animation to widget
- self.widgets[widget].append(anim)
- else:
- # setup first animation for widget
- self.animations.append(anim)
- self.widgets[widget] = [anim]
- Clock.schedule_once(self.makeAnimStart(
- anim, spos, widget), timedelay)
+ animTask = LAnimationTask(anim, spos, widget, offset)
+ Clock.schedule_once(lambda dt: self.taskQ.taskInsert(animTask), 0.016)
LAnimationManager = LAnimationMgr()
@@ -673,7 +676,8 @@ class LRectangle(Widget, LBase):
# =============================================================================
# Represents a Card as Kivy Window. Will contain an LImage item as child.
# Images are managed in cards.py according to the cards state. Processes
-# Events/Action on the card.
+# Events/Action on the card or other images, as LImage is designed to not
+# process events. Should not take more than one child (LImage) at a time.
class LImageItem(BoxLayout, LBase):
@@ -719,29 +723,28 @@ class LImageItem(BoxLayout, LBase):
def on_touch_down(self, touch):
- print('LCardImage: size = %s' % self.size)
+ # print('LCardImage: size = %s' % self.size)
if self.collide_point(*touch.pos):
- for c in self.children:
- # print('child at %s' % c)
- if (c.on_touch_down(touch) and self.game):
- for stack in self.game.allstacks:
- for i in range(len(stack.cards)):
- if stack.cards[i] == self.card:
- print('LCardImage: stack = %s' % stack)
- print('LCardImage: touch = %s' % str(touch))
- print('grab')
- # grab the touch!
- touch.grab(self)
- ppos, psize = self.game.canvas.KivyToCore(
- touch.pos, self.size)
- event = LEvent()
- event.x = ppos[0]
- event.y = ppos[1]
- self.dragstart = touch.pos
- event.cardid = i
- self.send_event_pressed(touch, event)
- return True
+ if (self.game):
+ for stack in self.game.allstacks:
+ for i in range(len(stack.cards)):
+ if stack.cards[i] == self.card:
+ print('LCardImage: stack = %s' % stack)
+ print('LCardImage: touch = %s' % str(touch))
+ print('grab')
+ # grab the touch!
+ touch.grab(self)
+ ppos, psize = self.game.canvas.KivyToCore(
+ touch.pos, self.size)
+ event = LEvent()
+ event.x = ppos[0]
+ event.y = ppos[1]
+ self.dragstart = touch.pos
+ event.cardid = i
+ self.send_event_pressed(touch, event)
+ AndroidScreenRotation.lock(toaster=False)
+ return True
if self.group is not None:
print('LCardImage: self=%s group=%s' % (self, self.group))
@@ -775,22 +778,19 @@ class LImageItem(BoxLayout, LBase):
if self.collide_point(*touch.pos):
- for c in self.children:
- # print('child at %s' % c)
-
- if (c.on_touch_up(touch) and self.game):
- for stack in self.game.allstacks:
- for i in range(len(stack.cards)):
- if stack.cards[i] == self.card:
- print('LCardImage: stack = %s' % stack)
- ppos, psize = self.game.canvas.KivyToCore(
- touch.pos, self.size)
- event = LEvent()
- event.x = ppos[0]
- event.y = ppos[1]
- event.cardid = i
- self.send_event_released_1(event)
- return True
+ if (self.game):
+ for stack in self.game.allstacks:
+ for i in range(len(stack.cards)):
+ if stack.cards[i] == self.card:
+ print('LCardImage: stack = %s' % stack)
+ ppos, psize = self.game.canvas.KivyToCore(
+ touch.pos, self.size)
+ event = LEvent()
+ event.x = ppos[0]
+ event.y = ppos[1]
+ event.cardid = i
+ self.send_event_released_1(event)
+ return True
if self.group is not None:
print('LCardImage: self=%s group=%s' % (self, self.group))
@@ -1266,7 +1266,7 @@ class LMenuItem(ActionButton, LBase):
pass
def setCommand(self, cmd):
- # print('LMenuItem: setCommand')
+ print('LMenuItem: setCommand')
self.bind(on_release=cmd)
# def __str__(self):
@@ -1575,7 +1575,6 @@ class LMainWindow(BoxLayout, LTkBase):
def on_touch_down(self, touch):
ret = False
-
if super().on_touch_down(touch):
return True
@@ -1655,7 +1654,6 @@ class LMainWindow(BoxLayout, LTkBase):
def on_longPress(self, instance, timestamp):
print('longPressed at {time}'.format(time=timestamp))
- AndroidScreenRotation.lock()
# Menubar:
@@ -1889,7 +1887,7 @@ class LApp(App):
if app is None:
return
- AndroidScreenRotation.unlock()
+ AndroidScreenRotation.unlock(toaster=False)
so = get_screen_ori()
go = so # flake8: F841 nonsense!
diff --git a/pysollib/kivy/LImage.py b/pysollib/kivy/LImage.py
index 91b0d125..5bc7e02f 100644
--- a/pysollib/kivy/LImage.py
+++ b/pysollib/kivy/LImage.py
@@ -31,7 +31,7 @@ class LImage(Widget, LBase):
COVER = 2
SCALE_DOWN = 3
TILING = 4
- fit_mode = StringProperty("fill")
+ fit_mode = StringProperty("contain")
texture = ObjectProperty(None, allownone=True)
def make_scale_down(self, s, p):
@@ -63,12 +63,9 @@ class LImage(Widget, LBase):
def make_cover(self, s, p):
aspect = self.texture.size[0]/self.texture.size[1]
waspect = self.size[0]/self.size[1]
- print ('aspect: ', aspect) # noqa
- print ('waspect: ', waspect) # noqa
# 'clamp_to_edge','repeat','mirrored_repeat'
self.texture.wrap = 'repeat'
- print ('wrap: ',self.texture.wrap) # noqa
# set rect size/pos to window
self.rect.size = s
@@ -172,7 +169,8 @@ class LImage(Widget, LBase):
self.tex_coord_update(self.texture)
# initial size is the natural size of the image.
- self.size = self.texture.size
+ if self.texture is not None:
+ self.size = self.texture.size
def tex_coord_update(self, texture):
if hasattr(self, "rect"):
@@ -202,10 +200,12 @@ class LImage(Widget, LBase):
self.make_format(self.size, p)
def on_fit_mode(self, a, m):
+ print('on_fit_mode', m)
self.fit_num_update(self.fit_mode)
self.make_format(self.size, self.pos)
def on_texture(self, a, texture):
+ print('on_texture', texture)
self.tex_coord_update(self.texture)
self.make_format(self.size, self.pos)
@@ -221,24 +221,4 @@ class LImage(Widget, LBase):
def subsample(self, r):
return LImage(texture=self.texture)
- def on_touch_down(self, touch):
- # print('LImage: touch_down on %s' % str(touch.pos))
- if self.collide_point(*touch.pos):
- if (self.source is not None):
- print('LImage match %s' % self.source)
- else:
- print('LImage match with texture')
- return True
- return False
-
- def on_touch_up(self, touch):
- # print('LImage: touch_up on %s' % str(touch.pos))
- if self.collide_point(*touch.pos):
- if (self.source is not None):
- print('LImage match %s' % self.source)
- else:
- print('LImage match with texture')
- return True
- return False
-
# =============================================================================
diff --git a/pysollib/kivy/LTask.py b/pysollib/kivy/LTask.py
new file mode 100644
index 00000000..3aa37ad2
--- /dev/null
+++ b/pysollib/kivy/LTask.py
@@ -0,0 +1,112 @@
+# -*- mode: python; coding: utf-8; -*-
+# ---------------------------------------------------------------------------##
+# Copyright 2016, 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 .
+
+from kivy._event import EventDispatcher
+from kivy.clock import Clock
+from kivy.properties import BooleanProperty, ListProperty
+
+
+class LTask(EventDispatcher):
+ done = BooleanProperty(False)
+
+ def __init__(self, name):
+ super(LTask, self).__init__()
+ self.done = False
+ self.name = name
+ self.delay = 0.01
+
+ def start(self):
+ # print('start of ',self.name)
+ self.done = False
+
+ def stop(self, *args):
+ # print('stop of ',self.name)
+ self.done = True
+
+ def on_done(self, instance, value):
+ # print ('on_done',instance,value)
+ pass
+
+
+class LTaskQ(EventDispatcher):
+ waitQ = ListProperty([])
+ runQ = ListProperty([])
+
+ def __init__(self, **kwargs):
+ super(LTaskQ, self).__init__(**kwargs)
+ self.waitQ = []
+ self.waitQlen = 0
+ self.runQ = []
+ self.runQlen = 0
+ self.runQmax = 52
+ self.runSeq = 1.0/10.0 # default delay.
+
+ def scheduleNext(self, dt):
+ if (self.waitQlen > 0):
+ # run as long as there is enough place in the runQ
+ # do not run more than one job with the same name
+ # at the same time.
+ delayed = False
+ if (self.runQlen < self.runQmax):
+ names = [ t.name for t in self.runQ ] # noqa
+ if self.waitQ[0].name not in names:
+ self.runQ.append(self.waitQ[0])
+ del self.waitQ[0]
+ else:
+ delayed = True
+
+ delay = self.runSeq
+ if self.waitQlen > 0 and not delayed:
+ delay = self.waitQ[0].delay
+
+ if (self.waitQlen > 0 or self.runQlen > 0):
+ Clock.schedule_once(self.scheduleNext, delay)
+
+ def on_runQ(self, instance, value):
+ lastlen = self.runQlen
+ self.runQlen = len(self.runQ)
+
+ if (self.runQlen > lastlen):
+ self.runQ[-1].bind(done=self.taskStopped)
+ self.runQ[-1].start()
+
+ def on_waitQ(self, instance, value):
+ self.waitQlen = len(self.waitQ)
+ if (self.waitQlen > 0 and self.runQlen == 0):
+ self.scheduleNext(0)
+
+ def taskQsAreEmpty(self):
+ return (self.waitQlen == 0 and self.runQlen == 0)
+
+ def taskInsert(self, task):
+ # print('taskInsert called', task)
+ self.waitQ.append(task)
+
+ def taskStopped(self, instance, value):
+ if (value is True):
+ idx = 0
+ while (idx < self.runQlen):
+ if (self.runQ[idx] is instance):
+ break
+ idx += 1
+
+ if (idx < self.runQlen):
+ # print('taskStopped', instance, 'index', idx)
+ del self.runQ[idx]
+ else:
+ # print('taskStopped: index out of range!')
+ pass
diff --git a/pysollib/kivy/androidrot.py b/pysollib/kivy/androidrot.py
index 72499be7..22bdc613 100644
--- a/pysollib/kivy/androidrot.py
+++ b/pysollib/kivy/androidrot.py
@@ -20,20 +20,22 @@ class AndroidRot(object):
def isLocked(self):
return self.locked
- def lock(self):
+ def lock(self, toaster=True):
if jnius is not None:
if not self.locked:
self.currentActivity.setRequestedOrientation(
self.ActivityInfo.SCREEN_ORIENTATION_LOCKED)
- AndroidToaster.toastShort(_("screen rotation disabled"))
+ if toaster:
+ AndroidToaster.toastShort(_("screen rotation disabled"))
self.locked = True
- def unlock(self):
+ def unlock(self, toaster=True):
if jnius is not None:
if self.locked:
self.currentActivity.setRequestedOrientation(
self.ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR)
- AndroidToaster.toastShort(_("screen rotation enabled"))
+ if toaster:
+ AndroidToaster.toastShort(_("screen rotation enabled"))
self.locked = False
def toggle(self):
diff --git a/pysollib/kivy/card.py b/pysollib/kivy/card.py
index 747ab0cc..75381938 100644
--- a/pysollib/kivy/card.py
+++ b/pysollib/kivy/card.py
@@ -24,23 +24,17 @@
from pysollib.acard import AbstractCard
from pysollib.kivy.LApp import LImageItem
from pysollib.kivy.LImage import LImage
-from pysollib.kivy.tkcanvas import MfxCanvasGroup, MfxCanvasImage
+from pysollib.kivy.tkcanvas import MfxCanvasImage
class _HideableCard(AbstractCard):
def hide(self, stack):
if stack is self.hide_stack:
return
- self.item.config(state="hidden")
- self.hide_stack = stack
- # print "hide:", self.id, self.item.coords()
def unhide(self):
if self.hide_stack is None:
return 0
- # print "unhide:", self.id, self.item.coords()
- self.item.config(state="normal")
- self.hide_stack = None
return 1
# moveBy aus Basisklasse überschreiben.
@@ -76,9 +70,6 @@ class _OneImageCard(_HideableCard):
self._face_image = LImage(texture=fimage.texture)
self._back_image = LImage(texture=bimage.texture)
- # self._face_image = Image(source=fimage.source)
- # self._back_image = Image(source=bimage.source)
- self._shade_image = game.getCardShadeImage()
aimage = LImageItem(
pos=(x, -y), size=self._face_image.size, game=game, card=self)
@@ -87,7 +78,6 @@ class _OneImageCard(_HideableCard):
self.item = MfxCanvasImage(
game.canvas, self.x, self.y, image=aimage, anchor="nw")
- self.shade_item = None
# print ('card: face = %s xy=%s/%s' % (self._face_image.source, x, y))
# print ('card: back = %s xy=%s/%s' % (self._back_image.source, x, y))
@@ -117,151 +107,22 @@ class _OneImageCard(_HideableCard):
if not self.face_up:
self._setImage(image=self._back_image)
+ '''
def setSelected(self, s, group=None):
print('card: setselected(%s, %s)' % (s, group))
# wird nicht bedient.
+ # NOTE:
+ # This is one of the zombie methods (nowhere impelemeted: close,
+ # unclose, and somewhat dummy implemented ones: hide, unhide)
+ # of the base class AbstractCard.
+ # (-> some clean ups for clarity would be nice)
pass
+ '''
def animatedMove(self, dx, dy, duration=0.2):
self.item.animatedMove(dx, dy, duration)
-# ************************************************************************
-# * New idea since 3.00
-# *
-# * Hide a card by configuring the canvas image to None.
-# ************************************************************************
-
-class _OneImageCardWithHideByConfig(_OneImageCard):
- def hide(self, stack):
- if stack is self.hide_stack:
- return
- self._setImage(image=None)
- self.hide_stack = stack
-
- def unhide(self):
- if self.hide_stack is None:
- return 0
- if self.face_up:
- self._setImage(image=self._face_image)
- else:
- self._setImage(image=self._back_image)
- self.hide_stack = None
- return 1
-
- #
- # much like in _OneImageCard
- #
-
- def showFace(self, unhide=1):
- if not self.face_up:
- if unhide:
- self._setImage(image=self._face_image)
- self.item.tkraise()
- self.face_up = 1
-
- def showBack(self, unhide=1):
- if self.face_up:
- if unhide:
- self._setImage(image=self._back_image)
- self.item.tkraise()
- self.face_up = 0
-
- def updateCardBackground(self, image):
- self._back_image = image
- if not self.face_up and not self.hide_stack:
- self._setImage(image=image)
-
-
-# ************************************************************************
-# * Old implemetation prior to 2.10
-# *
-# * The card consists of two CanvasImages. To show the card face up,
-# * the face item is placed in front of the back. To show it face
-# * down, this is reversed.
-# ************************************************************************
-
-
-class _TwoImageCard(_HideableCard):
- # Private instance variables:
- # __face, __back -- the canvas items making up the card
- def __init__(self, id, deck, suit, rank, game, x=0, y=0):
- _HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y)
- self.item = MfxCanvasGroup(game.canvas)
- self.__face = MfxCanvasImage(
- game.canvas, self.x, self.y,
- image=game.getCardFaceImage(deck, suit, rank), anchor="nw")
- self.__back = MfxCanvasImage(
- game.canvas, self.x, self.y,
- image=game.getCardBackImage(deck, suit, rank), anchor="nw")
- self.__face.addtag(self.item)
- self.__back.addtag(self.item)
-
- def showFace(self, unhide=1):
- if not self.face_up:
- self.__face.tkraise()
- self.tkraise(unhide)
- self.face_up = 1
-
- def showBack(self, unhide=1):
- if self.face_up:
- self.__back.tkraise()
- self.tkraise(unhide)
- self.face_up = 0
-
- def updateCardBackground(self, image):
- self.__back.config(image=image)
-
-
-# ************************************************************************
-# * New idea since 2.90
-# *
-# * The card consists of two CanvasImages. Instead of raising
-# * one image above the other we move the inactive image out
-# * of the visible canvas.
-# ************************************************************************
-
-
-class _TwoImageCardWithHideItem(_HideableCard):
- # Private instance variables:
- # __face, __back -- the canvas items making up the card
- def __init__(self, id, deck, suit, rank, game, x=0, y=0):
- _HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y)
- self.item = MfxCanvasGroup(game.canvas)
- self.__face = MfxCanvasImage(
- game.canvas, self.x, self.y + 11000,
- image=game.getCardFaceImage(deck, suit, rank), anchor="nw")
- self.__back = MfxCanvasImage(
- game.canvas, self.x, self.y,
- image=game.getCardBackImage(deck, suit, rank), anchor="nw")
- self.__face.addtag(self.item)
- self.__back.addtag(self.item)
-
- def showFace(self, unhide=1):
- if not self.face_up:
- self.__back.move(0, 10000)
- # self.__face.tkraise()
- self.__face.move(0, -11000)
- self.tkraise(unhide)
- self.face_up = 1
-
- def showBack(self, unhide=1):
- if self.face_up:
- self.__face.move(0, 11000)
- # self.__back.tkraise()
- self.__back.move(0, -10000)
- self.tkraise(unhide)
- self.face_up = 0
-
- def updateCardBackground(self, image):
- self.__back.config(image=image)
-
-
-# choose the implementation
-# Card = _TwoImageCardWithHideItem
-# Card = _TwoImageCard
-# Card = _OneImageCardWithHideByConfig
Card = _OneImageCard
-
'''end of file'''
diff --git a/pysollib/kivy/menubar.py b/pysollib/kivy/menubar.py
index 88703261..990dde5f 100644
--- a/pysollib/kivy/menubar.py
+++ b/pysollib/kivy/menubar.py
@@ -176,6 +176,9 @@ class MainMenuDialog(LMenuDialog):
super(MainMenuDialog, self).__init__(
menubar, parent, title, app, **kw)
+ print('MainMenuDialog starting')
+ AndroidScreenRotation.unlock()
+
def buildTree(self, tv, node):
rg = tv.add_node(
LTreeNode(
@@ -222,6 +225,7 @@ class FileMenuDialog(LMenuDialog):
def make_game_command(self, key, command):
def game_command():
+ self.closeWindow(0)
command(key)
return game_command
@@ -2086,7 +2090,7 @@ class PysolMenubarTk:
return
self.game.doPause()
self.tkopt.pause.set(self.game.pause)
- AndroidScreenRotation.unlock()
+ AndroidScreenRotation.unlock(toaster=False)
def mOptLanguage(self, *args):
if self._cancelDrag(break_pause=False):
diff --git a/pysollib/kivy/tkcanvas.py b/pysollib/kivy/tkcanvas.py
index 1ef46672..add0ef98 100644
--- a/pysollib/kivy/tkcanvas.py
+++ b/pysollib/kivy/tkcanvas.py
@@ -26,12 +26,11 @@ from __future__ import division
import logging
import math
+# import inspect
+
from kivy.clock import Clock
-from kivy.graphics import Color
-from kivy.graphics import Rectangle
from kivy.uix.anchorlayout import AnchorLayout
-from kivy.uix.widget import Widget
from pysollib.kivy.LApp import LAnimationManager
from pysollib.kivy.LApp import LColorToKivy
@@ -39,7 +38,6 @@ from pysollib.kivy.LApp import LImageItem
from pysollib.kivy.LApp import LLine
from pysollib.kivy.LApp import LRectangle
from pysollib.kivy.LApp import LText
-from pysollib.kivy.LBase import LBase
from pysollib.kivy.LImage import LImage
# ************************************************************************
@@ -147,12 +145,26 @@ class MfxCanvasGroup():
# damit is 0 das unterste image und -1 das oberste.
return ilst
+ def makeDeferredRaise(self, pos):
+ def animCallback():
+ self.tkraise(position=pos)
+ return animCallback
+
def tkraise(self, position=None):
# print(self, ' tkraise(', position, ')')
# Das wird bei Mahjongg extensiv aufgerufen, wenn der Move
# abeschlossen ist. Wird aber auch bei andern games benutzt.
+ # print('stack[1] = ',inspect.stack()[1].frame)
+ # print('stack[2] = ',inspect.stack()[2].frame)
+
+ if LAnimationManager.checkRunning():
+ LAnimationManager.addEndCallback(
+ self.makeDeferredRaise(position))
+ return
imgs = self._imglist(self)
+ # print('number of imaages:', len(imgs))
+
if position is not None:
# In self.canvas suchen: das oberste image, welches zu position
# gehört und liste der images oberhalb einfüllen u.a.a.O weglassen.
@@ -178,9 +190,21 @@ class MfxCanvasGroup():
for w in ws:
self.canvas.add_widget(w)
+ def makeDeferredLower(self, pos):
+ def animCallback():
+ self.lower(position=pos)
+ return animCallback
+
def lower(self, position=None):
# print(self, ' lower(', position, ')')
# dasselbe wi tkraise aber vorher statt nachher einfügen.
+ # print('stack[1] = ',inspect.stack()[1].frame)
+ # print('stack[2] = ',inspect.stack()[2].frame)
+
+ if LAnimationManager.checkRunning():
+ LAnimationManager.addEndCallback(
+ self.makeDeferredLower(position))
+ return
imgs = self._imglist(self)
if position is not None:
@@ -221,10 +245,8 @@ class MfxCanvasGroup():
def cardmagnif(canvas, size):
-
def pyth(s):
return math.sqrt(s[0]*s[0]+s[1]*s[1])
-
cs = canvas.wmain.app.images.getSize()
csl = pyth(cs)
sl = pyth(size)
@@ -258,7 +280,10 @@ class MfxCanvasImage(object):
super(MfxCanvasImage, self).__init__()
self.canvas = canvas
+
+ # animation support:
self.animation = None
+ self.deferred_raises = []
ed = kwargs['image']
size = ed.size
@@ -301,15 +326,27 @@ class MfxCanvasImage(object):
def config(self, **kw):
pass
+ def makeDeferredRaise(self, pos):
+ def animCallback():
+ self.canvas.tag_raise(self.image, pos)
+ return animCallback
+
def tkraise(self, aboveThis=None):
- # print(self, ': tkraise, above =', aboveThis)
abitm = None
if aboveThis:
- if isinstance(aboveThis, MfxCanvasImage):
- abitm = aboveThis.widget
- if isinstance(aboveThis, LImageItem):
- abitm = aboveThis
+ abitm = aboveThis.widget
+
+ # print('stack[1] = ', inspect.stack()[1].frame)
+ # print('stack[2] = ', inspect.stack()[2].frame)
+ # print('stack[3] = ', inspect.stack()[3].frame)
+
+ if self.animation:
+ print('defer tkraise to animation', abitm)
+ self.deferred_raises.append(self.makeDeferredRaise(abitm))
+ return
+
+ # print('direct tkraise', abitm)
self.canvas.tag_raise(self.image, abitm)
def addtag(self, tag):
@@ -340,21 +377,30 @@ class MfxCanvasImage(object):
def makeAnimStart(self):
def animStart(anim, widget):
- # print('MfxCanvasImage: animStart %s' % self)
- # nothing to do hiere
- pass
+ print('MfxCanvasImage: animStart %s' % self)
+ # karte nach vorne nehmen - vorgänger karte merken
+ # für restore.
+ # self.canvas.tag_raise(self.image)
+
+ for cb in self.deferred_raises:
+ print('do deferred tkraise:')
+ cb()
+ self.deferred_raises = []
+
return animStart
def makeAnimEnd(self, dpos, dsize):
def animEnd(anim, widget):
- # print('MfxCanvasImage: animEnd %s' % self)
+ print('MfxCanvasImage: animEnd %s' % self)
+ # karte wieder vor die vorgängerkarte setzen.
self.animation = False
+ self.deferred_raises = []
image = self.image
image.pos, image.size = self.canvas.CoreToKivy(dpos, dsize)
return animEnd
def animatedMove(self, dx, dy, duration=0.2):
- # print ('MfxCanvasImage: animatedMove %s, %s' % (dx, dy))
+ print('MfxCanvasImage: animatedMove %s, %s' % (dx, dy))
image = self.image
dsize = image.coreSize
@@ -512,13 +558,13 @@ class MfxCanvasText(object):
# ************************************************************************
-class MfxCanvas(Widget, LBase):
+class MfxCanvas(LImage):
def __str__(self):
return f''
def __init__(self, wmain, *args, **kw):
- super(MfxCanvas, self).__init__()
+ super(MfxCanvas, self).__init__(background=True)
# print('MfxCanvas: __init__()')
# self.tags = {} # bei basisklasse widget (ev. nur vorläufig)
@@ -646,91 +692,23 @@ class MfxCanvas(Widget, LBase):
# Hintergrund update.
- self.canvas.before.clear()
+ kc = LColorToKivy(self._bg_color)
texture = None
if self._bg_img:
texture = self._bg_img.texture
- # Color only: Nur eine Hintergrundfarbe wird installiert.
+ self.texture = texture
if texture is None:
- kc = LColorToKivy(self._bg_color)
- self.canvas.before.add(
- Color(kc[0], kc[1], kc[2], kc[3]))
- self.canvas.before.add(
- Rectangle(pos=self.pos, size=self.size))
- return
-
- # Image: Das Bild wird im Fenster expandiert.
- if self._stretch_bg_image:
- if self._save_aspect_bg_image == 0:
- self.canvas.before.add(
- Rectangle(texture=texture, pos=self.pos, size=self.size))
- else:
- # save aspect
- aspect = texture.size[0]/texture.size[1]
- waspect = self.size[0]/self.size[1]
- print ('aspect: ', aspect) # noqa
- print ('waspect: ', waspect) # noqa
-
- # 'clamp_to_edge','repeat','mirrored_repeat'
- texture.wrap = 'repeat'
- print ('wrap: ',texture.wrap) # noqa
-
- # add new rectangle to canvas.
- r = Rectangle(texture=texture, pos=self.pos, size=self.size)
- self.canvas.before.add(r)
-
- # evaluate original texture coords.
- uu = r.tex_coords[0]
- vv = r.tex_coords[1]
- ww = r.tex_coords[2] - uu
- hh = r.tex_coords[5] - vv
-
- # in order to center the image in the window
- # modify texture coords
- if waspect < aspect:
- w = ww/aspect*waspect # noqa
- h = hh
- u = 0.5 - w/2.0 # noqa
- v = vv
- else:
- w = ww
- h = hh*aspect/waspect # noqa
- u = uu
- v = 0.5 - h/2.0 # noqa
-
- # and update them.
- tc = ( u, v, u + w, v, u + w, v + h, u, v + h ) # noqa
- r.tex_coords = tc
-
- print ('tex_coords (orig):',uu,vv,ww,hh) # noqa
- print ('tex_coords (mod): ',u,v,w,h) # noqa
- return
-
+ self.setColor(kc)
else:
- # Tiles placement, reference point is bottom left.
-
- texture.wrap = 'repeat'
- r = Rectangle(texture=texture, pos=self.pos, size=self.size)
- self.canvas.before.add(r)
-
- # stsize = (texture.size[0] * self.scale,
- # texture.size[1] * self.scale)
- stsize = texture.size
- stepsy = self.size[1] / stsize[1]
- stepsx = self.size[0] / stsize[0]
-
- u = r.tex_coords[0]
- v = r.tex_coords[1]
- ww = r.tex_coords[2] - u
- hh = r.tex_coords[5] - v
- w = ww * stepsx
- h = hh * stepsy
-
- # move reference point to top left:
- v = stepsy - math.floor(stepsy)
-
- r.tex_coords = ( u, v, u + w, v, u + w, v + h, u, v + h ) # noqa
+ self.setColor([1,1,1,1]) # noqa
+ if self._stretch_bg_image:
+ if self._save_aspect_bg_image == 0:
+ self.fit_mode = "fill"
+ else:
+ self.fit_mode = "cover"
+ else:
+ self.fit_mode = "tiling"
# Funktionen, welche vom Core aufgerufen werden.
diff --git a/pysollib/kivy/tkwidget.py b/pysollib/kivy/tkwidget.py
index c3342335..ba251bee 100644
--- a/pysollib/kivy/tkwidget.py
+++ b/pysollib/kivy/tkwidget.py
@@ -440,7 +440,7 @@ class MfxScrolledCanvas(object):
tile.color == app.opt.colors['table']):
return False
#
- print('setTile2: %s' % (tile.filename))
+ print('setTile2: %s, %s' % (tile.filename, tile.color))
if not self.canvas.setTile(
tile.filename, tile.stretch, tile.save_aspect):