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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1973 - (show annotations) (download) (as text)
Mon Dec 29 06:53:09 2008 UTC (13 years, 6 months ago) by jpye
File MIME type: text/x-python
File size: 9282 byte(s)
Fixed ConnectorTool to work with proposed patch to Gaphas (sent to Gaphor mailing list).
1 import cairo
2 from gaphas.tool import HandleTool
3 from gaphas.connector import *
4
5 class DisconnectHandle(object):
6
7 def __init__(self, item, handle):
8 self.canvas = item.canvas
9 self.item = item
10 self.handle = handle
11
12 def __call__(self):
13 self.handle_disconnect()
14
15 def handle_disconnect(self):
16 canvas = self.canvas
17 item = self.item
18 handle = self.handle
19 try:
20 canvas.solver.remove_constraint(handle.connection_data)
21 except KeyError:
22 print 'constraint was already removed for', item, handle
23 pass # constraint was alreasy removed
24 else:
25 print 'constraint removed for', item, handle
26 handle.connection_data = None
27 handle.connected_to = None
28 # Remove disconnect handler:
29 handle.disconnect = None
30
31 class ConnectHandleTool(HandleTool):
32 """
33 Modified version of ConnectHandleTool (see Gaphas `tool.py`) that allows
34 for undefined item and handle in the `glue` method.
35 """
36 # distance between line and item
37 GLUE_DISTANCE = 10
38
39 def glue(self, view, line, handle, vpos):
40 """
41 Find an item for connection with a line.
42
43 Method looks for items in glue rectangle (which is defined by
44 ``vpos`` (vx, vy) and glue distance), then finds the closest port.
45
46 Glue position for closest port is calculated as well. Handle of
47 a line is moved to glue point to indicate that connection is about
48 to happen.
49
50 Found item and its connection port are returned. If item is not
51 found nor suitable port, then tuple `(None, None)` is returned.
52
53 :Parameters:
54 view
55 View used by user.
56 line
57 Connecting item.
58 handle
59 Handle of line (connecting item).
60 """
61 if handle and not handle.connectable:
62 return None
63
64 item, port, gluepos = self.find_connectable_port(view, vpos)
65
66 # if gluable port found...
67 if port is not None:
68 # check if line and found item can be connected on closest port
69 if not self.can_glue(view, line, handle, item, port):
70 item, port = None, None
71
72 if line is not None and handle is not None:
73 # transform coordinates from view space to the line space and
74 # update position of line's handle
75 v2i = view.get_matrix_v2i(line).transform_point
76 handle.pos = v2i(*glue_pos)
77 # else item and port will be set to None
78
79 return item, port
80
81 def find_connectable_port(self, view, vpos):
82 dist = self.GLUE_DISTANCE
83 max_dist = dist
84 port = None
85 glue_pos = None
86 item = None
87 v2i = view.get_matrix_v2i
88 vx, vy = vpos
89
90 rect = (vx - dist, vy - dist, dist * 2, dist * 2)
91 items = view.get_items_in_rectangle(rect, reverse=True)
92 for i in items:
93 if i is line:
94 continue
95 for p in i.ports():
96 if not p.connectable:
97 continue
98
99 ix, iy = v2i(i).transform_point(vx, vy)
100 pg, d = p.glue((ix, iy))
101
102 if d >= max_dist:
103 continue
104
105 item = i
106 port = p
107
108 # transform coordinates from connectable item space to view
109 # space
110 i2v = view.get_matrix_i2v(i).transform_point
111 glue_pos = i2v(*pg)
112
113 return item, port, glue_pos
114
115 def can_glue(self, view, line, handle, item, port):
116 """
117 Determine if line's handle can connect to a port of an item.
118
119 `True` is returned by default. Override this method to disallow
120 glueing in higher level of application stack (i.e. when classes of
121 line and item does not match).
122
123 :Parameters:
124 view
125 View used by user.
126 line
127 Item connecting to connectable item.
128 handle
129 Handle of line connecting to connectable item.
130 item
131 Connectable item.
132 port
133 Port of connectable item.
134 """
135 return True
136
137
138 def post_connect(self, line, handle, item, port):
139 """
140 The method is invoked just before connection is performed by
141 `ConnectHandleTool.connect` method. It can be overriden by deriving
142 tools to perform connection in higher level of application stack.
143
144 :Parameters:
145 line
146 Item connecting to connectable item.
147 handle
148 Handle of line connecting to connectable item.
149 item
150 Connectable item.
151 port
152 Port of connectable item.
153 """
154 pass
155
156
157 def connect(self, view, line, handle, vpos):
158 """
159 Connect a handle of a line to connectable item.
160
161 Connectable item is found by `ConnectHandleTool.glue` method.
162
163 :Parameters:
164 view
165 View used by user.
166 line
167 Connecting item.
168 handle
169 Handle of connecting item.
170 """
171 # find connectable item and its port
172 item, port = self.glue(view, line, handle, vpos)
173
174 # disconnect when
175 # - no connectable item
176 # - currently connected item is not connectable item
177 if not item \
178 or item and handle.connected_to is not item:
179 handle.disconnect()
180
181 # no connectable item, no connection
182 if not item:
183 return
184
185 # low-level connection
186 self.connect_handle(line, handle, item, port)
187 # connection in higher level of application stack
188 self.post_connect(line, handle, item, port)
189
190
191 def connect_handle(self, line, handle, item, port):
192 """
193 Create constraint between handle of a line and port of connectable
194 item.
195
196 :Parameters:
197 line
198 Connecting item.
199 handle
200 Handle of connecting item.
201 item
202 Connectable item.
203 port
204 Port of connectable item.
205 """
206 ConnectHandleTool.create_constraint(line, handle, item, port)
207
208 handle.connected_to = item
209 handle.disconnect = DisconnectHandle(line, handle)
210
211
212 def disconnect(self, view, line, handle):
213 """
214 Disconnect line (connecting item) from an item.
215
216 :Parameters:
217 view
218 View used by user.
219 line
220 Connecting item.
221 handle
222 Handle of connecting item.
223 """
224 if handle.disconnect:
225 handle.disconnect()
226
227
228 @staticmethod
229 def find_port(line, handle, item):
230 """
231 Find port of an item at position of line's handle.
232
233 :Parameters:
234 line
235 Line supposed to connect to an item.
236 handle
237 Handle of a line connecting to an item.
238 item
239 Item to be connected to a line.
240 """
241 port = None
242 max_dist = sys.maxint
243 canvas = item.canvas
244
245 # line's handle position to canvas coordinates
246 i2c = canvas.get_matrix_i2c(line)
247 hx, hy = i2c.transform_point(*handle.pos)
248
249 # from canvas to item coordinates
250 c2i = canvas.get_matrix_c2i(item)
251 ix, iy = c2i.transform_point(hx, hy)
252
253 # find the port using item's coordinates
254 for p in item.ports():
255 pg, d = p.glue((ix, iy))
256 if d >= max_dist:
257 continue
258 port = p
259 max_dist = d
260
261 return port
262
263
264 @staticmethod
265 def create_constraint(line, handle, item, port):
266 """
267 Create connection constraint between line's handle and item's port.
268
269 If constraint already exists, then it is removed and new constraint
270 is created instead.
271
272 :Parameters:
273 line
274 Line connecting to an item.
275 handle
276 Handle of a line connecting to an item.
277 item
278 Item to be connected to a line.
279 port
280 Item's port used for connection with a line.
281 """
282 canvas = line.canvas
283 solver = canvas.solver
284
285 if handle.connection_data:
286 solver.remove_constraint(handle.connection_data)
287
288 constraint = port.constraint(canvas, line, handle, item)
289 handle.connection_data = constraint
290 solver.add_constraint(constraint)
291
292
293 @staticmethod
294 def remove_constraint(line, handle):
295 """
296 Remove connection constraint created between line's handle and
297 connected item's port.
298
299 :Parameters:
300 line
301 Line connecting to an item.
302 handle
303 Handle of a line connecting to an item.
304 """
305 if handle.connection_data:
306 line.canvas.solver.remove_constraint(handle.connection_data)
307 handle.connection_data = None
308
309 class PortHandleTool(ConnectHandleTool):
310 """
311 Subclass of ConnectHandleTool that records connection information in the
312 LineInstance of a Line.
313 """
314 def post_connect(self,line, handle, item, port):
315 # this handle belongs to the line.
316 pass
317
318 # vim: sw=4:et:ai

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