This commit is contained in:
yumoqing 2021-12-16 15:34:07 +08:00
parent c06e8a541e
commit 23fb775723
3 changed files with 196 additions and 85 deletions

View File

@ -5,7 +5,8 @@ from kivy.graphics import Color, Rectangle
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory from kivy.factory import Factory
from kivy.uix.image import AsyncImage from kivy.uix.image import AsyncImage
from kivy.properties import NumericProperty, ObjectProperty, StringProperty, BooleanProperty from kivy.properties import NumericProperty, DictProperty, \
ObjectProperty, StringProperty, BooleanProperty
from kivyblocks.ready import WidgetReady from kivyblocks.ready import WidgetReady
from kivyblocks.bgcolorbehavior import BGColorBehavior from kivyblocks.bgcolorbehavior import BGColorBehavior
@ -26,6 +27,7 @@ class ClickableBox(TouchRippleButtonBehavior, Box):
**kw) **kw)
self.border_width = border_width self.border_width = border_width
self.bind(minimum_height=self.setter('height')) self.bind(minimum_height=self.setter('height'))
self.bind(minimum_width=self.setter('width'))
def on_press(self,o=None): def on_press(self,o=None):
pass pass
@ -35,27 +37,44 @@ class ClickableText(ClickableBox):
def __init__(self, **kw): def __init__(self, **kw):
super(ClickableText, self).__init__(**kw) super(ClickableText, self).__init__(**kw)
self.txt_w = Text(text=self.text, i18n=True) self.txt_w = Text(text=self.text, i18n=True)
self.txt_w.size_hint = (None, None) # self.txt_w.size_hint = (None, None)
self.txt_w.bind(minimum_height=self.self.txt_w.setter('height')) # self.txt_w.bind(minimum_height=self.self.txt_w.setter('height'))
self.txt_w.bind(minimum_width=self.self.txt_w.setter('width')) # self.txt_w.bind(minimum_width=self.self.txt_w.setter('width'))
self.add_widget(self.txt_w) self.add_widget(self.txt_w)
def on_text(self, o, txt): def on_text(self, o, txt):
self.txt_w.text = txt self.txt_w.text = txt
class ClickableIconText(ClickableText):
source = StringProperty(None)
img_kw = DictProperty({})
def __init__(self, **kw):
super(ClickableIconText, self).__init__(**kw)
self.img_w = None
if source:
self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w, index=0)
def on_source(self, o, source):
if self.img_w:
self.img_w.source = source
return
self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w, index=0)
class ToggleText(ClickableText): class ToggleText(ClickableText):
""" """
construct commad construct commad
ToggleText(**{ ToggleText(**{
"text":"test", "text":"test",
"on_css":"selected", "css_on":"selected",
"off_css":"normal" "css_off":"normal"
}) })
""" """
select_state = BooleanProperty(False) select_state = BooleanProperty(False)
on_css = StringProperty('default') css_on = StringProperty('default')
off_css = StringProperty('default') css_off = StringProperty('default')
def __init__(self, **kw): def __init__(self, **kw):
super(ToggleText, self).__init__(**kw) super(ToggleText, self).__init__(**kw)
@ -71,36 +90,62 @@ class ToggleText(ClickableText):
def state(self): def state(self):
return self.select_state return self.select_state
def on_press(self, o=None):
self.select_state = False if self.select_state else True
def on_select_state(self, o, f): def on_select_state(self, o, f):
if f: self.clscss = self.css_on if f else self.css_off
self.clscss = self.on_css
else:
self.clscss = self.off_css
class ToggleIconText(ToggleText):
"""
{
"orientation",
"text",
"css_on",
"css_off",
"source_on",
"source_off"
}
"""
source_on = StringProperty(None)
source_off = StringProperty(None)
source = StringProperty(None)
img_kw = DictProperty({})
def __init__(self, **kw):
super(ToggleIconText, self).__init__(**kw)
self.img_w = None
self.source = source_off
def on_select_state(self, o, f):
super(ToggleIconText, self).on_select_state(o,f)
self.source = source_on if f else source_off
def on_source(self, o, source):
if not self.img_w:
self.img_w = AsyncImage(self.source, **self.img_kw)
self.add_widget(sef.img_w, index=0)
class ClickableImage(ClickableBox): class ClickableImage(ClickableBox):
source=StringProperty(None) source=StringProperty(None)
img_height = NumericProperty(None) img_kw = DictProperty(None)
img_width = NumericProperty(None)
def __init__(self, **kw): def __init__(self, **kw):
super(ClickableImage, self).__init__(**kw) super(ClickableImage, self).__init__(**kw)
self.img_w = None self.img_w = None
if source: if source:
self.img_w = AsyncImage(source=self.source) self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w)
def on_source(self, o, source): def on_source(self, o, source):
if self.img_w: if self.img_w:
self.img_w.source = source self.img_w.source = source
return return
self.img_w = AsyncImage(source=self.source) self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w)
class ToggleImage(ClickableImage): class ToggleImage(ClickableImage):
on_source = StringProperty(None) source_on = StringProperty(None)
source_off = StringProperty(None)
select_state = BooleanProperty(False) select_state = BooleanProperty(False)
def __init__(self, **kw): def __init__(self, **kw):
super(ToggleImage, self).__init__(**kw) super(ToggleImage, self).__init__(**kw)
self.source = source_on
def toggle(self): def toggle(self):
self.select_state = False if self.select_state else True self.select_state = False if self.select_state else True
@ -114,23 +159,16 @@ class ToggleImage(ClickableImage):
def state(self): def state(self):
return self.select_state return self.select_state
def on_press(self, o):
self.select_state = False if self.select_state else True
def on_select_state(self, o, f): def on_select_state(self, o, f):
if self.img_w: if f:
if self.select_state and self.on_source is not None: self.source = self.source_on
self.img_w.source = self.on_source
else:
self.img_w.source = self.source
return
if self.select_state and self.on_source is not None:
self.img_w = AsyncImage(source=self.on_source)
else: else:
self.img_w = AsyncImage(source=self.source) self.source = self.source_off
r = Factory.register r = Factory.register
r('ClickableBox', ClickableBox) r('ClickableBox', ClickableBox)
r('ClickableText',ClickableText) r('ClickableText',ClickableText)
r('ClickableIconText',ClickableIconText)
r('ToggleText',ToggleText) r('ToggleText',ToggleText)
r('ToggleIconText',ToggleIconText)
r('ClickableImage',ClickableImage) r('ClickableImage',ClickableImage)

