This commit is contained in:
yumoqing 2022-01-29 16:32:51 +08:00
parent b70e2def12
commit b455374a00
13 changed files with 2112 additions and 2167 deletions

View File

@ -3,7 +3,7 @@ import math
from traceback import print_exc from traceback import print_exc
from kivy.properties import ObjectProperty, StringProperty, \ from kivy.properties import ObjectProperty, StringProperty, \
NumericProperty, BooleanProperty NumericProperty, BooleanProperty, OptionProperty
from kivy.app import App from kivy.app import App
from kivy.utils import platform from kivy.utils import platform
from kivy.uix.button import Button, ButtonBehavior from kivy.uix.button import Button, ButtonBehavior
@ -221,11 +221,16 @@ class Title6(Text):
kw.update({'texttype':'title6','bold':True}) kw.update({'texttype':'title6','bold':True})
Text.__init__(self, **kw) Text.__init__(self, **kw)
class Modal(WidgetCSS, WidgetReady, ModalView): class Modal(VBox):
content = DictProperty(None) content = DictProperty(None)
auto_open = BooleanProperty(True) auto_open = BooleanProperty(True)
auto_dismiss = BooleanProperty(True)
position = OptionProperty('tc',options=['tl', 'tc', 'tr',
'cl', 'cc', 'cr',
'bl', 'bc', 'br'])
def __init__(self, **kw): def __init__(self, **kw):
super(ModalView, self).__init__(**kw) SUPER(Modal, self, kw)
if self.content: if self.content:
blocks = Factory.Blocks() blocks = Factory.Blocks()
self.content_w = blocks.widgetBuild(self.content) self.content_w = blocks.widgetBuild(self.content)
@ -233,10 +238,69 @@ class Modal(WidgetCSS, WidgetReady, ModalView):
self.add_widget(self.content_w) self.add_widget(self.content_w)
else: else:
print(content,':cannot build widget') print(content,':cannot build widget')
self.register_event_type('on_open')
self.register_event_type('on_pre_open')
self.register_event_type('on_pre_dismiss')
self.register_event_type('on_dismiss')
def on_touch_down(self, touch):
if not self.collide_point(touch.x, touch.y):
if self.auto_dismiss:
self.dispatch('on_pre_dismiss')
self.dismiss()
return True
return super().on_touch_down(touch)
def set_modal_position(self, w):
xn = self.position[1]
yn = self.position[0]
x, y = 0, 0
if xn == 'c':
x = (w.width - self.width) / 2
elif xn == 'r':
x = w.width - self.width
if x < 0:
x = 0
if yn == 'c':
y = (w.height - self.height) / 2
elif yn == 'b':
y = w.height - self.height
if y < 0:
y = 0
if w == Window:
self.pos = x, y
else:
self.pos = w.pos[0] + x, w.pos[1] + y
def open(self, widget=None):
self.dispatch('on_pre_open')
if widget is None:
widget = Window
self.set_modal_position(widget)
Window.add_widget(self)
self.dispatch('on_open')
def dismiss(self, *args):
self.dispatch('on_pre_dismiss')
self.dispatch('on_dismiss')
Window.remove_widget(self)
def on_open(self, *args):
pass
def on_dismiss(self, *args):
pass
def on_pre_open(self, *args):
pass
def on_pre_dismiss(self, *args):
pass
def add_widget(self, w, *args, **kw): def add_widget(self, w, *args, **kw):
super().add_widget(w, *args, **kw) super().add_widget(w, *args, **kw)
# super().add_widget(Label(text='1111'))
if self.auto_open: if self.auto_open:
self.open() self.open()
@ -244,7 +308,7 @@ class TimedModal(Modal):
show_time = NumericProperty(0) show_time = NumericProperty(0)
def __init__(self, **kw): def __init__(self, **kw):
self.time_task = None self.time_task = None
Modal.__init__(self, **kw) SUPER(TimedModal, self, kw)
def open(self, *args, **kw): def open(self, *args, **kw):
if self.time_task is not None: if self.time_task is not None:
@ -259,7 +323,7 @@ class TimedModal(Modal):
if self.time_task: if self.time_task:
self.time_task.cancel() self.time_task.cancel()
self.time_task = None self.time_task = None
super().dismiss(*args, **kw) super().dismiss()
class PressableImage(ButtonBehavior,AsyncImage): class PressableImage(ButtonBehavior,AsyncImage):
def on_press(self): def on_press(self):

