/[ascend]/trunk/pygtk/canvas/blockitem.py
ViewVC logotype

Diff of /trunk/pygtk/canvas/blockitem.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1954 by jpye, Tue Nov 11 10:01:18 2008 UTC revision 1970 by jpye, Sat Dec 27 07:19:35 2008 UTC
# Line 1  Line 1 
1  from gaphas.item import Element  
2  from gaphas.constraint import LineConstraint, LessThanConstraint, EqualsConstraint, Constraint, _update, BalanceConstraint  from gaphas.constraint import LineConstraint, LessThanConstraint, EqualsConstraint, Constraint, _update, BalanceConstraint
3  from gaphas.item import Line, SW, NE, NW, SE, Element, Handle  from gaphas.item import Line, SW, NE, NW, SE, Item, Handle
4  from gaphas.util import *  from gaphas.util import *
5    from gaphas.connector import PointPort, VariablePoint
6    from gaphas.solver import solvable, WEAK, NORMAL, STRONG, VERY_STRONG
7    from gaphas.state import observed, reversible_method, reversible_pair, reversible_property, disable_dispatching
8    from gaphas.geometry import distance_rectangle_point
9    
10    class ElementNoPorts(Item):
11        """
12        This is a copy of the Element class, but without the declaration
13        of the LinePorts in the __init__ method. It will be proposed to the
14        Gaphor team that the Element class be modified like this, because
15        there is quite a lot of useful code aside from the LinePort definition.
16        """
17    
18        def __init__(self, width=10, height=10):
19            super(ElementNoPorts, self).__init__()
20            self._handles = [ h(strength=VERY_STRONG) for h in [Handle]*4 ]
21    
22            handles = self._handles
23            h_nw = handles[NW]
24            h_ne = handles[NE]
25            h_sw = handles[SW]
26            h_se = handles[SE]
27    
28            # no element ports by default
29            self._ports = []
30    
31            # setup constraints
32            self.constraint(horizontal=(h_nw.pos, h_ne.pos))
33            self.constraint(horizontal=(h_se.pos, h_sw.pos))
34            self.constraint(vertical=(h_nw.pos, h_sw.pos))
35            self.constraint(vertical=(h_se.pos, h_ne.pos))
36    
37            # create minimal size constraints
38            self._c_min_w = self.constraint(left_of=(h_nw.pos, h_se.pos), delta=10)
39            self._c_min_h = self.constraint(above=(h_nw.pos, h_se.pos), delta=10)
40    
41            # set width/height when minimal size constraints exist
42            self.width = width
43            self.height = height
44    
45    
46        def setup_canvas(self):
47            super(ElementNoPorts, self).setup_canvas()
48    
49            # Set width/height explicitly, so the element will maintain it
50            self.width = self.width
51            self.height = self.height
52    
53        def _set_width(self, width):
54            """
55            >>> b=ElementNoPorts()
56            >>> b.width = 20
57            >>> b.width
58            20.0
59            >>> b._handles[NW].x
60            Variable(0, 40)
61            >>> b._handles[SE].x
62            Variable(20, 40)
63            """
64            if width < self.min_width:
65                width = self.min_width
66            h = self._handles
67            h[SE].x = h[NW].x + width
68    
69    
70        def _get_width(self):
71            """
72            Width of the box, calculated as the distance from the left and
73            right handle.
74            """
75            h = self._handles
76            return float(h[SE].x) - float(h[NW].x)
77    
78        width = property(_get_width, _set_width)
79    
80        def _set_height(self, height):
81            """
82            >>> b=ElementNoPorts()
83            >>> b.height = 20
84            >>> b.height
85            20.0
86            >>> b.height = 2
87            >>> b.height
88            10.0
89            >>> b._handles[NW].y
90            Variable(0, 40)
91            >>> b._handles[SE].y
92            Variable(10, 40)
93            """
94            if height < self.min_height:
95                height = self.min_height
96            h = self._handles
97            h[SE].y = h[NW].y + height
98    
99        def _get_height(self):
100            """
101            Height.
102            """
103            h = self._handles
104            return float(h[SE].y) - float(h[NW].y)
105    
106        height = property(_get_height, _set_height)
107    
108        @observed
109        def _set_min_width(self, min_width):
110            """
111            Set minimal width.
112            """
113            if min_width < 0:
114                raise ValueError, 'Minimal width cannot be less than 0'
115    
116            self._c_min_w.delta = min_width
117            if self.canvas:
118                self.canvas.solver.request_resolve_constraint(self._c_min_w)
119    
120        min_width = reversible_property(lambda s: s._c_min_w.delta, _set_min_width)
121    
122        @observed
123        def _set_min_height(self, min_height):
124            """
125            Set minimal height.
126            """
127            if min_height < 0:
128                raise ValueError, 'Minimal height cannot be less than 0'
129    
130            self._c_min_h.delta = min_height
131            if self.canvas:
132                self.canvas.solver.request_resolve_constraint(self._c_min_h)
133    
134        min_height = reversible_property(lambda s: s._c_min_h.delta, _set_min_height)
135    
136            
137        def point(self, pos):
138            """
139            Distance from the point (x, y) to the item.
140            """
141            h = self._handles
142            hnw, hse = h[NW], h[SE]
143            return distance_rectangle_point(map(float, (hnw.x, hnw.y, hse.x, hse.y)), pos)
144    
 from port import *  
