This commit is contained in:
yumoqing 2021-03-27 14:04:10 +08:00
parent 094f81195a
commit e21a5757ee
12 changed files with 147 additions and 138 deletions

View File

@ -73,6 +73,8 @@ from .tab import TabsPanel
from .qrdata import QRCodeWidget
from .threadcall import HttpClient
from .i18n import I18n
from .widget_css import WidgetCSS
from .ready import WidgetReady
from .utils import CSize
if platform == 'android':
@ -85,40 +87,9 @@ 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 Box(BGColorBehavior, BoxLayout):
def __init__(self,color_level=-1,radius=[],**kw):
BoxLayout.__init__(self, **kw)
BGColorBehavior.__init__(self, color_level=color_level,
radius=radius)
def add_widget(self, w, *args, **kw):
super().add_widget(w, *args, **kw)
self.setWidgetTextColor(w)
def setWidgetTextColor(self,w):
if isinstance(w,Box):
return
if isinstance(w,Text):
if not w.bgcolor:
w.color = self.fgcolor
return
for c in w.children:
self.setWidgetTextColor(c)
def selected(self):
super().selected()
if self.fgcolor == self.selected_fgcolor:
return
for c in self.children:
self.setWidgetTextColor(c)
def unselected(self):
super().unselected()
if self.fgcolor == self.normal_fgcolor:
return
for c in self.children:
self.setWidgetTextColor(c)
class Box(WidgetCSS, WidgetReady, BoxLayout):
def __init__(self, **kw):
super(Box, self).__init__(**kw)
class HBox(Box):
def __init__(self,**kw):
@ -239,11 +210,9 @@ class Title6(Text):
kw.update({'texttype':'title6','bold':True})
Text.__init__(self, **kw)
class Modal(BGColorBehavior, ModalView):
def __init__(self, auto_open=False, color_level=-1, radius=[], **kw):
class Modal(ModalView):
def __init__(self, auto_open=False, **kw):
ModalView.__init__(self, **kw)
BGColorBehavior.__init__(self, color_level=color_level,
radius=radius)
self.auto_open = auto_open
def add_widget(self,w, *args, **kw):

View File

@ -51,6 +51,7 @@ def wrap_ready(klass):
Factory.unregister(klass)
globals()[klass] = w
except:
print_exc()
w = globals().get(klass)
if w is None:
return None
@ -222,6 +223,7 @@ class Blocks(EventDispatcher):
# print('Blocks.py :resp=',resp)
return resp
except Exception as e:
print_exc()
if errback:
return errback(None,e)
return None
@ -598,9 +600,10 @@ class Blocks(EventDispatcher):
widget = self.w_build(desc)
self.dispatch('on_built',widget)
if hasattr(widget,'ready'):
widget.ready()
widget.ready = True
return widget
except Exception as e:
print_exc()
self.dispatch('on_failed',e)
return None
@ -643,7 +646,6 @@ class Blocks(EventDispatcher):
@classmethod
def getWidgetById(self,id,from_widget=None):
print('getWidgetById(%s,%s) ...' % (id, from_widget))
def find_widget_by_id(id, from_widget):
if id=='self':
return from_widget
@ -694,7 +696,6 @@ class Blocks(EventDispatcher):
if from_widget is None:
from_widget = app.root
for id in ids:
print('finding', id)
w = find_widget_by_id(id,from_widget=from_widget)
if w is None \
and id == ids[0] \

View File

@ -109,6 +109,7 @@ class BlocksApp(App):
hc = HttpClient()
d = hc.get(self.realurl(config.css.css_url))
self.buildCsses(d)
Logger.info('blocksapp: csses=%s', self.csses)
def buildCsses(self, dic):
for k,v in dic.items():

View File

