This commit is contained in:
yumoqing 2021-12-22 11:25:49 +08:00
parent ad2cf5ca73
commit 4a564de48a
5 changed files with 132 additions and 105 deletions

View File

@ -22,7 +22,6 @@ class TinyText(Text):
def on_texture_size(self, o, ts): def on_texture_size(self, o, ts):
self._label.refresh() self._label.refresh()
self.size = self.texture_size self.size = self.texture_size
print('TinyText:texture_size=', self.texture_size, 'text=', self.text)
class ClickableBox(TouchRippleButtonBehavior, Box): class ClickableBox(TouchRippleButtonBehavior, Box):
def __init__(self, def __init__(self,
@ -32,6 +31,16 @@ class ClickableBox(TouchRippleButtonBehavior, Box):
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')) # self.bind(minimum_width=self.setter('width'))
self.bind(children=self.reset_size)
def reset_size(self, o, s):
self.size_hint = (None,None)
if self.orientation == 'horizontal':
self.height = max([c.height for c in self.children])
self.width = sum([c.width for c in self.children])
else:
self.height = sum([c.height for c in self.children])
self.width = max([c.width for c in self.children])
def on_press(self,o=None): def on_press(self,o=None):
pass pass
@ -43,23 +52,15 @@ class ClickableText(ClickableBox):
print('ClickableText begin inited') print('ClickableText begin inited')
self.txt_w = None self.txt_w = None
SUPER(ClickableText, self, kw) SUPER(ClickableText, self, kw)
self.txt_w = TinyText(text=self.text, self.txt_w = TinyText(otext=self.text,
i18n=True, i18n=True,
font_size=CSize(self.fontsize)) font_size=CSize(self.fontsize))
self.txt_w.bind(texture_size=self.reset_size) self.txt_w.bind(texture_size=self.reset_size)
self.add_widget(self.txt_w) self.add_widget(self.txt_w)
self.txt_w.size_hint = (None, None) self.txt_w.size_hint = (None, None)
self.txt_w.size = self.txt_w.texture_size self.txt_w.size = self.txt_w.texture_size
#self.txt_w.bind(minimum_height=self.txt_w.setter('height'))
#self.txt_w.bind(minimum_width=self.txt_w.setter('width'))
print('ClickableText inited')
def reset_size(self, o, s):
self.size_hint = (None,None)
self.size = self.txt_w.texture_size
def on_text(self, o, txt): def on_text(self, o, txt):
print('on_text fired')
if self.txt_w: if self.txt_w:
self.txt_w.text = self.text self.txt_w.text = self.text
@ -73,22 +74,12 @@ class ClickableIconText(ClickableText):
SUPER(ClickableIconText, self, kw) SUPER(ClickableIconText, self, kw)
print('ClickableIconText inited') print('ClickableIconText inited')
def reset_size(self, o, s):
self.size_hint = (None,None)
if self.orientation == 'horizontal':
self.height = max(self.txt_w.texture_size[1], self.img_w.height)
self.width = self.txt_w.texture_size[0] + self.img_w.width
else:
self.height = self.txt_w.texture_size[1] + self.img_w.height
self.width = max(self.txt_w.texture_size[0], self.img_w.width)
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_kw) self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w, index=-1) self.add_widget(self.img_w, index=len(self.children))
class ToggleText(ClickableText): class ToggleText(ClickableText):
""" """
@ -142,17 +133,7 @@ class ToggleIconText(ToggleText):
SUPER(ToggleIconText, self, kw) SUPER(ToggleIconText, self, kw)
self.source = self.source_off self.source = self.source_off
self.img_w = AsyncImage(source=self.source, **self.img_kw) self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w, index=-1) self.add_widget(self.img_w, index=len(self.children))
def reset_size(self, o, s):
self.size_hint = (None,None)
if self.orientation == 'horizontal':
self.height = max(self.txt_w.texture_size[1], self.img_w.height)
self.width = self.txt_w.texture_size[0] + self.img_w.width
else:
self.height = self.txt_w.texture_size[1] + self.img_w.height
self.width = max(self.txt_w.texture_size[0], self.img_w.width)
print(f'ToggleIconText:w,h={self.width},{self.height}')
def on_select_state(self, o, f): def on_select_state(self, o, f):
super(ToggleIconText, self).on_select_state(o,f) super(ToggleIconText, self).on_select_state(o,f)
@ -168,12 +149,27 @@ class ClickableImage(ClickableBox):
def __init__(self, **kw): def __init__(self, **kw):
self.img_w = None self.img_w = None
SUPER(ClickableImage, self, kw) SUPER(ClickableImage, self, kw)
self.img_w = AsyncImage(source=self.source, **self.img_kw) # self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w) # self.add_widget(self.img_w)
def on_source(self, o, source): def on_source(self, o, source):
if self.source is None:
self.source = blockImage('broken.png')
self.build_widget()
def on_img_kw(self, o, img_kw):
self.build_widget()
def build_widget(self):
if not self.source:
return
if not self.img_kw:
self.img_kw = {}
if self.img_w: if self.img_w:
self.img_w.source = source self.img_w.source = self.source
for k,v in self.img_kw.items():
setattr(self.img_w, k,v)
return return
self.img_w = AsyncImage(source=self.source, **self.img_kw) self.img_w = AsyncImage(source=self.source, **self.img_kw)
self.add_widget(self.img_w) self.add_widget(self.img_w)
@ -204,8 +200,25 @@ class ToggleImage(ClickableImage):
else: else:
self.source = self.source_off self.source = self.source_off
class CheckBox(ToggleImage):
otext = StringProperty(None)
def __init__(self, **kw):
SUPER(CheckBox, self, kw)
self.source_on = blockImage('checkbox-on.png')
self.source_off = blockImage('ceckbox-off.png')
if self.otext:
self.txt_w = TinyText(otext=self.otext, i18n=True)
self.add_widget(self.txt_w)
def getValue(self):
return self.state()
def setValue(self, v):
self.select_state = False if v else True
r = Factory.register r = Factory.register
r('TinyText', TinyText) r('TinyText', TinyText)
r('CheckBox', CheckBox)
r('ClickableBox', ClickableBox) r('ClickableBox', ClickableBox)
r('ClickableText',ClickableText) r('ClickableText',ClickableText)
r('ClickableIconText',ClickableIconText) r('ClickableIconText',ClickableIconText)

