Source code for core.control.manager

# -*- python -*-
# -*- coding: utf8 -*-
#
#       OpenAlea.OALab
#
#       Copyright 2014 INRIA - CIRAD - INRA
#
#       File author(s): Guillaume Baty <guillaume.baty@inria.fr>
#
#       File contributor(s):
#
#       Distributed under the Cecill-C License.
#       See accompanying file LICENSE.txt or copy at
#           http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
#       OpenAlea WebSite : http://openalea.gforge.inria.fr
#
###############################################################################
"""
"""
import copy

from openalea.core.observer import Observed, AbstractListener, lock_notify
from openalea.core.singleton import Singleton
from .control import Control


[docs]class Follower(AbstractListener): def __init__(self, name, func): AbstractListener.__init__(self) self._old_value = None self.name = name self.callback = func self._listen = True
[docs] def ignore_events(self): self._listen = False
[docs] def follow_events(self): self._listen = True
@lock_notify
[docs] def notify(self, sender, event): if self._listen is False: return if event: signal, data = event if signal == 'control_value_changed': control, value = data if control.name == self.name and value != self._old_value: old_value = self._old_value self._old_value = value self.callback(old_value, value)
[docs]class ControlContainer(Observed, AbstractListener): """ >>> from openalea.core.control.manager import ControlContainer """ def __init__(self): Observed.__init__(self) AbstractListener.__init__(self) self.follower = {} self._controls = []
[docs] def control(self, name=None, uid=None): """ Return all control with name "name". If no control found, returns None, if only one found, returns it else return a list of control. If uid is passed, returns corresponding control or None if not found. If uid is passed, it never returns a list as uid is unique. """ if name is None and uid is None: return [control for control in self._controls] elif name is None and uid: for control in self._controls: if str(id(control)) == str(uid): return control elif name and uid is None: controls = [] for control in self._controls: if control.name == name: controls.append(control) if len(controls) == 0: return None elif len(controls) == 1: return controls[0] else: return controls else: return self.control(None, uid)
[docs] def add(self, name, **kwds): """ Convenience method to create a control and add it to container. See :class:`~openealea.core.control.control.Control`. >>> container = ControlContainer() >>> container.add('i', interface='IInt', value=1) Control('i', IInt, value=1) :param name: Control name :param kwds: Control keywords like interface, value, ... """ control = Control(name, **kwds) self.add_control(control) return control
[docs] def update(self, dic): """ Update controls with dict values. If a name is not referenced in ControlContainer, nothing is done. .. note:: Example: Let "container" a Container with one control "a" with value 1:: container: - a:IInt = 1 after container.update({'a':2, 'b':3}) we get container: - a:IInt = 2 :param dic: :obj:`dict` name -> value """ for name, value in dic.items(): control = self.control(name=name) if control is None: continue control.value = value
[docs] def add_control(self, control): """ :param control: Control object """ assert isinstance(control, Control) if control not in self._controls: self._controls.append(control) control.register_listener(self) self.notify_listeners(('state_changed', (control)))
[docs] def remove_control(self, control): """ :param control: Control object """ assert isinstance(control, Control) if control in self._controls: self._controls.remove(control) control.unregister_listener(self) self.notify_listeners(('state_changed', (control)))
[docs] def clear(self): # make a copy of the list, required by for loop for control in list(self._controls): self.remove_control(control)
[docs] def namespace(self, interface=None): """ Returns namespace (dict control name -> value). :param tag: returns namespace corresponding to given tag. Default, returns global namespace """ ns = {} for control in self.controls(): if interface is None: ns[control.name] = copy.deepcopy(control.value) else: from openalea.core.service.interface import interface_name if interface_name(control.interface) == interface: ns[control.name] = copy.deepcopy(control.value) return ns
[docs] def changed(self): """ Like :meth:`~openealea.core.control.manager.ControlContainer.namespace` but dictionnary contains only controls with value different than default value. """ dic = {} for control in self._controls: if control.value != control.default: dic[control.name] = control.value return dic
[docs] def controls(self): """ Returns a list of :class:`~openealea.core.control.control.Control` objects. """ return list(self._controls)
[docs] def notify(self, sender, event): if isinstance(sender, Control): signal, data = event if signal == 'value_changed': self.notify_listeners( ('control_value_changed', (sender, data))) if signal == 'name_changed': self.notify_listeners(('control_name_changed', (sender, data)))
def __contains__(self, key): for control in self.controls(): if key == control.name: return True return False
[docs] def disable_followers(self): for follower in self.follower.values(): follower.ignore_events()
[docs] def enable_followers(self): for follower in self.follower.values(): follower.follow_events()
[docs] def register_follower(self, name, func): if name in self.follower: self.unregister_follower(name) follower = Follower(name, func) self.register_listener(follower) self.follower[name] = follower
[docs] def unregister_follower(self, name): if name in self.follower: self.unregister_listener(self.follower[name]) del self.follower[name]
[docs] def clear_followers(self): for follower_name in self.follower.keys(): self.unregister_follower(follower_name)
[docs]class ControlManager(ControlContainer): __metaclass__ = Singleton
[docs]def control_dict(): """ Get the controls from the control manager in a dictionary (key = name, value = object) :return: dict of controls """ cm = ControlManager() controls = cm.namespace() return controls