graphics/GraphicCommons.py
changeset 361 62570186dad4
parent 358 4eeb0129f5d2
child 364 deee68313770
--- a/graphics/GraphicCommons.py	Thu May 28 08:10:18 2009 +0200
+++ b/graphics/GraphicCommons.py	Sat May 30 17:15:22 2009 +0200
@@ -23,6 +23,7 @@
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 import wx
+import time
 from math import *
 from types import *
 
@@ -188,6 +189,98 @@
 
 
 #-------------------------------------------------------------------------------
+#                            Debug Data Consumer Class
+#-------------------------------------------------------------------------------
+
+class DebugDataConsumer:
+    
+    def __init__(self):
+        self.LastValue = None
+        self.Value = None
+        self.Inhibited = False
+    
+    def Inhibit(self, inhibit):
+        self.Inhibited = inhibit
+        if inhibit and self.LastValue is not None:
+            self.SetValue(self.LastValue)
+            self.LastValue = None
+        
+    def NewValue(self, tick, value):
+        if self.Inhibited:
+            self.LastValue = value
+        else:
+            self.SetValue(value)
+
+    def SetValue(self, value):
+        self.Value = value
+
+#-------------------------------------------------------------------------------
+#                               Debug Viewer Class
+#-------------------------------------------------------------------------------
+
+REFRESH_PERIOD = 0.1
+
+class DebugViewer:
+    
+    def __init__(self, producer, debug, register_tick=True):
+        self.DataProducer = producer
+        self.Debug = debug
+        
+        self.DataConsumers = {}
+        
+        self.LastRefreshTime = time.time()
+        
+        if register_tick:
+            self.DataProducer.SubscribeDebugIECVariable("__tick__", self)
+        
+        self.RefreshTimer = wx.Timer(self, -1)
+        self.Bind(wx.EVT_TIMER, self.OnRefreshTimer, self.RefreshTimer)
+    
+    def __del__(self):
+        self.DataProducer.UnsubscribeDebugIECVariable("__tick__", self)
+        self.DeleteDataConsumers()
+        self.RefreshTimer.Stop()
+        
+    def Inhibit(self, inhibit):
+        for consumer, iec_path in self.DataConsumers.iteritems():
+            consumer.Inhibit(inhibit)
+    
+    def AddDataConsumer(self, iec_path, consumer):
+        result = self.DataProducer.SubscribeDebugIECVariable(iec_path, consumer) is not None
+        if result is not None and consumer != self:
+            self.DataConsumers[consumer] = iec_path
+        return result
+    
+    def RemoveDataConsumer(self, consumer):
+        iec_path = self.DataConsumers.pop(consumer, None)
+        if iec_path is not None:
+            self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer)
+    
+    def DeleteDataConsumers(self):
+        for consumer, iec_path in self.DataConsumers.iteritems():
+            self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer)
+        self.DataConsumers = {}
+    
+    def OnRefreshTimer(self, event):
+        self.RefreshNewData()
+        event.Skip()
+    
+    def NewDataAvailable(self):
+        self.Inhibit(True)
+        current_time = time.time()
+        if current_time - self.LastRefreshTime > REFRESH_PERIOD:
+            self.LastRefreshTime = current_time
+            wx.CallAfter(self.RefreshViewOnNewData)
+
+    def RefreshViewOnNewData(self):
+        if self:
+            self.RefreshNewData()
+            self.RefreshTimer.Start(int(REFRESH_PERIOD * 1000), oneShot=True)
+    
+    def RefreshNewData(self):
+        self.Inhibit(False)
+
+#-------------------------------------------------------------------------------
 #                               Viewer Rubberband
 #-------------------------------------------------------------------------------
 
@@ -293,7 +386,7 @@
                 self.currentBox.height)
 
 #-------------------------------------------------------------------------------
-#                               Viewer Rubberband
+#                               Viewer ToolTip
 #-------------------------------------------------------------------------------
 
 """
@@ -312,10 +405,14 @@
         
     def SetTip(self, tip):
         self.Tip = tip
-        dc = wx.ClientDC(self)
-        w, h = dc.GetTextExtent(tip)
-        self.SetSize(wx.Size(w + 4, h + 4))
-        self.Refresh()
+        wx.CallAfter(self.RefreshTip)
+        
+    def RefreshTip(self):
+        if self:
+            dc = wx.ClientDC(self)
+            w, h = dc.GetTextExtent(self.Tip)
+            self.SetSize(wx.Size(w + 4, h + 4))
+            self.Refresh()
         
     def OnPaint(self, event):
         dc = wx.AutoBufferedPaintDC(self)
@@ -1433,11 +1530,12 @@
 Class that implements a wire for connecting two blocks
 """
 
-class Wire(Graphic_Element):
+class Wire(Graphic_Element, DebugDataConsumer):
     
     # Create a new wire
     def __init__(self, parent, start = None, end = None):
         Graphic_Element.__init__(self, parent)
+        DebugDataConsumer.__init__(self)
         self.StartPoint = start
         self.EndPoint = end
         self.StartConnected = None
@@ -1451,14 +1549,12 @@
             self.Segments = []
         self.SelectedSegment = None
         self.Valid = True
-        self.Value = None
         self.ValueSize = None
         self.ComputedValue = None
         self.OverStart = False
         self.OverEnd = False
         self.ComputingType = False
         self.ToolTip = None
-        self.Font = parent.GetMiniFont()
         
     def Flush(self):
         self.StartConnected = None
@@ -1492,7 +1588,6 @@
             rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey))
         if self.ValueSize is not None:
             width, height = self.ValueSize
-            width, height = self.ValueSize
             if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4:
                 x = self.Points[0].x + width * self.StartPoint[1][0] / 2
                 y = self.Points[0].y + (height * self.StartPoint[1][1] - 1) / 2
@@ -1624,7 +1719,7 @@
         return False
     
     def SetValue(self, value):
-        if self.Value != value and self.Parent:
+        if self.Value != value:
             self.Value = value
             if value is not None and not isinstance(value, BooleanType):
                 if isinstance(value, StringType):
@@ -1636,16 +1731,14 @@
                 if len(self.ComputedValue) > 4:
                     self.ComputedValue = self.ComputedValue[:4] + "..."
             if isinstance(self.ComputedValue, StringType):
-                dc = wx.ClientDC(self.Parent)
-                dc.SetFont(self.Font)
-                self.ValueSize = dc.GetTextExtent(self.ComputedValue)
+                self.ValueSize = self.Parent.GetMiniTextExtent(self.ComputedValue)
             else:
                 self.ValueSize = None
             if self.StartConnected:
                 self.StartConnected.RefreshValue()
             if self.EndConnected:
                 self.EndConnected.RefreshValue()
-            self.Refresh()
+            self.Parent.UpdateRefreshRect(self.GetRedrawRect())
             if isinstance(value, BooleanType) and self.StartConnected is not None:
                 block = self.StartConnected.GetParentBlock()
                 block.SpreadCurrent()
@@ -2514,7 +2607,7 @@
             if self.SelectedSegment == len(self.Segments) - 1:
                 dc.DrawPoint(self.Points[-1].x, self.Points[-1].y)
         if self.Value is not None and not isinstance(self.Value, BooleanType) and self.Value != "undefined":
-            dc.SetFont(self.Font)
+            dc.SetFont(self.Parent.GetMiniFont())
             dc.SetTextForeground(wx.NamedColour("purple"))
             width, height = self.ValueSize
             if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4: