bugfix
This commit is contained in:
parent
01442309d9
commit
9e2b5db1a6
@ -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]
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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.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.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_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 remove_widget(self, w):
|
||||
return self.content.remove_widget(w)
|
||||
|
||||
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 parse_viewer(self, rec):
|
||||
return json.loads(self.engine.renders(self.viewer_tmpl, rec))
|
||||
|
||||
def loadData(self, *args, **kw):
|
||||
kw['page'] = 1
|
||||
self.dataloader.do_search(None,kw)
|
||||
|
||||
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()
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import os
|
||||
from kivy.uix.image import AsyncImage
|
||||
from kivy.factory import Factory
|
||||
from kivy.properties import StringProperty
|
||||
|
@ -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
|
||||
|
@ -58,9 +58,12 @@ class I18n:
|
||||
if config.i18n_url:
|
||||
url = '%s%s' % (config.uihome, config.i18n_url)
|
||||
hc = HttpClient()
|
||||
d = hc.get(url)
|
||||
if isinstance(d, list):
|
||||
return d
|
||||
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()
|
||||
d = hc.get(url)
|
||||
print('i18n() %s get data=' % url, d, type(d))
|
||||
self.kvlang[lang] = d
|
||||
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:
|
||||
|
BIN
kivyblocks/imgs/.DS_Store
vendored
BIN
kivyblocks/imgs/.DS_Store
vendored
Binary file not shown.
BIN
kivyblocks/imgs/add.png
Normal file
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
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
BIN
kivyblocks/imgs/deletex.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
kivyblocks/imgs/lensid.png
Executable file
BIN
kivyblocks/imgs/lensid.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
@ -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),
|
||||
|
@ -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.doBufferMaintain()
|
||||
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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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', \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
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)
|
||||
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)
|
||||
else:
|
||||
rfname = v.get('rfname')
|
||||
if rfname:
|
||||
rf = RegisterFunction()
|
||||
f = rf.get(rfname)
|
||||
if f:
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user