diff --git a/kivyblocks/baseWidget.py b/kivyblocks/baseWidget.py index ec6502a..def226c 100755 --- a/kivyblocks/baseWidget.py +++ b/kivyblocks/baseWidget.py @@ -63,7 +63,7 @@ from .widgetExt.scrollwidget import ScrollWidget from .widgetExt.binstateimage import BinStateImage from .widgetExt.jsoncodeinput import JsonCodeInput from .widgetExt.inputext import FloatInput,IntegerInput, \ - StrInput,SelectInput, BoolInput, AmountInput + StrInput,SelectInput, BoolInput, Password from .widgetExt.messager import Messager from .charts.bar import Bar from .bgcolorbehavior import BGColorBehavior diff --git a/kivyblocks/clickable.py b/kivyblocks/clickable.py index 17519bf..7d82af4 100644 --- a/kivyblocks/clickable.py +++ b/kivyblocks/clickable.py @@ -13,7 +13,7 @@ from kivyblocks.bgcolorbehavior import BGColorBehavior from kivyblocks.utils import CSize, SUPER, blockImage from kivyblocks.baseWidget import Box, Text from kivyblocks.widget_css import WidgetCSS -from kivyblocks.uitype import view_register, input_register, get_value +from .uitype.factory import UiFactory, get_value class TinyText(Text): def __init__(self, **kw): @@ -286,8 +286,7 @@ def build_checkbox(desc, rec=None): x = SingleCheckBox(select_state=v) return x -view_register('checkbox', build_checkbox) -input_register('checkbox', build_checkbox) +UiFactory.register('checkbox', build_checkbox, build_checkbox) r = Factory.register r('TinyText', TinyText) diff --git a/kivyblocks/dateinput.py b/kivyblocks/dateinput.py index 6c2dfff..db3ca51 100644 --- a/kivyblocks/dateinput.py +++ b/kivyblocks/dateinput.py @@ -140,7 +140,7 @@ class DateInput(HBox): self.datetype = 'yyyy-mm-dd' y = int(datestr[:4]) m = int(datestr[5:7]) - d = int(datestr[9:10]) + d = int(datestr[8:10]) return y, m, d def ymd2str(self, y, m, d): @@ -175,6 +175,8 @@ class DateInput(HBox): return None def setValue(self, datestr): + if datestr == '': + datestr = curDateString() self.old_value = datestr y, m, d = self.str2ymd(datestr) self.yw.setValue(y) diff --git a/kivyblocks/dg.c b/kivyblocks/dg.c index 35deb30..49ea73e 100644 --- a/kivyblocks/dg.c +++ b/kivyblocks/dg.c @@ -1607,7 +1607,6 @@ static const char __pyx_k_row_id[] = "row_id"; static const char __pyx_k_select[] = "select"; static const char __pyx_k_tailer[] = "tailer"; static const char __pyx_k_target[] = "target"; -static const char __pyx_k_uitype[] = "uitype"; static const char __pyx_k_update[] = "update"; static const char __pyx_k_valign[] = "valign"; static const char __pyx_k_Factory[] = "Factory"; @@ -1648,6 +1647,7 @@ static const char __pyx_k_setWidth[] = "setWidth"; static const char __pyx_k_vertical[] = "vertical"; static const char __pyx_k_BoxLayout[] = "BoxLayout"; static const char __pyx_k_Rectangle[] = "Rectangle"; +static const char __pyx_k_UiFactory[] = "UiFactory"; static const char __pyx_k_WidgetCSS[] = "WidgetCSS"; static const char __pyx_k_bar_width[] = "bar_width"; static const char __pyx_k_cell_type[] = "cell_type"; @@ -1759,6 +1759,7 @@ static const char __pyx_k_on_scroll_stop[] = "on_scroll_stop"; static const char __pyx_k_row_normal_css[] = "row_normal_css"; static const char __pyx_k_selected_rowid[] = "selected_rowid"; static const char __pyx_k_tailer_widgets[] = "tailer_widgets"; +static const char __pyx_k_uitype_factory[] = "uitype.factory"; static const char __pyx_k_BGColorBehavior[] = "BGColorBehavior"; static const char __pyx_k_Body_delRowById[] = "Body.delRowById"; static const char __pyx_k_Body_getRowData[] = "Body.getRowData"; @@ -1935,6 +1936,7 @@ static PyObject *__pyx_n_s_StringProperty; static PyObject *__pyx_n_s_Text; static PyObject *__pyx_n_s_TimeCost; static PyObject *__pyx_n_s_Toolbar; +static PyObject *__pyx_n_s_UiFactory; static PyObject *__pyx_n_s_VBox; static PyObject *__pyx_n_s_WidgetCSS; static PyObject *__pyx_n_s_WidgetReady; @@ -2171,7 +2173,7 @@ static PyObject *__pyx_n_s_time; static PyObject *__pyx_n_s_toolbar; static PyObject *__pyx_n_s_toolbar_2; static PyObject *__pyx_n_s_txt; -static PyObject *__pyx_n_s_uitype; +static PyObject *__pyx_n_s_uitype_factory; static PyObject *__pyx_n_s_ujson; static PyObject *__pyx_n_s_unselect_row; static PyObject *__pyx_n_s_unselected; @@ -2937,7 +2939,7 @@ static PyObject *__pyx_pf_10kivyblocks_2dg_4Cell___init__(CYTHON_UNUSED PyObject * self.cell_type = 'header' * else: * self.cell_type = 'data' # <<<<<<<<<<<<<< - * bl = build_view_widget(desc,self.row.row_data) + * bl = UiFactory.build_view_widget(desc,self.row.row_data) * self.colume_name = desc['name'] */ /*else*/ { @@ -2946,43 +2948,46 @@ static PyObject *__pyx_pf_10kivyblocks_2dg_4Cell___init__(CYTHON_UNUSED PyObject /* "kivyblocks/dg.pyx":72 * else: * self.cell_type = 'data' - * bl = build_view_widget(desc,self.row.row_data) # <<<<<<<<<<<<<< + * bl = UiFactory.build_view_widget(desc,self.row.row_data) # <<<<<<<<<<<<<< * self.colume_name = desc['name'] * if bl: */ - __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_build_view_widget); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 72, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_UiFactory); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_row); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_build_view_widget); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_row_data); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 72, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_row); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 72, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_row_data); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = NULL; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = NULL; __pyx_t_7 = 0; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_1)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_1); + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_4); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); + __Pyx_DECREF_SET(__pyx_t_1, function); __pyx_t_7 = 1; } } #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_4)) { - PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_desc, __pyx_t_2}; - __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 72, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_desc, __pyx_t_2}; + __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 72, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_GOTREF(__pyx_t_5); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; } else #endif #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { - PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_desc, __pyx_t_2}; - __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 72, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { + PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_desc, __pyx_t_2}; + __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 72, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_GOTREF(__pyx_t_5); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; } else @@ -2990,8 +2995,8 @@ static PyObject *__pyx_pf_10kivyblocks_2dg_4Cell___init__(CYTHON_UNUSED PyObject { __pyx_t_3 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - if (__pyx_t_1) { - __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); __pyx_t_1 = NULL; + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); __pyx_t_4 = NULL; } __Pyx_INCREF(__pyx_v_desc); __Pyx_GIVEREF(__pyx_v_desc); @@ -2999,11 +3004,11 @@ static PyObject *__pyx_pf_10kivyblocks_2dg_4Cell___init__(CYTHON_UNUSED PyObject __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_7, __pyx_t_2); __pyx_t_2 = 0; - __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 72, __pyx_L1_error) + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_bl = __pyx_t_5; __pyx_t_5 = 0; } @@ -3011,7 +3016,7 @@ static PyObject *__pyx_pf_10kivyblocks_2dg_4Cell___init__(CYTHON_UNUSED PyObject /* "kivyblocks/dg.pyx":73 * self.cell_type = 'data' - * bl = build_view_widget(desc,self.row.row_data) + * bl = UiFactory.build_view_widget(desc,self.row.row_data) * self.colume_name = desc['name'] # <<<<<<<<<<<<<< * if bl: * self.add_widget(bl) @@ -3022,7 +3027,7 @@ static PyObject *__pyx_pf_10kivyblocks_2dg_4Cell___init__(CYTHON_UNUSED PyObject __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; /* "kivyblocks/dg.pyx":74 - * bl = build_view_widget(desc,self.row.row_data) + * bl = UiFactory.build_view_widget(desc,self.row.row_data) * self.colume_name = desc['name'] * if bl: # <<<<<<<<<<<<<< * self.add_widget(bl) @@ -3038,27 +3043,27 @@ static PyObject *__pyx_pf_10kivyblocks_2dg_4Cell___init__(CYTHON_UNUSED PyObject * * class Row(BoxLayout): */ - __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_add_widget); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 75, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_add_widget); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 75, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4); + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1); if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); __Pyx_INCREF(__pyx_t_3); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } } - __pyx_t_5 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_3, __pyx_v_bl) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_bl); + __pyx_t_5 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_3, __pyx_v_bl) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_bl); __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 75, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; /* "kivyblocks/dg.pyx":74 - * bl = build_view_widget(desc,self.row.row_data) + * bl = UiFactory.build_view_widget(desc,self.row.row_data) * self.colume_name = desc['name'] * if bl: # <<<<<<<<<<<<<< * self.add_widget(bl) @@ -17656,6 +17661,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_Text, __pyx_k_Text, sizeof(__pyx_k_Text), 0, 0, 1, 1}, {&__pyx_n_s_TimeCost, __pyx_k_TimeCost, sizeof(__pyx_k_TimeCost), 0, 0, 1, 1}, {&__pyx_n_s_Toolbar, __pyx_k_Toolbar, sizeof(__pyx_k_Toolbar), 0, 0, 1, 1}, + {&__pyx_n_s_UiFactory, __pyx_k_UiFactory, sizeof(__pyx_k_UiFactory), 0, 0, 1, 1}, {&__pyx_n_s_VBox, __pyx_k_VBox, sizeof(__pyx_k_VBox), 0, 0, 1, 1}, {&__pyx_n_s_WidgetCSS, __pyx_k_WidgetCSS, sizeof(__pyx_k_WidgetCSS), 0, 0, 1, 1}, {&__pyx_n_s_WidgetReady, __pyx_k_WidgetReady, sizeof(__pyx_k_WidgetReady), 0, 0, 1, 1}, @@ -17892,7 +17898,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_toolbar, __pyx_k_toolbar, sizeof(__pyx_k_toolbar), 0, 0, 1, 1}, {&__pyx_n_s_toolbar_2, __pyx_k_toolbar_2, sizeof(__pyx_k_toolbar_2), 0, 0, 1, 1}, {&__pyx_n_s_txt, __pyx_k_txt, sizeof(__pyx_k_txt), 0, 0, 1, 1}, - {&__pyx_n_s_uitype, __pyx_k_uitype, sizeof(__pyx_k_uitype), 0, 0, 1, 1}, + {&__pyx_n_s_uitype_factory, __pyx_k_uitype_factory, sizeof(__pyx_k_uitype_factory), 0, 0, 1, 1}, {&__pyx_n_s_ujson, __pyx_k_ujson, sizeof(__pyx_k_ujson), 0, 0, 1, 1}, {&__pyx_n_s_unselect_row, __pyx_k_unselect_row, sizeof(__pyx_k_unselect_row), 0, 0, 1, 1}, {&__pyx_n_s_unselected, __pyx_k_unselected, sizeof(__pyx_k_unselected), 0, 0, 1, 1}, @@ -19608,7 +19614,7 @@ if (!__Pyx_RefNanny) { * from .toolbar import Toolbar * from .bgcolorbehavior import BGColorBehavior # <<<<<<<<<<<<<< * from .widget_css import WidgetCSS - * from .uitype import build_view_widget + * from .uitype.factory import UiFactory */ __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); @@ -19628,7 +19634,7 @@ if (!__Pyx_RefNanny) { * from .toolbar import Toolbar * from .bgcolorbehavior import BGColorBehavior * from .widget_css import WidgetCSS # <<<<<<<<<<<<<< - * from .uitype import build_view_widget + * from .uitype.factory import UiFactory * */ __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 32, __pyx_L1_error) @@ -19648,26 +19654,26 @@ if (!__Pyx_RefNanny) { /* "kivyblocks/dg.pyx":33 * from .bgcolorbehavior import BGColorBehavior * from .widget_css import WidgetCSS - * from .uitype import build_view_widget # <<<<<<<<<<<<<< + * from .uitype.factory import UiFactory # <<<<<<<<<<<<<< * * class BLabel(ButtonBehavior, Text): */ __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 33, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_n_s_build_view_widget); - __Pyx_GIVEREF(__pyx_n_s_build_view_widget); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_build_view_widget); - __pyx_t_2 = __Pyx_Import(__pyx_n_s_uitype, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 33, __pyx_L1_error) + __Pyx_INCREF(__pyx_n_s_UiFactory); + __Pyx_GIVEREF(__pyx_n_s_UiFactory); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_UiFactory); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_uitype_factory, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 33, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_build_view_widget); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 33, __pyx_L1_error) + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_UiFactory); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 33, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_build_view_widget, __pyx_t_1) < 0) __PYX_ERR(0, 33, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_UiFactory, __pyx_t_1) < 0) __PYX_ERR(0, 33, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "kivyblocks/dg.pyx":35 - * from .uitype import build_view_widget + * from .uitype.factory import UiFactory * * class BLabel(ButtonBehavior, Text): # <<<<<<<<<<<<<< * def __init__(self, **kw): @@ -19703,7 +19709,7 @@ if (!__Pyx_RefNanny) { __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; /* "kivyblocks/dg.pyx":35 - * from .uitype import build_view_widget + * from .uitype.factory import UiFactory * * class BLabel(ButtonBehavior, Text): # <<<<<<<<<<<<<< * def __init__(self, **kw): diff --git a/kivyblocks/dg.pyx b/kivyblocks/dg.pyx index 25ed58c..7c5bf90 100644 --- a/kivyblocks/dg.pyx +++ b/kivyblocks/dg.pyx @@ -30,7 +30,7 @@ from .ready import WidgetReady from .toolbar import Toolbar from .bgcolorbehavior import BGColorBehavior from .widget_css import WidgetCSS -from .uitype import build_view_widget +from .uitype.factory import UiFactory class BLabel(ButtonBehavior, Text): def __init__(self, **kw): @@ -69,7 +69,7 @@ class Cell(ButtonBehavior, WidgetCSS, BoxLayout): self.cell_type = 'header' else: self.cell_type = 'data' - bl = build_view_widget(desc,self.row.row_data) + bl = UiFactory.build_view_widget(desc,self.row.row_data) self.colume_name = desc['name'] if bl: self.add_widget(bl) diff --git a/kivyblocks/form.py b/kivyblocks/form.py index 5bca9ed..464e476 100644 --- a/kivyblocks/form.py +++ b/kivyblocks/form.py @@ -1,9 +1,11 @@ +from math import floor from kivy.factory import Factory from kivy.properties import NumericProperty, StringProperty, \ DictProperty, ListProperty, OptionProperty, BooleanProperty from kivy.logger import Logger from kivy.uix.textinput import TextInput from kivy.uix.boxlayout import BoxLayout +from kivy.uix.stacklayout import StackLayout from kivy.core.window import Window from kivy.graphics import Color from .responsivelayout import VResponsiveLayout @@ -16,7 +18,7 @@ from .dataloader import DataGraber from .ready import WidgetReady from .widget_css import WidgetCSS from .dateinput import DateInput -from .uitype import get_input_builder +from .uitype.factory import UiFactory # import get_input_builder """ form options @@ -58,7 +60,6 @@ class InputBox(BoxLayout): self.options = options self.uitype = options.get('uitype',options.get('datatype','str')) self.size_hint = (None, None) - width = self.form.inputwidth height = self.form.inputheight if self.uitype == 'text': if not options.get('height'): @@ -74,16 +75,21 @@ class InputBox(BoxLayout): else: kwargs['size_hint_y'] = None kwargs['height'] = CSize(height) - if width <= 1: - kwargs['size_hint_x'] = width + if self.form.input_width <= 1: + kwargs['size_hint_x'] = self.form.input_width else: kwargs['size_hint_x'] = None - kwargs['width'] = CSize(width) + kwargs['width'] = self.form.input_width super().__init__(**kwargs) self.initflag = False - self.bind(size=self.setSize, - pos=self.setSize) self.register_event_type("on_datainput") + self.init() + + def focus_act(self, *args): + show_widget_info(self,'test') + show_widget_info(self.labeltext,'test') + show_widget_info(self.input_widget,'test') + def on_size(self, *args): if self.input_widget is None: @@ -97,6 +103,10 @@ class InputBox(BoxLayout): self.input_widget.size_hint_x = None 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): print('on_datainput fired ...',o,v) @@ -104,44 +114,42 @@ class InputBox(BoxLayout): if self.initflag: return i18n = I18n() - opts = { - "orientation":"horizontal", - "size_hint_y":None, - "height":CSize(self.form.inputheight) - } - if self.form.inputwidth > 1: - opts['size_hint_x'] = None - opts['width'] = CSize(self.form.inputwidth) - else: - opts['size_hint_x'] = self.form.inputwidth - - bl = BoxLayout(**opts) - self.add_widget(bl) label = self.options.get('label',self.options.get('name')) kwargs = { "i18n":True, "otext":label, "font_size":CSize(1), } - if self.form.labelwidth < 1: + if self.form.labelwidth <= 1: kwargs['size_hint_x'] = self.form.labelwidth else: kwargs['size_hint_x'] = None kwargs['width'] = CSize(self.form.labelwidth) self.labeltext = Text(**kwargs) - bl.add_widget(self.labeltext) + self.add_widget(self.labeltext) if self.options.get('required',False): star = Label(text='*', color=(1,0,0,1), size_hint_x=None, width=CSize(1)) - bl.add_widget(star) + self.add_widget(star) options = self.options.copy() options['hint_text'] = i18n(self.options.get('hint_text')) - f = get_input_builder(self.uitype) - self.input_widget = f(options) + options['size_hint_y'] = None + options['height'] = self.height + print('options=', options) + self.input_widget = UiFactory.build_input_widget(options) + + print('inputw.height=',self.input_widget.height) + try: + self.input_widget.bind(focus=self.focus_act) + except: + pass + self.input_widget.height = self.height + self.input_widget.size_hint_y = None + if self.form.labelwidth < 1: self.input_widget.size_hint_x = 1 - self.form.labelwidth else: @@ -186,9 +194,6 @@ class InputBox(BoxLayout): if self.old_value != o.text: self.dispatch('on_datainput',o.text) - def setSize(self,o,v=None): - self.init() - def setValue(self,v): self.input_widget.setValue(v) @@ -225,7 +230,7 @@ def defaultToolbar(): } class Form(WidgetCSS, WidgetReady, BoxLayout): - cols = NumericProperty(1) + cols = NumericProperty(None) csscls=StringProperty('formcss') input_css=StringProperty('formfieldcss') inputwidth=NumericProperty(1) @@ -239,22 +244,60 @@ class Form(WidgetCSS, WidgetReady, BoxLayout): submit=DictProperty(None) clear=DictProperty(None) notoolbar=BooleanProperty(False) - def __init__(self, - **options): + def __init__(self, **options): + self.cols = 1 if self.toolbar_at in ['top','bottom']: options['orientation'] = 'vertical' else: options['orientation'] = 'horizontal' SUPER(Form, self, options) - if self.inputwidth <= 1: - self.cols = 1 - self.options_cols = self.cols - if isHandHold() and Window.width < Window.height: - self.cols = 1 - self.options = options + self.setup_cols_and_inputwidth() self.init() self.register_event_type('on_submit') + def setup_cols_and_inputwidth(self): + if isHandHold() and Window.width < Window.height: + self._cols = 1 + self.input_width = 1 + print('1-inputwidth=', self.inputwidth, + 'input_width=',self.input_width, + 'CSize(1)=', CSize(1)) + return + if self.cols is None and self.inputwidth is None: + self.input_width = 1 + self._cols = 1 + print('2-inputwidth=', self.inputwidth, + 'input_width=',self.input_width, + 'CSize(1)=', CSize(1)) + return + if self.inputwidth > 1: + self.input_width = CSize(self.inputwidth) + self._cols = -1 # auto calculate + print('3-inputwidth=', self.inputwidth, + 'input_width=',self.input_width, + 'CSize(1)=', CSize(1), CSize(self.inputwidth)) + return + if self.cols is not None: + self._cols = self.cols + if self.inputwidth is None: + self.input_width = -1 + else: + self.input_width = CSize(self.inputwidth) + print('4-inputwidth=', self.inputwidth, + 'input_width=',self.input_width, + 'CSize(1)=', CSize(1)) + return + self.input_width = -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): + if self._cols == 1 and self.input_width <= 1: + self.input_width = self.width + self.fsc.box_width = self.input_width + def on_size(self, *args): if not hasattr(self,'fsc'): return @@ -269,7 +312,7 @@ class Form(WidgetCSS, WidgetReady, BoxLayout): self.fsc.height = self.height else: self.fsc.width = self.width - self.fsc.org_box_width = self.width / self.options_cols + self.set_grid_attrs() def init(self): if not self.notoolbar: @@ -303,8 +346,7 @@ class Form(WidgetCSS, WidgetReady, BoxLayout): self.toolbar_w = Factory.Toolbar(**desc) self.fsc = VResponsiveLayout( - self.inputwidth, - self.cols, + box_width = self.input_width, size_hint=(1,1) ) diff --git a/kivyblocks/imgs/error.png b/kivyblocks/imgs/error.png new file mode 100644 index 0000000..9091bb4 Binary files /dev/null and b/kivyblocks/imgs/error.png differ diff --git a/kivyblocks/imgs/info.png b/kivyblocks/imgs/info.png new file mode 100644 index 0000000..eba41f4 Binary files /dev/null and b/kivyblocks/imgs/info.png differ diff --git a/kivyblocks/message.py b/kivyblocks/message.py index 2173684..baffdcb 100644 --- a/kivyblocks/message.py +++ b/kivyblocks/message.py @@ -3,11 +3,16 @@ from kivy.factory import Factory from kivy.properties import StringProperty, NumericProperty from kivy.uix.image import AsyncImage from .utils import * -from .baseWidget import Modal, Text, HBox,VBox +from .baseWidget import Modal, Text, HBox,VBox, TimedModal from .widget_css import register_css from .clickable import ClickableIconText from .toggleitems import PressableBox +error_default_title_css = { + "bgcolor":[0.88,0,0,1], + "fgcolor":[0.12,0.12,0.12,1] +} + conform_default_title_css = { "bgcolor":[0.88,0.88,0.88,1], "fgcolor":[0.12,0.12,0.12,1] @@ -28,10 +33,53 @@ cancel_button_default_css = { } register_css('conform_default_title_css', conform_default_title_css) +register_css('message_default_title_css', conform_default_title_css) +register_css('error_default_title_css', error_default_title_css) register_css('conform_default_body_css', conform_default_body_css) +register_css('message_default_body_css', conform_default_body_css) register_css('conform_button_default_css', conform_button_default_css) register_css('cancel_button_default_css', cancel_button_default_css) +class Message(TimedModal): + title = StringProperty(None) + default_title = 'Message' + default_message = 'Message' + title_icon = StringProperty(blockImage('info.png')) + message = StringPrperty(None) + body_css = StringProperty('message_default_body_css') + title_css = StringProperty('message_default_title_css') + def __init__(self, **kw): + SUPER(Message, self, kw) + b = VBox(csscls=self.title_css) + b1 = HBox(size_hint_y=None, height=CSize(2)) + b1.add_widget(AsyncImage(source=self.title_icon, + size_hint=[None,None], + height=CSize(1.2), + width=CSize(1.2))) + b1.add_widget(Text(otext=self.title or self.default_title, + font_size=CSize(1.2), + i18n=True, + wrap=True, + halign='left', + valign='center', + )) + b.add_widget(b1) + b2 = HBox(csscls=self.body_css) + b2.add_widget(Text(text=self.message or self.default_message, + i18n=True, + wrap=True, + halign='left', + size_hint=(1,1), + font_size=CSize(1))) + b.add_widget(b2) + self.add_widget(b) + +class Error(Message): + default_title = 'Error' + default_message = 'Error message' + title_icon = StringProperty(blockImage('error.png')) + title_css = StringProperty('error_default_title_css') + class Conform(Modal): title = StringProperty(None) title_icon = StringProperty(None) diff --git a/kivyblocks/price.py b/kivyblocks/price.py index 638e24d..b7f46fe 100644 --- a/kivyblocks/price.py +++ b/kivyblocks/price.py @@ -3,11 +3,13 @@ from kivy.uix.label import Label from kivy.properties import NumericProperty, ColorProperty from kivy.factory import Factory -from kivyblocks.uitype import view_register, get_value +from .baseWidget import FloatInput + +from .uitype.factory import UiFactory, get_value class PriceView(Label): dec = NumericProperty(4) - old_price = NumericProperty(None) + compare_price = NumericProperty(None) price = NumericProperty(None) nor_color = ColorProperty([0.9,0.9,0.9,1]) # white inc_color = ColorProperty([0.9,0,0,1]) # red @@ -15,7 +17,9 @@ class PriceView(Label): def __init__(self, **kw): super(PriceView, self).__init__(text='', **kw) - def on_price(self, price): + def on_compare_price(self, *args): + self.on_price() + def on_price(self, *args): if self.price is None: return if not isinstance(self.price, float) and \ @@ -23,16 +27,15 @@ class PriceView(Label): return f = '%%.0%df' % self.dec - self.text = f % price - if self.old_price is None: + self.text = f % self.price + if self.compare_price is None: self.color = self.nor_color - elif self.price > self.old_price: + elif self.price > self.compare_price: self.color = self.inc_color - elif self.price < self.old_price: + elif self.price < self.compare_price: self.color = self.dec_color else: self.color = nor_color - self.old_price = self.price def getValue(self): return self.price @@ -40,14 +43,26 @@ class PriceView(Label): def setValue(self, v): self.price = v + @classmethod + def builder(desc, rec=None): + v = get_value(desc, rec=rec) + return PriceView(price=v, + font_size=CSize(1), + halign='right', + valign='middle' + ) + +class PriceInput(FloatInput): + @classmethod + def builder(self, desc, rec=None): + v = get_value(desc, rec=rec) + kw = desc.get('uiparams', {}) + w = PriceInput(**kw) + if v is not None: + w.setValue(v) + return w + Factory.register('PriceView', PriceView) -def build_view_price_widget(desc, rec=None): - v = get_value(desc, rec=rec) - return Factory.PriceView(price=v, - font_size=CSize(1), - halign='right', - valign='middle' - ) -view_register('price', build_view_price_widget) +UiFactory.register('price', PriceInput.builder, PriceView.builder) diff --git a/kivyblocks/register.py b/kivyblocks/register.py index ca25ea3..2c65fa0 100644 --- a/kivyblocks/register.py +++ b/kivyblocks/register.py @@ -97,7 +97,6 @@ r('IntegerInput',IntegerInput) r('StrInput',StrInput) r('SelectInput',SelectInput) r('BoolInput',BoolInput) -r('AmountInput',AmountInput) r('Messager',Messager) r('Bar',Bar) r('LoginForm',LoginForm) diff --git a/kivyblocks/responsivelayout.py b/kivyblocks/responsivelayout.py index 4872408..6c79724 100644 --- a/kivyblocks/responsivelayout.py +++ b/kivyblocks/responsivelayout.py @@ -1,35 +1,42 @@ +from math import floor +from kivy.properties import NumericProperty from kivy.utils import platform from kivy.uix.scrollview import ScrollView from kivy.uix.gridlayout import GridLayout from kivy.graphics import Color, Ellipse,Rectangle from kivy.clock import Clock -from .utils import CSize, isHandHold +from .utils import CSize, isHandHold, show_widget_info class VResponsiveLayout(ScrollView): - def __init__(self,box_width,cols, **kw): - self.org_box_width = box_width - self.org_cols = cols - self.box_width = box_width - self.box_cols = cols + box_width = NumericProperty(1) + def __init__(self, **kw): + self._inner = None super(VResponsiveLayout, self).__init__(**kw) self.options = kw - self._inner = GridLayout(cols=self.org_cols, padding=2, + self._inner = GridLayout(cols=1, padding=2, spacing=2,size_hint=(1,None)) + self._inner.col_force_default = True + self._inner.col_default_width = self.box_width super(VResponsiveLayout,self).add_widget(self._inner) self._inner.bind( minimum_height=self._inner.setter('height')) - self.sizeChangedTask = None + self.setCols() self.bind(pos=self.setCols,size=self.setCols) + def on_box_width(self, *args): + if not self._inner: + return + self._inner.col_default_width = self.box_width + for w in self._inner.children: + w.size_hint_x = None + w.width = self.box_width + self.setCols() + def on_orientation(self,o): self.setCols() def add_widget(self,widget,**kw): - width = self.box_width - if hasattr(widget, 'cols'): - width = widget.cols * self.box_width - widget.width = width a = self._inner.add_widget(widget,**kw) return a @@ -41,13 +48,13 @@ class VResponsiveLayout(ScrollView): return a def setCols(self,*args): - cols = round(self.width / self.org_box_width) + cols = floor(self.width / self.box_width) if cols < 1: cols = 1 - if isHandHold() and self.width < self.height and self.org_cols >= 2: - cols = 2 - box_width = self.width / cols - 2 self._inner.cols = cols - for w in self._inner.children: - w.width = box_width + #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) diff --git a/kivyblocks/toolbar.py b/kivyblocks/toolbar.py index 208d1cf..1a90bcc 100644 --- a/kivyblocks/toolbar.py +++ b/kivyblocks/toolbar.py @@ -155,7 +155,6 @@ class Toolbar(ScrollPanel): w.bind(on_press=self.tool_press) w.bind(minimum_width=w.setter('width')) w.bind(minimum_height=w.setter('height')) - print(w, 'children=', len(w.children)) def delete_tool(self, o): w, t = o.data diff --git a/kivyblocks/uitype.py b/kivyblocks/uitype.py deleted file mode 100644 index 96287a9..0000000 --- a/kivyblocks/uitype.py +++ /dev/null @@ -1,374 +0,0 @@ -#uitype.py -""" -each ui type need to provides a view widget and a input widget -to auto construct the form widget and record show widget. - -we use a register machinans to maintian the ui type information to build the view widget and input widget -""" - -import ujson as json -from kivy.factory import Factory -from kivy.properties import NumericProperty, StringProperty, \ - BooleanProperty -from kivy.uix.label import Label - -from appPublic.myTE import string_template_render - -from kivyblocks.utils import CSize -from .baseWidget import WrapText, Text -from .dateinput import DateInput -from .widgetExt.inputext import FloatInput,IntegerInput, \ - StrInput,SelectInput, BoolInput, AmountInput, Password - -class StringView(Label): - def __init__(self, **kw): - super(StringView, self).__init__(**kw) - self.wrap = True - self.halign = 'left' - self.valign = 'middle' - - def getValue(self): - return self.text - - def setValue(self, v): - self.text = str(v) - -class PasswordView(StringView): - def __init__(self, text='*', **kw): - super(PasswordView, self).__init__(text=text, **kw) - - def getValue(self): - return None - - def setValue(self, v): - pass - -class TextView(WrapText): - def getValue(self): - return self.text - - def setValue(self, v): - self.text = v - -view_widget_builders = { -} - -input_widget_builders = {} - -def view_register(uitype, f): - view_widget_builders.update({uitype:f}) - -def input_register(uitype, f): - input_widget_builders.update({uitype:f}) - -def get_input_builder(uitype): - return input_widget_builders.get(uitype, \ - input_widget_builders.get('str', None)) - -def get_view_builder(uitype): - return view_widget_builders.get(uitype, \ - view_widget_builders.get('str', None)) - -def build_view_widget(desc, rec = None): - viewer = desc.get('viewer') - if viewer: - if isinstance(viewer,dict): - viewer = json.dumps(viewer) - rendered = string_template_render(viewer, rec) - dic = json.loads(rendered) - if dic is None: - return None - w = Factory.Blocks().widgetBuild(dic) - return w - - f = get_view_builder(desc.get('uitype')) - return f(desc, rec) - -def build_input_widget(desc, rec=None): - f = get_input_builder(desc.get('uitype')) - return f(desc, rec) - -def get_value(desc, rec=None): - if rec: - return rec.get(desc['name']) - return desc.get('value', desc.get('defaultvalue', '')) - -def build_view_str_widget(desc, rec=None): - txt = get_value(desc, rec=rec) - return StringView(text=str(txt) if txt else '', - font_size=CSize(1), - halign='left', - valign='middle') - -view_register('str', build_view_str_widget) -view_register('date', build_view_str_widget) -view_register('time', build_view_str_widget) -view_register('timestamp', build_view_str_widget) - -def build_view_text_widget(desc, rec=None): - txt = get_value(desc, rec=rec) - return TextView(text=str(txt) if txt else '', - font_size=CSize(1), - halign='left', - valign='middle') - -view_register('text', build_view_text_widget) - -def build_view_passwd_widget(desc, rec=None): - return PasswordView(text='*', - font_size=CSize(1), - halign='left', - valign='middle') - -view_register('password', build_view_passwd_widget) - -class BoolView(Label): - value = BooleanProperty(False) - def __init__(self, text='', **kw): - super(BoolView, self).__init__(text='', **kw) - self.wrap = True - self.halign = 'center' - self.valign = 'middle' - - def on_value(self, *args): - if self.value: - self.text = 'true' - else: - self.text = 'false' - - def getValue(self): - return self.value - - def setValue(self, v): - self.value = v - -def build_view_bool_widget(desc, rec=None): - v = get_value(desc, rec) - if v is not None: - return BoolView(value=v, - font_size=CSize(1), - halign='left', - valign='middle') - - default_value = desc.get('nullvalue',False) - return BoolView(value=default_Value, - font_size=CSize(1), - halign='left', - valign='middle') - -view_register('bool', build_view_bool_widget) - -class IntView(Text): - value = NumericProperty(None) - nullstr = StringProperty('') - def __init__(self, **kw): - super(IntView, self).__init__(text='', **kw) - self.wrap = True - self.halign = 'right' - self.valign = 'middle' - - def on_value(self, *args): - if self.value is not None: - self.text = str(v) - else: - self.text = self.nullstr - - def setValue(self, v): - self.value = v - - def getValue(self): - return self.value - -def build_view_int_widget(desc, rec=None): - v = get_value(desc, rec=rec) - return IntValue(value=v, - nullstr=desc.get('nullstr',''), - font_size=CSize(1), - halign='right', - valign='middle' - ) - -view_register('int', build_view_int_widget) - -class FloatView(Text): - value = NumericProperty(None) - nullstr = StringProperty('') - dec = NumericProperty(2) - def __init__(self, **kw): - super(FloatView, self).__init__(text=self.nullstr, **kw) - self.wrap = True - self.halign = 'right' - self.valign = 'middle' - - def on_value(self, *args): - if self.value is None: - self.text = self.bullstr - f = '%%.0%df' % self.dec - self.text = f % self.value - - def getValue(self): - return self.value - - def setValue(self, v): - self.value = v - -def build_view_float_widget(desc, rec=None): - v = get_value(desc, rec=rec) - return FloatView(value=v, - dec=desc.get('dec', 2), - nullstr=desc.get('nullstr',''), - font_size=CSize(1), - halign='right', - valign='middle' - ) - -view_register('float', build_view_float_widget) - -def build_view_code_widget(desc, rec=None): - tf = desc.get('textField','text') - vf = desc.get('valueField','value') - v = rec.get(tf,rec.get(vf, ' ')) - return Text(text=v, - i18n=True, - font_size = CSize(1), - wrap=True, - halign='center', - valign='middle' - ) - -view_register('code', build_view_code_widget) - -class AmountView(FloatView): - def on_value(self, *args): - if self.value is None: - self.text = self.nullstr - else: - self.text = self.amount_str() - - def amount_str(self): - f = '%%.0%df' % self.dec - s = f % self.value - parts = s.split('.') - p_int = parts[0] - subs = [] - if p_int[0] == '-': - subs.append('-') - p_int = p_int[1:] - l = [i for i in p_int] - l.reverse() - k = [] - for i,c in enumerate(l): - if i and (i) % 3 == 0: - k.append(',') - k.append(c) - k.reverse() - subs.append(''.join(k)) - if len(parts) > 1: - subs.append(f'.{parts[1]}') - return ''.join(subs) - -def build_view_amount_widget(desc, rec=None): - v = get_value(desc, rec=rec) - defaultvalue = desc.get('nullstr', '') - return Amount(value=v, - dec=desc.get('dec', 2), - nullstr=defaultvale, - font_size=CSize(1), - halign='right', - valign='middle' - ) - -view_register('amount', build_view_amount_widget) - -def build_input_str_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = StrInput(**kw) - if v: - w.setValue(v) - return w - -input_register('str', build_input_str_widget) - -def build_input_text_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - kw['multiline'] = True - w = StrInput(**kw) - if v: - w.setValue(v) - return w - -input_register('text', build_input_text_widget) - -def build_input_int_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = IntegerInput(**kw) - if v: - w.setValue(v) - return w - -input_register('int', build_input_int_widget) -input_register('time', build_input_int_widget) - -def build_input_float_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = FloatInput(**kw) - if v: - w.setValue(v) - return w - -input_register('float', build_input_float_widget) - -def build_input_amount_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = AmountInput(**kw) - if v: - w.setValue(v) - return w - -input_register('amount', build_input_amount_widget) - -def build_input_date_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = DateInput(**kw) - if v: - w.setValue(v) - return w - -input_register('date', build_input_date_widget) - -def build_input_bool_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = BoolInput(**kw) - if v: - w.setValue(v) - return w - -input_register('bool', build_input_bool_widget) - -def build_input_code_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = SelectInput(**kw) - if v: - w.setValue(v) - return w - -input_register('code', build_input_code_widget) - -def build_input_password_widget(desc, rec=None): - v = get_value(desc, rec=rec) - kw = desc.get('uiparams', {}) - w = Password(**kw) - if v: - w.setValue(v) - return w - -input_register('password', build_input_password_widget) - diff --git a/kivyblocks/utils.py b/kivyblocks/utils.py index 361741f..8f45d4a 100644 --- a/kivyblocks/utils.py +++ b/kivyblocks/utils.py @@ -74,6 +74,20 @@ def loading(parent): view.open() return view +def set_widget_width(self, width): + if width <= 1: + self.size_hint_x = width + else: + self.size_hint_x = None + self.width = width + +def set_widget_height(self, height): + if height <= 1: + self.size_hint_y = height + else: + self.size_hint_y = None + self.height = height + def setSizeOptions(desc,kw): """ desc's width, and height to setup a widget's size options @@ -217,5 +231,5 @@ def absurl(url,parent): def show_widget_info(w, tag='DEBUG'): id = getattr(w, 'widget_id', 'null') - msg=f"""{tag}:size_hint={w.size_hint},size={w.size},pos={w.pos},widget_id={id}""" + msg=f"""{tag}:size_hint={w.size_hint},size={w.size},pos={w.pos},widget_id={id},{w}""" Logger.info(msg) diff --git a/kivyblocks/widgetExt/__init__.py b/kivyblocks/widgetExt/__init__.py index c5f70bf..9cf1d29 100755 --- a/kivyblocks/widgetExt/__init__.py +++ b/kivyblocks/widgetExt/__init__.py @@ -1,14 +1,13 @@ from kivy.utils import platform from .binstateimage import BinStateImage from .jsoncodeinput import JsonCodeInput -from .inputext import FloatInput,IntegerInput,StrInput,SelectInput, BoolInput, AmountInput, Password +from .inputext import FloatInput,IntegerInput,StrInput,SelectInput, BoolInput, Password from .scrollwidget import ScrollWidget from .messager import Messager __all__ = [ BinStateImage, JsonCodeInput, FloatInput, -AmountInput, Password, BoolInput, IntegerInput, diff --git a/kivyblocks/widgetExt/inputext.py b/kivyblocks/widgetExt/inputext.py index b84342f..284765b 100755 --- a/kivyblocks/widgetExt/inputext.py +++ b/kivyblocks/widgetExt/inputext.py @@ -10,10 +10,11 @@ from kivy.uix.dropdown import DropDown from kivy.uix.switch import Switch from kivy.metrics import sp,dp from kivy.app import App -from kivy.properties import BooleanProperty, ListProperty +from kivy.properties import BooleanProperty, ListProperty, \ + NumericProperty from ..threadcall import HttpClient -from ..utils import CSize +from ..utils import CSize, set_widget_height, set_widget_width from ..widget_css import WidgetCSS, get_css class BoolInput(Switch): @@ -34,12 +35,11 @@ class BoolInput(Switch): def setValue(self,v): self.active = v -class StrInput(TextInput): - def __init__(self,csscls='default', - **kv): +class StrInput(WidgetCSS, TextInput): + length = NumericProperty(None) + def __init__(self, **kv): if kv is None: kv = {} - css = get_css(csscls) a = { "allow_copy":True, "password":False, @@ -51,26 +51,17 @@ class StrInput(TextInput): "write_tab":False } a.update(kv) - a['background_color'] = css['bgcolor'] - a['foreground_color'] = css['fgcolor'] - w = kv.get('width',1) - h = kv.get('height',1) - if w <= 1: - a['size_hint_x'] = w - else: - a['size_hint_x'] = None - a['width'] = CSize(w) - if h <= 1: - a['size_hint_y'] = h - else: - a['size_hint_y'] = None - a['height'] = CSize(h) - super(StrInput, self).__init__(**a) self.text = self.old_value = '' self.register_event_type('on_changed') self.bind(on_text_validate=self.checkChange) + def on_bgcolor(self, *args): + self.background_color = self.bgcolor + + def on_fgcolor(self, *args): + self.foreground_color = self.fgcolor + def on_changed(self,v=None): pass @@ -80,6 +71,14 @@ class StrInput(TextInput): self.old_value = v self.dispatch('on_changed',v) + def insert_text(self, substring, from_undo=False): + if self.length: + if len(self.text) + len(substring) > self.length: + return None + ret = super().insert_text(substring, from_undo=from_undo) + # ret is None + return ret + def getValue(self): return self.text @@ -89,11 +88,10 @@ class StrInput(TextInput): self.text = str(v) self.old_value = self.text - class Password(StrInput): def __init__(self, **kw): - kw['password'] = True super().__init__(**kw) + self.password = True class IntegerInput(StrInput): def __init__(self,**kw): @@ -101,49 +99,23 @@ class IntegerInput(StrInput): a.update(kw) a['halign'] = 'right' super().__init__(**a) + self.input_filter = 'int' - pat = re.compile('[^0-9]') - def insert_text(self, substring, from_undo=False): - pat = self.pat - s = re.sub(pat, '', substring) - return StrInput.insert_text(self,s, from_undo=from_undo) - def on_focus(self,t,v): self.cursor = (0,len(self.text)) + def getValue(self): + return int(self.text) + class FloatInput(IntegerInput): - pat = re.compile('[^0-9]') - def filter(self,substring): - pat = self.pat - if '.' in self.text: - s = re.sub(pat, '', substring) - else: - s = '.'.join([re.sub(pat, '', s) for s in substring.split('.', 1)]) - return s + dec = NumericProperty(2) + def __init__(self,**kw): + super(FloatInput, self).__init__(**kw) + self.input_filter = 'float' - def insert_text(self, substring, from_undo=False): - s = self.filter(substring) - return StrInput.insert_text(self,s, from_undo=from_undo) + def getValue(self): + return float(self.text) -class AmountInput(FloatInput): - def filter(self,substring): - s = super(AmountInput,self).filter(substring) - a = s.split('.') - b = a[0] - if len(b)>3: - k = [] - while len(b)>3: - x = b[-3:] - k.insert(0,x) - b = b[:-3] - a[0] = ','.join(k) - s = '.'.join(a) - return '.'.join(a) - - def insert_text(self, substring, from_undo=False): - s = self.filter(substring) - return StrInput.insert_text(self,s, from_undo=from_undo) - class MyDropDown(DropDown): def __init__(self,csscls='input', **kw): super(MyDropDown,self).__init__()