graphics/GraphicCommons.py
changeset 249 d8425712acef
parent 243 c5da8b706cde
child 253 d9391572655f
--- a/graphics/GraphicCommons.py	Fri Sep 05 18:12:23 2008 +0200
+++ b/graphics/GraphicCommons.py	Fri Sep 05 18:13:18 2008 +0200
@@ -24,6 +24,7 @@
 
 import wx
 from math import *
+from types import *
 
 #-------------------------------------------------------------------------------
 #                               Common constants
@@ -309,9 +310,19 @@
         self.Pos = wx.Point(0, 0)
         self.Size = wx.Size(0, 0)
         self.BoundingBox = wx.Rect(0, 0, 0, 0)
+        self.Visible = False
         self.CurrentCursor = 0
         ResetCursors()
     
+    def TestVisible(self, screen):
+        self.Visible = self.BoundingBox.Intersects(screen)
+    
+    def IsVisible(self):
+        return self.Visible
+    
+    def SpreadCurrent(self):
+        pass
+    
     def IsOfType(self, type, reference):
         return self.Parent.IsOfType(type, reference)
     
@@ -663,6 +674,12 @@
     def __del__(self):
         self.Elements = []
     
+    def IsVisible(self):
+        for element in self.Elements:
+            if element.IsVisible():
+                return True
+        return False
+    
     # Refresh the list of wire excluded
     def RefreshWireExclusion(self):
         self.WireExcluded = []
@@ -862,10 +879,18 @@
             self.Negated = False
             self.Edge = "none"
         self.OneConnected = onlyone
+        self.Valid = True
+        self.Value = None
         self.Pen = wx.BLACK_PEN
         self.Errors = {}
         self.RefreshNameSize()
     
+    def Flush(self):
+        self.ParentBlock = None
+        for wire, handle in self.Wires:
+            wire.Flush()
+        self.Wires = []
+    
     # Returns the RedrawRect
     def GetRedrawRect(self, movex = 0, movey = 0):
         parent_pos = self.ParentBlock.GetPosition()
@@ -941,9 +966,23 @@
         self.Name = name
         self.RefreshNameSize()
 
-    def SetValue(self, value):
+    def RefreshValue(self):
+        self.Value = self.ReceivingCurrent()
+    
+    def MarkAsInvalid(self):
+        self.Valid = False
+    
+    def ReceivingCurrent(self):
+        current = False
         for wire, handle in self.Wires:
-            wire.SetValue(value)
+            value = wire.GetValue()
+            if isinstance(value, BooleanType):
+                current |= wire.GetValue()
+        return current
+    
+    def SpreadCurrent(self, spreading):
+        for wire, handle in self.Wires:
+            wire.SetValue(spreading)
     
     # Changes the connector name size
     def RefreshNameSize(self):
@@ -1105,15 +1144,15 @@
     # Tests if the point given is near from the end point of this connector
     def TestPoint(self, pt, direction = None, exclude = True):
         parent_pos = self.ParentBlock.GetPosition()
-        if not (len(self.Wires) > 0 and self.OneConnected and exclude):
-            if direction is None or self.Direction == direction:
-                # Calculate a square around the end point of this connector
-                x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE - ANCHOR_DISTANCE
-                y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE
-                width = ANCHOR_DISTANCE * 2 + abs(self.Direction[0]) * CONNECTOR_SIZE
-                height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
-                rect = wx.Rect(x, y, width, height)
-                return rect.InsideXY(pt.x, pt.y)
+        if (not (len(self.Wires) > 0 and self.OneConnected and exclude) or self.Type == "BOOL")\
+            and direction is None or self.Direction == direction:
+            # Calculate a square around the end point of this connector
+            x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE - ANCHOR_DISTANCE
+            y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE
+            width = ANCHOR_DISTANCE * 2 + abs(self.Direction[0]) * CONNECTOR_SIZE
+            height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
+            rect = wx.Rect(x, y, width, height)
+            return rect.InsideXY(pt.x, pt.y)
         return False
     
     # Draws the highlightment of this element if it is highlighted
@@ -1152,7 +1191,12 @@
             dc.SetPen(wx.RED_PEN)
             dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0)))
         else:
-            dc.SetPen(self.Pen)
+            if not self.Valid:
+                dc.SetPen(wx.RED_PEN)
+            elif isinstance(self.Value, BooleanType) and self.Value:
+                dc.SetPen(wx.GREEN_PEN)
+            else:
+                dc.SetPen(self.Pen)
             dc.SetBrush(wx.WHITE_BRUSH)
         parent_pos = self.ParentBlock.GetPosition()
         
@@ -1226,12 +1270,14 @@
         self.SelectedSegment = None
         self.Valid = True
         self.Value = None
+        self.ValueSize = None
         self.OverStart = False
         self.OverEnd = False
         self.ComputingType = False