@ -1,5 +1,6 @@
from kivy.event import EventDispatcher
from kivy.app import App
from .threadcall import HttpClient
from .utils import absurl
from appPublic.registerfunction import RegisterFunction
@ -125,7 +126,8 @@ class DataLoader(EventDispatcher):
class HttpDataLoader(DataLoader):
def load(self, *args, **kw):
url = absurl(self.data_user.url,self.data_user.target.parenturl)
app = App.get_running_app()
url = app.realurl(self.data_user.url)
method = self.data_user.method
params = self.data_user.params.copy()
params.update({

View File

@ -6,7 +6,7 @@ from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label
from kivy.uix.button import ButtonBehavior
from kivy.clock import Clock
from kivy.properties import BooleanProperty
from kivy.properties import BooleanProperty, StringProperty
from kivy.properties import ListProperty
from kivy.graphics import Color, Rectangle
from kivy.app import App
@ -112,8 +112,8 @@ class Cell(BoxLayout):
def cell_press(self,obj):
self.row.selected()
class Row(GridLayout):
def __init__(self,part, rowdesc,header=False,data=None):
class Row(WidgetCSS, GridLayout):
def __init__(self,part, rowdesc,header=False,data=None, **kw):
"""
rowdesc=[
{
@ -130,8 +130,12 @@ class Row(GridLayout):
self.row_id = None
self.linewidth = 1
self.rowdesc = rowdesc
super().__init__(cols=len(self.rowdesc),spacing=self.linewidth)
self.spacing = 2
opts = kw.copy()
opts.update({
"cols":len(self.rowdesc),
"spacing":2
})
super(Row, self).__init__(**opts)
# Clock.schedule_once(self.init,0)
self.init(0)
@ -159,10 +163,10 @@ class Row(GridLayout):
self.part.datagrid.select_row = self
self.part.datagrid.dispatch('on_selected',self)
class Header(ScrollWidget, WidgetReady, WidgetCSS):
def __init__(self,part,color_level=-1,**kw):
self.part = part
class Header(WidgetReady, ScrollWidget):
def __init__(self,part,**kw):
super(Header, self).__init__(**kw)
self.part = part
self.init(1)
self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop)
if self.part.freeze_flag:
@ -173,11 +177,11 @@ class Header(ScrollWidget, WidgetReady, WidgetCSS):
[ f.update({'value':self.part.fields[i].get('label', \
self.part.fields[i].get('name'))}) \
for i,f in enumerate(rd) ]
self.header = Row(self.part,rd,header=True)
self.header = Row(self.part,rd,header=True, csscls=self.part.datagrid.header_css)
self.add_widget(self.header)
self.height = self.header.height
class Body(ScrollWidget, WidgetReady, WidgetCSS):
class Body(WidgetReady, ScrollWidget):
def __init__(self,part,**kw):
self.part = part
super(Body, self).__init__(**kw)
@ -189,7 +193,7 @@ class Body(ScrollWidget, WidgetReady, WidgetCSS):
def addRow(self,id, data,index=0):
rd = [ f.copy() for f in self.part.rowdesc ]
[ f.update({'value':data.get(f['name'])}) for f in rd ]
row = Row(self.part,rd,data=data)
row = Row(self.part,rd,data=data, csscls=self.part.datagrid.body_css)
row.row_id = id
self.add_widget(row,index=index)
self.idRow[id] = row
@ -220,7 +224,6 @@ class DataGridPart(WidgetReady, BoxLayout):
self.fields_width = None
BoxLayout.__init__(self, orientation='vertical')
WidgetReady.__init__(self)
# Clock.schedule_once(self.init,0.1)
self.init(0)
def setWidth(self):
@ -250,7 +253,6 @@ class DataGridPart(WidgetReady, BoxLayout):
kw['size_hint'] = (None,None)
else:
kw['size_hint'] = (1,None)
kw['height'] = self.datagrid.rowHeight()
if not self.datagrid.noheader:
@ -269,7 +271,7 @@ class DataGridPart(WidgetReady, BoxLayout):
return self.body.addRow(id, data)
class DataGrid(WidgetReady, BGColorBehavior, BoxLayout):
class DataGrid(WidgetReady, BoxLayout):
"""
DataGrid data format:
{
@ -303,28 +305,19 @@ class DataGrid(WidgetReady, BGColorBehavior, BoxLayout):
]
}
"""
header_css = StringProperty(None)
body_css = StringProperty(None)
noheader = BooleanProperty(False)
row_selected = BooleanProperty(False)
def __init__(self,color_level=-1,radius=[],**options):
kw = DictObject()
kw = setSizeOptions(options, kw)
kw.orientation = 'vertical'
self.color_level = color_level
self.radius = radius
self.select_rowid = None
def __init__(self,**options):
options['orientation'] = 'vertical'
BoxLayout.__init__(self)
WidgetReady.__init__(self)
BoxLayout.__init__(self,**kw)
BGColorBehavior.__init__(self,color_level=color_level,
radius=radius)
self.parenturl = options.get('parenturl',None)
self.select_rowid = None
self.options = options
self.noheader = options.get('noheader',False)
self.header_bgcolor = options.get('header_bgcolor',[0.29,0.29,0.29,1])
self.body_bgcolor = options.get('body_bgcolor',[0.25,0.25,0.25,1])
self.color = options.get('color',[0.91,0.91,0.91,1])
self.row_height = None
self.on_sizeTask = None
self.selected_rowid = None
self.dataUrl = self.options.get('dataurl')
self.show_rows = 0
self.toolbar = None
self.freeze_part = None

View File

@ -7,6 +7,7 @@ from kivy.uix.label import Label
from kivy.uix.image import AsyncImage
from .baseWidget import ScrollWidget, getDataHandler, VBox
from .utils import CSize
import re
@ -220,9 +221,8 @@ class MarkdownBody(VBox):
Logger.info('resize:parent is null')
def build_source(self,source_desc):
color_level = self.color_level+1
w = MarkdownBody(md_obj=self.md_obj,
color_level=color_level,size_hint_y=None)
csscls=md_obj.second_css, size_hint_y=None)
w.show_mdtext(source_desc)
self.add_widget(w)
w.resize()
@ -386,17 +386,19 @@ description file format
"widgettype":"Markdown",
"options":{
"source": the markdown file
"first_css":,
"second_css":
other options
}
}
"""
source = StringProperty(None)
def __init__(self, color_level=0, **kw):
self.color_level = color_level
ScrollView.__init__(self, **kw)
first_css = StringProperty("default")
second_css = StringProperty("default")
def __init__(self, **kw):
ScrollView.__init__(self)
self.root_body = MarkdownBody(md_obj=self,
color_level=color_level,
csscls=self.first_css,
size_hint_y=None
)
self.root_body.bind(minimum_height=self.root_body.setter('height'))

View File

@ -6,7 +6,7 @@ from kivy.clock import Clock
from kivyblocks.swipebehavior import SwipeBehavior
from kivyblocks.ready import WidgetReady
class OrientationLayout(WidgetReady, SwipeBehavior, FloatLayout):
class OrientationLayout(FloatLayout, WidgetReady, SwipeBehavior):
"""
TwinStyleLayout layout two widget verical when parital orientation
and second widget hide when it is in landscape
@ -17,9 +17,7 @@ class OrientationLayout(WidgetReady, SwipeBehavior, FloatLayout):
self.widget_main = None
self.widget_second = None
self.second_flg = False
FloatLayout.__init__(self, **kw)
SwipeBehavior.__init__(self)
WidgetReady.__init__(self)
super(OrientationLayout, self).__init__(**kw)
self.build_children()
self.bind(on_swipe_left=self.toggle_second)
self.bind(on_swipe_right=self.toggle_second)

View File

@ -1,4 +1,5 @@
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.utils import platform
from kivy.app import App
from kivy.properties import BooleanProperty
@ -11,24 +12,18 @@ desktopOSs=[
class WidgetReady(object):
fullscreen = BooleanProperty(False)
ready = BooleanProperty(False)
_fullscreen = False
def __init__(self, **kw):
self.register_event_type('on_ready')
self._fullscreen_state = False
self._ready = False
def on_ready(self):
def on_ready(self, *args):
pass
def ready(self):
if self._ready:
return
self.dispatch('on_ready')
self._ready = True
def set_ready(self, *args):
self.ready = True
def reready(self):
self._ready = False
self.ready()
self.ready = False
Clock.schedule_once(self.set_ready, 0.1)
def use_keyboard(self):
self.my_kb = Window.request_keyboard(None, self)

View File

@ -1,35 +1,47 @@
from functools import partial
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.factory import Factory
from kivy.properties import ObjectProperty, StringProperty, BooleanProperty
from kivyblocks.ready import WidgetReady
from kivyblocks.bgcolorbehavior import BGColorBehavior
from kivyblocks.utils import CSize
from kivyblocks.baseWidget import Box
from kivyblocks.widget_css import WidgetCSS
class PressableBox(TouchRippleButtonBehavior, Box):
normal_css = StringProperty("default")
actived_css = StringProperty("default")
box_actived = BooleanProperty(False)
def __init__(self,border_width=1,
color_level=-1,
user_data=None,
radius=[],
**kw):
Box.__init__(self, padding=[border_width,
super(PressableBox, self).__init__(
padding=[border_width,
border_width,
border_width,
border_width],
color_level=color_level,
radius=radius,
**kw)
TouchRippleButtonBehavior.__init__(self)
self.border_width = border_width
self.user_data = user_data
self.unselected()
self.actived = False
self.csscls = self.normal_css
def on_box_actived(self, o, v):
if self.box_actived:
self.csscls = self.actived_css
else:
self.csscls = self.normal_css
def on_press(self,o=None):
print('on_press fired')
self.selected()
self.box_actived = True
def setValue(self,d):
self.user_data = d
@ -48,7 +60,7 @@ ToggleItems format:
orientation:
}
"""
class ToggleItems(BGColorBehavior, BoxLayout):
class ToggleItems(BoxLayout, WidgetCSS):
def __init__(self,
color_level=1,
radius=[],
@ -56,6 +68,8 @@ class ToggleItems(BGColorBehavior, BoxLayout):
unit_size=3,
items_desc=[],
border_width=1,
normal_css="default",
actived_css="default",
**kw):
self.unit_size_pix = CSize(unit_size)
kw1 = {
@ -72,13 +86,11 @@ class ToggleItems(BGColorBehavior, BoxLayout):
kw1['size_hint_min_y'] = self.unit_size_pix
BoxLayout.__init__(self, **kw1)
BGColorBehavior.__init__(self,
color_level=color_level,
radius=radius)
self.item_widgets = []
kw = {
"border_width":border_width,
"color_level":color_level,
"normal_css":normal_css,
"actived_css":actived_css,
"radius":radius
}
kw.update(kw1)
@ -101,7 +113,7 @@ class ToggleItems(BGColorBehavior, BoxLayout):
b.widgetBuild(desc)
if len(self.item_widgets) > 0:
self.item_widgets[0].selected()
self.item_widgets[0].actived = True
else:
print('items_desc=',items_desc,'error')
self.register_event_type('on_press')
@ -111,19 +123,23 @@ class ToggleItems(BGColorBehavior, BoxLayout):
pass
def select_item(self,o=None):
[i.unselected() for i in self.item_widgets if i != o]
for i in self.item_widgets:
if i!=o:
i.box_actived = False
self.dispatch('on_press',o.getValue())
def getValue(self):
for i in self.item_widgets:
if i.is_selected():
if i.actived:
return i.getValue()
return None
def setValue(self,v):
for i in self.item_widgets:
if i.getValue() == v:
i.selected()
i.actived = True
self.select_item(i)
return
else:
i.actived = False

View File

@ -9,6 +9,7 @@ from kivy.uix.widget import Widget
from kivy.app import App
from kivy.clock import Clock
from kivy.factory import Factory
from kivy.properties import StringProperty
from appPublic.dictObject import DictObject
from appPublic.registerfunction import RegisterFunction
@ -17,14 +18,12 @@ from .widgetExt.scrollwidget import ScrollWidget
from .utils import *
from .ready import WidgetReady
from .color_definitions import getColors
from .bgcolorbehavior import BGColorBehavior
from .baseWidget import Text
from .toggleitems import PressableBox, ToggleItems
from .baseWidget import Text, Box
from .toggleitems import ToggleItems
"""
toolbar options
{
color_level:
radius:
"mode":"icon", "icontext","text"
img_size=1.5,
@ -39,19 +38,21 @@ toolbar options
]
}
"""
class Toolbar(BoxLayout):
def __init__(self, color_level=-1,
class Toolbar(Box):
def __init__(self,
radius=[],
img_size=1.5,
text_size=0.5,
tools=[], **opts):
self.color_level = color_level
tools=[],
normal_css="default",
actived_css="default",
**opts):
self.radius = radius
self.img_size = img_size
self.text_size = text_size
self.tools = tools
self.tool_widgets={}
BoxLayout.__init__(self, **opts)
Box.__init__(self, **opts)
self.register_event_type('on_press')
first = True
subs_desc = []
@ -89,11 +90,12 @@ class Toolbar(BoxLayout):
subs_desc.append(desc)
self.toggle_items = ToggleItems(
color_level=self.color_level,
radius=self.radius,
unit_size=self.img_size + self.text_size,
items_desc=subs_desc,
orientation=opts.get('orientation','horizontal')
normal_css=normal_css,
actived_css=actived_css,
**opts
)
for ti in self.toggle_items.item_widgets:
ti.widget_id = ti.user_data
@ -112,7 +114,6 @@ Toolpage options
img_size:1.5,
text_size:0.7,
tool_at:"left","right","top","bottom",
color_level:0,
radius:
"show_name":"default open tool's name"
tools:[
@ -128,8 +129,10 @@ Toolpage options
]
"""
class ToolPage(BGColorBehavior, BoxLayout):
def __init__(self,color_level=-1,radius=[],
class ToolPage(BoxLayout):
normal_css=StringProperty(None)
actived_css=StringProperty(None)
def __init__(self,radius=[],
toolbar_size=None,
img_size=1.5,
text_size=0.7,
@ -151,13 +154,9 @@ class ToolPage(BGColorBehavior, BoxLayout):
self.content_widgets = {}
self.show_name = show_name
self.color_level=self.opts.color_level or 0
self.sub_radius = self.opts.radius
self.tool_at = tool_at
BoxLayout.__init__(self,orientation=orient)
BGColorBehavior.__init__(self,
color_level=color_level,
radius=[])
self.content = None
self.toolbar = None
self.init()
@ -165,9 +164,6 @@ class ToolPage(BGColorBehavior, BoxLayout):
Clock.schedule_once(self.show_page, 0.5)
def show_page(self, *args):
print('toolbar=',self.toolbar.width,self.toolbar.height, \
'toggleitems=',self.toolbar.toggle_items.width, \
self.toolbar.toggle_items.height)
toggle_items = self.toolbar.toggle_items
for c in toggle_items.item_widgets:
cvalue = c.getValue()
@ -202,7 +198,7 @@ class ToolPage(BGColorBehavior, BoxLayout):
opts['size_hint_x'] = None
opts['width'] = CSize(self.toolbar_size)
opts['orientation'] = 'vertical'
self.toolbar = Toolbar(color_level=self.color_level,
self.toolbar = Toolbar(
radius=self.sub_radius,
img_size=self.img_size,
text_size=self.text_size,

View File

@ -2,15 +2,20 @@ from kivy.uix.popup import Popup
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from ..widget_css import WidgetCSS
class MyPopup(WidgetCSS, Popup):
def __init__(self,content=None, title='', **kw):
super(MyPopup, self).__init__(content=content,
title=title, **kw)
class Messager:
def __init__(self, show_time=0, title=None):
def __init__(self, show_time=0, title=None, **kw):
self.show_time = show_time
self.title = title if title else 'Message'
self.time_task = None
self.w = Popup(content=BoxLayout(orientation='vertical'),
title=self.title,
size_hint=(0.8,0.8))
size_hint=(0.8,0.8), **kw)
self.messager = TextInput(size=self.w.content.size,
multiline=True,readonly=True)
self.w.content.add_widget(self.messager)

View File

@ -1,3 +1,4 @@
from kivy.logger import Logger
from kivy.properties import NumericProperty, ListProperty, StringProperty
from kivy.graphics import Color, Rectangle, RoundedRectangle
from kivy.uix.textinput import TextInput
@ -13,11 +14,17 @@ class WidgetCSS(object):
width_cm = NumericProperty(None)
bgcolor = ListProperty(None)
fgcolor = ListProperty(None)
csscls = StringProperty(None)
csscls = StringProperty("default")
radius = ListProperty(None)
background_rec = None
bg_func = Rectangle
def on_size(self, o, s):
self.set_background_color()
def on_pos(self, o, p):
self.set_background_color()
def on_height_nm(self, o, v):
if not self.height_nm:
return
@ -60,6 +67,24 @@ class WidgetCSS(object):
self.size_hint_x = None
self.width = CSize(self.width_cm)
def set_child_fgcolor(self, c):
if not hasattr(c,'fgcolor'):
return
if c.fgcolor:
return
if isinstance(c, TextInput):
c.foreground_color = self.fgcolor
return
if isinstance(c, Label):
c.color = self.fgcolor
return
for x in c.children:
self.set_child_fgcolor(x)
def on_children(self, o, c):
for c in self.children:
self.set_child_fgcolor(c)
def on_fgcolor(self, o, c):
if not self.fgcolor:
return
@ -68,6 +93,8 @@ class WidgetCSS(object):
if isinstance(self, Label):
self.color = self.fgcolor
return
for c in self.children:
self.set_child_fgcolor(c)
return
def on_bgcolor(self, o, c):
@ -82,7 +109,7 @@ class WidgetCSS(object):
self.set_background_color()
def on_radius(self, o, r):
if not radius:
if not self.radius:
self.bg_func = Rectangle
return
self.bg_func = RoundedRectangle
@ -90,8 +117,12 @@ class WidgetCSS(object):
def set_background_color(self, *args):
if not self.bgcolor:
Logger.info('WidgetCSS: set_bg_color(), bgcolor is null, (%s)',
self.__class__.__name__)
return
if not self.canvas:
Logger.info('WidgetCSS: set_bg_color(), canvas is null(%s)',
self.__class__.__name__)
return
with self.canvas.before: