From 5317227fbd61cc6dc4e065691b68af14f378705e Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 27 Dec 2021 13:54:00 +0800 Subject: [PATCH] bugfix --- kivyblocks/.toolbar.py.swp | Bin 24576 -> 0 bytes kivyblocks/clickable.py | 63 +++++++++--- kivyblocks/multi_select.py | 160 +++++++++++++++++++++++-------- kivyblocks/ready.py | 2 + kivyblocks/tree.py | 14 +-- kivyblocks/typewriterbox.py | 50 ---------- kivyblocks/utils.py | 8 +- kivyblocks/widgetExt/inputext.py | 3 +- 8 files changed, 191 insertions(+), 109 deletions(-) delete mode 100644 kivyblocks/.toolbar.py.swp delete mode 100644 kivyblocks/typewriterbox.py diff --git a/kivyblocks/.toolbar.py.swp b/kivyblocks/.toolbar.py.swp deleted file mode 100644 index cbcb8e3e382cf3a40916d8f2c5db8ed653a3ee78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 zcmeI4dyr&TS-?9>h&1F45z9Z~-KL~_mfp_p1|f_L7W)V!th+;Y6O#;6Z9i_$bf%|o z=l1RC8CD3vSOJU#u+$=jP!J#lDG_T$0>Mb)ACyR-R32_pQka4SN|X`>#aQ_JzVo=Z zduDc1ScO`3r}EqGd(U^y`ObIF`OdS`+;iPkzZ_gq+gIT4!b0Kb-48b8>ywWc3LC38 z%hxmh9XxdGRmYFc@80*~7w$cH;J~)>2WKxEY+Sa|UEA2*>_x4Wp?pT_4-xR3}EC;!VWkXs

