This commit is contained in:
yumoqing 2022-11-14 17:07:42 +08:00
parent 1352d23245
commit 9b6084e15d
11 changed files with 335 additions and 230 deletions

View File

@ -2,8 +2,8 @@ from kivy.logger import Logger
from kivy.graphics import Color, Rectangle, RoundedRectangle
from kivy.properties import ListProperty, NumericProperty
from .color_definitions import getColors
from .mixin import register_mixin
_logcnt = 0
class BGColorBehavior(object):
color_level=NumericProperty(0)
radius = ListProperty([])
@ -65,3 +65,5 @@ class BGColorBehavior(object):
self.bgcolor = self.normal_bgcolor
self.color = self.fgcolor = self.normal_fgcolor
self.on_bgcolor()
register_mixin('BGColorBehavior', BGColorBehavior)

View File

@ -103,6 +103,7 @@ def registerWidget(name:str,widget):
globals()[name] = widget
klass_cnt = 0
class Blocks(EventDispatcher):
def __init__(self):
EventDispatcher.__init__(self)
@ -113,6 +114,47 @@ class Blocks(EventDispatcher):
config = getConfig()
self.script = Script()
def klassBuild(self, klass_name, options):
global klass_cnt
exclude_mixin = filter_mixin(options)
mixins = get_mixins(options)
klasses = [
{
'name':klass_name,
'klass':Factory.get(klass_name),
'opts':exclude_mixin
}
]
if mixins == {}:
return Factory.get(klass_name)(**options)
env = globals().copy()
lenv = {}
for n, d, in mixins.items():
klasses.append({
'name':n,
'klass':Factory.get(n),
'opts':d
})
print('mixins=', mixins)
env['klasses'] = klasses
ids = [ i for i in range(len(klasses))]
ids.reverse()
klasslist = ','.join([f'klasses[{i}]["klass"]' for i in ids])
code = f"""class ClassX{klass_cnt}({klasslist}):
def __init__(self):
for i in range(len(klasses)):
print(klasses[i]['opts'])
klasses[i]['klass'].__init__(self, **klasses[i]['opts'])
x = ClassX{klass_cnt}()
"""
print(code)
exec(code, env, lenv)
w = lenv.get('x', None)
klass_cnt += 1
return w
def set(self, k:str, v):
self.env[k] = v
@ -243,19 +285,17 @@ class Blocks(EventDispatcher):
if not widgetClass:
Logger.info("Block: w_build(), desc invalid", desc)
raise Exception(desc)
widgetClass = desc['widgettype']
opts_org = self.valueExpr(desc.get('options',{}).copy())
opts = filter_mixin(opts_org)
bopts = get_mixins(opts_org)
widget = None
try:
"""
klass = Factory.get(widgetClass)
widget = klass(**opts)
mixin_behaviors(widget, bopts)
"""
widget = self.klassBuild(widgetClass, opts_org)
except Exception as e:
print('Error:',widgetClass,'contructon error')
print('Error:',widgetClass,'construction error')
print_exc()
raise NotExistsObject(widgetClass)
@ -314,7 +354,7 @@ class Blocks(EventDispatcher):
kw = self.valueExpr(sw.copy(),
localnamespace={'self':widget})
w = b.widgetBuild(kw)
if w:
if w and not w.parent:
widget.add_widget(w)
@ -684,7 +724,9 @@ class Blocks(EventDispatcher):
if widgettype is None:
print('Block3: desc must be a dict object not None')
return None
return doit(desc)
w = doit(desc)
print('widgetBuild():w=', w)
return w
@classmethod
def findWidget(self, id:str, from_widget:Widget=None) -> Widget:

View File