145    
146  class BlockItem(Element):  class BlockItem(ElementNoPorts):
147      """      """
148      This is an ASCEND 'block' in the canvas-based modeller. The block will have      This is an ASCEND 'block' in the canvas-based modeller. The block will have
149      sets of input and output ports to which connector lines can be 'glued'.      sets of input and output ports to which connector lines can be 'glued'.
# Line 16  class BlockItem(Element): Line 154  class BlockItem(Element):
154      """      """
155    
156      def __init__(self, width=64, height=64):      def __init__(self, width=64, height=64):
   
         self.ports = []  
157          super(BlockItem, self).__init__(width, height)          super(BlockItem, self).__init__(width, height)
158    
159      def draw(self, context):      def draw(self, context):
160          #print 'Box.draw', self          """
161          c = context.cairo          We want all ports within ASCEND to have a common appearance, so we
162                implement the drawing of ports here, and allow sub-classes of BlockItem
163            to implement the drawing of the other parts of the block, including the
164            outline etc.
165    
166            Connected ports will be coloured red, other ports will be pale blue.
167            """
168            c = context.cairo  
169          phalfsize = 3          phalfsize = 3
170          for p in self.ports:          for p in self._ports:
171              c.rectangle(p.x - phalfsize, p.y - phalfsize, 2*phalfsize, 2*phalfsize)              if hasattr(p,"point"):
172              if p.connected_to is None:                  c.rectangle(p.point.x - phalfsize, p.point.y - phalfsize, 2*phalfsize, 2*phalfsize)
173                    #if p.connected_to is None:
174                  c.set_source_rgba(0.8,0.8,1, 0.8)                  c.set_source_rgba(0.8,0.8,1, 0.8)
175              else:                  #else:
176                  c.set_source_rgba(1,0,0,1)                  #   c.set_source_rgba(1,0,0,1)
177              c.fill_preserve()                  c.fill_preserve()
178              c.set_source_rgb(0.8,0.8,0)                  c.set_source_rgb(0.8,0.8,0)
179              c.stroke()                  c.stroke()
180    
181      def glue(self,item, handle, ix, iy):      # removing the 'glue' method now, as ports are now built in to gaphas.
         gluerange = 10  
         mindist = -1;  
         minport = None  
         for p in self.ports:  
             dist = math.sqrt((ix-p.x)**2 + (iy-p.y)**2)  
             if dist < gluerange:  
                 if not minport or dist<mindist:  
                     mindist = dist  
                     minport = p  
         return mindist, minport  
182    
183      def pre_update(self,context):      def pre_update(self,context):
184          #print "PRE-UPDATE BLOCK"          #print "PRE-UPDATE BLOCK"
# Line 56  class DefaultBlockItem(BlockItem): Line 189  class DefaultBlockItem(BlockItem):
189      This is a 'default block' with a certain number of input and output ports      This is a 'default block' with a certain number of input and output ports
190      shown depending on the values sent to __init__. It is drawn as a simple      shown depending on the values sent to __init__. It is drawn as a simple
191      box with the input ports on the left and the output ports on the right.      box with the input ports on the left and the output ports on the right.
192    
193        @TODO Not clear yet whether blocks with 'custom' representations should have
194        as their parent class: this class or BlockItem.
195      """      """
196    
197      def __init__(self, blockinstance):      def __init__(self, blockinstance):
# Line 73  class DefaultBlockItem(BlockItem): Line 209  class DefaultBlockItem(BlockItem):
209          h_sw = handles[SW]          h_sw = handles[SW]
210          h_se = handles[SE]          h_se = handles[SE]
211    
212            _ports = []
213          for i in range(inputs):          for i in range(inputs):
214              p = Port(self)              p = PointPort(VariablePoint((0,0),strength=WEAK))
215              self.ports.append(p)              self._constraints.append(eq(p.point.x, h_nw.x))
216              self._constraints.append(eq(p.x, h_nw.x))              self._constraints.append(bal(band=(h_nw.y, h_sw.y),v=p.point.y, balance=(0.5 + i)/inputs))
217              self._constraints.append(bal(band=(h_nw.y, h_sw.y),v=p.y, balance=(0.5 + i)/inputs))              _ports.append(p)
218    
219          for i in range(outputs):          for i in range(outputs):
220              p = Port(self)              p = PointPort(VariablePoint((0,0),strength=WEAK))
221              self.ports.append(p)              _ports.append(p)
222              self._constraints.append(eq(p.x, h_ne.x))              self._constraints.append(eq(p.point.x, h_ne.x))
223              self._constraints.append(bal(band=(h_ne.y,h_se.y),v=p.y, balance=(0.5 + i)/outputs))              self._constraints.append(bal(band=(h_ne.y,h_se.y),v=p.point.y, balance=(0.5 + i)/outputs))
224    
225            self._ports = _ports
226    
227      def draw(self, context):      def draw(self, context):
228          # draw the box itself          # draw the box itself

Legend:
Removed from v.1954  
changed lines
  Added in v.1970

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22