-4MefybLaZ@10vHJPh~3hu{vl9hRUCH^O0< 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 diff --git a/kivyblocks/clickable.py b/kivyblocks/clickable.py index 0385ed3..a31b263 100644 --- a/kivyblocks/clickable.py +++ b/kivyblocks/clickable.py @@ -10,13 +10,14 @@ from kivy.properties import NumericProperty, DictProperty, \ from kivyblocks.ready import WidgetReady from kivyblocks.bgcolorbehavior import BGColorBehavior -from kivyblocks.utils import CSize, SUPER +from kivyblocks.utils import CSize, SUPER, blockImage from kivyblocks.baseWidget import Box, Text from kivyblocks.widget_css import WidgetCSS class TinyText(Text): def __init__(self, **kw): SUPER(TinyText, self, kw) + self.size_hint = (None, None) self.on_texture_size(self, (1,1)) def on_texture_size(self, o, ts): @@ -28,6 +29,7 @@ class ClickableBox(TouchRippleButtonBehavior, Box): border_width=1, **kw): SUPER(ClickableBox, self, kw) + self.size_hint = [None, None] self.border_width = border_width # self.bind(minimum_height=self.setter('height')) # self.bind(minimum_width=self.setter('width')) @@ -49,7 +51,6 @@ class ClickableText(ClickableBox): text = StringProperty(' ') fontsize = NumericProperty(1) def __init__(self, **kw): - print('ClickableText begin inited') self.txt_w = None SUPER(ClickableText, self, kw) self.txt_w = TinyText(otext=self.text, @@ -72,7 +73,6 @@ class ClickableIconText(ClickableText): def __init__(self, **kw): self.img_w = None SUPER(ClickableIconText, self, kw) - print('ClickableIconText inited') def on_source(self, o, source): if self.img_w: @@ -111,7 +111,6 @@ class ToggleText(ClickableText): def on_select_state(self, o, f): self.csscls = self.css_on if f else self.css_off - print(f'using {self.csscls}') class ToggleIconText(ToggleText): """ @@ -149,8 +148,6 @@ class ClickableImage(ClickableBox): def __init__(self, **kw): self.img_w = None SUPER(ClickableImage, self, kw) - # self.img_w = AsyncImage(source=self.source, **self.img_kw) - # self.add_widget(self.img_w) def on_source(self, o, source): if self.source is None: @@ -200,25 +197,69 @@ class ToggleImage(ClickableImage): else: self.source = self.source_off -class CheckBox(ToggleImage): +class SingleCheckBox(ClickableBox): otext = StringProperty(None) + select_state = BooleanProperty(False) def __init__(self, **kw): - SUPER(CheckBox, self, kw) + self.old_state = None + self.register_event_type('on_changed') + SUPER(SingleCheckBox, self, kw) self.source_on = blockImage('checkbox-on.png') - self.source_off = blockImage('ceckbox-off.png') + self.source_off = blockImage('checkbox-off.png') + self.select(False) + self.create_img_w() if self.otext: self.txt_w = TinyText(otext=self.otext, i18n=True) + self.txt_w.bind(size=self.reset_size) self.add_widget(self.txt_w) + self.reset_size(self, None) + + def on_changed(self, o=None): + pass + + def on_press(self, o=None): + self.toggle() + + def select(self, f): + self.select_state = f + + def change_img_source(self): + self.img_w.source = self.source_on if self.select_state else \ + self.source_off + + def toggle(self): + self.select_state = False if self.select_state else True + + def state(self): + return self.select_state + + def on_select_state(self, o, f): + self.change_img_source() + self.dispatch('on_changed', self.select_state) def getValue(self): return self.state() def setValue(self, v): - self.select_state = False if v else True + self.select(True if v else False) + + def create_img_w(self): + if self.select_state: + self.img_w = AsyncImage(source=self.source_on, + size_hint=(None, None), + size=CSize(1, 1) + ) + else: + self.img_w = AsyncImage(source=self.source_off, + size_hint=(None, None), + size=CSize(1, 1) + ) + self.add_widget(self.img_w) + self.img_w.bind(size=self.reset_size) r = Factory.register r('TinyText', TinyText) -r('CheckBox', CheckBox) +r('SingleCheckBox', SingleCheckBox) r('ClickableBox', ClickableBox) r('ClickableText',ClickableText) r('ClickableIconText',ClickableIconText) diff --git a/kivyblocks/multi_select.py b/kivyblocks/multi_select.py index fed71a5..21260ec 100644 --- a/kivyblocks/multi_select.py +++ b/kivyblocks/multi_select.py @@ -1,67 +1,149 @@ +from kivy.clock import Clock +from kivy.factory import Factory +from kivy.uix.stacklayout import StackLayout from kivy.properties import BooleanProperty, StringProperty,\ - ListProperty, DictProperty + ListProperty, DictProperty, OptionProperty, \ + NumericProperty + from kivyblocks.baseWidget import VBox from kivyblocks.clickable import ToggleText, ToggleImage -from kivyblocks.typewriterbox import TypeWriterBox -from kivy.factory import Factory +from kivyblocks.utils import SUPER, CSize +from kivyblocks.widget_css import WidgetCSS +from kivyblocks.ready import WidgetReady -class MultiSelect(TypeWriterBox): +class MultiSelect(WidgetCSS, WidgetReady, StackLayout): + """ + { + "widgettype":"MultiSelect", + "options":{ + "valueField" + "textField" + "items" + "item_css" + "item_selected_css" + "all_position" + "need_others" + "default_selected" + } + } + """ + valueField = StringProperty('value') + textField = StringProperty('text') + x_spacing_c = NumericProperty(1) + y_spacing_c = NumericProperty(0.5) items = ListProperty([]) - item_css = DictProperty({}) - item_selected_css = DictProperty({}) - all_button_position = StringProperty(None) - default_selected=StringProperty([]) - + item_css = StringProperty({}) + item_selected_css = StringProperty({}) + all_position = OptionProperty(None, \ + options=[None, 'begin', 'end']) + need_others = BooleanProperty(False) + default_selected=ListProperty([]) + result = ListProperty([]) def __init__(self, **kw): - super(MultiSelect, self).__init__(**kw) + SUPER(MultiSelect, self, kw) + self.spacing = CSize(self.x_spacing_c, self.y_spacing_c) + self.orientation = 'lr-tb' + self.build_all_items() + self.old_result = [] + self.register_event_type('on_changed') self.button_dic = {} self.value_b = {} + self.buildWidgets() + + def build_all_items(self): + items = [i for i in self.items ] + if self.need_others: + dic = { + self.valueField:'_other_', + self.textField:'others' + } + items.append(dic) - def buildItem(self, dic): + if self.all_position is not None: + dic = { + self.textField:'all', + self.valueField:'_all_', + } + if self.all_position == 'begin': + items.insert(0, dic) + else: + items.append(dic) + self.all_items = items + + def on_changed(self, d): + pass + + def build_item_widget(self, dic): keys = dic.keys() ToggleText = Factory.ToggleText ToggleImage = Factory.ToggleImage - if 'text' in keys and 'value' in keys: - desc = dic.copy() - desc['off_css'] = self.item_css - desc['on_css'] = self.item_selected_css + ToggleIconText = Factory.ToggleIconText + if self.textField in keys and 'source_on' in keys and \ + 'source_off' in keys: + desc['text'] = dic[self.textField] + desc['css_off'] = self.item_css + desc['css_on'] = self.item_selected_css + desc["source_on"] = dic['source_on'], + desc["source_off"] = dic['source_off'] + print('ToggleIconText', desc) + return ToggleIconText(**desc) + + if self.textField in keys: + desc = {} + desc['text'] = dic[self.textField] + desc['css_off'] = self.item_css + desc['css_on'] = self.item_selected_css + print('ToggleText', desc) return ToggleText(**desc) - if 'source' in keys and 'on_source' in keys: - return ToggleImage(**dic) - - def on_items(self, o, items): - self.clear_widgets() - if all_button_position is not None: - dic = { - 'text':'all', - 'value':'_all_', + if 'source_on' in keys and 'source_off' in keys: + desc = { + "source_on":dic['source_on'], + "source_off":dic['source_off'] } - if all_button_position == 'begin': - items.insert(dic,0) - else: - items.append(dic) - for item in items: - b = self.buildItem(item) + print('ToggleImage', desc) + return ToggleImage(**desc) + + def buildWidgets(self): + self.clear_widgets() + for item in self.all_items: + b = self.build_item_widget(item) b.bind(on_press=self.button_pressed) - self.button_dic.update({b:dic}) - self.value_b.update({dic['value']:b}) + self.button_dic.update({b:item}) + self.add_widget(b) def button_pressed(self, o): o.toggle() - if self.button_dic[o]['value'] == '_all_' and o.state(): - for b, dic in self.button_dic.copy().items(): + if self.button_dic[o][self.valueField] == '_all_' and o.state(): + for b, dic in self.button_dic.items(): if b == o: continue b.select(False) + if self.button_dic[o][self.valueField] == '_other_' and o.state(): + for b, dic in self.button_dic.items(): + if b == o: + continue + b.select(False) + if self.button_dic[o][self.valueField] not in ['_all_', '_other_'] \ + and o.state(): + for b, dic in self.button_dic.items(): + if dic[self.valueField] in ['_all_', '_other_']: + b.select(False) + Clock.schedule_once(self.set_result, 0.1) + + def set_result(self, t=None): + self.result = [ d[self.valueField] for b, d in \ + self.button_dic.items() if b.state() ] + if self.result != self.old_result: + self.dispatch('on_changed', self.result) + self.old_result = self.result def getValue(self): - selected_buttons = [ b for b in self.button_dic.item() \ - if b.state() ] - r = [ dic['value'] for b, dic in self.button_dic.items() \ - if b in selected_buttons ] - return r + self.set_result() + return self.result def setValue(self, value): + self.result = value + self.old_result = value for v in value: b = self.value_b[v] b.select(True) diff --git a/kivyblocks/ready.py b/kivyblocks/ready.py index 77c0147..ad0dd18 100644 --- a/kivyblocks/ready.py +++ b/kivyblocks/ready.py @@ -1,6 +1,8 @@ + from traceback import print_exc from contextlib import contextmanager +from kivy.graphics import Fbo, Color, Rectangle from kivy.core.window import Window from kivy.clock import Clock from kivy.utils import platform diff --git a/kivyblocks/tree.py b/kivyblocks/tree.py index 4b78dc6..b20bbf3 100644 --- a/kivyblocks/tree.py +++ b/kivyblocks/tree.py @@ -19,7 +19,7 @@ from appPublic.registerfunction import getRegisterFunctionByName from .baseWidget import PressableLabel, Text, HBox, VBox from .color_definitions import getColors from .widget_css import WidgetCSS -from .utils import alert,absurl +from .utils import alert,absurl, SUPER from .toggleitems import PressableBox from .threadcall import HttpClient @@ -38,12 +38,11 @@ class EmptyBox(Label): class NodeTrigger(ButtonBehavior, EmptyBox): open_status = BooleanProperty(False) color = ListProperty([1,0,0,1]) - def __init__(self, color=[1,0,0,1],**kw): - # super(NodeTrigger, self).__init__(**kw) - EmptyBox.__init__(self, **kw) - ButtonBehavior.__init__(self) + def __init__(self, **kw): + self.open_points = None + self.close_points = None + SUPER(NodeTrigger, self, kw) self.countPoints() - self.color = color self.bind(size=self.onSize,pos=self.onSize) def countPoints(self): @@ -65,7 +64,6 @@ class NodeTrigger(ButtonBehavior, EmptyBox): def on_press(self, *args): self.open_status = False if self.open_status else True - # self.showOpenStatus() def on_open_status(self, *largs): self.showOpenStatus() @@ -74,6 +72,8 @@ class NodeTrigger(ButtonBehavior, EmptyBox): self.showOpenStatus() def showOpenStatus(self): + if self.close_points is None: + return points = self.close_points if self.open_status: points = self.open_points diff --git a/kivyblocks/typewriterbox.py b/kivyblocks/typewriterbox.py deleted file mode 100644 index 8ccc43b..0000000 --- a/kivyblocks/typewriterbox.py +++ /dev/null @@ -1,50 +0,0 @@ -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.widget import Widget -from kivy.factory import Factory -from kivyblocks.widget_css import WidgetCSS -from kivyblocks.ready import WidgetReady - -class TypeWriterBox(WidgetCSS, WidgetReady, Widget): - def __init__(self, **kw): - super(TypeWriterBox, self).__init__(**kw) - self.size_hint_y = None - self.sub_widgets = [] - self.curbox = self.add_vertical_box() - self.bind(minimum_height=self.setter('height')) - - def on_width(self, o, size): - self.relocate() - - def add_widget(self, w, *args): - width = 0 - for c in self.curbox.children: - width += c.width - if width + c.width > self.width: - self.curbox = self.add_vertical_box() - self.curbox.add_widget(w, *args) - self.sub_widgets.append(w) - - def del_widget(self, w): - self.sub_widgets = [i for i in self.sub_widgets.copy() if i !=w ] - self.relocate() - - def add_veritcal_box(self): - box = BoxLayout(orientation='vertical', size_hint_y=None) - box.bind(minimum_height = box.setter('height')) - super(TypeWriterBox, self).add_widget(box) - return box - - def relocate(self): - with self.fboContext(): - for b in self.children: - b.clear_widgets() - width = 0 - self.clear_widgets() - self.curbox = add_vertical_box() - for w in self.sub_widgets: - if width + w.width > self.width: - self.curbox = self.add_vertical_box() - width = 0 - self.curbox.add_widget(w) - -Factory.register('TypeWriterBox', TypeWriterBox) diff --git a/kivyblocks/utils.py b/kivyblocks/utils.py index 637f238..7583f7f 100644 --- a/kivyblocks/utils.py +++ b/kivyblocks/utils.py @@ -1,5 +1,6 @@ import os from traceback import print_exc +from traceback import print_exc from kivy.app import App from appPublic.jsonConfig import getConfig from kivy.uix.popup import Popup @@ -42,7 +43,12 @@ def SUPER(klass, obj, kw): 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) + try: + setattr(obj, k, v) + except Exception as e: + print(f'obj={obj}, setattr(obj, "{k}","{v}") error') + print_exc() + raise e def blockImage(name): p = os.path.dirname(os.path.abspath(__file__)) diff --git a/kivyblocks/widgetExt/inputext.py b/kivyblocks/widgetExt/inputext.py index a65de22..e41d8ea 100755 --- a/kivyblocks/widgetExt/inputext.py +++ b/kivyblocks/widgetExt/inputext.py @@ -77,7 +77,6 @@ class StrInput(TextInput): def checkChange(self,o,v=None): v = self.getValue() - print('StrInput():v=', v) if v != self.old_value: self.old_value = v self.dispatch('on_changed',v) @@ -89,6 +88,8 @@ class StrInput(TextInput): if v is None: v = '' self.text = str(v) + self.old_value = self.text + class Password(StrInput): def __init__(self, **kw):