-    
-    # Destructor of a wire
-    def __del__(self):
+        parent_font = parent.GetFont()
+        self.Font = wx.Font(parent_font.GetPointSize() * 0.75, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = parent_font.GetFaceName())
+        
+    def Flush(self):
         self.StartConnected = None
         self.EndConnected = None
     
@@ -1242,6 +1288,21 @@
             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
         if self.EndConnected:
             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
+                rect = rect.Union(wx.Rect(x, y, width, height))
+                x = self.Points[-1].x + width * self.EndPoint[1][0] / 2
+                y = self.Points[-1].y + (height * self.EndPoint[1][1] - 1) / 2
+                rect = rect.Union(wx.Rect(x, y, width, height))
+            else:
+                middle = len(self.Segments) / 2 + len(self.Segments) % 2 - 1
+                x = self.Points[middle].x - width / 2
+                y = self.Points[middle].y - height / 2
+                rect = rect.Union(wx.Rect(x, y, width, height))
         return rect
     
     # Forbids to change the wire position
@@ -1315,7 +1376,32 @@
         return False
     
     def SetValue(self, value):
-        self.Value = value
+        if value is not None and not isinstance(value, BooleanType):
+            if isinstance(value, StringType):
+                value = "\"%s\""%value
+            else:
+                value = str(value)
+            if len(value) > 4:
+                value = value[:4] + "_"
+        if self.Value != value:
+            self.Value = value
+            if isinstance(self.Value, StringType):
+                dc = wx.ClientDC(self.Parent)
+                dc.SetFont(self.Font)
+                self.ValueSize = dc.GetTextExtent(self.Value)
+            else:
+                self.ValueSize = None
+            if self.StartConnected:
+                self.StartConnected.RefreshValue()
+            if self.EndConnected:
+                self.EndConnected.RefreshValue()
+            self.Refresh()
+            if isinstance(value, BooleanType):
+                block = self.StartConnected.GetParentBlock()
+                block.SpreadCurrent()
+    
+    def GetValue(self):
+        return self.Value
     
     # Unconnect the start and end points
     def Clean(self):
@@ -1362,9 +1448,9 @@
     def MarkAsInvalid(self):
         self.Valid = False
         if self.StartConnected:
-            self.StartConnected.SetPen(wx.RED_PEN)
+            self.StartConnected.MarkAsInvalid()
         if self.EndConnected:
-            self.EndConnected.SetPen(wx.RED_PEN)
+            self.EndConnected.MarkAsInvalid()
     
     # Reinitialize the wire points
     def ResetPoints(self):
@@ -1750,7 +1836,7 @@
                 height = lastheight
             # Calculate the real points from the new size, it's important for
             # keeping a proportionality in the points position with the size
-            # duringa resize dragging
+            # during a resize dragging
             for i, point in enumerate(self.RealPoints):
                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
                     point[0] = point[0] * width / float(max(lastwidth, 1))
@@ -2093,10 +2179,12 @@
     # Draws the wire lines and points
     def Draw(self, dc):
         Graphic_Element.Draw(self, dc)
-        if self.Valid:
+        if not self.Valid:
+            dc.SetPen(wx.RED_PEN)
+        elif isinstance(self.Value, BooleanType) and self.Value:
+            dc.SetPen(wx.GREEN_PEN)
+        else:
             dc.SetPen(wx.BLACK_PEN)
-        else:
-            dc.SetPen(wx.RED_PEN)
         dc.SetBrush(wx.BLACK_BRUSH)
         # Draw the start and end points if they are not connected or the mouse is over them
         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
@@ -2107,12 +2195,30 @@
         dc.DrawLines(self.Points)
         dc.DrawPoint(self.Points[-1].x, self.Points[-1].y)
         # Draw the segment selected in red
-        if self.SelectedSegment != None:
+        if self.SelectedSegment is not None:
             dc.SetPen(wx.RED_PEN)
             dc.DrawLine(self.Points[self.SelectedSegment].x, self.Points[self.SelectedSegment].y,
                         self.Points[self.SelectedSegment + 1].x, self.Points[self.SelectedSegment + 1].y)
             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):
+            dc.SetFont(self.Font)
+            dc.SetTextForeground(wx.NamedColour("purple"))
+            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
+                dc.DrawText(self.Value, x, y)
+                x = self.Points[-1].x + width * self.EndPoint[1][0] / 2
+                y = self.Points[-1].y + height * (self.EndPoint[1][1] - 1) / 2
+                dc.DrawText(self.Value, x, y)
+            else:
+                middle = len(self.Segments) / 2 + len(self.Segments) % 2 - 1
+                x = (self.Points[middle].x + self.Points[middle + 1].x - width) / 2
+                y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
+                dc.DrawText(self.Value, x, y)
+            dc.SetFont(self.Parent.GetFont())
+            dc.SetTextForeground(wx.BLACK)
 
 
 #-------------------------------------------------------------------------------
@@ -2283,3 +2389,4 @@
                     y += wordheight + 5
             if y + wordheight > self.Pos.y + self.Size[1] - 10:
                 break
+