@ -1,27 +1,62 @@
from kivy.factory import Factory
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.behaviors import CodeNavigationBehavior
from kivy.uix.behaviors import CompoundSelectionBehavior
from kivy.uix.behaviors import CoverBehavior
from kivy.uix.behaviors import DragBehavior
from kivy.uix.behaviors import EmacsBehavior
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.uix.behaviors import TouchRippleBehavior
from kivy.uix.behaviors import TouchRippleButtonBehavior
from kivy.factory import Factory
_mix_ins = {}
# def on_press(inst, *args):
# pass
# ButtonBehavior.on_press = on_press
def filter_mixin(kwargs):
return {k:v for k, v in kwargs.items() if not k.endswith('behavior')}
return {k:v for k, v in kwargs.items() if not k.endswith('Behavior')}
def get_mixins(kwargs):
return {k:v for k, v in kwargs.items() if k.endswith('behavior')}
return {k:v for k, v in kwargs.items() if k.endswith('Behavior')}
def register_mixin(name, klass):
_mix_ins[name] = klass
Factory.register(name, klass)
def mix_other(inst, other):
for k,v in other.__dict__.items():
setattr(inst, k, v)
excluded = ['__class__', '__dict__', '__weakref__']
keys = [ k for k in dir(other) if k not in excluded ]
for k in keys:
if not hasattr(inst, k):
setattr(inst, k, getattr(other, k))
def mixin_behaviors(inst, kwargs):
behaviors_kw = get_mixins(kwargs)
for name, dic in behaviors_kw.items():
klass = _mix_ins.get(name)
if klass:
other = Factory.Blocks().widgetBuild(dic)
mix_other(klass, inst.__class__)
desc = {
"widgettype":name,
"options":dic
}
other = Factory.Blocks().widgetBuild(desc)
if other:
mix_other(inst, other)
register_mixin('ButtonBehavior', ButtonBehavior)
register_mixin('CodeNavigationBehavior', CodeNavigationBehavior)
register_mixin('CompoundSelectionBehavior', CompoundSelectionBehavior)
register_mixin('CoverBehavior', CoverBehavior)
register_mixin('DragBehavior', DragBehavior)
register_mixin('EmacsBehavior', EmacsBehavior)
register_mixin('FocusBehavior', FocusBehavior)
register_mixin('ToggleButtonBehavior', ToggleButtonBehavior)
register_mixin('TouchRippleBehavior', TouchRippleBehavior)
register_mixin('TouchRippleButtonBehavior', TouchRippleButtonBehavior)

View File

@ -1,10 +1,9 @@
from kivy.core.window import Window
from kivy.properties import DictProperty, BooleanProperty, \
StringProperty, OptionProperty, \
NumericProperty
from mixin import register_mixin
class ModalBehavior(object):
auto_open = BooleanProperty(True)
auto_dismiss = BooleanProperty(True)
@ -14,9 +13,10 @@ class ModalBehavior(object):
'cl', 'cc', 'cr',
'bl', 'bc', 'br'])
def __init__(self, **kw):
for k,v in kw.items():
setattr(self, k,v)
self.time_task = None
self._target = None
super(Modal, self).__init__(**kw)
self.set_size_position()
self._target.bind(size=self.set_size_position)
self.register_event_type('on_open')
@ -28,11 +28,17 @@ class ModalBehavior(object):
self.open()
def on_touchdown(self, o, touch):
if not self.collide_point(touch.x, touch.y):
print('on_touchdown() called')
if not self.collide_point(touch.x, touch.y):
if self.auto_dismiss:
print('on_touchdown():auto_dismiss()')
self.dispatch('on_pre_dismiss')
self.dismiss()
return True
else:
print('on_touchdown(): not auto_dismiss')
else:
print('on_touchdown():inside modal')
def on_target(self, *args):
self._target = None
@ -77,6 +83,7 @@ class ModalBehavior(object):
self.pos = x, y
else:
self.pos = self._target.pos[0] + x, self._target.pos[1] + y
print("modal",self._target.size, self.position, self.pos, self.size, self.size_hint)
def open(self):
if self.time_task is not None:
@ -94,6 +101,7 @@ class ModalBehavior(object):
self._target.disabled = True
def dismiss(self, *args):
print('dismiss() called')
if self.time_task:
self.time_task.cancel()
self.time_task = None
@ -115,4 +123,3 @@ class ModalBehavior(object):
def on_pre_dismiss(self, *args):
pass
register_mixin('modalbehavior', ModalBehavior)

