Allow to have more than one notification type in Service
[gregoa/zavai.git] / zavai / registry.py
index 63e9412d07ef89506fde50f19adedf568b168763..ec0a4a2c4f3b29c9bc497de4c6b1bedecc63bf77 100644 (file)
@@ -47,21 +47,23 @@ class Registry(object):
         self.objects = dict()
         self.labels = dict()
 
-    def register(self, name, obj, label = None):
+    def register(self, obj, name=None):
         """Register an object at the given path.
 
         Name the path to this object, like "menu.gps.monitor".
         """
+        if name is None:
+            name = obj.props.name
+
         if name in self.objects:
             return KeyError("%s is already registered", name)
         zavai.info("Registering", name)
         self.objects[name] = obj
-        if label is not None: self.labels[name] = label
 
         if name.startswith("menu."):
             self.add_to_menu(name)
 
-    def register_factory(self, name, fac, label = None):
+    def register_factory(self, fac, name, label = None):
         """Register an object factory at the given path.
 
         Name the path to this object, like "menu.gps.monitor".
@@ -72,43 +74,31 @@ class Registry(object):
         self.factories[name] = fac
         if label is not None: self.labels[name] = label
 
-        if name.startswith("menu."):
-            self.add_to_menu(name)
-
-    def register_action(self, name, obj):
-        """Register an object at the given path.
-
-        Name the path to this object, like "menu.gps.monitor".
-        """
-        if name in self.objects:
-            return KeyError("%s is already registered", name)
-        zavai.info("Registering action", name)
-        self.objects[name] = obj
-
-        if name.startswith("menu."):
-            parent = get_parent(name)
-            if parent is not None:
-                zavai.info("Add action to menu", name, parent)
-                menu = self.menu(parent)
-                if isinstance(obj, gtk.ToggleAction):
-                    menu.add_child(zavai.ToggleButton(self, name, action=obj))
-                else:
-                    menu.add_child(zavai.LinkButton(self, name, action=obj))
-
     def add_to_menu(self, name):
         "Add the applet with the given name to the menu structure"
         parent = get_parent(name)
         if parent is not None:
             zavai.info("Add to menu", name, parent)
             menu = self.menu(parent)
-            menu.add_child(zavai.LinkButton(self, name, self.label(name)))
+
+            obj = self.resource(name)
+            if isinstance(obj, gtk.ToggleAction):
+                menu.add_child(zavai.ToggleButton(self, name, action=obj))
+            elif isinstance(obj, gtk.Action):
+                menu.add_child(zavai.LinkButton(self, name, action=obj))
+            else:
+                menu.add_child(zavai.LinkButton(self, name, self.label(name)))
 
     def label(self, name):
         "Return the label for the object with the given name"
         res = self.labels.get(name)
         if res is not None:
             return res
-        return default_label(name)
+        try:
+            obj = self.resource(name)
+            return obj.props.label
+        except:
+            return default_label(name)
 
     def resource(self, name):
         """Get a resource from the registry.
@@ -142,7 +132,7 @@ class Registry(object):
                 parent = get_parent(name)
 
             res = zavai.Menu(self, name, parent)
-            self.register(name, res)
+            self.register(res, name)
         return res
 
     def shutdown(self):
@@ -155,6 +145,9 @@ class Registry(object):
         self.objects.clear()
 
 class Resource(object):
+    def __init__(self):
+        super(Resource, self).__init__()
+
     def shutdown(self):
         """Shut down this resource.
 
@@ -165,3 +158,49 @@ class Resource(object):
         releasing a FSO resource, restoring mixer settings and so on.
         """
         pass
+
+class Service(Resource):
+    "Service that is activated only when someone is listening"
+    def __init__(self):
+        """
+        Initialise a service that can emit signals for the given event types
+        """
+        super(Service, self).__init__(types = [])
+        self.callbacks = dict()
+        for t in types:
+            self.callbacks[t] = set()
+
+    def shutdown(self):
+        self.stop()
+
+    def start(self):
+        "Activate the service"
+        pass
+
+    def stop(self):
+        "Deactivate the service"
+        pass
+
+    def notify(self, type, *args, **kw):
+        "Call all callbacks with the given parameters"
+        for cb in self.callbacks[type]:
+            cb(*args, **kw)
+
+    def has_callbacks(self):
+        for i in self.callbacks.values():
+            if i: return True
+        return False
+
+    def connect(self, type, callback):
+        "Connect a callback to this resource, activating it if needed"
+        do_start = not self.has_callbacks()
+        self.callbacks[type].add(callback)
+        if do_start:
+            self.start()
+
+    def disconnect(self, type, callback):
+        "Disconnect a callback to this resource, activating it if needed"
+        if not self.has_callbacks(): return
+        self.callbacks.discard(callback)
+        if not self.has_callbacks():
+            self.stop()