View File

@ -21,7 +21,7 @@ from appPublic.timecost import TimeCost
from appPublic.uniqueID import getID from appPublic.uniqueID import getID
from appPublic.myTE import string_template_render from appPublic.myTE import string_template_render
from .utils import CSize, setSizeOptions, loading, loaded, absurl, alert from .utils import CSize, setSizeOptions, loading, loaded, absurl, alert, SUPER
from .baseWidget import Text, HBox, VBox from .baseWidget import Text, HBox, VBox
from .scrollpanel import ScrollPanel from .scrollpanel import ScrollPanel
from .paging import Paging, RelatedLoader from .paging import Paging, RelatedLoader
@ -166,7 +166,7 @@ class Row(BoxLayout):
class Header(WidgetReady, ScrollPanel): class Header(WidgetReady, ScrollPanel):
def __init__(self,part,**kw): def __init__(self,part,**kw):
super(Header, self).__init__(**kw) SUPER(Header, self, kw)
self.part = part self.part = part
self.init(1) self.init(1)
self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop) self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop)
@ -185,8 +185,8 @@ class Header(WidgetReady, ScrollPanel):
class Body(WidgetReady, ScrollPanel): class Body(WidgetReady, ScrollPanel):
def __init__(self,part,**kw): def __init__(self,part,**kw):
self.part = part self.part = part
kw.update({'spacing':self.part.datagrid.linewidth}) SUPER(Body, self, kw)
super(Body, self).__init__(**kw) self._inner.spacing = self.part.datagrid.linewidth
self.size_hint=(1,1) self.size_hint=(1,1)
self.idRow = {} self.idRow = {}
self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop) self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop)
@ -262,6 +262,11 @@ class DataGridPart(WidgetReady, BoxLayout):
if not self.datagrid.noheader: if not self.datagrid.noheader:
self.header = Header(self,**kw) self.header = Header(self,**kw)
self.add_widget(self.header) self.add_widget(self.header)
inner = {
"widgettype":"VBox",
"options":{
}
}
self.body = Body(self) self.body = Body(self)
self.add_widget(self.body) self.add_widget(self.body)
if not self.freeze_flag: if not self.freeze_flag:
@ -522,6 +527,8 @@ class DataGrid(WidgetReady, BoxLayout):
data['data'] = recs2 data['data'] = recs2
f = partial(self.add_page_delay,data) f = partial(self.add_page_delay,data)
Clock.schedule_once(f, 0) Clock.schedule_once(f, 0)
print('body=', self.normal_part.body.size,
'inner=', self.normal_part.body._inner.size)
def add_page_delay(self, data, *args): def add_page_delay(self, data, *args):
recs = data['data'] recs = data['data']