View File

@ -14,14 +14,14 @@ class ScrollPanel(ScrollView):
orient = StringProperty('V') orient = StringProperty('V')
def __init__(self,inner=None, **kw): def __init__(self,inner=None, **kw):
super(ScrollPanel,self).__init__() super(ScrollPanel,self).__init__(**kw)
self.effect_cls = ScrollEffect self.effect_cls = ScrollEffect
if not inner: if not inner:
kw.update({ kw = {
'size_hint':(None,None), 'size_hint':(None,None),
'bgcolor':self.bgcolor, 'bgcolor':self.bgcolor,
'orientation':'vertical' 'orientation':'vertical' if self.orient=='V' else 'horizontal'
}) }
desc = { desc = {
"widgettype":"Box", "widgettype":"Box",
"options":kw "options":kw

View File

@ -129,39 +129,118 @@ Toolpage options
] ]
""" """
class ScrollToolbar(ToolbarPanel):
"""
tool has the follow attributes
{
"name",
"source_on,
"source_off,
"label",
}
toolbar has follow attributes
{
"img_height_c":image height in charecter size
"img_width_c":image width in charecter size
"css_on",
"css_off",
"orient":"V" or "H"
"tools":
}
"""
css_on = StringProperty('default')
css_off = StringProperty('default')
tools = ListProperty([])
img_height_c = NumericProperty(2)
img_width_c = NumericProperty(2)
def __init__(self, **kw):
super(ScrollToolbar, self).__init__(**kw)
self.register_event_type('on_press')
self.w_dic = {}
def on_tools(self, o, tools):
for t in self.tools:
label = t.get('label')
source_on = t.get('source_on', t.get('img_src',None))
source_off = t.get('source_off', t.get('img_src', None))
ToggleIconText = Factory.ToggleIconText
ToggleText = Factory.ToggleText
ToggleIcon = Factory.ToggleIcon
if label and source_on:
w = ToggleIconText(css_on=self.css_on,
css_off=self.css_off,
text=label,
source_on=source_on,
source_off=source_off,
img_kw={
"size_hint":(None, None),
"height":CSize(self.img_height_c),
"width":CSize(self.img_width_c)
}
)
elif label:
w = ToggleText(css_on=self.css_on,
css_off=self.css_off,
text=label)
elif source_on:
w = ToggleIcon( source_on=source_on,
source_off=source_off,
img_kw={
"size_hint":(None, None),
"height":CSize(self.img_height_c),
"width":"CSize(self.img_width_c)
}
)
if w:
self.add_widget(w)
self.w_dic[w] = t
w.bind(on_press=self.tool_press)
def on_press(self, o):
pass
def select(self,name):
for w, v in self.w_dic.items():
if v['name'] == name:
w.select(True)
self.tool_press(w)
break
def tool_press(self, o):
for w,v in self.w_dic.items():
if w == o:
ret_v = v
w.select(True)
else:
w.select(False)
self.dispatch('on_press', ret_v)
class ToolPage(BoxLayout): class ToolPage(BoxLayout):
normal_css=StringProperty(None) normal_css=StringProperty(None)
actived_css=StringProperty(None) actived_css=StringProperty(None)
def __init__(self,radius=[], toolbar_size = NumericProperty(2)
toolbar_size=None, img_size = NumericProperty(1.5)
img_size=1.5, text_size = NumericProperty(0.7)
text_size=0.7, tool_at = StringProperty('top')
show_name=None, tool_at='top', **opts): tools = ListProperty([])
self.opts = DictObject(**opts) def __init__(self, **kw):
if tool_at in [ 'top','bottom']: if self.tool_at in [ 'top','bottom']:
orient = 'vertical' orient = 'vertical'
else: else:
orient = 'horizontal' orient = 'horizontal'
if not toolbar_size: kw['orientation'] = orient
toolbar_size = img_size + text_size + 0.3 super(ToolPage, self).__init__(**kw)
self.toolbar_size = toolbar_size if not self.toolbar_size:
self.img_size = img_size self.toolbar_size = self.img_size + self.text_size + 0.3
self.text_size = text_size
names = [i.name for i in self.opts.tools]
if not show_name or \
not show_name in names:
show_name = self.opts.tools[0].name
self.content_widgets = {} self.content_widgets = {}
self.show_name = show_name
self.sub_radius = self.opts.radius
self.tool_at = tool_at
BoxLayout.__init__(self,orientation=orient)
self.content = None self.content = None
self.toolbar = None self.toolbar = None
self.init() self.init()
print('Toolpage():self.show_name=', self.show_name) name = self.tools[0]['name']
Clock.schedule_once(self.show_page, 0.5) self.toolbar.select(name)
def show_page(self, *args): def show_page(self, *args):
toggle_items = self.toolbar.toggle_items toggle_items = self.toolbar.toggle_items
@ -187,37 +266,30 @@ class ToolPage(BoxLayout):
self.mywidgets = {} self.mywidgets = {}
self.content = BoxLayout() self.content = BoxLayout()
self.content.widget_id = 'content' self.content.widget_id = 'content'
opts = self.opts.copy() opts = {}
opts['img_height_c"] = self.img_size,
opts['img_width_c"] = self.img_size,
opts['css_on'] = self.actived_css
opts['css_off'] = self.normal_css
opts['orient'] = 'H'
if self.tool_at in ['top','bottom']: if self.tool_at in ['top','bottom']:
opts['size_hint_x'] = 1 opts['size_hint_x'] = 1
opts['size_hint_y'] = None opts['size_hint_y'] = None
opts['height'] = CSize(self.toolbar_size) opts['height'] = CSize(self.toolbar_size)
opts['orientation'] = 'horizontal'
else: else:
opts['size_hint_y'] = 1 opts['size_hint_y'] = 1
opts['size_hint_x'] = None opts['size_hint_x'] = None
opts['width'] = CSize(self.toolbar_size) opts['width'] = CSize(self.toolbar_size)
opts['orientation'] = 'vertical' opts['tools'] = self.tools
self.toolbar = Toolbar( self.toolbar = ScrollToolbar(**opts)
radius=self.sub_radius,
img_size=self.img_size,
text_size=self.text_size,
**opts)
if self.tool_at in ['top','left']: if self.tool_at in ['top','left']:
self.add_widget(self.toolbar) self.add_widget(self.toolbar)
self.add_widget(self.content) self.add_widget(self.content)
else: else:
self.add_widget(self.content) self.add_widget(self.content)
self.add_widget(self.toolbar) self.add_widget(self.toolbar)
toggle_items = self.toolbar.toggle_items
for t in toggle_items.item_widgets: self.toolbar.bind(on_press=self.on_press_handle)
t.bind(on_press=self.on_press_handle)
def get_tool_by_name(self,name):
for t in self.opts.tools:
if t.name == name:
return t
return None
def build_widget(self, url): def build_widget(self, url):
desc = { desc = {
@ -229,27 +301,28 @@ class ToolPage(BoxLayout):
b = Factory.Blocks() b = Factory.Blocks()
return b.widgetBuild(desc) return b.widgetBuild(desc)
def on_press_handle(self, o): def on_press_handle(self, o, v):
name = o.getValue() name = v.get('name')
t = self.get_tool_by_name(name) fress = v.get('fress')
w = self.content_widgets.get(name) w = self.content_widgets.get(name)
self.content.clear_widgets() self.content.clear_widgets()
if w is None or t.fresh: if w is None or fresh:
if t.url: url = v.get('url')
w = self.build_widget(t.url) if url:
w = self.build_widget(url)
if w: if w:
self.content_widgets[name] = w self.content_widgets[name] = w
self.content.add_widget(w) self.content.add_widget(w)
return return
if t.rfname: rfname = v.get('rfname')
if rfname:
rf = RegisterFunction() rf = RegisterFunction()
f = rf.get(t.rfname) f = rf.get(rfname)
if f: if f:
r = f() r = f()
if isinstance(r,Widget): if isinstance(r,Widget):
self.content.add_widget(r) self.content.add_widget(r)
return return
if w: if w:
print('toolbar.py: Use old widget')
self.content.add_widget(w) self.content.add_widget(w)