diff --git a/kivyblocks/baseWidget.py b/kivyblocks/baseWidget.py index f1cd716..4cada0e 100755 --- a/kivyblocks/baseWidget.py +++ b/kivyblocks/baseWidget.py @@ -4,6 +4,7 @@ from traceback import print_exc from kivy.properties import ObjectProperty, StringProperty, \ NumericProperty, BooleanProperty, OptionProperty +from kivy.properties import DictProperty from kivy.app import App from kivy.utils import platform from kivy.uix.button import Button, ButtonBehavior @@ -86,6 +87,34 @@ class WrapText(Label): self.bind(width=lambda *x: self.setter('text_size')(self, (self.width, None)), texture_size=lambda *x: self.setter('height')(self, self.texture_size[1])) +class StackBox(WidgetCSS, WidgetReady, StackLayout): + def __init__(self, **kw): + super().__init__(**kw) + +class AnchorBox(WidgetCSS, WidgetReady, AnchorLayout): + def __init__(self, **kw): + super().__init__(**kw) + +def FloatBox(WidgetCSS, WidgetReady, FloatLayout): + def __init__(self, **kw): + super().__init__(**kw) + +def RelativeBox(WidgetCSS, WidgetReady, RelativeLayout): + def __init__(self, **kw): + super().__init__(**kw) + +def GridBox(WidgetCSS, WidgetReady, GridLayout): + def __init__(self, **kw): + super().__init__(**kw) + +def PageBox(WidgetCSS, WidgetReady, PageLayout): + def __init__(self, **kw): + super().__init__(**kw) + +def ScatterBox(WidgetCSS, WidgetReady, ScatterLayout): + def __init__(self, **kw): + super().__init__(**kw) + class Box(WidgetCSS, WidgetReady, BoxLayout): def __init__(self, **kw): try: @@ -471,3 +500,69 @@ def device_type(): else: return "mobile" +class ExAccordion(WidgetCSS, WidgetReady, Accordion): + """ + { + "widgettype":"Accordion", + "options":{ + "csscls", + "items":[{ + "title":"titl1", + "active":false, + "widget":{ + } + } + ] + } + } + """ + items = ListProperty(None) + def __init__(self, **kw): + print('ExAccordion() init...') + super().__init__(**kw) + self.width = self.height = 800 + # Clock.schedule_once(self._build_children, 0.1) + self._build_children() + + def _build_children(self, *args): + for i in self.items: + bk = Factory.Blocks() + w = bk.widgetBuild(i['widget']) + if w is None: + continue + tw = AccordionItem() + if isinstance(i['title'], str): + tw.title = i['title'] + else: + tw.title = bk.widgetBuild(i['title']) + tw.add_widget(w) + if i.get('active'): + self.collapse = False + else: + self.collapse = True + self.add_widget(tw) + +class Slider(Carousel): + """ + { + "widgettype":"Slider", + "options":{ + "direction":"right", + "loop":true, + "items":[ + { + "widgettype":.... + } + ] + } + } + """ + items = ListProperty(None) + def __init__(self, **kw): + print('Carousel pro=', dir(Carousel)) + super().__init__(**kw) + bk = Factory.Blocks() + for desc in self.items: + w = bk.widgetBuild(desc) + self.add_widget(w) + diff --git a/kivyblocks/blocks.py b/kivyblocks/blocks.py index e050d72..bce72f2 100755 --- a/kivyblocks/blocks.py +++ b/kivyblocks/blocks.py @@ -286,7 +286,7 @@ class Blocks(EventDispatcher): if isinstance(v,dict) and v.get('widgettype'): b = Blocks() v = self.valueExpr(v, localnamespace={'self':widget}) - w = b.w_build(v) + w = b.widgetBuild(v) if hasattr(widget,k): aw = getattr(widget,k) if isinstance(aw,Layout): diff --git a/kivyblocks/ffpyplayer_video.py b/kivyblocks/ffpyplayer_video.py index 8667a7d..a42b38e 100644 --- a/kivyblocks/ffpyplayer_video.py +++ b/kivyblocks/ffpyplayer_video.py @@ -12,9 +12,10 @@ from kivy.clock import Clock from kivy.properties import StringProperty, BooleanProperty, \ OptionProperty, NumericProperty from kivy.graphics.texture import Texture +from kivyblocks.ready import WidgetReady -class FFVideo(Image): +class FFVideo(WidgetReady, Image): v_src = StringProperty(None) status = OptionProperty('stop', \ options=['stop', 'play', 'pause']) @@ -39,6 +40,7 @@ class FFVideo(Image): self.lib_opts = {} self.headers_pattern = {} super(FFVideo, self).__init__(**kwargs) + self.set_black() self.register_event_type('on_frame') self.register_event_type('on_open_failed') self.register_event_type('on_leave_focus') @@ -48,7 +50,7 @@ class FFVideo(Image): def on_open_failed(self, *args): pass - def on_load_syccess(self, *args): + def on_load_success(self, *args): pass def on_enter_focus(self, *args): @@ -194,6 +196,9 @@ class FFVideo(Image): lib_opts=lib_opts) self._play_start() + def file_opened(self, files): + self.v_src = files[0] + def play(self): if self._player is None: return @@ -254,7 +259,7 @@ class FFVideo(Image): return image_texture = Texture.create( size=self.size, colorfmt='rgb') - buf = b'\x00' * self.width * self.height * 3 + buf = b'\x00' * int(self.width * self.height * 3) image_texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte') self.texture = image_texture self.is_black = True diff --git a/kivyblocks/filebrowser.py b/kivyblocks/filebrowser.py index 0f30817..7e17c86 100644 --- a/kivyblocks/filebrowser.py +++ b/kivyblocks/filebrowser.py @@ -13,12 +13,9 @@ from kivyblocks.baseWidget import PressableImage, StrInput import os -def i18n(s): - return s - class FileLoaderBrowser(Popup): def __init__(self,rootpath='/', title='load file', choose_dir=False, **kwargs): - # i18n = I18n() + i18n = I18n() self.content = BoxLayout(orientation='vertical') Popup.__init__(self, content = self.content, title=i18n(title), diff --git a/kivyblocks/pagepanel.py b/kivyblocks/pagepanel.py index e9b3e94..f693f1f 100644 --- a/kivyblocks/pagepanel.py +++ b/kivyblocks/pagepanel.py @@ -352,7 +352,7 @@ sub-widget's description file format return True mc = MenuContainer() mc.add_widget(w.menu_widget) - self.w.menu_widget.bind(on_press=mc.dismiss) + w.menu_widget.bind(on_press=mc.dismiss) mc.size_hint = (None,None) mc.height = self.content.height mc.width = self.width * 0.4 diff --git a/kivyblocks/ready.py b/kivyblocks/ready.py index ad0dd18..05c0361 100644 --- a/kivyblocks/ready.py +++ b/kivyblocks/ready.py @@ -8,6 +8,7 @@ from kivy.clock import Clock from kivy.utils import platform from kivy.app import App from kivy.properties import BooleanProperty +from plyer import filechooser desktopOSs=[ "win", @@ -124,3 +125,24 @@ class WidgetReady(object): self.size = state['size'] if state['parent'] is not window: state['parent'].add_widget(self) + + def file_open_for_read(self, *args, **kw): + method_name = kw.get('on_selection') + if method_name is None: + return + f = getattr(self, method_name) + if f is None: + return + kw['on_selection'] = f + filechooser.open_file(**kw) + + def file_open_for_write(self, *args, **kw): + method_name = kw.get('on_selection') + if method_name is None: + return + f = getattr(self, method_name) + if f is None: + return + kw['on_selection'] = f + filechooser.save_file(**kw) + diff --git a/kivyblocks/register.py b/kivyblocks/register.py index a58e2ee..fb135fc 100644 --- a/kivyblocks/register.py +++ b/kivyblocks/register.py @@ -46,6 +46,13 @@ from .ffpyplayer_video import FFVideo r = Factory.register # if kivy.platform in ['win','linux', 'macosx']: # r('ScreenWithMic', ScreenWithMic) +r('AnchorBox', AnchorBox) +r('FloatBox', FloatBox) +r('RelativeBox', RelativeBox) +r('GridBox', GridBox) +r('PageBox', PageBox) +r('ScatterBox', ScatterBox) +r('StackBox', StackBox) r('DateInput', DateInput) r('HTTPSeriesData', HTTPSeriesData) r('HTTPDataHandler', HTTPDataHandler) @@ -109,6 +116,8 @@ r('HBox',HBox) r('VBox',VBox) r('SwipeBox',SwipeBox) r('ToggleItems',ToggleItems) +r('ExAccordion', ExAccordion) +r('Slider', Slider) if platform == 'android': r('PhoneButton',PhoneButton) r('AWebView',AWebView) diff --git a/kivyblocks/script.py b/kivyblocks/script.py index 3cb43ba..e02d062 100644 --- a/kivyblocks/script.py +++ b/kivyblocks/script.py @@ -19,12 +19,12 @@ def set_script_env(n,v): class Script: def __init__(self, root): - print('root=', root) self.root = root self.env = {} self.handlers = {} self.register('.tmpl', TemplateHandler) self.register('.dspy', DspyHandler) + self.register('.ui', TemplateHandler) def url2filepath(self, url): if url.startswith('file://'): @@ -41,7 +41,7 @@ class Script: env['root_path'] = self.root env['url'] = url env['filepath'] = filepath - h = handler(env, **kw) + h = handler(env) d = h.render() try: return json.loads(d) @@ -60,9 +60,15 @@ class BaseHandler: url.startswith('http://') or \ url.startswith('hppts://'): return url + tokens = url.split('/') + if tokens[0] == '': + root = self.env['root_path'] + tokens[0] = root + return '/'.join(tokens) + p1 = self.env['url'].split('/')[:-1] - p2 = url.split('/') - return '/'.join(p1+p2) + return '/'.join(p1+tokens) + def __init__(self, env): self.env = env self.env['entire_url'] = self.entire_url @@ -80,6 +86,7 @@ class TemplateHandler(BaseHandler): cpath = join(cpath, p) paths.append(cpath) + paths.reverse() self.engine = MyTemplateEngine(paths) def render(self): diff --git a/test/script/conf/config.json b/test/script/conf/config.json index 15756fb..3c4603f 100644 --- a/test/script/conf/config.json +++ b/test/script/conf/config.json @@ -12,7 +12,7 @@ "root":{ "widgettype":"urlwidget", "options":{ - "url":"file://index.tmpl" + "url":"file://index.ui" } } } diff --git a/test/script/main.py b/test/script/main.py index f7786c3..43b32ad 100644 --- a/test/script/main.py +++ b/test/script/main.py @@ -1,10 +1,12 @@ +from kivyblocks.setconfig import config_set from kivyblocks.blocksapp import BlocksApp from kivyblocks.blocks import registerWidget, Blocks import kivyblocks.register - +from kivyblocks.script import set_script_env class ScriptApp(BlocksApp): pass if __name__ == '__main__': + set_script_env('userid', 'testuser') ScriptApp().run() diff --git a/test/script/scripts/index.tmpl b/test/script/scripts/index.tmpl deleted file mode 100644 index a0e10d3..0000000 --- a/test/script/scripts/index.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -{ - "widgettype":"VBox", - "options":{}, - "subwidgets":[ - { - "widgettype":"Button", - "options":{ - "text":"Hello" - } - } - ] -}