diff --git a/kivy/lang.py b/kivy/lang.py index 5b96b08ec5..02f7f13c1b 100644 --- a/kivy/lang.py +++ b/kivy/lang.py @@ -464,6 +464,7 @@ from kivy import kivy_data_dir, require from kivy.lib.debug import make_traceback import kivy.metrics as metrics +from weakref import ref trace = Logger.trace @@ -1264,6 +1265,17 @@ def _apply_rule(self, widget, rule, rootrule, template_ctx=None): # if we got an id, put it in the root rule for a later global usage if rule.id: rctx['ids'][rule.id] = widget + # set id name as a attribute for root widget so one can in python + # code simply access root_widget.id_name + _ids = dict(rctx['ids']) + _root = _ids.pop('root') + _new_ids = _root.ids + for _key in _ids.keys(): + if _ids[_key] == _root: + # skip on self + continue + _new_ids[_key] = ref(_ids[_key]) + _root.ids = _new_ids # first, ensure that the widget have all the properties used in # the rule if not, they will be created as ObjectProperty. diff --git a/kivy/properties.pyx b/kivy/properties.pyx index 2c0342991b..4cfb5f2277 100644 --- a/kivy/properties.pyx +++ b/kivy/properties.pyx @@ -234,9 +234,11 @@ cdef class Property: :Parameters: `errorhandler`: callable - If set, must take a single argument and return a valid substitute value + If set, must take a single argument and return a valid substitute + value `errorvalue`: object - If set, will replace an invalid property value (overrides errorhandler) + If set, will replace an invalid property value (overrides + errorhandler) .. versionchanged:: 1.4.2 Parameters errorhandler and errorvalue added @@ -601,8 +603,34 @@ class ObservableDict(dict): self.obj = largs[1] super(ObservableDict, self).__init__(*largs[2:]) + def _weak_return(self, item): + if isinstance(item, ref): + return item() + return item + + def __getattr__(self, attr): + try: + return self._weak_return(self.__getitem__(attr)) + except KeyError: + try: + return self._weak_return( + super(ObservableDict, self).__getattr__(attr)) + except AttributeError: + raise KeyError(attr) + + def __setattr__(self, attr, value): + if attr in ('prop', 'obj'): + super(ObservableDict, self).__setattr__(attr, value) + return + self.__setitem__(attr, value) + def __setitem__(self, key, value): - dict.__setitem__(self, key, value) + if value is None: + # remove attribute if value is None + # is this really needed? + self.__delitem__(key) + else: + dict.__setitem__(self, key, value) observable_dict_dispatch(self) def __delitem__(self, key): diff --git a/kivy/uix/widget.py b/kivy/uix/widget.py index 9eddb38d7c..57c4ecd185 100644 --- a/kivy/uix/widget.py +++ b/kivy/uix/widget.py @@ -82,7 +82,7 @@ def callback_pos(instance, value): from kivy.factory import Factory from kivy.properties import NumericProperty, StringProperty, \ AliasProperty, ReferenceListProperty, ObjectProperty, \ - ListProperty + ListProperty, DictProperty from kivy.graphics import Canvas from kivy.base import EventLoop from kivy.lang import Builder @@ -564,6 +564,16 @@ def set_center_y(self, value): dict. ''' + ids = DictProperty({}) + '''This is a Dictionary of id's defined in your kv language. This will only + be populated if you use id's in your kv language code. + + .. versionadded:: 1.6.0 + + :data:`ids` is a :class:`~kivy.properties.DictProperty`, defaults to a empty + dict {}. + ''' + opacity = NumericProperty(1.0) '''Opacity of the widget and all the children.