File diff suppressed because it is too large Load Diff

View File

@ -332,7 +332,6 @@ class Blocks(EventDispatcher):
Logger.info('Block: get a null function,%s',str(desc)) Logger.info('Block: get a null function,%s',str(desc))
return return
w.bind(**{event:f}) w.bind(**{event:f})
# Logger.info('Block: %s bind built', str(desc))
def multipleAction(self, widget:Widget, desc, *args): def multipleAction(self, widget:Widget, desc, *args):
desc1 = {k:v for k, v in desc.items() if k != 'actions'} desc1 = {k:v for k, v in desc.items() if k != 'actions'}
@ -356,11 +355,6 @@ class Blocks(EventDispatcher):
w.open() w.open()
def uniaction(self, widget:Widget, desc, *args): def uniaction(self, widget:Widget, desc, *args):
Logger.info('Block: uniaction() called, desc=%s, args=%s', \
str(desc),
args
)
acttype = desc.get('actiontype') acttype = desc.get('actiontype')
if acttype=='blocks': if acttype=='blocks':
return self.blocksAction(widget,desc, *args) return self.blocksAction(widget,desc, *args)
@ -415,7 +409,7 @@ class Blocks(EventDispatcher):
if isinstance(w, ModalView): if isinstance(w, ModalView):
return return
if target: if target and not w.parent:
if add_mode == 'replace': if add_mode == 'replace':
target.clear_widgets() target.clear_widgets()
target.add_widget(w) target.add_widget(w)
@ -431,10 +425,6 @@ class Blocks(EventDispatcher):
b.widgetBuild(opts) b.widgetBuild(opts)
def urlwidgetAction(self, widget:Widget, desc, *args): def urlwidgetAction(self, widget:Widget, desc, *args):
Logger.info('Block: urlwidgetAction() called, desc=%s, args=%s', \
str(desc),
args
)
target = self.get_target(widget, desc) target = self.get_target(widget, desc)
add_mode = desc.get('mode','replace') add_mode = desc.get('mode','replace')
opts = desc.get('options').copy() opts = desc.get('options').copy()
@ -454,7 +444,7 @@ class Blocks(EventDispatcher):
if isinstance(w, ModalView): if isinstance(w, ModalView):
return return
if target: if target and not w.parent:
if add_mode == 'replace': if add_mode == 'replace':
target.clear_widgets() target.clear_widgets()
target.add_widget(w) target.add_widget(w)

View File

