-
-
Save tito/3868300 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/kivy/lang.py b/kivy/lang.py | |
index 10cdd21..5fa43bc 100644 | |
--- a/kivy/lang.py | |
+++ b/kivy/lang.py | |
@@ -613,6 +613,7 @@ class ParserRule(object): | |
''' | |
__slots__ = ('ctx', 'line', 'name', 'children', 'id', 'properties', | |
+ 'nested_properties', | |
'canvas_before', 'canvas_root', 'canvas_after', | |
'handlers', 'level', 'cache_marked') | |
@@ -632,6 +633,8 @@ class ParserRule(object): | |
self.id = None | |
#: Properties associated to the rule | |
self.properties = OrderedDict() | |
+ #: Nested properties | |
+ self.nested_properties = OrderedDict() | |
#: Canvas normal | |
self.canvas_root = None | |
#: Canvas before | |
@@ -651,6 +654,8 @@ class ParserRule(object): | |
def precompile(self): | |
for x in self.properties.itervalues(): | |
x.precompile() | |
+ for x in self.nested_properties.itervalues(): | |
+ x.precompile() | |
for x in self.handlers: | |
x.precompile() | |
for x in self.children: | |
@@ -671,6 +676,12 @@ class ParserRule(object): | |
for name in self.properties: | |
if not hasattr(widget, name): | |
widget.create_property(name) | |
+ for name in self.nested_properties: | |
+ key = name.split('.', 1)[0] | |
+ if not hasattr(widget, key): | |
+ rule = self.nested_properties[name] | |
+ raise ParserException(rule.ctx, rule.line, | |
+ 'No property {0} in {1}'.format(key, widget.__class__)) | |
def _forbid_selectors(self): | |
c = self.name[0] | |
@@ -737,7 +748,7 @@ class Parser(object): | |
CLASS_RANGE = range(ord('A'), ord('Z') + 1) | |
PROP_RANGE = range(ord('A'), ord('Z') + 1) + \ | |
range(ord('a'), ord('z') + 1) + \ | |
- range(ord('0'), ord('9') + 1) + [ord('_')] | |
+ range(ord('0'), ord('9') + 1) + [ord('_'), ord('.')] | |
__slots__ = ('rules', 'templates', 'root', 'sourcecode', | |
'directives', 'filename') | |
@@ -940,7 +951,10 @@ class Parser(object): | |
if name[:3] == 'on_': | |
current_object.handlers.append(rule) | |
else: | |
- current_object.properties[name] = rule | |
+ if '.' in name: | |
+ current_object.nested_properties[name] = rule | |
+ else: | |
+ current_object.properties[name] = rule | |
else: | |
current_property = name | |
current_propobject = None | |
@@ -968,8 +982,12 @@ class Parser(object): | |
if current_property[:3] == 'on_': | |
current_object.handlers.append(current_propobject) | |
else: | |
- current_object.properties[current_property] = \ | |
- current_propobject | |
+ if '.' in name: | |
+ current_object.nested_properties[current_property] = \ | |
+ current_propobject | |
+ else: | |
+ current_object.properties[current_property] = \ | |
+ current_propobject | |
else: | |
current_propobject.value += '\n' + content | |
@@ -1010,7 +1028,14 @@ def create_handler(iself, element, key, value, rule, idmap): | |
e_value = eval(value, idmap) | |
if __debug__: | |
trace('Builder: call_fn => value=%r' % (e_value, )) | |
- setattr(element, key, e_value) | |
+ if type(key) is tuple: | |
+ _key, subkey = key | |
+ subelement = getattr(element, _key) | |
+ if subelement is None: | |
+ return | |
+ setattr(subelement, subkey, e_value) | |
+ else: | |
+ setattr(element, key, e_value) | |
# bind every key.value | |
if rule.watched_keys is not None: | |
@@ -1228,6 +1253,7 @@ class BuilderBase(object): | |
assert(rule not in self.rulectx) | |
self.rulectx[rule] = rctx = { | |
'ids': {'root': widget}, | |
+ 'nset': [], | |
'set': [], 'hdl': []} | |
# extract the context of the rootrule (not rule!) | |
@@ -1311,6 +1337,8 @@ class BuilderBase(object): | |
# append the properties and handlers to our final resolution task | |
if rule.properties: | |
rctx['set'].append((widget, rule.properties.values())) | |
+ if rule.nested_properties: | |
+ rctx['nset'].append((widget, rule.nested_properties.values())) | |
if rule.handlers: | |
rctx['hdl'].append((widget, rule.handlers)) | |
@@ -1331,6 +1359,19 @@ class BuilderBase(object): | |
value, rule, rctx['ids']) | |
setattr(widget_set, key, value) | |
+ # now apply nested handlers | |
+ for widget_set, rules in reversed(rctx['nset']): | |
+ for rule in rules: | |
+ assert(isinstance(rule, ParserRuleProperty)) | |
+ key, subkey = rule.name.split('.', 1) | |
+ value = rule.co_value | |
+ if type(value) is CodeType: | |
+ value = create_handler(widget_set, widget_set, (key, subkey), | |
+ value, rule, rctx['ids']) | |
+ element = getattr(widget_set, key) | |
+ if element is not None: | |
+ setattr(element, subkey, value) | |
+ | |
# build handlers | |
for widget_set, rules in rctx['hdl']: | |
for crule in rules: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from kivy.app import App | |
from kivy.lang import Builder | |
from kivy.clock import Clock | |
''' | |
Facts: | |
1. can't use "self.texture_1.tex_coords", texture_1 have a bind() method, but doesn't correspond to the Property bind(). | |
2. self.tex_coords_1 or (0, 0, 0, 0, 0, 0, 0, 0) is needed because self.tex_coords_1 is None by default | |
3. can't use "self.texture_1.tex_coords" because texture_1 is None at the start | |
''' | |
root = Builder.load_string( | |
''' | |
#:import Image kivy.core.image.Image | |
#:import time time.time | |
Widget: | |
boottime: 0 | |
texture_1: Image('Sky_back_layer.png').texture | |
texture_2: Image('Vegetation_(middle_layer).png').texture | |
texture_3: Image('Ground_(front_layer).png').texture | |
texture_1.wrap: 'repeat' | |
texture_2.wrap: 'repeat' | |
texture_3.wrap: 'repeat' | |
texture_1.uvpos: root.boottime * 0.001, 0 | |
texture_2.uvpos: root.boottime * 0.01, 0 | |
texture_3.uvpos: root.boottime * 0.1, 0 | |
tex_coords_1: (getattr(self.texture_1, 'tex_coords'), root.boottime)[0] | |
tex_coords_2: (getattr(self.texture_2, 'tex_coords'), root.boottime)[0] | |
tex_coords_3: (getattr(self.texture_3, 'tex_coords'), root.boottime)[0] | |
canvas: | |
Rectangle: | |
pos: self.pos | |
size: self.size | |
texture: self.texture_1 | |
tex_coords: self.tex_coords_1 or (0, 0, 0, 0, 0, 0, 0, 0) | |
Rectangle: | |
pos: self.pos | |
size: self.size | |
texture: self.texture_2 | |
tex_coords: self.tex_coords_2 or (0, 0, 0, 0, 0, 0, 0, 0) | |
Rectangle: | |
pos: self.pos | |
size: self.size | |
texture: self.texture_3 | |
tex_coords: self.tex_coords_3 or (0, 0, 0, 0, 0, 0, 0, 0) | |
''') | |
class MyApp(App): | |
def build(self): | |
Clock.schedule_interval(self.set_time, 0) | |
return root | |
def set_time(self, dt): | |
self.root.boottime = Clock.get_boottime() | |
if __name__ == '__main__': | |
MyApp().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment