This commit is contained in:
yumoqing 2021-01-26 18:03:28 +08:00
parent bf6aece31d
commit a817b5e1e9
2 changed files with 149 additions and 16 deletions

View File

@ -6,11 +6,21 @@ from kivy.factory import Factory
from .baseWidget import VBox, HBox from .baseWidget import VBox, HBox
from .toggleitems import PressableBox from .toggleitems import PressableBox
from .utils import * from .utils import *
from .swipebehavior import SwipeBehavior
class PageContent(SwipeBehavior, VBox):
def __init__(self, **kw):
VBox.__init__(self, **kw)
SwipeBehavior.__init__(self)
class MenuContainer(VBox): class MenuContainer(VBox):
def __init__(self, **kw): def __init__(self, **kw):
VBox.__init__(self, **kw) VBox.__init__(self, **kw)
self.bind(on_touch_down=self.check_press) self.bind(on_touch_down=self.check_press)
self.register_event_type('on_dismiss')
def on_dismiss(self, *args):
print('on_dismiss fire')
def open(self): def open(self):
if self in Window.children: if self in Window.children:
@ -20,6 +30,7 @@ class MenuContainer(VBox):
def dismiss(self, *args): def dismiss(self, *args):
self.clear_widgets() self.clear_widgets()
Window.remove_widget(self) Window.remove_widget(self)
self.dispatch('on_dismiss')
def check_press(self, o, touch): def check_press(self, o, touch):
if touch.is_mouse_scrolling: if touch.is_mouse_scrolling:
@ -27,14 +38,103 @@ class MenuContainer(VBox):
if not self.collide_point(touch.x, touch.y): if not self.collide_point(touch.x, touch.y):
self.dismiss() self.dismiss()
return True return True
return False return True
class PagePanel(VBox): class PagePanel(VBox):
"""
# PagePanel widget
PagePanel widget provide a control bar and a subwidget container, control bar and content layout using vertical layout.
in control bar, there is a optional left menu icon, page title, right menu icon, and if there is more than one subwidgets add in the PagePanel, it will show the sub-widget last added. and a backward icon will show in the leftest control bar.
* backward icon uses to show the previous page in the PagePanel.
* left menu icon uses to show the system wide's menu
* right menu icon uses to show the current page's menu, the widget is identified by "menu_widget" in sub-widget description file
* title to show current page title, the widget is identified by "title_widget" in sub-widget description file.
## Description file format
PagePanel description file format
```
{
"bar_size": bar size in CSize unit
"bar_at": "top" or "bottom"
"left_menu": if defined, it must be a widget instance or a dict
recognized by Blocks
other VBox initial options
}
usage examples:
{
"widgettype":"PagePanel",
"options":{
"bar_size":2,
"enable_on_close":true,
"left_menu":{
"widgettype":"Text",
"options":{
"text":"Text"
}
},
"radius":[10,10,10,10]
},
"subwidgets":[
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('page.ui')}}"
}
}
]
}
```
sub-widget's description file format
```
and page.ui is:
{
"widgettype":"Button",
"options":{
"text":"button {{cnt or 0}}"
},
"title_widget":{
"widgettype":"Text",
"options":{
"text":"test title"
}
},
"menu_widget":{
"widgettype":"Text",
"options":{
"text":"TTTT"
}
},
"binds":[
{
"wid":"self",
"target":"root",
"actiontype":"urlwidget",
"event":"on_press",
"options":{
"params":{
"cnt":{{int(cnt or 0) + 1}}
},
"url":"{{entire_url('page.ui')}}"
}
}
]
}
```
##
"""
def __init__(self, bar_size=2, bar_at='top', enable_on_close=False, def __init__(self, bar_size=2, bar_at='top', enable_on_close=False,
left_menu=False, **kw): left_menu=None, **kw):
print('PagePanel().__init__():', bar_size, bar_at, left_menu) print('PagePanel().__init__():', bar_size, bar_at, left_menu)
self.bar_size = bar_size self.bar_size = bar_size
self.bar_at = bar_at self.bar_at = bar_at
self.swipe_buffer = []
self.swipe_right = False
self.enable_on_close = enable_on_close self.enable_on_close = enable_on_close
if self.enable_on_close: if self.enable_on_close:
@ -46,7 +146,6 @@ class PagePanel(VBox):
elif isinstance(left_menu, Widget): elif isinstance(left_menu, Widget):
self.left_menu = left_menu self.left_menu = left_menu
else: else:
print('left_menu=', left_menu, type(left_menu))
self.left_menu = Factory.Blocks().widgetBuild(left_menu) self.left_menu = Factory.Blocks().widgetBuild(left_menu)
self.sub_widgets = [] self.sub_widgets = []
VBox.__init__(self, **kw) VBox.__init__(self, **kw)
@ -54,7 +153,9 @@ class PagePanel(VBox):
spacing=CSize(bar_size/6), spacing=CSize(bar_size/6),
height=CSize(bar_size)) height=CSize(bar_size))
bcsize = bar_size * 0.85 bcsize = bar_size * 0.85
self.content = VBox() self.content = PageContent()
self.content.bind(on_swipe_left=self.on_swipe_next_page)
self.content.bind(on_swipe_right=self.pop)
self.bar_back = VBox(size_hint=(None,None),size=CSize(bcsize,bcsize)) self.bar_back = VBox(size_hint=(None,None),size=CSize(bcsize,bcsize))
self.bar_back_w = Factory.Blocks().widgetBuild({ self.bar_back_w = Factory.Blocks().widgetBuild({
"widgettype":"PressableBox", "widgettype":"PressableBox",
@ -118,7 +219,8 @@ class PagePanel(VBox):
else: else:
super().add_widget(self.content) super().add_widget(self.content)
super().add_widget(self.bar) super().add_widget(self.bar)
self.menu_container = MenuContainer() self.left_menu_showed = False
self.right_menu_showed = False
def on_close_handle(self, o, *args): def on_close_handle(self, o, *args):
print('app.on_close fired, ...') print('app.on_close fired, ...')
@ -130,13 +232,11 @@ class PagePanel(VBox):
return True return True
def pop(self, o, *args): def pop(self, o, *args):
self.bar_back.clear_widgets()
self.content.clear_widgets()
self.bar_title.clear_widgets()
self.bar_right_menu.clear_widgets()
if len(self.sub_widgets) < 1: if len(self.sub_widgets) < 1:
return return
self.clear_widgets()
diss_w = self.sub_widgets[-1] diss_w = self.sub_widgets[-1]
self.swipe_buffer.insert(0,diss_w)
self.sub_widgets = self.sub_widgets[:-1] self.sub_widgets = self.sub_widgets[:-1]
self.show_currentpage() self.show_currentpage()
@ -150,6 +250,14 @@ class PagePanel(VBox):
if hasattr(w, 'menu_widget'): if hasattr(w, 'menu_widget'):
self.bar_right_menu.add_widget(self.bar_right_menu_w) self.bar_right_menu.add_widget(self.bar_right_menu_w)
def on_swipe_next_page(self, o, *args):
if len(self.swipe_buffer) < 1:
return
self.swipe_right = True
w = self.swipe_buffer[0]
del self.swipe_buffer[0]
self.add_widget(w)
def clear_widgets(self): def clear_widgets(self):
self.bar_back.clear_widgets() self.bar_back.clear_widgets()
self.content.clear_widgets() self.content.clear_widgets()
@ -157,35 +265,58 @@ class PagePanel(VBox):
self.bar_right_menu.clear_widgets() self.bar_right_menu.clear_widgets()
def add_widget(self, w, *args): def add_widget(self, w, *args):
if not self.swipe_right:
self.swipe_buffer = []
self.swipe_right = False
self.clear_widgets()
if len(self.sub_widgets) > 0: if len(self.sub_widgets) > 0:
pass pass
self.sub_widgets.append(w) self.sub_widgets.append(w)
self.show_currentpage() self.show_currentpage()
def show_left_menu(self, o): def show_left_menu(self, o):
def x(*args):
self.left_menu_showed = False
print('dismiss fired, left_menu_showed=',self.left_menu_showed)
print('left_menu fired') print('left_menu fired')
if len(self.sub_widgets) < 1: if len(self.sub_widgets) < 1:
return return
if self.left_menu_showed:
return
mc = MenuContainer() mc = MenuContainer()
mc.add_widget(self.left_menu) mc.add_widget(self.left_menu)
mc.size_hint_x = 0.4 mc.size_hint = (None, None)
mc.size_hint_y = 1 mc.width = self.width * 0.4
mc.height = self.content.height
mc.x = self.x mc.x = self.x
mc.y = self.y mc.y = self.y if self.bar_at=='top' else self.content.y
self.left_menu_showed = True
mc.bind(on_dismiss=x)
mc.open() mc.open()
def show_right_menu(self, o): def show_right_menu(self, o):
def x(*args):
self.right_menu_showed = False
print('dismiss fired, right_menu_showed=',self.right_menu_showed)
print('right fired') print('right fired')
if len(self.sub_widgets) < 1: if len(self.sub_widgets) < 1:
return return
if self.right_menu_showed:
return
w = self.sub_widgets[-1] w = self.sub_widgets[-1]
if not hasattr(w, 'menu_widget'): if not hasattr(w, 'menu_widget'):
return True return True
mc = MenuContainer() mc = MenuContainer()
mc.add_widget(w.menu_widget) mc.add_widget(w.menu_widget)
mc.size_hint_x = 0.4 mc.size_hint = (None,None)
mc.size_hint_y = 1 mc.height = self.content.height
mc.width = self.width * 0.4
mc.x = self.x + self.width * 0.6 mc.x = self.x + self.width * 0.6
mc.y = self.y mc.y = self.y if self.bar_at == 'top' else self.content.y
self.right_menu_showed = True
mc.bind(on_dismiss=x)
mc.open() mc.open()

View File

@ -68,11 +68,13 @@ class SwipeBehavior(object):
self.sb_end_point = touch.pos self.sb_end_point = touch.pos
def on_touchup(self,o,touch): def on_touchup(self,o,touch):
ret = False
if self.collide_point(*touch.pos) and self.swipeenable: if self.collide_point(*touch.pos) and self.swipeenable:
# Logger.info('SwipeBehavior:touch_up fired') # Logger.info('SwipeBehavior:touch_up fired')
self.sb_end_point = touch.pos self.sb_end_point = touch.pos
self.sb_end_time = time.time() self.sb_end_time = time.time()
self.check_context_menu() self.check_context_menu()
ret = True
self.check_swipe() self.check_swipe()
self.sb_start_point = None self.sb_start_point = None
self.sb_end_point = None self.sb_end_point = None