This commit is contained in:
yumoqing 2020-03-08 17:39:01 +08:00
parent 8657c9764f
commit bf6b9144ad
8 changed files with 230 additions and 101 deletions

View File

@ -1,9 +1,9 @@
import os import os
from kivy import logger from kivy.logger import logging
__version_info__ = (0.5.0) __version_info__ = "0.5.0"
__version__ = '0.5.0' __version__ = '0.5.0'
path = os.path.dirname(__file__) path = os.path.dirname(__file__)
fonts_path = os.path.join(path,"ttf/") fonts_path = os.path.join(path,"ttf/")
images_path = os.path.join(path,'imgs/') images_path = os.path.join(path,'imgs/')
logger.info("kivyblocks:kivblocks version:{}".format(__version__) logging.info("kivyblocks:kivblocks version:{}".format(__version__))

View File

@ -55,7 +55,6 @@ from .widgetExt.inputext import FloatInput,IntegerInput, \
StrInput,SelectInput, BoolInput, AmountInput StrInput,SelectInput, BoolInput, AmountInput
from .widgetExt.messager import Messager from .widgetExt.messager import Messager
from .charts.bar import Bar from .charts.bar import Bar
from .tree import Tree, TextTree
if platform == 'android': if platform == 'android':
from .widgetExt.phonebutton import PhoneButton from .widgetExt.phonebutton import PhoneButton

View File

@ -30,6 +30,7 @@ from .serverImageViewer import ServerImageViewer
from .vplayer import VPlayer from .vplayer import VPlayer
from .form import InputBox, Form, StrSearchForm from .form import InputBox, Form, StrSearchForm
from .boxViewer import BoxViewer from .boxViewer import BoxViewer
from .tree import Tree, TextTree
def showError(e): def showError(e):
print('error',e) print('error',e)

View File

@ -1,3 +1,5 @@
from kivy.logger import logging
colors = { colors = {
'Red': { 'Red': {
'200': 'ef9a9a', '200': 'ef9a9a',
@ -341,45 +343,6 @@ light_colors = {
'Light': ['White', 'MainBackground', 'DialogBackground'] 'Light': ['White', 'MainBackground', 'DialogBackground']
} }
level_bg_colors = [
'50',
'100',
'200',
'300',
]
level_selected_bg_colors = [
'400',
'500',
'600',
'700'
]
def getColors(style,level):
i = level % len(level_bg_colors)
text_color = text_colors[style][ level_bg_colors[i]]
bg_color = colors[style][ level_bg_colors[i]]
return color
def getSelectedColors(style,level):
i = level % len(level_selected_bg_colors)
text_color = text_colors[style][ level_bg_colors[i]]
bg_color = colors[style][ level_bg_colors[i]]
return text_color, bg_color
error_color_id = '900',
info_color_id = '800'
def getErrorColor(style):
text_color = text_colors[style][ error_color_id ]
bg_color = colors[style][ error_color_id ]
return text_color, bg_color
def getInfoColor(style):
text_color = text_colors[style][ info_color_id ]
bg_color = colors[style][ info_color_id ]
return text_color, bg_color
text_colors = { text_colors = {
'Red': { 'Red': {
'50': '000000', '50': '000000',
@ -674,3 +637,43 @@ text_colors = {
'900': 'ffffff', '900': 'ffffff',
}, },
} }
level_bg_colors = [
'900',
'800',
'700',
'600',
]
level_selected_bg_colors = [
'500',
'400',
'300',
'200'
]
def getColors(style,level=0):
i = level % len(level_bg_colors)
logging.info('TEST : style=%s,level=%d', style, level)
text_color = text_colors[style][ level_bg_colors[i]]
bg_color = colors[style][ level_bg_colors[i]]
return text_color,bg_color
def getSelectedColors(style,level=0):
i = level % len(level_selected_bg_colors)
text_color = text_colors[style][ level_selected_bg_colors[i]]
bg_color = colors[style][ level_selected_bg_colors[i]]
return text_color, bg_color
error_color_id = '100',
info_color_id = '50'
def getErrorColors(style):
text_color = text_colors[style][ error_color_id ]
bg_color = colors[style][ error_color_id ]
return text_color, bg_color
def getInfoColors(style):
text_color = text_colors[style][ info_color_id ]
bg_color = colors[style][ info_color_id ]
return text_color, bg_color

View File

@ -9,7 +9,7 @@ class GPS:
pass pass
def on_status(self,**kw): def on_status(self,**kw):
pass
def __del__(self): def __del__(self):
gps.stop() gps.stop()

View File

@ -0,0 +1,39 @@
from kivy.graphics import Color, Rectangle
from kivy.logger import logging
from kivyblocks.colorcalc import toArrayColor
from appPublic.jsonConfig import getConfig
from .color_definitions import getColors, getSelectedColors
from .color_definitions import getInfoColors, getErrorColors
class StyleBehavior(object):
def __init__(self,level=0):
config = getConfig()
style = config.style
self.style_level = level
self.selected_flag = False
logging.info('Tree : style=%s,level=%d',style, level)
c1, c2 = getColors(style,level)
self.text_color, self.bg_color = toArrayColor(c1),toArrayColor(c2)
c1, c2 = getSelectedColors(style,level)
self.s_text_color,self.s_bg_color = toArrayColor(c1), toArrayColor(c2)
self.bind(size=self.setBGColor,pos=self.setBGColor)
def setBGColor(self,o=None,v=None):
c = self.bg_color
if self.selected_flag:
c = self.s_bg_color
logging.info('selected=%s,color=%s',str(self.selected_flag),str(c))
with self.canvas.before:
Color(*c)
Rectangle(pos=self.pos,size=self.size)
def selected(self):
self.selected_flag = True
self.setBGColor()
def unselected(self):
self.selected_flag = False
self.setBGColor()

View File

@ -1,60 +1,72 @@
from kivy.app import App from kivy.app import App
from kivy.graphics import Color, Triangle from kivy.logger import logging
from kivy.graphics import Color, Rectangle, Triangle
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label from kivy.uix.label import Label
from kivy.uix.widget import Widget from kivy.uix.widget import Widget
from kivy.uix.button import ButtonBehavior from kivy.uix.button import ButtonBehavior
from kivyblocks.widgetExt import ScrollWidget from kivyblocks.widgetExt import ScrollWidget
from kivyblocks.blocksapp import BlocksApp
from kivyblocks.utils import CSize from kivyblocks.utils import CSize
from baseWidget import PressableLabel
from appPublic.dictObject import DictObject from appPublic.dictObject import DictObject
from .baseWidget import PressableLabel
from .stylebehavior import StyleBehavior
class NodeTrigger(ButtonBehavior, Widget): class EmptyBox(Label):
def __init__(self, open_status=False,color=[1,0,0,1]): def __init__(self,size_cnt=1):
siz = CSize(1) self.size_cnt = size_cnt
super().__init__(size_hint=(None,None),size=[siz,siz]) #CSize(1)) siz=CSize(self.size_cnt)
super().__init__(text=' ',font_size=siz,
text_size=(siz,siz),
halign='center',
size_hint=[None,None],size=[siz,siz])
def onSize(self,o=None,v=None):
return
class NodeTrigger(ButtonBehavior, EmptyBox):
def __init__(self, size_cnt=1,open_status=False,color=[1,0,0,1]):
super().__init__(size_cnt=size_cnt)
self.open_status = open_status self.open_status = open_status
self.line_color = color self.line_color = color
self.register_event_type('on_change') self.countPoints()
self.open_points = [0,self.height, self.width,self.height,self.width/2,0]
self.close_points = [0,self.height, 0,0, self.width,self.height/2]
self.showOpenStatus() self.showOpenStatus()
self.bind(size=self.on_size) self.bind(size=self.onSize,pos=self.onSize)
def on_change(self,status): def countPoints(self):
print('new_status=',status) self.open_points = [0,self.height,
self.width,self.height,
self.width/2,0]
self.close_points = [0,self.height,
0,0, self.width,
self.height/2]
def pointsShift(self,points):
x = [ p + self.pos[0] if i % 2 == 0 else p + self.pos[1] \
for i,p in enumerate(points) ]
return x
def on_size(self,o,v): def onSize(self,o=None,v=None):
self.open_points = [0,self.height, self.width,self.height,self.width/2,0] self.countPoints()
self.close_points = [0,self.height, 0,0, self.width,self.height/2] self.showOpenStatus()
def on_press(self): def on_press(self):
self.open_status = False if self.open_status else True self.open_status = False if self.open_status else True
self.showOpenStatus() self.showOpenStatus()
self.dispatch('on_change',self.open_status)
def showOpenStatus(self): def showOpenStatus(self):
points = self.close_points points = self.close_points
if self.open_status: if self.open_status:
points = self.open_points points = self.open_points
self.canvas.clear() self.canvas.clear()
points = self.pointsShift(points)
with self.canvas: with self.canvas:
Color(*self.line_color) Color(*self.line_color)
Triangle(points=points) Triangle(points=points)
# print('pos=',self.pos,'size=',self.size)
class EmptyBox(Widget):
def __init__(self):
siz=CSize(1)
super().__init__(size_hint=[None,None],size=[siz,siz])
class TreeNode(BoxLayout): class TreeNode(BoxLayout):
def __init__(self,tree:Tree=None, def __init__(self,data,tree=None,
parentNode:TreeNode=None, parentNode=None,
data:dict): ):
""" """
base TreeNode base TreeNode
data:{ data:{
@ -74,16 +86,25 @@ class TreeNode(BoxLayout):
self.hasChildren_nodes = True if not n is None else False self.hasChildren_nodes = True if not n is None else False
self.children_nodes = n self.children_nodes = n
self.children_loaded = False self.children_loaded = False
self.hasChildren = data.get('hasChildren') self.hasChildren_nodes = data.get('children')
if hasChildren_nodes: if self.hasChildren_nodes:
self.trigger = NodeTrigger() self.trigger = NodeTrigger()
self.trigger.bind(on_change=self.toggleChildren) self.trigger.bind(on_press=self.toggleChildren)
self.buildChildrenContainer() self.buildChildrenContainer()
else: else:
self.trigger = EmptyBox() self.trigger = EmptyBox()
self.add_widget(self.node_box)
self.node_box.add_widget(self.trigger) self.node_box.add_widget(self.trigger)
self.buildContent() self.add_widget(self.node_box)
self.addContent()
self.setSize()
def setSize(self):
if self.children_open:
self.height = self.node_box.height + self.node_box1.height
else:
self.height = self.node_box.height
self.width = self.trigger.width + \
max(self.node_box.width,self.node_box1.width)
def buildChildrenContainer(self): def buildChildrenContainer(self):
self.node_box1.add_widget(EmptyBox()) self.node_box1.add_widget(EmptyBox())
@ -105,42 +126,66 @@ class TreeNode(BoxLayout):
self.buildContent() self.buildContent()
self.node_box.add_widget(self.content) self.node_box.add_widget(self.content)
self.node_box.height = self.content.height + CSize(1) self.node_box.height = self.content.height + CSize(1)
self.node_box.width = self.trigger.width + self.content.width self.node_box.width = self.trigger.width + \
self.content.width + CSize(1)
logging.info('Tree : content=(%d,%d),box=(%d,%d)', \
self.content.width,self.content.height,
self.node_box.width,self.node_box.height)
def buildChildren(self): def buildChildren(self):
if self.data.children is None: if self.data.children is None:
logging.info('Tree : is a leaf node')
return return
if self.data.children == []: if self.data.children == []:
self.treeObj.getUrlData(self.addChildren,self.data) self.treeObj.getUrlData(self.addChildren,self.data)
return return
if len(self.subNodes) == 0: if len(self.subNodes) == 0:
logging.info('Tree : add subnodes')
self.addChildren(self.data.children) self.addChildren(self.data.children)
else:
logging.info('Tree : not need add subnodes')
def childrenSizeChange(self,tn,v):
h = 0
w = 0
for n in self.subNodes:
h += n.height
w = max(w,n.width)
self.children_box.height = h
self.children_box.width = w
self.node_box1.height = self.children_box.height
self.node_box1.width = self.trigger.width + self.children_box.width
self.setSize()
def addChildren(self,children): def addChildren(self,children):
self.data.children = children self.data.children = children
self.children_box.height = 0
self.children_box.width = 0
for c in children: for c in children:
options = {}
options['tree'] = self.treeObj options['tree'] = self.treeObj
options['parentNode'] = self options['parentNode'] = self
options['data'] = c options['data'] = c
tn = self.teeeObj.NodeKlass(**options) tn = self.treeObj.NodeKlass(**options)
tn.bind(size=self.childrenSizeChange)
self.subNodes.append(tn) self.subNodes.append(tn)
self.children_box.add_widget(tn) self.children_box.add_widget(tn)
self.children_box.height += tn.height
self.children_box.width = max(self.children_box.width,tn.width)
self.node_box1.height = self.children_box.height
self.node_box1.width = self.trigger.width + self.children_box.width
def toggleChildren(self,o,v): def toggleChildren(self,o):
if v: self.treeObj.unselected()
self.children_open = True if not self.children_open else False
if self.children_open:
self.buildChildren() self.buildChildren()
self.add_widget(self.node_box1) self.add_widget(self.node_box1)
self.children_open = True
self.height = self.node_box.height + self.node_box1.height
else: else:
self.remove_widget(self.node_box1) self.remove_widget(self.node_box1)
self.height = self.node_box.height self.setSize()
self.children_open = False
def on_size(self,o,v):
print('************treenode on_size', o, v)
self.node_box1.height = self.children_box.height
""" """
tree options tree options
@ -156,16 +201,31 @@ tree options
"data" # array of {children:{},...} "data" # array of {children:{},...}
} }
""" """
class Tree(ScrollWidget): class Tree(StyleBehavior,ScrollWidget):
def __init__(self,**options): def __init__(self,**options):
super().__init__() #orientation="vertical") ScrollWidget.__init__(self)
level = options.get('level',0)
StyleBehavior.__init__(self,level=level)
self.options = DictObject(**options) self.options = DictObject(**options)
self.nodes = [] self.nodes = []
self.initflag = False self.initflag = False
self.selected_node = None
self.bind(size=self.onSize,pos=self.onSize) self.bind(size=self.onSize,pos=self.onSize)
def select_row(self, node):
self.unselect_row()
self.selected_node = node
node.selected()
def unselect_row(self):
if self.selected_node:
logging.info('selected node unselected')
self.selected_node.unselected()
self.selected_node = None
def onSize(self,o,v=None): def onSize(self,o,v=None):
if not self.initflag: if not self.initflag:
self.initflag = True
self.buildTree(self) self.buildTree(self)
for n in self.nodes: for n in self.nodes:
n.setMinWidth(self.width) n.setMinWidth(self.width)
@ -190,8 +250,10 @@ class Tree(ScrollWidget):
if self.options.url: if self.options.url:
return self.getUrlData(self.dataLoaded,kv) return self.getUrlData(self.dataLoaded,kv)
data = self.options.data data = self.options.data
logging.info("Tree : buildTree,data=%s",data)
self.dataLoaded(data) self.dataLoaded(data)
def dataLoaded(self,d): def dataLoaded(self,d):
self.data = d self.data = d
self.addNodes() self.addNodes()
@ -201,39 +263,57 @@ class Tree(ScrollWidget):
options = {} options = {}
options['tree'] = self options['tree'] = self
options['parentNode'] = None options['parentNode'] = None
options['data'] = DictObject(c) options['data'] = DictObject(**c)
self.nodes.append(self.NodeKlass(**options)) w = self.NodeKlass(**options)
for w in self.nodes: self.nodes.append(w)
self.add_widget(w) self.add_widget(w)
logging.info('Tree : node=%s',type(w))
class TextContent(StyleBehavior, PressableLabel):
def __init__(self,level=0,**options):
PressableLabel.__init__(self,**options)
StyleBehavior.__init__(self,level=level)
class TextTreeNode(TreeNode): class TextTreeNode(TreeNode):
def buildContent(self): def buildContent(self):
txt = self.data.get(self.treeObj.options.textField, txt = self.data.get(self.treeObj.options.textField,
self.data.get(self.treeObj.options.idField,'defaulttext')) self.data.get(self.treeObj.options.idField,'defaulttext'))
self.content = PressableLabel(text=txt, self.content = TextContent(level=self.treeObj.style_level,
text=txt,
size_hint=(None,None), size_hint=(None,None),
font_size=CSize(1), font_size=CSize(1),
text_size=CSize(len(txt),1), text_size=CSize(len(txt)-1,1),
halign='left', halign='left',
height=CSize(2),width=CSize(len(txt))) height=CSize(2),
width=CSize(len(txt)))
self.content.text_color = [0,0,0,1] #self.treeObj.text_color
self.content.bind(on_press=self.onPress) self.content.bind(on_press=self.onPress)
return return
def onPress(self,o,v=None): def onPress(self,o,v=None):
if self.hasChildren_nodes:
v = True if not self.children_open else False
self.toggleChildren(self)
self.trigger.on_press()
return
logging.info('select the leaf node')
self.treeObj.select_row(self) self.treeObj.select_row(self)
def selected(self): def selected(self):
pass logging.info('content selected ........')
self.content.selected()
def unselected(self): def unselected(self):
pass logging.info('content unselected ........')
self.content.unselected()
class TextTree(Tree): class TextTree(Tree):
def __init__(self,**options): def __init__(self,**options):
self.NodeKlass = TextTReeNode self.NodeKlass = TextTreeNode
super().__init__(**options) super().__init__(**options)
self.register_event_type('on_press') self.register_event_type('on_press')
def onPress(self,o,v=None): def onPress(self,o,v=None):
if self.selectNode: if self.selectNode:
self.selectNode.unselected() self.selectNode.unselected()

View File

@ -16,7 +16,14 @@ email = "yumoqing@icloud.com"
packages=find_packages() packages=find_packages()
package_data = { package_data = {
"kivyblocks":['imgs/*.png', 'imgs/*.gif','imgs/*.jpg','ttf/*.ttf', 'ui/*.uidesc' ], "kivyblocks":[
'imgs/*.png',
'imgs/*.atlas',
'imgs/*.gif',
'imgs/*.jpg',
'ttf/*.ttf',
'ui/*.uidesc'
],
} }
setup( setup(