View File

@ -241,8 +241,8 @@ class InputBox(BoxLayout):
def defaultToolbar(): def defaultToolbar():
return { return {
"img_size":1.5, "img_size_c":1.5,
"text_size":0.7, "text_size_c":0.7,
"tools":[ "tools":[
{ {
"name":"__submit", "name":"__submit",
@ -320,18 +320,6 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
self.fsc.org_box_width = self.width / self.options_cols self.fsc.org_box_width = self.width / self.options_cols
if self.notoolbar: if self.notoolbar:
return return
if self.toolbar_at in [ 'top', 'bottom' ]:
Logger.info('Form: height:tb:%d,ti:%d,fsc:%d, fm:%d',
self.toolbar.height,
self.toolbar.toggle_items.height,
self.fsc.height, self.height
)
else:
Logger.info('Form: width:tb:%d,ti:%d,fsc:%d, fm:%d',
self.toolbar.width,
self.toolbar.toggle_items.width,
self.fsc.width, self.width
)
def init(self): def init(self):
if not self.notoolbar: if not self.notoolbar:
@ -359,11 +347,13 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
if self.toolbar_at in ['top', 'bottom']: if self.toolbar_at in ['top', 'bottom']:
desc['orientation'] = 'horizontal' desc['orientation'] = 'horizontal'
desc['size_hint_y'] = None desc['size_hint_y'] = None
desc['height'] = CSize(desc['img_size'] + desc['text_size']) desc['height'] = CSize(desc['img_size_c'] + \
desc['text_size_c'])
else: else:
desc['orientation'] = 'vertical' desc['orientation'] = 'vertical'
desc['size_hint_x'] = None desc['size_hint_x'] = None
desc['width'] = CSize(desc['img_size'] + desc['text_size']) desc['width'] = CSize(desc['img_size_c'] + \
desc['text_size_c'])
self.toolbar = Toolbar(**desc) self.toolbar = Toolbar(**desc)
self.fsc = VResponsiveLayout( self.fsc = VResponsiveLayout(

View File

@ -1,4 +1,5 @@
from kivy.properties import NumericProperty, StringProperty, ListProperty from kivy.properties import NumericProperty, StringProperty, \
OptionProperty, ListProperty
from kivy.uix.scrollview import ScrollView from kivy.uix.scrollview import ScrollView
from kivy.effects.scroll import ScrollEffect from kivy.effects.scroll import ScrollEffect
from kivy.uix.widget import Widget from kivy.uix.widget import Widget
@ -8,38 +9,41 @@ from kivy.factory import Factory
from kivyblocks.utils import * from kivyblocks.utils import *
class ScrollPanel(ScrollView): class ScrollPanel(ScrollView):
x_padding_c = NumericProperty(0) orientation = OptionProperty('vertical', \
y_padding_c = NumericProperty(0) options=['vertical', 'horizontal'])
bgcolor = ListProperty([0.2, 0.2, 0.2, 1]) bgcolor = ListProperty([0.2, 0.2, 0.2, 1])
padding_c = NumericProperty(1)
def __init__(self,inner=None, **kw): def __init__(self,inner=None, **kw):
print('ScrollPanel:kw=', kw)
SUPER(ScrollPanel, self, kw) SUPER(ScrollPanel, self, kw)
self.effect_cls = ScrollEffect self.effect_cls = ScrollEffect
if not inner: if not inner:
self.create_default_inner()
elif isinstance(inner, Widget):
self._inner = inner
else:
self._inner = Factory.Blocks().widgetBuild(inner)
super(ScrollPanel,self).add_widget(self._inner)
self._inner.bind(
minimum_height=self._inner.setter('height'))
self._inner.bind(
minimum_width=self._inner.setter('width'))
def create_default_inner(self):
kw = { kw = {
'size_hint':(None,None), 'size_hint':(None,None),
'bgcolor':self.bgcolor, 'orientation':self.orientation
} }
desc = { desc = {
"widgettype":"Box", "widgettype":"Box",
"options":kw "options":kw
} }
self._inner = Factory.Blocks().widgetBuild(desc) self._inner = Factory.Blocks().widgetBuild(desc)
self._inner.bgcolor = self.bgcolor
if not self._inner: if not self._inner:
print('desc=', desc) print('desc=', desc)
raise Exception('widget build failed') raise Exception('widget build failed')
self._inner.padding = self._inner.spacing = \ self._inner.spacing = CSize(self.padding_c)
[CSize(self.x_padding_c), CSize(self.y_padding_c)]
elif isinstance(inner, Widget):
self._inner = inner
else:
self._inner = Factory.Blocks().widgetBuild(inner)
self._inner.bind(
minimum_height=self._inner.setter('height'))
self._inner.bind(
minimum_width=self._inner.setter('width'))
super(ScrollPanel,self).add_widget(self._inner)
def add_widget(self,widget,**kw): def add_widget(self,widget,**kw):
a = self._inner.add_widget(widget,**kw) a = self._inner.add_widget(widget,**kw)

View File

@ -10,7 +10,7 @@ from kivy.app import App
from kivy.clock import Clock from kivy.clock import Clock
from kivy.factory import Factory from kivy.factory import Factory
from kivy.properties import StringProperty, DictProperty, \ from kivy.properties import StringProperty, DictProperty, \
ListProperty, NumericProperty OptionProperty, ListProperty, NumericProperty
from appPublic.dictObject import DictObject from appPublic.dictObject import DictObject
from appPublic.registerfunction import RegisterFunction from appPublic.registerfunction import RegisterFunction
@ -23,7 +23,7 @@ from .baseWidget import Text, Box
from .scrollpanel import ScrollPanel from .scrollpanel import ScrollPanel
from .toggleitems import ToggleItems from .toggleitems import ToggleItems
class ScrollToolbar(ScrollPanel): class Toolbar(ScrollPanel):
""" """
tool has the follow attributes tool has the follow attributes
{ {
@ -38,7 +38,6 @@ class ScrollToolbar(ScrollPanel):
} }
toolbar has follow attributes toolbar has follow attributes
{ {
"padding_c":x spacing
"img_size_c":image height in charecter size "img_size_c":image height in charecter size
"text_size_c": "text_size_c":
"toolbar_orient":"H" or "V" "toolbar_orient":"H" or "V"
@ -52,54 +51,44 @@ class ScrollToolbar(ScrollPanel):
css_on = StringProperty('default') css_on = StringProperty('default')
css_off = StringProperty('default') css_off = StringProperty('default')
tools = ListProperty([]) tools = ListProperty([])
tool_orient = StringProperty('horizontal') tool_orient = OptionProperty('horizontal', \
toolbar_orient = StringProperty('H') options=['horizontal', 'vertical'])
padding_c = NumericProperty(1) toolbar_orient = OptionProperty('H', options=['H', 'V'])
img_size_c = NumericProperty(2) img_size_c = NumericProperty(2)
text_size_c = NumericProperty(1) text_size_c = NumericProperty(1)
def __init__(self, **kw): def __init__(self, **kw):
SUPER(ScrollToolbar, self, kw) self.w_dic = {}
SUPER(Toolbar, self, kw)
self.register_event_type('on_press') self.register_event_type('on_press')
self.register_event_type('on_delete_tool')
if self.toolbar_orient == 'H': if self.toolbar_orient == 'H':
self._inner.orientation = 'horizontal' self._inner.orientation = 'horizontal'
else: else:
self._inner.orientation = 'vertical' self._inner.orientation = 'vertical'
self.clear_widgets() self.clear_widgets()
self.w_dic = {}
for t in self.tools: for t in self.tools:
self.add_tool(t) self.add_tool(t)
self.bar_width = 0 self.bar_width = 0
if self.toolbar_orient == 'H': if self.toolbar_orient == 'H':
self.do_scroll_y = False self.do_scroll_y = False
self._inner.spacing = CSize(self.padding_c,0)
else: else:
self.do_scroll_x = False self.do_scroll_x = False
self._inner.spacing = CSize(0, self.padding_c)
def on_children_size(self, o, size): def on_children_size(self, o, size):
self.on_size(None, None) self.on_size(None, None)
def on_size(self, o, size): def on_size(self, o, size):
print('on_size=', size)
if self.toolbar_orient == 'H': if self.toolbar_orient == 'H':
self.size_hint_x = 1 self.size_hint_x = 1
self.size_hint_y = None self.size_hint_y = None
if len(self.w_dic.keys()) > 0: if len(self.w_dic.keys()) > 0:
self.height = max([w.height for w in self.w_dic.keys()]) self.height = max([w.height for w in self.w_dic.keys()])
self._inner.spacing = CSize(self.padding_c,0)
else: else:
self.size_hint_x = None self.size_hint_x = None
self.size_hint_y = 1 self.size_hint_y = 1
if len(self.w_dic.keys()) > 0: if len(self.w_dic.keys()) > 0:
self.width = max([w.width for w in self.w_dic.keys() ]) 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): def add_tool(self, t):
label = t.get('label', t.get('name', None)) label = t.get('label', t.get('name', None))
@ -108,6 +97,7 @@ class ScrollToolbar(ScrollPanel):
ToggleIconText = Factory.ToggleIconText ToggleIconText = Factory.ToggleIconText
ToggleText = Factory.ToggleText ToggleText = Factory.ToggleText
ToggleImage = Factory.ToggleImage ToggleImage = Factory.ToggleImage
ClickableImage = Factory.ClickableImage
if label and source_on: if label and source_on:
w = ToggleIconText(css_on=self.css_on, w = ToggleIconText(css_on=self.css_on,
css_off=self.css_off, css_off=self.css_off,
@ -142,6 +132,18 @@ class ScrollToolbar(ScrollPanel):
} }
) )
print(w, 'children=', len(w.children))
if t.get('deletable', False):
x = ClickableImage(source=blockImage('delete.png'),
img_kw={
"size_hint":(None, None),
"size":CSize(1,1)
}
)
x.data = (w, t)
x.bind(on_press=self.delete_tool)
w.add_widget(x)
if w: if w:
self.add_widget(w) self.add_widget(w)
self.w_dic[w] = t self.w_dic[w] = t
@ -150,13 +152,20 @@ class ScrollToolbar(ScrollPanel):
w.bind(on_press=self.tool_press) w.bind(on_press=self.tool_press)
w.bind(minimum_width=w.setter('width')) w.bind(minimum_width=w.setter('width'))
w.bind(minimum_height=w.setter('height')) w.bind(minimum_height=w.setter('height'))
print(w, 'children=', len(w.children))
def del_tool(self, name): def delete_tool(self, o):
m = [ x for x,y in self.w_dic.items() if y['name'] == name ] w, t = o.data
for w in m: self.del_tool(w)
self.remove(w) self.dispatch('on_delete_tool', o.data)
def on_delete_tool(self, o, d=None):
pass
def del_tool(self, w):
self.remove_widget(w)
self.w_dic = {k:v for k,v in self.w_dic.copy().items() \ self.w_dic = {k:v for k,v in self.w_dic.copy().items() \
if k not in m } if k != w }
def on_press(self, o): def on_press(self, o):
pass pass
@ -187,7 +196,8 @@ class ToolPage(Box):
} }
""" """
toolbar_size = NumericProperty(2) toolbar_size = NumericProperty(2)
tool_at = StringProperty('top') tool_at = OptionProperty('top', \
options=['top', 'bottom', 'left', 'right'])
toolbar = DictProperty({}) toolbar = DictProperty({})
def __init__(self, **kw): def __init__(self, **kw):
print('ToolPage:kw=',kw) print('ToolPage:kw=',kw)
@ -202,16 +212,20 @@ class ToolPage(Box):
self.content_w = None self.content_w = None
self.toolbar_w = None self.toolbar_w = None
self.init() self.init()
self.toolbar_w.bind(on_delete_tool=self.delete_content_widget)
name = self.toolbar['tools'][0]['name'] name = self.toolbar['tools'][0]['name']
self.toolbar_w.select(name) self.toolbar_w.select(name)
def delete_content_widget(self, o, d):
w, dic = d
self.del_tool(dic['name'])
def add_tool(self, tool): def add_tool(self, tool):
self.toolbar_w.add_tool(tool) self.toolbar_w.add_tool(tool)
def del_tool(self, name): def del_tool(self, name):
self.toolbar_w.del_tool(o)
g = self.content_widgets.copy() g = self.content_widgets.copy()
self.content_widgets = {k:v for k,v in g.items()} self.content_widgets = {k:v for k,v in g.items() if k!=name}
def on_size(self,obj,size): def on_size(self,obj,size):
if self.content_w is None: if self.content_w is None:
@ -226,7 +240,7 @@ class ToolPage(Box):
def init(self): def init(self):
self.content_w = BoxLayout() self.content_w = BoxLayout()
self.content_w.widget_id = 'content' self.content_w.widget_id = 'content'
self.toolbar_w = ScrollToolbar(**self.toolbar) self.toolbar_w = Toolbar(**self.toolbar)
if self.tool_at in ['top','left']: if self.tool_at in ['top','left']:
self.add_widget(self.toolbar_w) self.add_widget(self.toolbar_w)
self.add_widget(self.content_w) self.add_widget(self.content_w)
@ -264,7 +278,8 @@ class ToolPage(Box):
def on_press_handle(self, o, v): def on_press_handle(self, o, v):
name = v.get('name') name = v.get('name')
refresh = v.get('refresh', False) refresh = v.get('refresh', False)
self.print_all() # self.print_all()
w = self.content_widgets.get(name) w = self.content_widgets.get(name)
self.content_w.clear_widgets() self.content_w.clear_widgets()
if w and not refresh: if w and not refresh:
@ -287,5 +302,3 @@ class ToolPage(Box):
if isinstance(r,Widget): if isinstance(r,Widget):
self.content_w.add_widget(r) self.content_w.add_widget(r)
Factory.register('ScrollToolbar', ScrollToolbar)
Toolbar = ScrollToolbar