@ -86,9 +86,7 @@ class InputBox(BoxLayout):
self.init() self.init()
def focus_act(self, *args): def focus_act(self, *args):
show_widget_info(self,'test') pass
show_widget_info(self.labeltext,'test')
show_widget_info(self.input_widget,'test')
def on_size(self, *args): def on_size(self, *args):
@ -103,12 +101,10 @@ class InputBox(BoxLayout):
self.input_widget.size_hint_x = None self.input_widget.size_hint_x = None
self.input_widget.width = self.width - self.labeltext.width - CSize(1) self.input_widget.width = self.width - self.labeltext.width - CSize(1)
show_widget_info(self,'test')
show_widget_info(self.labeltext,'test')
show_widget_info(self.input_widget,'test')
def on_datainput(self,o,v=None): def on_datainput(self,o,v=None):
print('on_datainput fired ...',o,v) pass
#print('on_datainput fired ...',o,v)
def init(self): def init(self):
if self.initflag: if self.initflag:
@ -139,10 +135,7 @@ class InputBox(BoxLayout):
options['hint_text'] = i18n(self.options.get('hint_text')) options['hint_text'] = i18n(self.options.get('hint_text'))
options['size_hint_y'] = None options['size_hint_y'] = None
options['height'] = self.height options['height'] = self.height
print('options=', options)
self.input_widget = UiFactory.build_input_widget(options) self.input_widget = UiFactory.build_input_widget(options)
print('inputw.height=',self.input_widget.height)
try: try:
self.input_widget.bind(focus=self.focus_act) self.input_widget.bind(focus=self.focus_act)
except: except:
@ -246,6 +239,7 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
notoolbar=BooleanProperty(False) notoolbar=BooleanProperty(False)
def __init__(self, **options): def __init__(self, **options):
self.cols = 1 self.cols = 1
self.toolbar_w = None
if self.toolbar_at in ['top','bottom']: if self.toolbar_at in ['top','bottom']:
options['orientation'] = 'vertical' options['orientation'] = 'vertical'
else: else:
@ -259,23 +253,14 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
if isHandHold() and Window.width < Window.height: if isHandHold() and Window.width < Window.height:
self._cols = 1 self._cols = 1
self.input_width = 1 self.input_width = 1
print('1-inputwidth=', self.inputwidth,
'input_width=',self.input_width,
'CSize(1)=', CSize(1))
return return
if self.cols is None and self.inputwidth is None: if self.cols is None and self.inputwidth is None:
self.input_width = 1 self.input_width = 1
self._cols = 1 self._cols = 1
print('2-inputwidth=', self.inputwidth,
'input_width=',self.input_width,
'CSize(1)=', CSize(1))
return return
if self.inputwidth > 1: if self.inputwidth > 1:
self.input_width = CSize(self.inputwidth) self.input_width = CSize(self.inputwidth)
self._cols = -1 # auto calculate self._cols = -1 # auto calculate
print('3-inputwidth=', self.inputwidth,
'input_width=',self.input_width,
'CSize(1)=', CSize(1), CSize(self.inputwidth))
return return
if self.cols is not None: if self.cols is not None:
self._cols = self.cols self._cols = self.cols
@ -283,15 +268,9 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
self.input_width = -1 self.input_width = -1
else: else:
self.input_width = CSize(self.inputwidth) self.input_width = CSize(self.inputwidth)
print('4-inputwidth=', self.inputwidth,
'input_width=',self.input_width,
'CSize(1)=', CSize(1))
return return
self.input_width = -1 self.input_width = -1
self._cols = 1 self._cols = 1
print('5-inputwidth=', self.inputwidth,
'input_width=',self.input_width,
'CSize(1)=', CSize(1), CSize(self.inputwidth))
def set_grid_attrs(self): def set_grid_attrs(self):
if self._cols == 1 and self.input_width <= 1: if self._cols == 1 and self.input_width <= 1:
@ -344,16 +323,16 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
desc['toolbar_orient'] = 'V' desc['toolbar_orient'] = 'V'
desc['tool_orient'] = 'veritcal' desc['tool_orient'] = 'veritcal'
self.toolbar_w = Factory.Toolbar(**desc) self.toolbar_w = Factory.Toolbar(**desc)
self.fsc = VResponsiveLayout( self.fsc = VResponsiveLayout(
box_width = self.input_width, box_width = self.input_width,
size_hint=(1,1) size_hint=(1,1)
) )
if self.toolbar_at in ['top', 'left'] and not self.notoolbar: if self.toolbar_at in ['top', 'left'] and self.toolbar_w:
self.add_widget(self.toolbar_w) self.add_widget(self.toolbar_w)
self.add_widget(self.fsc) self.add_widget(self.fsc)
if self.toolbar_at in ['bottom', 'right'] and not self.notoolbar: if self.toolbar_at in ['bottom', 'right'] and self.toolbar_w:
self.add_widget(self.toolbar_w) self.add_widget(self.toolbar_w)
self.fieldWidgets=[] self.fieldWidgets=[]
@ -407,7 +386,6 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
return True return True
def on_submit(self,o, v=None): def on_submit(self,o, v=None):
print('Form():on_submit fired ...',v)
return False return False
def on_submit_button(self,o,v=None): def on_submit_button(self,o,v=None):
@ -466,5 +444,4 @@ class StrSearchForm(BoxLayout):
self.dispatch('on_submit',d) self.dispatch('on_submit',d)
def on_submit(self,v=None): def on_submit(self,v=None):
print('StrSearchForm():on_submit fired ..........') pass

