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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1970 - (show annotations) (download) (as text)
Sat Dec 27 07:19:35 2008 UTC (14 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
2 from gaphas.constraint import LineConstraint, LessThanConstraint, EqualsConstraint, Constraint, _update, BalanceConstraint
3 from gaphas.item import Line, SW, NE, NW, SE, Item, Handle
4 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
145
146 class BlockItem(ElementNoPorts):
147 """
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 """
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 phalfsize = 3
170 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 c.set_source_rgba(0.8,0.8,1, 0.8)
175 #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
181 # removing the 'glue' method now, as ports are now built in to gaphas.
182
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
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):
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 _ports = []
213 for i in range(inputs):
214 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
219 for i in range(outputs):
220 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
225 self._ports = _ports
226
227 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

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