From ad2cf5ca730ec5044bd083b6e9bc11e5ecda7cee Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 20 Dec 2021 15:56:31 +0800 Subject: [PATCH] bugfix --- kivyblocks/baseWidget.py | 19 +-- kivyblocks/clickable.py | 37 ++--- kivyblocks/scrollpanel.py | 8 +- kivyblocks/toolbar.py | 341 ++++++++++++++++---------------------- kivyblocks/utils.py | 7 + 5 files changed, 175 insertions(+), 237 deletions(-) diff --git a/kivyblocks/baseWidget.py b/kivyblocks/baseWidget.py index 969b650..1c55924 100755 --- a/kivyblocks/baseWidget.py +++ b/kivyblocks/baseWidget.py @@ -74,7 +74,7 @@ from .threadcall import HttpClient from .i18n import I18n from .widget_css import WidgetCSS from .ready import WidgetReady -from .utils import CSize, kwarg_pop +from .utils import CSize, SUPER from .swipebehavior import SwipeBehavior if platform == 'android': @@ -90,8 +90,7 @@ class WrapText(Label): class Box(WidgetCSS, WidgetReady, BoxLayout): def __init__(self, **kw): try: - kwarg_pop(self, kw) - super(Box, self).__init__(**kw) + SUPER(Box, self, kw) except Exception as e: print('Box(',kw,') Error') raise e @@ -109,8 +108,7 @@ class VBox(Box): class SwipeBox(SwipeBehavior, Box): def __init__(self, **kw): - kwarg_pop(self, kw) - super(SwipeBox, self).__init__(**kw) + SUPER(SwipeBox, self, kw) class Text(Label): @@ -140,12 +138,13 @@ class Text(Label): pass else: kwargs.update(fontsize) - kwarg_pop(self, kwargs) - super().__init__(**kwargs) + if not kwargs.get('text'): + kwargs['text'] = kwargs.get('otext','') + + SUPER(Text, self, kwargs) if self._i18n: self.i18n = I18n() self.i18n.addI18nWidget(self) - self.otext = kw.get('text','') if self.wrap: self.size_hint_y = None self.text_size = self.width, None @@ -182,9 +181,9 @@ class Text(Label): def on_otext(self,o,v=None): if self._i18n: - self.text = self.i18n(v) + self.text = self.i18n(self.otext) else: - self.text = v + self.text = self.otext def changeLang(self,lang): self.lang = lang diff --git a/kivyblocks/clickable.py b/kivyblocks/clickable.py index 9d1abf5..1ddadc8 100644 --- a/kivyblocks/clickable.py +++ b/kivyblocks/clickable.py @@ -10,26 +10,25 @@ from kivy.properties import NumericProperty, DictProperty, \ from kivyblocks.ready import WidgetReady from kivyblocks.bgcolorbehavior import BGColorBehavior -from kivyblocks.utils import CSize, kwarg_pop +from kivyblocks.utils import CSize, SUPER from kivyblocks.baseWidget import Box, Text from kivyblocks.widget_css import WidgetCSS class TinyText(Text): + def __init__(self, **kw): + SUPER(TinyText, self, kw) + self.on_texture_size(self, (1,1)) + def on_texture_size(self, o, ts): + self._label.refresh() self.size = self.texture_size - print('TinyText:texture_size=', self.texture_size) + print('TinyText:texture_size=', self.texture_size, 'text=', self.text) class ClickableBox(TouchRippleButtonBehavior, Box): def __init__(self, border_width=1, **kw): - kwarg_pop(self, kw) - super(ClickableBox, self).__init__( - padding=[border_width, - border_width, - border_width, - border_width], - **kw) + SUPER(ClickableBox, self, kw) self.border_width = border_width # self.bind(minimum_height=self.setter('height')) # self.bind(minimum_width=self.setter('width')) @@ -43,9 +42,8 @@ class ClickableText(ClickableBox): def __init__(self, **kw): print('ClickableText begin inited') self.txt_w = None - kwarg_pop(self, kw) - super(ClickableText, self).__init__(**kw) - self.txt_w = TinyText(otext=self.text, + SUPER(ClickableText, self, kw) + self.txt_w = TinyText(text=self.text, i18n=True, font_size=CSize(self.fontsize)) self.txt_w.bind(texture_size=self.reset_size) @@ -72,8 +70,7 @@ class ClickableIconText(ClickableText): img_kw = DictProperty({}) def __init__(self, **kw): self.img_w = None - kwarg_pop(self, kw) - super(ClickableIconText, self).__init__(**kw) + SUPER(ClickableIconText, self, kw) print('ClickableIconText inited') def reset_size(self, o, s): @@ -107,8 +104,7 @@ class ToggleText(ClickableText): css_on = StringProperty('default') css_off = StringProperty('default') def __init__(self, **kw): - kwarg_pop(self, kw) - super(ToggleText, self).__init__(**kw) + SUPER(ToggleText, self, kw) def toggle(self): self.select_state = False if self.select_state else True @@ -143,8 +139,7 @@ class ToggleIconText(ToggleText): img_kw = DictProperty({}) def __init__(self, **kw): self.img_w = None - kwarg_pop(self, kw) - super(ToggleIconText, self).__init__(**kw) + SUPER(ToggleIconText, self, kw) self.source = self.source_off self.img_w = AsyncImage(source=self.source, **self.img_kw) self.add_widget(self.img_w, index=-1) @@ -172,8 +167,7 @@ class ClickableImage(ClickableBox): img_kw = DictProperty(None) def __init__(self, **kw): self.img_w = None - kwarg_pop(self, kw) - super(ClickableImage, self).__init__(**kw) + SUPER(ClickableImage, self, kw) self.img_w = AsyncImage(source=self.source, **self.img_kw) self.add_widget(self.img_w) @@ -189,8 +183,7 @@ class ToggleImage(ClickableImage): source_off = StringProperty(None) select_state = BooleanProperty(False) def __init__(self, **kw): - kwarg_pop(self, kw) - super(ToggleImage, self).__init__(**kw) + SUPER(ToggleImage, self, kw) self.source = self.source_on def toggle(self): diff --git a/kivyblocks/scrollpanel.py b/kivyblocks/scrollpanel.py index f641f95..b855004 100644 --- a/kivyblocks/scrollpanel.py +++ b/kivyblocks/scrollpanel.py @@ -11,10 +11,9 @@ class ScrollPanel(ScrollView): x_padding_c = NumericProperty(0) y_padding_c = NumericProperty(0) bgcolor = ListProperty([0.2, 0.2, 0.2, 1]) - orient = StringProperty('V') def __init__(self,inner=None, **kw): print('ScrollPanel:kw=', kw) - super(ScrollPanel,self).__init__(**kw) + SUPER(ScrollPanel, self, kw) self.effect_cls = ScrollEffect if not inner: kw = { @@ -29,11 +28,6 @@ class ScrollPanel(ScrollView): if not self._inner: print('desc=', desc) raise Exception('widget build failed') - if isinstance(self._inner, BoxLayout): - if self.orient.upper() == 'H': - self._inner.orientation = 'horizontal' - else: - self._inner.orientation = 'vertical' self._inner.padding = self._inner.spacing = \ [CSize(self.x_padding_c), CSize(self.y_padding_c)] elif isinstance(inner, Widget): diff --git a/kivyblocks/toolbar.py b/kivyblocks/toolbar.py index 088adf3..8981890 100644 --- a/kivyblocks/toolbar.py +++ b/kivyblocks/toolbar.py @@ -23,115 +23,6 @@ from .baseWidget import Text, Box from .scrollpanel import ScrollPanel from .toggleitems import ToggleItems -""" -toolbar options -{ - radius: - "mode":"icon", "icontext","text" - img_size=1.5, - text_size=0.5, - tools:[ - { - "name":"myid", - "img_src":"gggggg", - "label":"gggggg" - }, - ... - ] -} -""" -class Toolbar(Box): - def __init__(self, - radius=[], - img_size=1.5, - text_size=0.5, - tools=[], - normal_css="default", - actived_css="default", - **opts): - self.radius = radius - self.img_size = img_size - self.text_size = text_size - self.tools = tools - self.tool_widgets={} - Box.__init__(self, **opts) - self.register_event_type('on_press') - first = True - subs_desc = [] - for opt in self.tools: - subwidgets = [] - img_src = opt.get('img_src',None) - if img_src: - subwidgets.append({ - "widgettype":"AsyncImage", - "options":{ - "size_hint_y":None, - "height":CSize(self.img_size), - "source":img_src - } - }) - text = opt.get('label', None) - if text: - subwidgets.append({ - "widgettype":"Text", - "options":{ - "size_hint_y":None, - "i18n":True, - "height":CSize(self.text_size), - "fontsize":CSize(self.text_size), - "otext":text - } - }) - desc = { - "widgettype":"VBox", - "options":{ - }, - "subwidgets":subwidgets, - "data":opt.get('name') - } - subs_desc.append(desc) - - self.toggle_items = ToggleItems( - radius=self.radius, - unit_size=self.img_size + self.text_size, - items_desc=subs_desc, - normal_css=normal_css, - actived_css=actived_css, - **opts - ) - for ti in self.toggle_items.item_widgets: - ti.widget_id = ti.user_data - self.toggle_items.bind(on_press=self.tool_press) - self.add_widget(self.toggle_items) - - def on_press(self, o): - print('on_press(),', o) - - def tool_press(self,o,v=None): - self.dispatch('on_press',self.toggle_items.getValue()) - -""" -Toolpage options -{ - img_size:1.5, - text_size:0.7, - tool_at:"left","right","top","bottom", - radius: - "show_name":"default open tool's name" - tools:[ - { - "name":"myid", - "img_src":"gggggg", - "label":"gggggg" - "fresh":true - "url":"ggggggggg" - "rfname":"register_function_name" - }, - ... - ] - -""" - class ScrollToolbar(ScrollPanel): """ tool has the follow attributes @@ -139,111 +30,134 @@ class ScrollToolbar(ScrollPanel): "name", "source_on, "source_off, + # source_on, source_off, or "img_src", "label", + "deletable" + "url", + "rfname", } toolbar has follow attributes { "padding_c":x spacing "img_size_c":image height in charecter size "text_size_c": - "orient":"H" or "V" + "toolbar_orient":"H" or "V" "tool_orient":"horizontal" or "vertical" "css_on", "css_off", "tools": } - css_on='default', - css_off='default', - tools=[], - tool_orient = 'horizontal', - orient='H', - padding_c=1, - img_size_c=2, - text_size_c=1, - self.css_on = css_on - self.css_off = css_off - self.tools=tools - self.tool_orient = tool_orient - self.orient = orient - self.padding_c = padding_c - self.img_size_c = img_size_c - self.text_size_c = text_size_c """ css_on = StringProperty('default') css_off = StringProperty('default') tools = ListProperty([]) tool_orient = StringProperty('horizontal') - orient = StringProperty('H') + toolbar_orient = StringProperty('H') padding_c = NumericProperty(1) img_size_c = NumericProperty(2) text_size_c = NumericProperty(1) + def __init__(self, **kw): - kwarg_pop(self, kw) - super(ScrollToolbar, self).__init__(**kw) + SUPER(ScrollToolbar, self, kw) self.register_event_type('on_press') - if self.orient == 'H': + if self.toolbar_orient == 'H': self._inner.orientation = 'horizontal' else: self._inner.orientation = 'vertical' self.clear_widgets() self.w_dic = {} for t in self.tools: - label = t.get('label', t.get('name', None)) - 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 - ToggleImage = Factory.ToggleImage - if label and source_on: - w = ToggleIconText(css_on=self.css_on, - css_off=self.css_off, - text=label, - fontsize=CSize(self.text_size_c), - source_on=source_on, - source_off=source_off, - orientation=self.tool_orient, - img_kw={ - "size_hint":(None, None), - "height":CSize(self.img_size_c), - "width":CSize(self.img_size_c) - } - ) - elif label: - w = ToggleText(css_on=self.css_on, - css_off=self.css_off, - orientation=self.tool_orient, - fontsize=CSize(self.text_size_c), - text=label) - elif source_on: - w = ToggleImage( source_on=source_on, - source_off=source_off, - orientation=self.tool_orient, - img_kw={ - "size_hint":(None, None), - "height":CSize(self.img_size_c), - "width":CSize(self.img_size_c) - } - ) - - if w: - self.add_widget(w) - self.w_dic[w] = t - w.bind(on_press=self.tool_press) + self.add_tool(t) - if self.orient == 'horizontal': + self.bar_width = 0 + if self.toolbar_orient == 'H': self.do_scroll_y = False + self._inner.spacing = CSize(self.padding_c,0) + else: + self.do_scroll_x = False + self._inner.spacing = CSize(0, self.padding_c) + + def on_children_size(self, o, size): + self.on_size(None, None) + + def on_size(self, o, size): + print('on_size=', size) + if self.toolbar_orient == 'H': + self.size_hint_x = 1 self.size_hint_y = None if len(self.w_dic.keys()) > 0: self.height = max([w.height for w in self.w_dic.keys()]) self._inner.spacing = CSize(self.padding_c,0) else: - self.do_scroll_x = False self.size_hint_x = None + self.size_hint_y = 1 if len(self.w_dic.keys()) > 0: self.width = max([w.width for w in self.w_dic.keys() ]) self._inner.spacing = CSize(0, self.padding_c) + print('###size_hint=', + self.size_hint_x, + self.size_hint_y, + self.size_hint, + self.size) + + def add_tool(self, t): + label = t.get('label', t.get('name', None)) + 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 + ToggleImage = Factory.ToggleImage + if label and source_on: + w = ToggleIconText(css_on=self.css_on, + css_off=self.css_off, + text=label, + size_hint = (None, None), + fontsize=self.text_size_c, + source_on=source_on, + source_off=source_off, + orientation=self.tool_orient, + img_kw={ + "size_hint":(None, None), + "height":CSize(self.img_size_c), + "width":CSize(self.img_size_c) + } + ) + elif label: + w = ToggleText(css_on=self.css_on, + css_off=self.css_off, + size_hint = (None, None), + orientation=self.tool_orient, + fontsize=CSize(self.text_size_c), + text=label) + elif source_on: + w = ToggleImage( source_on=source_on, + source_off=source_off, + size_hint = (None, None), + orientation=self.tool_orient, + img_kw={ + "size_hint":(None, None), + "height":CSize(self.img_size_c), + "width":CSize(self.img_size_c) + } + ) + if w: + self.add_widget(w) + self.w_dic[w] = t + w.select(False) + w.bind(size=self.on_children_size) + w.bind(on_press=self.tool_press) + w.bind(minimum_width=w.setter('width')) + w.bind(minimum_height=w.setter('height')) + + def del_tool(self, name): + m = [ x for x,y in self.w_dic.items() if y['name'] == name ] + for w in m: + self.remove(w) + self.w_dic = {k:v for k,v in self.w_dic.copy().items() \ + if k not in m } + def on_press(self, o): pass @@ -263,13 +177,21 @@ class ScrollToolbar(ScrollPanel): w.select(False) self.dispatch('on_press', ret_v) -class ToolPage(BoxLayout): +class ToolPage(Box): + """ + ToolPage: + { + toolbar_size: + tool_at + toolbar + } + """ toolbar_size = NumericProperty(2) tool_at = StringProperty('top') toolbar = DictProperty({}) def __init__(self, **kw): print('ToolPage:kw=',kw) - super(ToolPage, self).__init__(**kw) + SUPER(ToolPage, self, kw) if self.tool_at in [ 'top','bottom']: self.orientation = 'vertical' else: @@ -283,16 +205,22 @@ class ToolPage(BoxLayout): name = self.toolbar['tools'][0]['name'] self.toolbar_w.select(name) + def add_tool(self, tool): + self.toolbar_w.add_tool(tool) + + def del_tool(self, name): + self.toolbar_w.del_tool(o) + g = self.content_widgets.copy() + self.content_widgets = {k:v for k,v in g.items()} + def on_size(self,obj,size): if self.content_w is None: return if self.tool_at in ['top','bottom']: - self.toolbar_w.width = self.width - self.content_w.width = self.width + self.toolbar_w.size_hint_y = None self.content_w.height = self.height - self.toolbar_w.height else: - self.toolbar_w.height = self.height - self.content_w.height = self.height + self.toolbar_w.size_hint_x = None self.content_w.width = self.width - self.toolbar_w.width def init(self): @@ -318,29 +246,46 @@ class ToolPage(BoxLayout): b = Factory.Blocks() return b.widgetBuild(desc) + def print_all(self): + self.print_info(self) + self.print_info(self.toolbar_w) + for w in self.toolbar_w.w_dic.keys(): + self.print_info(w) + for c in w.children: + self.print_info(c) + self.print_info(self.content_w) + for c in self.content_w.children: + self.print_info(c) + + def print_info(self, o): + print('self.size_hint=', o.__class__, o.size_hint, + 'self.x,y=', o.width, o.height) + def on_press_handle(self, o, v): name = v.get('name') - fress = v.get('fress') + refresh = v.get('refresh', False) + self.print_all() w = self.content_widgets.get(name) self.content_w.clear_widgets() - if w is None or fresh: - url = v.get('url') - if url: - w = self.build_widget(url) - if w: - self.content_widgets[name] = w - self.content_w.add_widget(w) - return - rfname = v.get('rfname') - if rfname: - rf = RegisterFunction() - f = rf.get(rfname) - if f: - r = f() - if isinstance(r,Widget): - self.content_w.add_widget(r) - return - if w: + if w and not refresh: self.content_w.add_widget(w) + return + url = v.get('url') + if url: + w = self.build_widget(url) + if w: + self.content_widgets[name] = w + self.content_w.add_widget(w) + print('w=', w) + return + rfname = v.get('rfname') + if rfname: + rf = RegisterFunction() + f = rf.get(rfname) + if f: + r = f() + if isinstance(r,Widget): + self.content_w.add_widget(r) Factory.register('ScrollToolbar', ScrollToolbar) +Toolbar = ScrollToolbar diff --git a/kivyblocks/utils.py b/kivyblocks/utils.py index 8cdc616..637f238 100644 --- a/kivyblocks/utils.py +++ b/kivyblocks/utils.py @@ -37,6 +37,13 @@ def kwarg_pop(obj, kw): if hasattr(obj, k): setattr(obj, k, kw.pop(k)) +def SUPER(klass, obj, kw): + keys = [ k for k in kw.keys() ] + dic = { k:kw.pop(k) for k in keys if hasattr(obj, k) } + super(klass, obj).__init__(**kw) + for k,v in dic.items(): + setattr(obj, k, v) + def blockImage(name): p = os.path.dirname(os.path.abspath(__file__)) return os.path.join(p,'imgs',name)