View File

@ -1,6 +1,8 @@
from kivy.factory import Factory from kivy.factory import Factory
from kivy.properties import StringProperty, NumericProperty from kivy.core.window import Window
from kivy.properties import StringProperty, NumericProperty, \
OptionProperty
from kivy.uix.image import AsyncImage from kivy.uix.image import AsyncImage
from .utils import * from .utils import *
from .baseWidget import Modal, Text, HBox,VBox, TimedModal from .baseWidget import Modal, Text, HBox,VBox, TimedModal
@ -45,11 +47,18 @@ class Message(TimedModal):
default_title = 'Message' default_title = 'Message'
default_message = 'Message' default_message = 'Message'
title_icon = StringProperty(blockImage('info.png')) title_icon = StringProperty(blockImage('info.png'))
message = StringPrperty(None) message = StringProperty(None)
body_css = StringProperty('message_default_body_css') body_css = StringProperty('message_default_body_css')
title_css = StringProperty('message_default_title_css') title_css = StringProperty('message_default_title_css')
show_position = OptionProperty('br', options=['tl','tc','tr',
'cl','cc','cr',
'bl','bc','br'])
width_c = NumericProperty(15)
height_c = NumericProperty(6)
def __init__(self, **kw): def __init__(self, **kw):
SUPER(Message, self, kw) SUPER(Message, self, kw)
self.size_hint = None, None
self.set_position()
b = VBox(csscls=self.title_css) b = VBox(csscls=self.title_css)
b1 = HBox(size_hint_y=None, height=CSize(2)) b1 = HBox(size_hint_y=None, height=CSize(2))
b1.add_widget(AsyncImage(source=self.title_icon, b1.add_widget(AsyncImage(source=self.title_icon,
@ -73,7 +82,35 @@ class Message(TimedModal):
font_size=CSize(1))) font_size=CSize(1)))
b.add_widget(b2) b.add_widget(b2)
self.add_widget(b) self.add_widget(b)
def on_size(self, *args):
self.set_position()
try:
super().on_size(*args)
except:
pass
def set_position(self):
# self.pos_hint = None, None
self.size_hint = None, None
self.width = CSize(self.width_c)
self.height = CSize(self.height_c)
xn = self.show_position[1]
yn = self.show_position[0]
if xn == 'l':
self.anchor_x = 'left'
elif xn == 'c':
self.anchor_x = 'center'
else:
self.anchor_x = 'right'
if yn == 't':
self.anchor_y = 'top'
elif yn == 'c':
self.anchor_y = 'center'
else:
self.anchor_y = 'bottom'
class Error(Message): class Error(Message):
default_title = 'Error' default_title = 'Error'
default_message = 'Error message' default_message = 'Error message'

View File

@ -310,9 +310,6 @@ sub-widget's description file format
self.sub_widgets = [] self.sub_widgets = []
self.sub_widgets.append(w) self.sub_widgets.append(w)
self.show_currentpage() self.show_currentpage()
show_widget_info(self)
for w in self.get_subwidgets():
show_widget_info(w)
def show_left_menu(self, o): def show_left_menu(self, o):
def x(*args): def x(*args):

View File

@ -52,9 +52,4 @@ class VResponsiveLayout(ScrollView):
if cols < 1: if cols < 1:
cols = 1 cols = 1
self._inner.cols = cols self._inner.cols = cols
#print(self.width, self._inner.width, self.box_width, cols, cols * self.box_width)
#for c in self.children[:2]:
# show_widget_info(c)
# for c1 in c.children:
# show_widget_info(c1)

View File

