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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1970 - (hide annotations) (download) (as text)
Sat Dec 27 07:19:35 2008 UTC (13 years, 9 months ago) by jpye
File MIME type: text/x-python
File size: 7609 byte(s)
Some steps towards support of latest release of Gaphas.
1 jpye 1970
2 jpye 1945 from gaphas.constraint import LineConstraint, LessThanConstraint, EqualsConstraint, Constraint, _update, BalanceConstraint
3 jpye 1970 from gaphas.item import Line, SW, NE, NW, SE, Item, Handle
4 jpye 1945 from gaphas.util import *
5 jpye 1970 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 jpye 1945
10 jpye 1970 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 jpye 1945
18 jpye 1970 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    
145    
146     class BlockItem(ElementNoPorts):
147 jpye 1945 """
148     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'.
150     The block will also have a corresponding ASCEND MODEL type, and a name
151     which will be used in ASCEND to refer to this block. Each of the ports will
152     be special visual elements, but note that these are not 'handles', because
153     they can not be used to resize/modify the element.
154     """
155    
156     def __init__(self, width=64, height=64):
157     super(BlockItem, self).__init__(width, height)
158    
159     def draw(self, context):
160 jpye 1970 """
161     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 jpye 1945 phalfsize = 3
170 jpye 1970 for p in self._ports:
171     if hasattr(p,"point"):
172     c.rectangle(p.point.x - phalfsize, p.point.y - phalfsize, 2*phalfsize, 2*phalfsize)
173     #if p.connected_to is None:
174 jpye 1945 c.set_source_rgba(0.8,0.8,1, 0.8)
175 jpye 1970 #else:
176     # c.set_source_rgba(1,0,0,1)
177     c.fill_preserve()
178     c.set_source_rgb(0.8,0.8,0)
179     c.stroke()
180 jpye 1945
181 jpye 1970 # removing the 'glue' method now, as ports are now built in to gaphas.
182 jpye 1945
183     def pre_update(self,context):
184     #print "PRE-UPDATE BLOCK"
185     pass
186    
187     class DefaultBlockItem(BlockItem):
188     """
189     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
191     box with the input ports on the left and the output ports on the right.
192 jpye 1970
193     @TODO Not clear yet whether blocks with 'custom' representations should have
194     as their parent class: this class or BlockItem.
195 jpye 1945 """
196    
197     def __init__(self, blockinstance):
198    
199     self.blockinstance = blockinstance
200     inputs = len(blockinstance.blocktype.inputs)
201     outputs = len(blockinstance.blocktype.outputs)
202     super(DefaultBlockItem, self).__init__(64, 64)
203    
204     eq = EqualsConstraint
205     bal = BalanceConstraint
206     handles = self._handles
207     h_nw = handles[NW]
208     h_ne = handles[NE]
209     h_sw = handles[SW]
210     h_se = handles[SE]
211    
212 jpye 1970 _ports = []
213 jpye 1945 for i in range(inputs):
214 jpye 1970 p = PointPort(VariablePoint((0,0),strength=WEAK))
215     self._constraints.append(eq(p.point.x, h_nw.x))
216     self._constraints.append(bal(band=(h_nw.y, h_sw.y),v=p.point.y, balance=(0.5 + i)/inputs))
217     _ports.append(p)
218 jpye 1945
219     for i in range(outputs):
220 jpye 1970 p = PointPort(VariablePoint((0,0),strength=WEAK))
221     _ports.append(p)
222     self._constraints.append(eq(p.point.x, h_ne.x))
223     self._constraints.append(bal(band=(h_ne.y,h_se.y),v=p.point.y, balance=(0.5 + i)/outputs))
224 jpye 1945
225 jpye 1970 self._ports = _ports
226    
227 jpye 1945 def draw(self, context):
228     # draw the box itself
229     c = context.cairo
230     nw = self._handles[NW]
231     c.rectangle(nw.x, nw.y, self.width, self.height)
232     if context.hovered:
233     c.set_source_rgba(.8,.8,1, .8)
234     else:
235     c.set_source_rgba(1,1,1, .8)
236     c.fill_preserve()
237     c.set_source_rgb(0,0,0.8)
238     c.stroke()
239    
240     text_center(c,self.width/2,self.height/2,self.blockinstance.name)
241    
242     # now the draw the ports using the base class
243     super(DefaultBlockItem, self).draw(context)
244 jpye 1954

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