View File

@ -45,10 +45,12 @@ from .ffpyplayer_video import FFVideo
from .upload import UploadFile
from .pyinterpreter import PyInterpreter
from .circle_progress import CircleProgress
from .modalbehavior import ModalBehavior
r = Factory.register
# if kivy.platform in ['win','linux', 'macosx']:
# r('ScreenWithMic', ScreenWithMic)
r('ModalBehavior', ModalBehavior)
r('CircleProgress', CircleProgress)
r('PyInterpreter', PyInterpreter)
r('UploadFile', UploadFile)

View File

@ -35,10 +35,10 @@ class Script:
self.register('.ui', TemplateHandler)
def url2filepath(self, url):
if url.startswith('file:///'):
url = url[8:]
if url.startswith('file://'):
url = url[7:]
ret = join(self.root, *url.split('/'))
# print('url2filepath():root=', self.root, url, ret)
print('url2filepath():root=', self.root, url, ret)
return ret
def show_info(self, env):

View File

@ -1,5 +1,6 @@
import time
from kivy.logger import Logger
from .mixin import register_mixin
class SwipeBehavior(object):
def __init__(self, **kwargs):
@ -56,6 +57,7 @@ class SwipeBehavior(object):
# Logger.info('SwipeBehavior:touch_down fired')
if self.swipeenable:
# Logger.info('SwipeBehavior:touch_down fired')
touch.grab(self)
self.sb_start_point = touch.pos
self.sb_start_time = time.time()
@ -69,8 +71,10 @@ class SwipeBehavior(object):
def on_touchup(self,o,touch):
ret = False
if self.collide_point(*touch.pos) and self.swipeenable:
if self.collide_point(*touch.pos) and self.swipeenable and \
touch.grab_current is self:
# Logger.info('SwipeBehavior:touch_up fired')
touch.ungrab(self)
self.sb_end_point = touch.pos
self.sb_end_time = time.time()
self.check_context_menu()
@ -116,3 +120,5 @@ class SwipeBehavior(object):
elif self.sb_start_point[1] - self.sb_end_point[1] >= \
self.threshold:
self.dispatch('on_swipe_down')
register_mixin('SwipeBehavior', SwipeBehavior)

View File

@ -48,8 +48,7 @@ def SUPER(klass, obj, kw):
super(klass, obj).__init__(**kw)
for k,v in dic.items():
try:
if v is not None:
setattr(obj, k, v)
setattr(obj, k, v)
except Exception as e:
print(f'obj={obj}, setattr(obj, "{k}","{v}") error')
print_exc()

View File

@ -8,6 +8,7 @@
"hugest":6.5
},
"font_name":"normal",
"uihome":"file://",
"script_root":"$[workdir]$/scripts",
"root":{
"widgettype":"urlwidget",

View File

@ -14,6 +14,21 @@
"label":"Setting",
"icon":"{{entire_url('/imgs/setting.png')}}",
"url":"{{entire_url('t.ui')}}"
},
{
"id":"behavior1",
"label":"behavior1",
"url":"{{entire_url('boxlayout/behavior.ui')}}"
},
{
"id":"modal1",
"label":"Modal Text",
"url":"{{entire_url('boxlayout/modalbehavior.ui')}}"
},
{
"id":"boxlayout",
"label":"WBoxLayout",
"url":"{{entire_url('boxlayout/normal.ui')}}"
}
]
}

View File

@ -1,4 +0,0 @@
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=898222,RESOLUTION=1047x576,CODECS="avc1.77.30,mp4a.40.2"
chunklist_w891111828.m3u8