@ -210,7 +210,6 @@ class ToolPage(Box):
options=['top', 'bottom', 'left', 'right']) options=['top', 'bottom', 'left', 'right'])
toolbar = DictProperty({}) toolbar = DictProperty({})
def __init__(self, **kw): def __init__(self, **kw):
print('ToolPage:kw=',kw)
SUPER(ToolPage, self, kw) SUPER(ToolPage, self, kw)
if self.tool_at in [ 'top','bottom']: if self.tool_at in [ 'top','bottom']:
self.orientation = 'vertical' self.orientation = 'vertical'
@ -306,7 +305,6 @@ class ToolPage(Box):
if w: if w:
self.content_widgets[name] = w self.content_widgets[name] = w
self.content_w.add_widget(w) self.content_w.add_widget(w)
print('w=', w)
return return
rfname = v.get('rfname') rfname = v.get('rfname')
if rfname: if rfname:

View File

@ -89,6 +89,7 @@ class TwoSides(WidgetReady, BoxLayout):
w = Factory.Blocks().widgetBuild({ w = Factory.Blocks().widgetBuild({
"widgettype":"Modal", "widgettype":"Modal",
"options":{ "options":{
"auto_open":False,
"auto_dismiss":True, "auto_dismiss":True,
"size_hint":[None,None], "size_hint":[None,None],
"size":(x,y), "size":(x,y),

View File

@ -7,4 +7,5 @@ from .amount import *
from .password import * from .password import *
from .text import * from .text import *
from .code import * from .code import *
from .viewer import *

View File

@ -23,12 +23,18 @@ class UiFactory:
def build_view_widget(self, desc, rec=None): def build_view_widget(self, desc, rec=None):
ut = desc.get('uitype', 'str') ut = desc.get('uitype', 'str')
f = view_widget_builders.get(ut) f = view_widget_builders.get(ut)
if f is None:
print(desc, 'view builder not defined')
return None
return f(desc, rec=rec) return f(desc, rec=rec)
@classmethod @classmethod
def build_input_widget(self, desc, rec=None): def build_input_widget(self, desc, rec=None):
ut = desc.get('uitype', 'str') ut = desc.get('uitype', 'str')
f = input_widget_builders.get(ut) f = input_widget_builders.get(ut)
if f is None:
print(desc, 'input builder not defined')
return None
return f(desc, rec=rec) return f(desc, rec=rec)
class StringView(Label): class StringView(Label):

View File

@ -0,0 +1,18 @@
import ujson as json
from kivy.factory import Factory
from .factory import UiFactory
from appPublic.myTE import MyTemplateEngine
def view_build_viewer(desc, rec=None):
viewer_desc = desc.get('viewer')
if not viewer_desc:
return None
if isinstance(viewer_desc, dict):
viewer_desc = json.dumps(viewer_desc)
mytmpl = MyTemplateEngine(['.'])
v_desc = mytmpl.renders(viewer_desc, rec)
vdesc = json.loads(v_desc)
return Factory.Blocks().widgetBuild(vdesc)
UiFactory.register('viewer', None, view_build_viewer)

View File

@ -105,7 +105,11 @@ class IntegerInput(StrInput):
self.cursor = (0,len(self.text)) self.cursor = (0,len(self.text))
def getValue(self): def getValue(self):
return int(self.text) try:
return int(self.text)
except:
pass
return None
class FloatInput(IntegerInput): class FloatInput(IntegerInput):
dec = NumericProperty(2) dec = NumericProperty(2)
@ -114,7 +118,11 @@ class FloatInput(IntegerInput):
self.input_filter = 'float' self.input_filter = 'float'
def getValue(self): def getValue(self):
return float(self.text) try:
return float(self.text)
except:
pass
return None
class MyDropDown(DropDown): class MyDropDown(DropDown):
def __init__(self,csscls='input', **kw): def __init__(self,csscls='input', **kw):
@ -151,7 +159,7 @@ class MyDropDown(DropDown):
if d.get(self.textField) == v: if d.get(self.textField) == v:
r = d.get(self.valueField) r = d.get(self.valueField)
return r return r
return '' return None
def setData(self,data): def setData(self,data):
self.si_data = data self.si_data = data