bugfix
This commit is contained in:
parent
0de5b5b0ac
commit
5f0a2d3b6a
@ -21,7 +21,7 @@ class TinyText(Text):
|
|||||||
self.on_texture_size(self, (1,1))
|
self.on_texture_size(self, (1,1))
|
||||||
|
|
||||||
def on_texture_size(self, o, ts):
|
def on_texture_size(self, o, ts):
|
||||||
self._label.refresh()
|
self.texture_update()
|
||||||
self.size = self.texture_size
|
self.size = self.texture_size
|
||||||
|
|
||||||
class ClickableBox(TouchRippleButtonBehavior, Box):
|
class ClickableBox(TouchRippleButtonBehavior, Box):
|
||||||
@ -48,24 +48,39 @@ class ClickableBox(TouchRippleButtonBehavior, Box):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class ClickableText(ClickableBox):
|
class ClickableText(ClickableBox):
|
||||||
text = StringProperty(' ')
|
text = StringProperty(None)
|
||||||
fontsize = NumericProperty(1)
|
fontsize = NumericProperty(1)
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
self.txt_w = None
|
self.txt_w = None
|
||||||
SUPER(ClickableText, self, kw)
|
SUPER(ClickableText, self, kw)
|
||||||
|
self.create_text_widget()
|
||||||
|
|
||||||
|
def create_text_widget(self):
|
||||||
|
if self.text is None:
|
||||||
|
return
|
||||||
self.txt_w = TinyText(otext=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.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
|
||||||
|
|
||||||
|
def on_fontsize(self, o, fs):
|
||||||
|
if self.txt_w:
|
||||||
|
self.txt_w.font_size = CSize(self.fontsize)
|
||||||
|
self.txt_w.texture_update()
|
||||||
|
|
||||||
def on_text(self, o, txt):
|
def on_text(self, o, txt):
|
||||||
|
if self.text is None:
|
||||||
|
return
|
||||||
|
if not self.txt_w:
|
||||||
|
self.create_text_widget()
|
||||||
|
return
|
||||||
if self.txt_w:
|
if self.txt_w:
|
||||||
self.txt_w.text = self.text
|
self.txt_w.text = self.text
|
||||||
|
self.txt_w.texture_update()
|
||||||
|
|
||||||
|
|
||||||
class ClickableIconText(ClickableText):
|
class ClickableIconText(ClickableText):
|
||||||
source = StringProperty(None)
|
source = StringProperty(None)
|
||||||
@ -139,6 +154,8 @@ class ToggleIconText(ToggleText):
|
|||||||
self.source = self.source_on if f else self.source_off
|
self.source = self.source_on if f else self.source_off
|
||||||
|
|
||||||
def on_source(self, o, source):
|
def on_source(self, o, source):
|
||||||
|
if source is None:
|
||||||
|
return
|
||||||
if self.img_w:
|
if self.img_w:
|
||||||
self.img_w.source = self.source
|
self.img_w.source = self.source
|
||||||
|
|
||||||
|
@ -29,50 +29,7 @@ from .ready import WidgetReady
|
|||||||
from .toolbar import Toolbar
|
from .toolbar import Toolbar
|
||||||
from .bgcolorbehavior import BGColorBehavior
|
from .bgcolorbehavior import BGColorBehavior
|
||||||
from .widget_css import WidgetCSS
|
from .widget_css import WidgetCSS
|
||||||
|
from .uitype import build_view_widget
|
||||||
def field_widget(desc, rec):
|
|
||||||
viewer = desc.get('viewer')
|
|
||||||
if viewer:
|
|
||||||
if not isinstance(viewer,str):
|
|
||||||
viewer = json.dumps(viewer)
|
|
||||||
rendered = string_template_render(viewer, rec)
|
|
||||||
dic = json.loads(rendered)
|
|
||||||
if dic is None:
|
|
||||||
return None
|
|
||||||
blocks = Factory.Blocks()
|
|
||||||
return blocks.widgetBuild(dic)
|
|
||||||
|
|
||||||
uitype = desc.get('uitype', 'str')
|
|
||||||
if uitype is None:
|
|
||||||
uitype = desc.get('datatype')
|
|
||||||
if uitype in [ 'str' 'date', 'time', 'timestamp' ]:
|
|
||||||
return Text(text = str(desc['value']),
|
|
||||||
font_size=CSize(1),wrap=True,
|
|
||||||
halign='left', valign='middle'
|
|
||||||
)
|
|
||||||
if uitype in [ 'long', 'int','integer' ]:
|
|
||||||
return Text(text=str(desc['value']),
|
|
||||||
font_size=CSize(1), wrap=True,
|
|
||||||
halign='right', valign='middle'
|
|
||||||
)
|
|
||||||
if uitype == 'float':
|
|
||||||
f = '%%.0%df' % desc.get('dec',2)
|
|
||||||
return Text(text=f % float(desc['value']),
|
|
||||||
font_size=CSize(1), wrap=True,
|
|
||||||
halign='right', valign='middle'
|
|
||||||
)
|
|
||||||
if uitype == 'code':
|
|
||||||
tf = desc.get('textField','text')
|
|
||||||
vf = desc.get('valueField','value')
|
|
||||||
v = rec.get(tf,rec.get(vf, ' '))
|
|
||||||
return Text(text=v, font_size = CSize(1), wrap=True,
|
|
||||||
halign='right', valign='middle'
|
|
||||||
)
|
|
||||||
return Text(text = str(desc['value']),
|
|
||||||
font_size=CSize(1),wrap=True,
|
|
||||||
halign='left', valign='middle'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BLabel(ButtonBehavior, Text):
|
class BLabel(ButtonBehavior, Text):
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
@ -107,7 +64,7 @@ class Cell(ButtonBehavior, WidgetCSS, BoxLayout):
|
|||||||
halign='left', valign='middle'
|
halign='left', valign='middle'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
bl = field_widget(desc,self.row.row_data)
|
bl = build_view_widget(desc,self.row.row_data)
|
||||||
if bl:
|
if bl:
|
||||||
self.add_widget(bl)
|
self.add_widget(bl)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ from kivy.properties import ListProperty, BooleanProperty, \
|
|||||||
StringProperty, DictProperty, NumericProperty
|
StringProperty, DictProperty, NumericProperty
|
||||||
from kivy.uix.treeview import TreeView, TreeViewNode, TreeViewLabel
|
from kivy.uix.treeview import TreeView, TreeViewNode, TreeViewLabel
|
||||||
from kivy.uix.boxlayout import BoxLayout
|
from kivy.uix.boxlayout import BoxLayout
|
||||||
|
from kivy.uix.image import AsyncImage
|
||||||
|
|
||||||
from .threadcall import HttpClient
|
from .threadcall import HttpClient
|
||||||
from .scrollpanel import ScrollPanel
|
from .scrollpanel import ScrollPanel
|
||||||
@ -27,7 +28,8 @@ class TreeViewComplexNode(BoxLayout, TreeViewLabel):
|
|||||||
cb.bind(on_press=self.set_checked)
|
cb.bind(on_press=self.set_checked)
|
||||||
self.add_widget(cb)
|
self.add_widget(cb)
|
||||||
if self.icon:
|
if self.icon:
|
||||||
img = AsyncImage(source=self.icon)
|
img = AsyncImage(source=self.icon, size_hint=(None,None))
|
||||||
|
img.size = CSize(1,1)
|
||||||
self.add_widget(img)
|
self.add_widget(img)
|
||||||
txt = Text(otext=self.otext, i18n=True)
|
txt = Text(otext=self.otext, i18n=True)
|
||||||
txt.texture_update()
|
txt.texture_update()
|
||||||
@ -52,6 +54,7 @@ class Hirarchy(ScrollPanel):
|
|||||||
data = ListProperty(None)
|
data = ListProperty(None)
|
||||||
checkbox = BooleanProperty(False)
|
checkbox = BooleanProperty(False)
|
||||||
icon = StringProperty(None)
|
icon = StringProperty(None)
|
||||||
|
single_expand = BooleanProperty(False)
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
self.register_event_type('on_selected')
|
self.register_event_type('on_selected')
|
||||||
self.tree = TreeView(hide_root=True)
|
self.tree = TreeView(hide_root=True)
|
||||||
@ -68,9 +71,19 @@ class Hirarchy(ScrollPanel):
|
|||||||
def node_selected(self, o, v):
|
def node_selected(self, o, v):
|
||||||
self.dispatch('on_selected', o.selected_node)
|
self.dispatch('on_selected', o.selected_node)
|
||||||
|
|
||||||
|
def collapse_others(self, node):
|
||||||
|
for n in self.tree.iterate_open_nodes(node=node.parent_node):
|
||||||
|
if n != node and n !=node.parent_node and n.is_open:
|
||||||
|
self.tree.toggle_node(n)
|
||||||
|
|
||||||
def check_load_subnodes(self, treeview, node):
|
def check_load_subnodes(self, treeview, node):
|
||||||
|
if self.single_expand:
|
||||||
|
self.collapse_others(node)
|
||||||
if node.is_loaded:
|
if node.is_loaded:
|
||||||
return
|
return
|
||||||
|
if not self.url:
|
||||||
|
node.is_loaded = True
|
||||||
|
return
|
||||||
data = self.get_remote_data(node)
|
data = self.get_remote_data(node)
|
||||||
for d in data:
|
for d in data:
|
||||||
self.create_new_node(d, node)
|
self.create_new_node(d, node)
|
||||||
@ -79,7 +92,7 @@ class Hirarchy(ScrollPanel):
|
|||||||
def create_new_node(self, data, node=None):
|
def create_new_node(self, data, node=None):
|
||||||
n = TreeViewComplexNode(otext=data[self.textField],
|
n = TreeViewComplexNode(otext=data[self.textField],
|
||||||
checkbox=self.checkbox,
|
checkbox=self.checkbox,
|
||||||
icon=self.icon
|
icon=data.get('icon') or self.icon
|
||||||
)
|
)
|
||||||
n.data = data
|
n.data = data
|
||||||
n.width = self.tree.indent_start + \
|
n.width = self.tree.indent_start + \
|
||||||
@ -97,6 +110,8 @@ class Hirarchy(ScrollPanel):
|
|||||||
n.is_loaded = True
|
n.is_loaded = True
|
||||||
|
|
||||||
def get_remote_data(self, node=None):
|
def get_remote_data(self, node=None):
|
||||||
|
if not self.url:
|
||||||
|
return
|
||||||
hc = HttpClient()
|
hc = HttpClient()
|
||||||
params = self.params.copy() if self.params else {}
|
params = self.params.copy() if self.params else {}
|
||||||
if node:
|
if node:
|
||||||
@ -115,4 +130,58 @@ class Hirarchy(ScrollPanel):
|
|||||||
for d in self.data:
|
for d in self.data:
|
||||||
self.create_new_node(d)
|
self.create_new_node(d)
|
||||||
|
|
||||||
|
class Menu(Hirarchy):
|
||||||
|
target = StringProperty(None)
|
||||||
|
def __init__(self, **kw):
|
||||||
|
self.target_w = None
|
||||||
|
super(Menu, self).__init__(**kw)
|
||||||
|
|
||||||
|
def on_selected(self, node):
|
||||||
|
data = {}
|
||||||
|
dw = node.data.get('datawidget')
|
||||||
|
if dw:
|
||||||
|
data_widget = Factory.Blocks.getWidgetById(dw)
|
||||||
|
if data_widget:
|
||||||
|
vn = node.data.get('datamethod', 'getValue')
|
||||||
|
if hasattr(data_widget, vn):
|
||||||
|
f = getattr(data_widget, vn)
|
||||||
|
data = f()
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
url = node.data.get('url')
|
||||||
|
target = Factory.Blocks.getWidgetById(node.data.get('target',self.target),self)
|
||||||
|
if url:
|
||||||
|
params = node.data.get('params',{})
|
||||||
|
params.update(data)
|
||||||
|
blocks = Factory.Blocks()
|
||||||
|
desc = {
|
||||||
|
"widgettype":"urlwidget",
|
||||||
|
"options":{
|
||||||
|
"url":url,
|
||||||
|
"params":params
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w = blocks.widgetBuild(desc)
|
||||||
|
if w and target:
|
||||||
|
target.add_widget(w)
|
||||||
|
return
|
||||||
|
|
||||||
|
rfname = node.data.get('rfname')
|
||||||
|
if rfname:
|
||||||
|
f = getRegisterFunctionByName(rfname)
|
||||||
|
if f:
|
||||||
|
f(self, **data)
|
||||||
|
return
|
||||||
|
|
||||||
|
script = node.data.get('script')
|
||||||
|
if script:
|
||||||
|
target_name = node.data.get('target', self.target)
|
||||||
|
target = Factory.Blocks.getWidgetById(target_name, self)
|
||||||
|
data.update({'self':target})
|
||||||
|
if target:
|
||||||
|
eval(script,data)
|
||||||
|
return
|
||||||
|
|
||||||
Factory.register('Hirarchy', Hirarchy)
|
Factory.register('Hirarchy', Hirarchy)
|
||||||
|
Factory.register('Menu', Menu)
|
||||||
|
@ -6,9 +6,10 @@ from kivy.uix.widget import Widget
|
|||||||
from kivy.uix.boxlayout import BoxLayout
|
from kivy.uix.boxlayout import BoxLayout
|
||||||
from kivy.factory import Factory
|
from kivy.factory import Factory
|
||||||
|
|
||||||
from kivyblocks.utils import *
|
from .utils import *
|
||||||
|
from .widget_css import WidgetCSS
|
||||||
|
|
||||||
class ScrollPanel(ScrollView):
|
class ScrollPanel(WidgetCSS, ScrollView):
|
||||||
orientation = OptionProperty('vertical', \
|
orientation = OptionProperty('vertical', \
|
||||||
options=['vertical', 'horizontal'])
|
options=['vertical', 'horizontal'])
|
||||||
bgcolor = ListProperty([0.2, 0.2, 0.2, 1])
|
bgcolor = ListProperty([0.2, 0.2, 0.2, 1])
|
||||||
|
106
kivyblocks/uitype.py
Normal file
106
kivyblocks/uitype.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#uitype.py
|
||||||
|
"""
|
||||||
|
each ui type need to provides a view widget and a input widget
|
||||||
|
to auto construct the form widget and record show widget.
|
||||||
|
|
||||||
|
we use a register machinans to maintian the ui type information to build the view widget and input widget
|
||||||
|
"""
|
||||||
|
|
||||||
|
from kivy.factory import Factory
|
||||||
|
|
||||||
|
from appPublic.myTE import string_template_render
|
||||||
|
|
||||||
|
view_widget_builders = {
|
||||||
|
}
|
||||||
|
|
||||||
|
input_widget_builders = {}
|
||||||
|
|
||||||
|
def view_register(uitype, f):
|
||||||
|
view_widget_builders.update({uitype:f})
|
||||||
|
|
||||||
|
def input_register(uitype, f):
|
||||||
|
input_widget_builders.update({uitype:f})
|
||||||
|
|
||||||
|
def get_input_builder(uitype):
|
||||||
|
return input_widget_builders.get(uitype, \
|
||||||
|
input_widget_builders.get('str', None))
|
||||||
|
|
||||||
|
def get_view_builder(uitype):
|
||||||
|
return view_widget_builders.get(uitype, \
|
||||||
|
view_widget_builders.get('str', None))
|
||||||
|
|
||||||
|
def build_view_widget(desc, rec = None):
|
||||||
|
if desc.get('viewer'):
|
||||||
|
if isinstance(viewer,dict):
|
||||||
|
viewer = json.dumps(viewer)
|
||||||
|
rendered = string_template_render(viewer, rec)
|
||||||
|
dic = json.loads(rendered)
|
||||||
|
if dic is None:
|
||||||
|
return None
|
||||||
|
w = Factory.Blocks().widgetBuild(dic)
|
||||||
|
return w
|
||||||
|
|
||||||
|
f = get_view_builder(desc.get('uitype'))
|
||||||
|
return f(desc, rec)
|
||||||
|
|
||||||
|
def build_input_widget(desc, rec=None):
|
||||||
|
f = get_input_builder(desc.get('uitype'))
|
||||||
|
return f(desc, rec)
|
||||||
|
|
||||||
|
def get_value(desc, rec=None):
|
||||||
|
if rec:
|
||||||
|
return rec.get(desc['name'])
|
||||||
|
return desc.get('value', desc.get('defaultvalue', ''))
|
||||||
|
|
||||||
|
def build_view_text_widget(desc, rec=None):
|
||||||
|
txt = get_value(desc, rec=rec)
|
||||||
|
return Factory.Text(text=str(txt),
|
||||||
|
font_size=CSize(1),
|
||||||
|
wrap=True,
|
||||||
|
halign='left',
|
||||||
|
valign='middle')
|
||||||
|
|
||||||
|
view_register('str', build_view_text_widget)
|
||||||
|
view_register('date', build_view_text_widget)
|
||||||
|
view_register('time', build_view_text_widget)
|
||||||
|
view_register('timestamp', build_view_text_widget)
|
||||||
|
|
||||||
|
def build_view_int_widget(desc, rec=None):
|
||||||
|
v = get_value(desc, rec=rec)
|
||||||
|
return Text(text=str(v),
|
||||||
|
font_size=CSize(1),
|
||||||
|
wrap=True,
|
||||||
|
halign='right',
|
||||||
|
valign='middle'
|
||||||
|
)
|
||||||
|
|
||||||
|
view_register('int', build_view_int_widget)
|
||||||
|
view_register('long', build_view_int_widget)
|
||||||
|
view_register('integer', build_view_int_widget)
|
||||||
|
|
||||||
|
def build_view_float_widget(desc, rec=None):
|
||||||
|
v = get_value(desc, rec=rec)
|
||||||
|
f = '%%.0%df' % desc.get('dec',2)
|
||||||
|
return Text(text=f % float(v),
|
||||||
|
font_size=CSize(1),
|
||||||
|
wrap=True,
|
||||||
|
halign='right',
|
||||||
|
valign='middle'
|
||||||
|
)
|
||||||
|
|
||||||
|
view_register('float', build_view_float_widget)
|
||||||
|
|
||||||
|
def build_view_code_widget(desc, rec=None):
|
||||||
|
tf = desc.get('textField','text')
|
||||||
|
vf = desc.get('valueField','value')
|
||||||
|
v = rec.get(tf,rec.get(vf, ' '))
|
||||||
|
return Text(text=v,
|
||||||
|
font_size = CSize(1),
|
||||||
|
wrap=True,
|
||||||
|
halign='center',
|
||||||
|
valign='middle'
|
||||||
|
)
|
||||||
|
|
||||||
|
view_register('code', build_view_code_widget)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user