This commit is contained in:
yumoqing 2023-10-26 17:55:34 +08:00
parent 01442309d9
commit 9e2b5db1a6
23 changed files with 332 additions and 233 deletions

View File

@ -89,16 +89,6 @@ font_names = {
'title1':resource_find('Alimama_ShuHeiTi_Bold.ttf')
}
font_sizes = {
'text':CSize(1),
'title6':CSize(1.1),
'title5':CSize(1.3),
'title4':CSize(1.5),
'title3':CSize(1.7),
'title2':CSize(1.9),
'title1':CSize(2.1)
}
if platform == 'android':
from .widgetExt.phonebutton import PhoneButton
from .widgetExt.androidwebview import AWebView
@ -162,10 +152,12 @@ class SwipeBox(SwipeBehavior, Box):
class Text(Label):
lang=StringProperty('')
otext = StringProperty('')
def __init__(self,i18n=False, texttype='text', wrap=False,
def __init__(self,i18n=False, texttype='text', wrap=False, rate=1,
fgcolor=None, **kw):
fontsize = font_sizes.get(texttype)
app = App.get_running_app()
self.rate = 1
fontsize = app.get_font_size(texttype) * self.rate
fontname = font_names.get(texttype)
self._i18n = i18n
self.i18n = I18n()
@ -181,6 +173,8 @@ class Text(Label):
kwargs['text'] = kwargs.get('otext','')
super(Text, self).__init__(**kwargs)
app.bind(font_size=self.reset_font_size)
# self.bind(texture_size=self.setter('size'))
if self._i18n:
self.i18n.addI18nWidget(self)
if self.wrap:
@ -190,6 +184,9 @@ class Text(Label):
if self.bgcolor:
self.color = self.bgcolor
def reset_font_size(self, app, fsize):
self.font_size = fsize * self.rate
def resize(self, *args):
if not self.size_hint_y:
ps = [0,0,0,0]

View File

@ -214,7 +214,14 @@ x = ClassX{klass_cnt}()
print_exc()
if errback:
return errback(None,e)
return None
return {
"widgettype":"Text",
"options":{
"text":f"{url=} error",
"wrap":True,
"halign":"left"
}
}
else:
config = getConfig()
url = config.uihome + url
@ -727,7 +734,7 @@ x = ClassX{klass_cnt}()
print('Block3: desc must be a dict object not None')
return None
w = doit(desc)
print('widgetBuild():w=', w)
# print('widgetBuild():w=', w)
return w
@classmethod
@ -769,7 +776,7 @@ x = ClassX{klass_cnt}()
children = [i for i in from_widget.children]
if hasattr(from_widget, 'get_subwidgets'):
children = from_widget.get_subwidgets()
Logger.info('children=%s', str(children))
# Logger.info('children=%s', str(children))
for c in children:
ret = _find_widget(name, from_widget=c, dir=dir)
if ret:

View File

@ -12,6 +12,7 @@ from appPublic.folderUtils import ProgramPath
from appPublic.uniqueID import getID
from appPublic.rsawrap import RSA
from kivy.properties import NumericProperty
from kivy.factory import Factory
from kivy.metrics import sp,dp,mm
from kivy.core.window import WindowBase, Window
@ -48,6 +49,7 @@ signal.signal(signal.SIGINT, signal_handler)
class BlocksApp(App):
font_size = NumericProperty(24)
def get_rotation(self):
return get_rotation()
@ -78,7 +80,26 @@ class BlocksApp(App):
if isinstance(v,dict):
register_css(k,v)
def set_fontsize(self, x):
self.font_size = x
def get_font_size(self, ttype='text'):
text_fontrates = {
'text':1,
'title6':1.1,
'title5':1.3,
'title4':1.5,
'title3':1.7,
'title2':1.9,
'title1':2.1
}
v = text_fontrates.get(ttype, 'text')
return v * self.font_size
def build(self):
tl = Label(text='test')
self.font_size = tl.font_size
print('##################app_font_size=', self.font_size)
config = getConfig()
self.workers = Workers(maxworkers=config.maxworkers or 80)
self.workers.start()
@ -93,10 +114,10 @@ class BlocksApp(App):
self.default_params.update(config.default_params)
self.public_headers = {
"client_uuid":getID(),
"platform":self.platform
}
# Window.borderless = True
print('Window.dpi=', Window.dpi, 'Metrics.dpi=', Metrics.dpi)
Window.bind(on_request_close=self.on_close)
Window.bind(on_rotate=self.on_rotate)
Window.bind(size=self.device_info)

View File

@ -29,7 +29,7 @@ from kivy.graphics import Fbo, Color, Rectangle
from kivy.properties import NumericProperty, StringProperty, DictProperty
from .responsivelayout import VResponsiveLayout
from .toolbar import Toolbar
from .paging import Paging, RelatedLoader
from .paging import RelatedLoader
from .utils import CSize, SUPER
from .ready import WidgetReady
from .baseWidget import VBox

View File

@ -3,6 +3,12 @@ from kivy.logger import Logger
from kivy.uix.behaviors import TouchRippleButtonBehavior
from kivy.graphics import Color, Rectangle
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.stacklayout import StackLayout
from kivy.factory import Factory
from kivy.uix.image import AsyncImage
from kivy.properties import NumericProperty, DictProperty, \
@ -395,6 +401,34 @@ def build_cmdbox_view(desc, rec=None):
x.setValue(vd)
return x
class PressableAnchorLayout(TouchRippleButtonBehavior, AnchorLayout):
def on_press(self, o=None, d=None):
pass
class PressableBoxLayout(TouchRippleButtonBehavior, BoxLayout):
def on_press(self, o=None, d=None):
pass
class PressableFloatLayout(TouchRippleButtonBehavior, FloatLayout):
def on_press(self, o=None, d=None):
pass
class PressableRelativeLayout(TouchRippleButtonBehavior, RelativeLayout):
def on_press(self, o=None, d=None):
pass
class PressableGridLayout(TouchRippleButtonBehavior, GridLayout):
def on_press(self, o=None, d=None):
pass
class PressableScatterLayout(TouchRippleButtonBehavior, ScatterLayout):
def on_press(self, o=None, d=None):
pass
class PressableStackLayout(TouchRippleButtonBehavior, StackLayout):
def on_press(self, o=None, d=None):
pass
UiFactory.register('checkbox', build_checkbox, build_checkbox)
UiFactory.register('cmdbox', build_cmdbox_view, build_cmdbox_view)
@ -409,3 +443,10 @@ r('ToggleText',ToggleText)
r('ToggleIconText',ToggleIconText)
r('ClickableImage',ClickableImage)
r('ToggleImage',ToggleImage)
r('PressableAnchorLayout',PressableAnchorLayout)
r('PressableBoxLayout',PressableBoxLayout)
r('PressableFloatLayout',PressableFloatLayout)
r('PressableRelativeLayout',PressableRelativeLayout)
r('PressableGridLayout',PressableGridLayout)
r('PressableScatterLayout',PressableScatterLayout)
r('PressableStackLayout',PressableStackLayout)

View File

@ -1,7 +1,12 @@
# container is ScrollView with a dataloader
from kivy.uix.scrollview import ScroppView
from kivy.properties import DictProperty, ListProperty, BooleanProperty
from .paging import Paging, RelatedLoader
import json
from appPublic.myTE import MyTemplateEngine
from kivy.uix.scrollview import ScrollView
from kivy.properties import DictProperty, ListProperty, BooleanProperty, StringProperty, NumericProperty
from kivy.clock import Clock
from kivyblocks.blocks import Blocks
from kivyblocks.paging import RelatedLoader
from kivyblocks.widget_css import WidgetCSS
class LayoutBuildFailed(Exception):
def __init__(self, desc):
@ -13,7 +18,7 @@ class LayoutBuildFailed(Exception):
def __expr__(self):
return str(self)
class Container(ScrollView):
class Container(WidgetCSS, ScrollView):
"""
"loader":{
"page":1,
@ -24,43 +29,118 @@ class Container(ScrollView):
}
},
"""
idField = StringProperty('id')
loader = DictProperty({})
data = ListProperty(None)
layout = DictProperty({})
viewer = DictProperty({})
min_threhold = NumericProperty(0.01)
max_htrehold = NumericProperty(0.99)
extend_x = BooleanProperty(False)
content = None
def __init__(self, **kw):
self.dataloader = None
self.engine = MyTemplateEngine('.')
self.id_widget = {}
super(Container, self).__init__(**kw)
self.content = Blocks.widgetBuild(self.layout, self)
self.content = Blocks().widgetBuild(self.layout)
if not self.content:
raise LayoutBuildFailed
if self.do_scroll_x:
self.content.bind(minimum_height=layout.setter('width'))
self.content.bind(minimum_width=self.content.setter('width'))
if self.do_scroll_y:
self.content.bind(minimum_height=layout.setter('height'))
super().add_widget(self.content)
self.content.bind(minimum_height=self.content.setter('height'))
self.add_widget(self.content)
self.viewer_tmpl = json.dumps(self.viewer)
self.bind(on_scroll_stop = self.on_scrollstop)
if self.data:
d = {
"dir":"down",
"rows":self.data,
"total":len(self.data)
}
self.add_page(d)
if self.loader:
self.dataloader = RelatedLoader(target=self, **self.loader)
self.dataloader.bind(on_deletepage=self.delete_page)
self.dataloader.bind(on_pageloaded=self.add_page)
self.dataloader.bind(on_pageloaded=self.update_tailer_info)
self.dataloader.bind(on_newbegin=self.clearRows)
self.dataloader.bind(on_newbegin=self.clear_records)
Clock.schedule_once(self.loadData, 0.5)
def delete_page(self, ):
def add_page(self, ):
def clear_records(self, ):
def print_info(self, *args):
print(f"{self.scroll_distance=}, {self.scroll_timeout=}, {self.do_scroll_x=} {self.do_scroll_y=}, {self.scroll_x=}, {self.scroll_y=}, {self.content.size=}")
def add_widget(self, w, index=0):
return self.content.add_widget(w,index=index)
def parse_viewer(self, rec):
return json.loads(self.engine.renders(self.viewer_tmpl, rec))
def remove_widget(self, w):
return self.content.remove_widget(w)
def loadData(self, *args, **kw):
kw['page'] = 1
self.dataloader.do_search(None,kw)
def clear_widgets(self):
return self.content.clear_widgets()
def add_data(self, row_data):
desc = self.transfer(row_data)
w = Blocks.widgetBuild(desc)
def add_record(self, rec, tail=True):
desc = self.parse_viewer(rec)
w = Blocks().widgetBuild(desc)
if w:
self.add_widget(w)
idx = 0
if not tail:
idx = -1
id = rec.get(self.idField)
self.id_widget[id] = w
self.content.add_widget(w, index=idx)
else:
print(f'create widget error {self.viewer_tmpl=}, {rec=}')
def delete_record(self, rec):
id = rec.get(self.idField)
w = self.id_widget.get(id)
if w:
self.content.remove_widget(w)
del self.id_widget[id]
def delete_page(self, o, d):
# print(f'delete_page():{o=}, {d=}')
for r in d:
self.delete_record(r)
def add_page(self, o, d):
# print(f'add_page():{o=},{d=}')
dir = d.get('dir', 'down')
recs = d.get('data', [])
tail = True
if dir != 'down':
tail = False
recs.reverse()
for r in recs:
self.add_record(r, tail=tail)
if self.extend_x:
self.scroll_x = d['locator']
else:
self.scroll_y = d['locator']
def clear_records(self, o):
# print(f'clear_records():{o=}')
self.content.clear_widgets()
self.id_Widget = {}
def on_scrollstop(self, o, d=None):
if self.dataloader is None:
return
if self.extend_x:
if self.scroll_x < self.min_threhold:
self.dataloader.loadNextPage()
if self.scroll_x > self.max_htrehold:
self.dataloader.loadPreviousPage()
print('return here ...')
return
if self.dataloader.loading:
print('loading is True')
return
if self.scroll_y < self.min_threhold:
print('load next page ...')
self.dataloader.loadNextPage()
if self.scroll_y > self.max_htrehold:
print('load previous page ...')
self.dataloader.loadPreviousPage()

View File

@ -1,3 +1,4 @@
import os
from kivy.uix.image import AsyncImage
from kivy.factory import Factory
from kivy.properties import StringProperty

View File

@ -1,11 +1,11 @@
import inspect
import asyncio
from functools improt wraps
from functools import wraps
def eventhandler(func):
@wraps(func)
def wrapper_func(*args, **kw):
if inspect.inspect.iscoroutinefunction(func):
if inspect.iscoroutinefunction(func):
return asyncio.gather(func(*args, **kw))
return func(*args, **kw)
return wrapper_func

View File

@ -58,9 +58,12 @@ class I18n:
if config.i18n_url:
url = '%s%s' % (config.uihome, config.i18n_url)
hc = HttpClient()
try:
d = hc.get(url)
if isinstance(d, list):
return d
except:
pass
return []
def loadI18n(self,lang):
@ -74,9 +77,12 @@ class I18n:
if config.i18n_url:
url = '%s%s/%s' % (config.uihome, config.i18n_url, lang)
hc = HttpClient()
try:
d = hc.get(url)
print('i18n() %s get data=' % url, d, type(d))
self.kvlang[lang] = d
except:
pass
def __call__(self,msg,lang=None):
if lang is None:

Binary file not shown.

BIN
kivyblocks/imgs/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
kivyblocks/imgs/delete.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
kivyblocks/imgs/deletex.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
kivyblocks/imgs/lensid.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -177,6 +177,8 @@ sub-widget's description file format
self.left_menu = Factory.Blocks().widgetBuild(left_menu)
self.sub_widgets = []
VBox.__init__(self, **kw)
app = App.get_running_app()
print('========================barsize=', CSize(bar_size), bar_size, app.font_size)
self.bar = HBox(size_hint_y=None,
csscls=bar_css,
spacing=CSize(bar_size/6),

View File

@ -17,28 +17,6 @@ from .dataloader import UrlDataLoader
from .dataloader import ListDataLoader
from .dataloader import RegisterFunctionDataLoader
class PagingButton(Button):
def __init__(self, **kw):
super().__init__(**kw)
self.size_hint = (None,None)
self.size = CSize(2,1.8)
self.font_size = CSize(1)
"""
{
dataurl
params
method
locater
filter
}
PageLoader load data in a page size once.
it fires two type of event
'on_newbegin':fire when start a new parameters loading series
'on_pageloaded':fire when a page data loads success
"""
class PageLoader(EventDispatcher):
def __init__(self,target=None, **options):
self.loading = False
@ -113,11 +91,11 @@ class PageLoader(EventDispatcher):
p += 1
self.total_cnt = d['total']
self.calculateTotalPage()
d = {
d.update( {
"page":self.curpage,
"data":d['rows'],
"dir":self.dir,
"data":d['rows']
}
})
self.dispatch('on_pageloaded',d)
self.loading = False
@ -129,10 +107,10 @@ class PageLoader(EventDispatcher):
def loadNextPage(self):
if self.loading:
print('is loading, return')
return
return -1
if self.total_page > 0 and self.curpage >=self.total_page:
return
return -1
p = self.curpage + 1
self.loadPage(p)
@ -163,39 +141,18 @@ class PageLoader(EventDispatcher):
self.curpage = p
self.loader.load()
"""
{
adder,
remover
target,
locater,
dataurl,
params,
method,
filter
}
events:
'on_deletepage': erase
"""
class RelatedLoader(PageLoader):
def __init__(self, **options):
super().__init__(**options)
self.objectPages = {}
self.totalObj = 0
self.MaxbufferPage = 3
self.locater = 1/self.MaxbufferPage
if self.filter:
self.widget = self.filter
else:
self.widget = None
self.buffered_pages = 0
self.register_event_type('on_deletepage')
def do_search(self,o,params):
self.objectPages = {}
self.totalObj = 0
self.MaxbufferPage = 3
self.locater = 1/self.MaxbufferPage
super().do_search(o, params)
def getLocater(self):
@ -216,13 +173,15 @@ class RelatedLoader(PageLoader):
self.calculateTotalPage()
def doBufferMaintain(self):
siz = len(self.objectPages.keys())
if siz >= self.MaxbufferPage:
siz = len([k for k in self.objectPages.keys()])
self.buffered_pages = siz
if siz > self.MaxbufferPage:
if self.dir == 'up':
p = max(self.objectPages.keys())
else:
p = min(self.objectPages.keys())
self.deleteBuffer(p)
self.buffered_pages = self.MaxbufferPage
def deleteBuffer(self,page):
d = self.objectPages[page]
@ -237,18 +196,25 @@ class RelatedLoader(PageLoader):
def show_page(self,o,data):
if self.objectPages.get(self.curpage):
self.deleteBuffer(self.curpage)
else:
self.bufferObjects(self.curpage, data['rows'])
self.doBufferMaintain()
self.totalObj += len(data['rows'])
if self.dir == 'down':
data['locator'] = 1/self.buffered_pages
else:
data['locator'] = 1 - 1/self.buffered_pages
super().show_page(o,data)
def loadPreviousPage(self):
pages = self.objectPages.keys()
if len(pages) < 1:
print('self.objectPages is null')
return
page = min(pages)
if page <= 1:
print('page < 1')
return
page -= 1
@ -257,68 +223,12 @@ class RelatedLoader(PageLoader):
def loadNextPage(self):
pages = self.objectPages.keys()
if len(pages) == 0:
print('self.objectPages is null')
return
page = max(pages)
if page>=self.total_page:
print('page > total page')
return
page += 1
self.loadPage(page)
"""
{
adder,
clearer
target,
dataurl
params,
method
}
"""
class Paging(PageLoader):
def __init__(self,**options):
PageLoader.__init__(self,**options)
self.target = options.get('target')
self.init()
def init(self):
kwargs = {}
kwargs['size_hint_y'] = None
kwargs['height'] = CSize(2)
kwargs['orientation'] = 'horizontal'
kwargs['spacing'] = CSize(1)
self.widget = BoxLayout(**kwargs)
self.b_f = PagingButton(text="|<")
self.b_p = PagingButton(text="<")
self.b_n = PagingButton(text=">")
self.b_l = PagingButton(text=">|")
self.b_f.bind(on_press=self.loadFirstPage)
self.b_p.bind(on_press=self.loadPreviousPage)
self.b_n.bind(on_press=self.loadNextPage)
self.b_l.bind(on_press=self.loadLastPage)
self.widget.add_widget(self.b_f)
self.widget.add_widget(self.b_p)
self.widget.add_widget(self.b_n)
self.widget.add_widget(self.b_l)
if self.filter:
self.widget.add_widget(self.filter)
def loadFirstPage(self,o=None):
if self.curpage == 1:
return
self.loadPage(1)
def loadPreviousPage(self,o=None):
if self.curpage < 2:
return
self.loadPage(self.curpage-1)
def loadNextPage(self,o=None):
if self.curpage >= self.total_page:
return
self.loadPage(self.curpage+1)
def loadLastPage(self,o=None):
if self.curpage >= self.total_page:
return
self.loadPage(self.total_page)

View File

@ -8,6 +8,7 @@ import kivyblocks.clickable
import kivyblocks.multi_select
from .baseWidget import *
from .container import Container
from .tree import Tree, TextTree, MenuTree, PopupMenu
from .toolbar import ToolPage, Toolbar
from .dg import DataGrid
@ -53,6 +54,7 @@ from .landscopehide import LandscopeHide
r = Factory.register
# if kivy.platform in ['win','linux', 'macosx']:
# r('ScreenWithMic', ScreenWithMic)
r('Container', Container)
r('LandscopeHide', LandscopeHide)
r('VideoBehavior', VideoBehavior)
r('ModalBehavior', ModalBehavior)

View File

@ -6,8 +6,8 @@ from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory
from .utils import *
from .widget_css import WidgetCSS
from kivyblocks.utils import *
from kivyblocks.widget_css import WidgetCSS
class ScrollPanel(WidgetCSS, ScrollView):
orientation = OptionProperty('vertical', \

View File

@ -24,8 +24,8 @@ from appPublic.uniqueID import getID
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelItem
from kivy.clock import Clock
from kivy.factory import Factory
from .utils import SUPER
from .widget_css import WidgetCSS
from kivyblocks.utils import SUPER
from kivyblocks.widget_css import WidgetCSS
class TabsPanel(WidgetCSS, TabbedPanel):
def __init__(self, tabs=[], **options):
@ -33,26 +33,44 @@ class TabsPanel(WidgetCSS, TabbedPanel):
SUPER(TabsPanel, self, options)
# TabbedPanel.__init__(self,**options)
# BGColorBehavior.__init__(self)
self.old_content = None
self.def_tab = None
self.register_event_type('on_content_show')
self.register_event_type('on_content_hide')
Clock.schedule_once(self.add_tabs,0)
def newname(self):
return getID()
def add_tab(self,name,text,desc):
def add(o,w):
if not hasattr(w,'widget_id'):
w.widget_id = name
self.add_widget(TabbedPanelItem(text=text,content=w))
def add_tab(self,desc):
if not desc.get('name'):
desc['name'] = getID()
blocks = Factory.Blocks()
blocks.bind(on_built=add)
blocks.widgetBuild(desc)
w = blocks.widgetBuild(desc['content'])
if w is None:
return
if not hasattr(w,'widget_id'):
w.widget_id = desc['name']
item = TabbedPanelItem(text=desc['text'],content=w)
if desc.get('isdefault', False):
self.def_tab = item
self.add_widget(item)
def add_tabs(self,*args):
for d in self.tabs_list:
name = d.get('name',self.newname())
text = d['text']
desc = d['content']
self.add_tab(name,text,desc)
self.add_tab(d)
if self.def_tab:
self.switch_to(self.def_tab)
self.bind(current_tab = self.content_changed)
def content_changed(self, o, v=None):
if self.old_content:
self.dispatch('on_content_hide', self.old_content)
self.old_content = self.current_tab.content
self.dispatch('on_content_show', self.old_content)
def on_content_show(self, *args):
print('content show', args)
def on_content_hide(self, *args):
print('content hide', args)
if __name__ == '__main__':
from kivy.app import App

View File

@ -221,6 +221,9 @@ class ToolPage(Box):
self.orientation = 'vertical'
else:
self.orientation = 'horizontal'
self.current_sub_content = None
self.register_event_type('on_content_show')
self.register_event_type('on_content_hide')
if not self.toolbar_size:
self.toolbar_size = self.img_size + self.text_size + 0.3
self.content_widgets = {}
@ -259,6 +262,7 @@ class ToolPage(Box):
def init(self):
self.content_w = BoxLayout()
self.curr_sub_content = None
self.content_w.widget_id = 'content'
self.toolbar_w = Toolbar(**self.toolbar)
if self.tool_at in ['top','left']:
@ -300,24 +304,37 @@ class ToolPage(Box):
refresh = v.get('refresh', False)
# self.print_all()
if self.current_sub_content:
self.dispatch('on_content_hide', self.current_sub_content)
w = self.content_widgets.get(name)
self.content_w.clear_widgets()
if w and not refresh:
self.content_w.add_widget(w)
return
else:
w = None
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
else:
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)
w = f()
if isinstance(w,Widget):
self.content_widgets[name] = w
self.content_w.add_widget(w)
if w:
self.current_sub_content = w
self.dispatch('on_content_show', w)
def on_content_show(self, content):
pass
def on_content_hide(self, content):
pass

View File

@ -158,12 +158,28 @@ class TreeNode(BoxLayout):
self.node_box1.width = width
for n in self.nodes:
n.setMinWidth(width)
def build_content(self):
self.buildContent()
x = self.content
cf = self.treeObj.checkField
if cf:
self.content = HBox(size_hint_y=None,
height=self.treeObj.rowHeight)
self.checkbox_w = CheckBox(active=self.data.get(cf, False)
self.content.add_widget(self.checkbox_w)
self.content.add_widget(x)
self.checkbox_w.bind(active=self.on_checkbox_active)
def on_checkbox_active(self, o, v):
cf = self.treeObj.checkField
self.data[cf] = v
self.treeObj.node_checkbox_changed(self)
def buildContent(self):
pass
def addContent(self):
self.buildContent()
self.build_content()
self.node_box.add_widget(self.content)
self.node_box.height = self.treeObj.rowheight
self.node_box.width = self.trigger.width + \
@ -304,8 +320,7 @@ tree options
"single_expand",
"select_leaf_only",
"bgcolor",
"checkbox",
"multplecheck",
"checkField",
"idField",
"textFiled",
"data" # array of {children:{},...}
@ -313,7 +328,7 @@ tree options
"""
class Tree(WidgetCSS, ScrollWidget):
data = ListProperty([])
def __init__(self,
def __init__(self,nodeKlass=TreeNode,
url=None,
params={},
single_expand=False,
@ -322,13 +337,13 @@ class Tree(WidgetCSS, ScrollWidget):
normal_css="default",
row_height=2,
selected_css="selected",
checkbox=False,
multiplecheck=False,
checkField=None,
idField='id',
textField='text',
data=None,
**options):
self.url = url
self.nodeKlass = nodeKlass
self.params = params
self.data = data
self.single_expand=single_expand
@ -338,8 +353,7 @@ class Tree(WidgetCSS, ScrollWidget):
self.bgcolor = bgcolor
self.normal_css = normal_css
self.selected_css = selected_css
self.checkbox = checkbox
self.multiplecheck = multiplecheck
self.checkFiled = checkField
self.idField = idField
self.textField = textField
print('options=',options)
@ -351,6 +365,10 @@ class Tree(WidgetCSS, ScrollWidget):
self.buildTree()
self.bind(size=self.onSize,pos=self.onSize)
self.register_event_type('on_press')
self.register_event_type('on_checked')
def node_checkbox_changed(self, node):
self.dispatch('on_checked', node.data)
def on_press(self,*larg):
pass

View File

@ -194,8 +194,11 @@ def getWidgetById(w,id):
return w.ids.get(id)
def CSize(x,y=None,name=None):
ks = KivySizes()
return ks.CSize(x,y=y,name=name)
app = App.get_running_app()
r = app.font_size
if not y:
return r * x
return r * x, r * y
def screenSize():
ks = KivySizes()

View File

@ -1,24 +0,0 @@
"""
tree description json format:
{
"url":a http(s) url for get data,
"checkbox":boolean, show a checkbox before text
"data":if undefined url,use data to construct the tree
"params":parameters attached to the http(s) request via url
"headers":headers need to set for the http request via url
"height":widget 's height
"width":widget's width
}
data structure :
{
"id":identified field,
"widgettype":widget type,
...other data...
"__children__":[
]
}
"""
from .scrollwidget import ScrollWidget
from kivy.uix.treeview import TreeView