mirror of https://github.com/kivy/kivy.git
Merge branch 'master' of github.com:tito/kivy
Conflicts: kivy/data/style.uxl kivy/factory_registers.py
This commit is contained in:
commit
de6b81d9e3
|
@ -1,13 +1,22 @@
|
||||||
from kivy.app import App
|
from kivy.app import App
|
||||||
|
from kivy.clock import Clock
|
||||||
from kivy.uix.widget import Widget
|
from kivy.uix.widget import Widget
|
||||||
from kivy.uix.button import Button
|
from kivy.uix.button import Button
|
||||||
from kivy.uix.label import Label
|
from kivy.uix.label import Label
|
||||||
from kivy.core.text import Label as CoreLabel
|
from kivy.core.text import Label as CoreLabel
|
||||||
from kivy.graphics import *
|
from kivy.graphics import *
|
||||||
|
|
||||||
|
from random import random
|
||||||
|
|
||||||
class TestApp(App):
|
class TestApp(App):
|
||||||
def build(self):
|
def build(self):
|
||||||
return Button(text='Hello world')
|
def print_fps(dt):
|
||||||
|
print 'FPS: ', Clock.get_fps()
|
||||||
|
Clock.schedule_interval(print_fps, 1)
|
||||||
|
a = Widget()
|
||||||
|
for x in xrange(100):
|
||||||
|
pos = random() * 500, random() * 500
|
||||||
|
a.add_widget(Button(text=str(x), pos=pos))
|
||||||
|
return a
|
||||||
|
|
||||||
TestApp().run()
|
TestApp().run()
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
Widget:
|
Widget:
|
||||||
Button:
|
Button:
|
||||||
label: "Hello World"
|
text: "Hello World"
|
||||||
|
|
||||||
Button:
|
Button:
|
||||||
label: "I'm another label"
|
text: "I'm another label"
|
||||||
pos: (200, 200)
|
pos: (200, 200)
|
||||||
|
|
|
@ -260,7 +260,6 @@ class LabelBase(object):
|
||||||
# update texture
|
# update texture
|
||||||
self.texture.blit_data(data)
|
self.texture.blit_data(data)
|
||||||
|
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
'''Force re-rendering of the text'''
|
'''Force re-rendering of the text'''
|
||||||
# first pass, calculating width/height
|
# first pass, calculating width/height
|
||||||
|
@ -284,7 +283,6 @@ class LabelBase(object):
|
||||||
self._text = str(text)
|
self._text = str(text)
|
||||||
except:
|
except:
|
||||||
self._text = text
|
self._text = text
|
||||||
self.refresh()
|
|
||||||
text = property(_get_text, _set_text, doc='Get/Set the text')
|
text = property(_get_text, _set_text, doc='Get/Set the text')
|
||||||
label = property(_get_text, _set_text, doc='Get/Set the text')
|
label = property(_get_text, _set_text, doc='Get/Set the text')
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
<Button>:
|
<Button>:
|
||||||
canvas:
|
canvas:
|
||||||
Color:
|
Color:
|
||||||
rgb: (1, 0, 0)
|
rgb: dict(normal=(0, 1, 1), down=(1, 0, 0))[root.state]
|
||||||
Rectangle:
|
Rectangle:
|
||||||
pos: self.pos
|
pos: self.pos
|
||||||
size: self.size
|
size: self.size
|
||||||
Label:
|
Label:
|
||||||
|
font_size: 30
|
||||||
canvas:
|
canvas:
|
||||||
Rectangle:
|
Color:
|
||||||
|
rgb: (1, 1, 1)
|
||||||
|
BorderRectangle:
|
||||||
texture: self.texture
|
texture: self.texture
|
||||||
|
size: self.texture_size
|
||||||
|
pos: root.center[0] - self.texture_size[0] / 2., root.center[1] - self.texture_size[1] / 2.
|
||||||
|
|
||||||
<Slider>:
|
<Slider>:
|
||||||
canvas:
|
canvas:
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Auto-generated file by setup.py build_factory
|
||||||
|
|
||||||
|
from kivy.factory import Factory
|
||||||
|
|
||||||
|
Factory.register('Gesture', module='kivy.gesture')
|
||||||
|
Factory.register('GestureDatabase', module='kivy.gesture')
|
||||||
|
Factory.register('GesturePoint', module='kivy.gesture')
|
||||||
|
Factory.register('GestureStroke', module='kivy.gesture')
|
||||||
|
Factory.register('Cache', module='kivy.cache')
|
||||||
|
Factory.register('Vector', module='kivy.vector')
|
||||||
|
Factory.register('LoggerHistory', module='kivy.logger')
|
||||||
|
Factory.register('ExceptionHandler', module='kivy.exceptions')
|
||||||
|
Factory.register('Texture', module='kivy.texture')
|
||||||
|
Factory.register('TextureRegion', module='kivy.texture')
|
||||||
|
Factory.register('SafeList', module='kivy.utils')
|
||||||
|
Factory.register('OBJ', module='kivy.obj')
|
||||||
|
Factory.register('Material', module='kivy.obj')
|
||||||
|
Factory.register('MaterialGroup', module='kivy.obj')
|
||||||
|
Factory.register('Mesh', module='kivy.obj')
|
||||||
|
Factory.register('MTContext', module='kivy.plugin')
|
||||||
|
Factory.register('MTPlugins', module='kivy.plugin')
|
||||||
|
Factory.register('FactoryException', module='kivy.factory')
|
||||||
|
Factory.register('ProxyImage', module='kivy.loader')
|
||||||
|
Factory.register('EventDispatcher', module='kivy.c_ext.event')
|
||||||
|
Factory.register('Canvas', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('GraphicInstruction', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('ContextInstruction', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PushMatrix', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PopMatrix', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('MatrixInstruction', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Transform', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Rotate', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Scale', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Translate', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('LineWidth', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Color', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('BindTexture', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('VertexDataInstruction', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Triangle', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Rectangle', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('BorderRectangle', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Ellipse', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Path', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PathInstruction', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PathStart', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PathLineTo', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PathClose', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PathEnd', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PathStroke', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('PathFill', module='kivy.c_ext.graphics')
|
||||||
|
Factory.register('Slider', module='kivy.uix.slider')
|
||||||
|
Factory.register('Button', module='kivy.uix.button')
|
||||||
|
Factory.register('Label', module='kivy.uix.label')
|
||||||
|
Factory.register('Widget', module='kivy.uix.widget')
|
||||||
|
Factory.register('TouchShape', module='kivy.input.shape')
|
||||||
|
Factory.register('TouchShapeRect', module='kivy.input.shape')
|
||||||
|
Factory.register('TouchProvider', module='kivy.input.provider')
|
||||||
|
Factory.register('TouchFactory', module='kivy.input.factory')
|
|
@ -4,6 +4,7 @@ Label:
|
||||||
|
|
||||||
__all__ = ('Label', )
|
__all__ = ('Label', )
|
||||||
|
|
||||||
|
from kivy.utils import curry
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.uix.widget import Widget
|
from kivy.uix.widget import Widget
|
||||||
from kivy.core.text import Label as CoreLabel
|
from kivy.core.text import Label as CoreLabel
|
||||||
|
@ -49,34 +50,42 @@ class Label(Widget):
|
||||||
#: Texture of the label
|
#: Texture of the label
|
||||||
texture = ObjectProperty(None, allownone=True)
|
texture = ObjectProperty(None, allownone=True)
|
||||||
|
|
||||||
|
#: Texture size of the label
|
||||||
|
texture_size = ListProperty([0, 0])
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(Label, self).__init__(**kwargs)
|
super(Label, self).__init__(**kwargs)
|
||||||
|
|
||||||
# bind all the property for recreating the texture
|
# bind all the property for recreating the texture
|
||||||
d = ('text', 'font_size', 'font_name', 'bold', 'italic', 'halign',
|
d = ('text', 'font_size', 'font_name', 'bold', 'italic', 'halign',
|
||||||
'valign', 'padding_x', 'padding_y')
|
'valign', 'padding_x', 'padding_y')
|
||||||
dkw = dict(zip(d, [self._trigger_texture_update] * len(d)))
|
dkw = {}
|
||||||
|
for x in d:
|
||||||
|
dkw[x] = curry(self._trigger_texture_update, x)
|
||||||
self.bind(**dkw)
|
self.bind(**dkw)
|
||||||
|
|
||||||
dkw = dict(zip(d, [getattr(self, x) for x in d]))
|
dkw = dict(zip(d, [getattr(self, x) for x in d]))
|
||||||
print dkw
|
|
||||||
self._label = CoreLabel(**dkw)
|
self._label = CoreLabel(**dkw)
|
||||||
|
|
||||||
# force the texture creation
|
# force the texture creation
|
||||||
self._trigger_texture_update()
|
self._texture_update()
|
||||||
|
'''
|
||||||
import pprint
|
|
||||||
def printm(sender, value):
|
def printm(sender, value):
|
||||||
print sender, value
|
print self.text, sender, value
|
||||||
self.bind(texture=printm)
|
self.bind(texture=printm)
|
||||||
|
'''
|
||||||
|
|
||||||
def _trigger_texture_update(self, source=None, value=None):
|
def _trigger_texture_update(self, name=None, source=None, value=None):
|
||||||
print '_trigger_texture_update()', source, value
|
|
||||||
if source:
|
if source:
|
||||||
self._label.options[source.name] = value
|
if name == 'text':
|
||||||
|
self._label.text = value
|
||||||
|
else:
|
||||||
|
self._label.options[name] = value
|
||||||
Clock.unschedule(self._texture_update)
|
Clock.unschedule(self._texture_update)
|
||||||
Clock.schedule_once(self._texture_update)
|
Clock.schedule_once(self._texture_update)
|
||||||
|
|
||||||
def _texture_update(self, *largs):
|
def _texture_update(self, *largs):
|
||||||
self._label.refresh()
|
self._label.refresh()
|
||||||
|
self.texture = None
|
||||||
self.texture = self._label.texture
|
self.texture = self._label.texture
|
||||||
|
self.texture_size = list(self.texture.size)
|
||||||
|
|
|
@ -12,7 +12,6 @@ __all__ = ('intersection', 'difference', 'curry', 'strtotuple',
|
||||||
import inspect
|
import inspect
|
||||||
import re
|
import re
|
||||||
import functools
|
import functools
|
||||||
from kivy.logger import Logger
|
|
||||||
|
|
||||||
def boundary(value, minvalue, maxvalue):
|
def boundary(value, minvalue, maxvalue):
|
||||||
'''Limit a value between a minvalue and maxvalue'''
|
'''Limit a value between a minvalue and maxvalue'''
|
||||||
|
@ -140,6 +139,7 @@ def deprecated(func):
|
||||||
func.func_code.co_filename,
|
func.func_code.co_filename,
|
||||||
func.func_code.co_firstlineno + 1,
|
func.func_code.co_firstlineno + 1,
|
||||||
file, line, caller)
|
file, line, caller)
|
||||||
|
from kivy.logger import Logger
|
||||||
Logger.warn(warning)
|
Logger.warn(warning)
|
||||||
if func.__doc__:
|
if func.__doc__:
|
||||||
Logger.warn(func.__doc__)
|
Logger.warn(func.__doc__)
|
||||||
|
|
98
kivy/uxl.py
98
kivy/uxl.py
|
@ -25,6 +25,8 @@ Example of Uxl files ::
|
||||||
|
|
||||||
__all__ = ('Uxl', 'UxlParser')
|
__all__ = ('Uxl', 'UxlParser')
|
||||||
|
|
||||||
|
import re
|
||||||
|
from copy import copy
|
||||||
from kivy.factory import Factory
|
from kivy.factory import Factory
|
||||||
from kivy.logger import Logger
|
from kivy.logger import Logger
|
||||||
|
|
||||||
|
@ -221,9 +223,49 @@ class UxlParser(object):
|
||||||
with open(filename, 'r') as fd:
|
with open(filename, 'r') as fd:
|
||||||
return fd.read()
|
return fd.read()
|
||||||
|
|
||||||
def create_handler(element, key):
|
def create_handler(element, key, value, idmap):
|
||||||
def call_fn(sender, value):
|
|
||||||
setattr(element, key, value)
|
# detect key.value inside value
|
||||||
|
kw = re.findall('([a-zA-Z0-9_.]+\.[a-zA-Z0-9_.]+)', value)
|
||||||
|
if not kw:
|
||||||
|
# look like no reference, just pass it
|
||||||
|
return eval(value)
|
||||||
|
|
||||||
|
# create an handler
|
||||||
|
idmap = copy(idmap)
|
||||||
|
def call_fn(sender, _value):
|
||||||
|
trace('Uxl: call_fn %s, key=%s, value=%s' % (element, key, value))
|
||||||
|
trace('Uxl: call_fn => value=%s' % str(eval(value, {}, idmap)))
|
||||||
|
setattr(element, key, eval(value, {}, idmap))
|
||||||
|
|
||||||
|
# bind every key.value
|
||||||
|
for x in kw:
|
||||||
|
k = x.split('.')
|
||||||
|
if len(k) != 2:
|
||||||
|
continue
|
||||||
|
f = idmap[k[0]]
|
||||||
|
f.bind(**{k[1]: call_fn})
|
||||||
|
|
||||||
|
return eval(value, {}, idmap)
|
||||||
|
|
||||||
|
# is the value is a string, numeric, tuple, list ?
|
||||||
|
if value[0] in ['(', '[', '"', '\'', '-'] + range(9):
|
||||||
|
value = eval(value, {}, self.idmap)
|
||||||
|
# must be an object.property
|
||||||
|
else:
|
||||||
|
value = value.split('.', 2)
|
||||||
|
if len(value) != 2:
|
||||||
|
raise UxlError(ctx, ln, 'Reference format should '
|
||||||
|
'be <id>.<property>')
|
||||||
|
# bind
|
||||||
|
m = self.idmap[value[0]]
|
||||||
|
kw = { value[1]: create_handler(element, key) }
|
||||||
|
m.bind(**kw)
|
||||||
|
trace('Uxl: bind %s.%s to %s.%s' % (
|
||||||
|
m, value[1], element, key))
|
||||||
|
value = getattr(self.idmap[value[0]], value[1])
|
||||||
|
trace('Uxl: set %s=%s for %s' % (key, value, element))
|
||||||
|
|
||||||
return call_fn
|
return call_fn
|
||||||
|
|
||||||
class UxlRule(object):
|
class UxlRule(object):
|
||||||
|
@ -256,6 +298,7 @@ class UxlBase(object):
|
||||||
super(UxlBase, self).__init__()
|
super(UxlBase, self).__init__()
|
||||||
self.rules = []
|
self.rules = []
|
||||||
self.idmap = {}
|
self.idmap = {}
|
||||||
|
self.idmaps = []
|
||||||
|
|
||||||
def add_rule(self, rule, defs):
|
def add_rule(self, rule, defs):
|
||||||
trace('Uxl: add rule %s' % str(rule))
|
trace('Uxl: add rule %s' % str(rule))
|
||||||
|
@ -285,21 +328,32 @@ class UxlBase(object):
|
||||||
def apply(self, widget):
|
def apply(self, widget):
|
||||||
'''Apply all the Uxl rules matching the widget on the widget.
|
'''Apply all the Uxl rules matching the widget on the widget.
|
||||||
'''
|
'''
|
||||||
trace('Uxl: Apply uxl to %s' % widget)
|
|
||||||
matches = self.match(widget)
|
matches = self.match(widget)
|
||||||
trace('Uxl: Found %d matches for %s' % (len(matches), widget))
|
trace('Uxl: Found %d matches for %s' % (len(matches), widget))
|
||||||
if not matches:
|
if not matches:
|
||||||
return
|
return
|
||||||
|
self._push_ids()
|
||||||
|
have_root = 'root' in self.idmap
|
||||||
|
if not have_root:
|
||||||
self.idmap['root'] = widget
|
self.idmap['root'] = widget
|
||||||
for defs in matches:
|
for defs in matches:
|
||||||
self.build_item(widget, defs, is_instance=True)
|
self.build_item(widget, defs, is_instance=True)
|
||||||
|
if not have_root:
|
||||||
del self.idmap['root']
|
del self.idmap['root']
|
||||||
|
self._pop_ids()
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Private
|
# Private
|
||||||
#
|
#
|
||||||
|
|
||||||
|
def _push_ids(self):
|
||||||
|
self.idmaps.append(self.idmap)
|
||||||
|
self.idmap = copy(self.idmap)
|
||||||
|
|
||||||
|
def _pop_ids(self):
|
||||||
|
self.idmap = self.idmaps.pop()
|
||||||
|
|
||||||
def build(self, objects):
|
def build(self, objects):
|
||||||
root = None
|
root = None
|
||||||
for item, params in objects:
|
for item, params in objects:
|
||||||
|
@ -313,6 +367,8 @@ class UxlBase(object):
|
||||||
return root
|
return root
|
||||||
|
|
||||||
def build_item(self, item, params, is_instance=False):
|
def build_item(self, item, params, is_instance=False):
|
||||||
|
self._push_ids()
|
||||||
|
|
||||||
if is_instance is False:
|
if is_instance is False:
|
||||||
trace('Uxl: build item %s' % item)
|
trace('Uxl: build item %s' % item)
|
||||||
if item.startswith('<'):
|
if item.startswith('<'):
|
||||||
|
@ -338,17 +394,13 @@ class UxlBase(object):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
value = eval(value)
|
value = create_handler(widget, key, value, self.idmap)
|
||||||
'''
|
trace('Uxl: set %s=%s for %s' % (key, value, widget))
|
||||||
# XXX FIXME be able to create live property
|
|
||||||
if not hasattr(widget, key):
|
|
||||||
widget.create_property(key, value)
|
|
||||||
else:
|
|
||||||
setattr(widget, key, value)
|
|
||||||
'''
|
|
||||||
setattr(widget, key, value)
|
setattr(widget, key, value)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise UxlError(ctx, ln, str(e))
|
m = UxlError(ctx, ln, str(e))
|
||||||
|
print m
|
||||||
|
raise
|
||||||
|
|
||||||
# second loop, only for canvas
|
# second loop, only for canvas
|
||||||
for key, value in params.iteritems():
|
for key, value in params.iteritems():
|
||||||
|
@ -358,6 +410,7 @@ class UxlBase(object):
|
||||||
with widget.canvas:
|
with widget.canvas:
|
||||||
self.build_canvas(item, value)
|
self.build_canvas(item, value)
|
||||||
|
|
||||||
|
self._pop_ids()
|
||||||
return widget
|
return widget
|
||||||
|
|
||||||
def build_canvas(self, item, elements):
|
def build_canvas(self, item, elements):
|
||||||
|
@ -369,26 +422,13 @@ class UxlBase(object):
|
||||||
continue
|
continue
|
||||||
value, ln, ctx = value
|
value, ln, ctx = value
|
||||||
try:
|
try:
|
||||||
# is the value is a string, numeric, tuple, list ?
|
value = create_handler(element, key, value, self.idmap)
|
||||||
if value[0] in ['(', '[', '"', '\'', '-'] + range(9):
|
|
||||||
print dir(self.idmap['self'])
|
|
||||||
value = eval(value, {}, self.idmap)
|
|
||||||
# must be an object.property
|
|
||||||
else:
|
|
||||||
value = value.split('.')
|
|
||||||
if len(value) != 2:
|
|
||||||
raise UxlError(ctx, ln, 'Reference format should '
|
|
||||||
'be <id>.<property>')
|
|
||||||
# bind
|
|
||||||
m = self.idmap[value[0]]
|
|
||||||
kw = { value[1]: create_handler(element, key) }
|
|
||||||
m.bind(**kw)
|
|
||||||
value = getattr(self.idmap[value[0]], value[1])
|
|
||||||
trace('Uxl: set %s=%s for %s' % (key, value, element))
|
trace('Uxl: set %s=%s for %s' % (key, value, element))
|
||||||
setattr(element, key, value)
|
setattr(element, key, value)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
m = UxlError(ctx, ln, str(e))
|
||||||
|
print m.message
|
||||||
raise
|
raise
|
||||||
raise UxlError(ctx, ln, str(e))
|
|
||||||
|
|
||||||
def build_rule(self, item, params):
|
def build_rule(self, item, params):
|
||||||
trace('Uxl: build rule for %s' % item)
|
trace('Uxl: build rule for %s' % item)
|
||||||
|
|
Loading…
Reference in New Issue