fsck_mainmenu by Moritz Venn
[enigma2.git] / lib / python / Components / Element.py
index 884c87d393d920f0b1bec8a2e012be0b80d25e0e..baab4cfb46d30284be8d3836d61e346e49a8b5bf 100644 (file)
@@ -4,11 +4,30 @@ from Tools.CList import CList
 # Render Converter Converter Source
 
 # a bidirectional connection
 # Render Converter Converter Source
 
 # a bidirectional connection
-class Element:
+
+def cached(f):
+       name = f.__name__
+       def wrapper(self):
+               if self.cache is None:
+                       return f(self)
+               if name not in self.cache:
+                       self.cache[name] = (True, f(self))
+               return self.cache[name][1]
+       return wrapper
+
+class Element(object):
+       CHANGED_DEFAULT = 0   # initial "pull" state
+       CHANGED_ALL = 1       # really everything changed
+       CHANGED_CLEAR = 2     # we're expecting a real update soon. don't bother polling NOW, but clear data.
+       CHANGED_SPECIFIC = 3  # second tuple will specify what exactly changed
+       CHANGED_POLL = 4      # a timer expired
+
        def __init__(self):
                self.downstream_elements = CList()
                self.master = None
                self.source = None
        def __init__(self):
                self.downstream_elements = CList()
                self.master = None
                self.source = None
+               self.__suspended = True
+               self.cache = None
 
        def connectDownstream(self, downstream):
                self.downstream_elements.append(downstream)
 
        def connectDownstream(self, downstream):
                self.downstream_elements.append(downstream)
@@ -18,7 +37,7 @@ class Element:
        def connectUpstream(self, upstream):
                assert self.source is None
                self.source = upstream
        def connectUpstream(self, upstream):
                assert self.source is None
                self.source = upstream
-               self.changed()
+               self.changed((self.CHANGED_DEFAULT,))
        
        def connect(self, upstream):
                self.connectUpstream(upstream)
        
        def connect(self, upstream):
                self.connectUpstream(upstream)
@@ -29,7 +48,10 @@ class Element:
                # we should not disconnect from upstream if
                # there are still elements depending on us.
                assert len(self.downstream_elements) == 0, "there are still downstream elements left"
                # we should not disconnect from upstream if
                # there are still elements depending on us.
                assert len(self.downstream_elements) == 0, "there are still downstream elements left"
-               self.source.disconnectDownstream(self)
+               
+               # Sources don't have a source themselves. don't do anything here.
+               if self.source is not None:
+                       self.source.disconnectDownstream(self)
        
        def disconnectDownstream(self, downstream):
                self.downstream_elements.remove(downstream)
        
        def disconnectDownstream(self, downstream):
                self.downstream_elements.remove(downstream)
@@ -41,8 +63,29 @@ class Element:
 
        # default action: push downstream
        def changed(self, *args, **kwargs):
 
        # default action: push downstream
        def changed(self, *args, **kwargs):
+               self.cache = { }
                self.downstream_elements.changed(*args, **kwargs)
                self.downstream_elements.changed(*args, **kwargs)
+               self.cache = None
 
        def reconnectUpstream(self, new_upstream):
                assert self.source is not None
                self.source = new_upstream
 
        def reconnectUpstream(self, new_upstream):
                assert self.source is not None
                self.source = new_upstream
+
+       def setSuspend(self, suspended):
+               changed = self.__suspended != suspended
+               if not self.__suspended and suspended:
+                       self.doSuspend(1)
+               elif self.__suspended and not suspended:
+                       self.doSuspend(0)
+                       
+               self.__suspended = suspended
+               if self.source is not None and changed:
+                       self.source.checkSuspend()
+       
+       suspended = property(lambda self: self.__suspended, setSuspend)
+       
+       def checkSuspend(self):
+               self.suspended = reduce(lambda x, y: x and y.__suspended, self.downstream_elements, True)
+
+       def doSuspend(self, suspend):
+               pass