Changeset 1551
- Timestamp:
- 07/02/07 11:08:18 (1 year ago)
- Files:
-
- gaphas/branches/hw/demo.py (modified) (3 diffs)
- gaphas/branches/hw/gaphas/canvas.py (modified) (1 diff)
- gaphas/branches/hw/gaphas/constraint.py (modified) (1 diff)
- gaphas/branches/hw/gaphas/examples.py (modified) (10 diffs)
- gaphas/branches/hw/gaphas/item.py (modified) (4 diffs)
- gaphas/branches/hw/gaphas/painter.py (modified) (2 diffs)
- gaphas/branches/hw/gaphas/tool.py (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
gaphas/branches/hw/demo.py
r1532 r1551 25 25 import cairo 26 26 from gaphas import Canvas, GtkView, View 27 from gaphas.examples import Box, Text, DefaultExampleTool27 from gaphas.examples import Box, Text, FatLine, DefaultExampleTool 28 28 from gaphas.item import Line, NW, SE 29 29 from gaphas.tool import PlacementTool, HandleTool … … 296 296 297 297 b=MyBox() 298 h = b.handles()[0] 299 h.x = 20 300 h.y = 20 298 301 b.min_width = 20 299 302 b.min_height = 30 300 print 'box', b301 303 b.matrix=(1.0, 0.0, 0.0, 1, 20,20) 302 304 b.width=b.height = 40 303 305 c.add(b) 304 306 305 bb=Box() 306 print 'box', bb 307 bb.matrix=(1.0, 0.0, 0.0, 1, 10,10) 308 c.add(bb, parent=b) 309 #v.selected_items = bb 310 311 # AJM: extra boxes: 312 bb=Box() 313 print 'box', bb 314 bb.matrix.rotate(math.pi/4.) 315 c.add(bb, parent=b) 316 for i in xrange(10): 317 bb=Box() 318 print 'box', bb 319 bb.matrix.rotate(math.pi/4.0 * i / 10.0) 320 c.add(bb, parent=b) 307 fl = FatLine() 308 h1, h2 = fl.handles() 309 h1.x = 50 310 h1.y = 50 311 fl.matrix.translate(50, 50) 312 c.add(fl) 313 fl.height = 50 314 fl.request_update() 315 316 # bb=Box() 317 # print 'box', bb 318 # bb.matrix=(1.0, 0.0, 0.0, 1, 10,10) 319 # c.add(bb, parent=b) 320 # #v.selected_items = bb 321 322 # # AJM: extra boxes: 323 # bb=Box() 324 # print 'box', bb 325 # bb.matrix.rotate(math.pi/4.) 326 # c.add(bb, parent=b) 327 # for i in xrange(1): 328 # bb=Box() 329 # print 'box', bb 330 # bb.matrix.rotate(math.pi/4.0 * i / 10.0) 331 # c.add(bb, parent=b) 321 332 322 333 t=MyText('Single line') … … 325 336 326 337 l=MyLine() 327 l.handles()[1].pos = (30, 30) 338 h = l.handles() 339 x, y = h[0].pos 340 h[0].x = 30 341 h[0].y = 30 342 h[1].x += h[0].x + 30 343 h[1].y += h[0].y + 30 328 344 l.split_segment(0, 3) 329 345 l.matrix.translate(30, 60) 346 print l, h[0].x, h[0].y, h[1].x, h[1].y 330 347 c.add(l) 331 l.orthogonal = True 348 print l, h[0].x, h[0].y, h[1].x, h[1].y 349 #l.orthogonal = True 332 350 333 351 off_y = 0 gaphas/branches/hw/gaphas/canvas.py
r1513 r1551 467 467 item._canvas_matrix_w2i.invert() 468 468 469 # Make sure handles are marked (for constraint solving)470 for h in item.handles():471 h.x.dirty()472 h.y.dirty()473 474 469 if recursive: 475 470 for child in self._tree.get_children(item): gaphas/branches/hw/gaphas/constraint.py
r1535 r1551 303 303 304 304 305 class LineConstraint(Constraint): 306 """ 307 Ensure a point is kept on a line, taking into account item 308 specific coordinates. 309 310 #>>> from solver import Variable 311 #>>> a, b = Variable(3.0), Variable(2.0) 312 #>>> lt = LessThanConstraint(smaller=a, bigger=b) 313 #>>> lt.solve_for('smaller') 314 #>>> a, b 315 #(Variable(3, 20), Variable(3, 20)) 316 #>>> b.value = 0.8 317 #>>> lt.solve_for('bigger') 318 #>>> a, b 319 #(Variable(0.8, 20), Variable(0.8, 20)) 320 """ 321 322 def __init__(self, canvas, connect_to_item, handle_1, handle_2, 323 connected_item, connected_handle): 324 super(LineConstraint, self).__init__(handle_1.x, 325 handle_1.y, 326 handle_2.x, 327 handle_2.y, 328 connected_handle.x, 329 connected_handle.y) 330 331 self._canvas = canvas 332 self._connect_to_item = connect_to_item 333 self._handle_1 = handle_1 334 self._handle_2 = handle_2 335 self._connected_item = connected_item 336 self._connected_handle = connected_handle 337 self.update_ratio() 338 339 340 def update_ratio(self): 341 """ 342 >>> from item import Handle, Item 343 >>> from canvas import Canvas 344 >>> c = Canvas() 345 >>> i1, i2 = Item(), Item() 346 >>> c.add(i1) 347 >>> c.add(i2) 348 >>> c.update_now() 349 >>> h1, h2, h3 = Handle(0, 0), Handle(30, 20), Handle(15, 4) 350 >>> eq = LineConstraint(c, i1, h1, h2, i2, h3) 351 >>> eq.ratio_x, eq.ratio_y 352 (0.5, 0.20000000000000001) 353 >>> h2.pos = 40, 30 354 >>> eq.solve_for(h3.x) 355 >>> eq.ratio_x, eq.ratio_y 356 (0.5, 0.20000000000000001) 357 >>> h3.pos 358 (Variable(20, 20), Variable(6, 20)) 359 """ 360 start = self._handle_1 361 end = self._handle_2 362 point = self._connected_handle 363 364 get_i2w = self._canvas.get_matrix_i2w 365 366 sx, sy = get_i2w(self._connect_to_item, calculate=True).transform_point(start.x, start.y) 367 ex, ey = get_i2w(self._connect_to_item).transform_point(end.x, end.y) 368 px, py = get_i2w(self._connected_item, calculate=True).transform_point(point.x, point.y) 369 370 try: 371 self.ratio_x = float(px - sx) / float(ex - sx) 372 except ZeroDivisionError: 373 self.ratio_x = 0.0 374 try: 375 self.ratio_y = float(py - sy) / float(ey - sy) 376 except ZeroDivisionError: 377 self.ratio_y = 0.0 378 379 def solve_for(self, var=None): 380 self._solve() 381 382 def _solve(self): 383 """ 384 Solve the equation for the connected_handle. 385 >>> from item import Handle, Item 386 >>> from canvas import Canvas 387 >>> c = Canvas() 388 >>> i1, i2 = Item(), Item() 389 >>> c.add(i1) 390 >>> c.add(i2) 391 >>> c.update_now() 392 >>> h1, h2, h3 = Handle(0, 0), Handle(30, 20), Handle(15, 4) 393 >>> eq = LineConstraint(c, i1, h1, h2, i2, h3) 394 >>> eq.solve_for(h3.x) 395 >>> h3.pos 396 (Variable(15, 20), Variable(4, 20)) 397 >>> h2.pos = 40, 30 398 >>> eq.solve_for(h3.x) 399 >>> h3.pos 400 (Variable(20, 20), Variable(6, 20)) 401 >>> i2.matrix.translate(5,5) 402 >>> i2.request_update() 403 >>> c.update_now() 404 >>> eq.solve_for(h3.x) 405 >>> h3.pos 406 (Variable(15, 20), Variable(1, 20)) 407 """ 408 start = self._handle_1 409 end = self._handle_2 410 point = self._connected_handle 411 412 get_i2w = self._canvas.get_matrix_i2w 413 get_w2i = self._canvas.get_matrix_w2i 414 415 sx, sy = get_i2w(self._connect_to_item).transform_point(start.x, start.y) 416 ex, ey = get_i2w(self._connect_to_item).transform_point(end.x, end.y) 417 418 px = sx + (ex - sx) * self.ratio_x 419 py = sy + (ey - sy) * self.ratio_y 420 421 point.x.value, point.y.value = \ 422 get_w2i(self._connected_item).transform_point(px, py) 423 # Need to queue a redraw of the manipulated item. 424 self._canvas.request_update(self._connected_item) 305 306 class BalanceConstraint(Constraint): 307 """ 308 Ensure that a variable @v is between values specified by @band 309 and in distance proportional from @band[0]. 310 311 Consider 312 >>> from solver import Variable, WEAK 313 >>> a, b, c = Variable(2.0), Variable(3.0), Variable(2.3, WEAK) 314 >>> bc = BalanceConstraint(band=(a,b), v=c) 315 >>> c.value = 2.4 316 >>> c 317 Variable(2.4, 10) 318 >>> bc.solve_for(c) 319 >>> a, b, c 320 (Variable(2, 20), Variable(3, 20), Variable(2.3, 10)) 321 322 Band does not have to be band[0] < band[1] 323 >>> a, b, c = Variable(3.0), Variable(2.0), Variable(2.45, WEAK) 324 >>> bc = BalanceConstraint(band=(a,b), v=c) 325 >>> c.value = 2.50 326 >>> c 327 Variable(2.5, 10) 328 >>> bc.solve_for(c) 329 >>> a, b, c 330 (Variable(3, 20), Variable(2, 20), Variable(2.45, 10)) 331 """ 332 333 def __init__(self, band=None, v=None): 334 super(BalanceConstraint, self).__init__(band[0], band[1], v) 335 self.band = band 336 b1, b2 = self.band 337 w = b2 - b1 338 if w != 0: 339 self.balance = (v - b1) / w 340 else: 341 self.balance = 0 342 self.v = v 343 print 'b', self.balance 344 345 def solve_for(self, var): 346 b1, b2 = self.band 347 w = b2 - b1 348 var.value = b1 + w * self.balance 425 349 426 350 gaphas/branches/hw/gaphas/examples.py
r1518 r1551 11 11 from solver import solvable 12 12 import tool 13 from constraint import LineConstraint13 from constraint import BalanceConstraint, LessThanConstraint, EqualsConstraint 14 14 from geometry import point_on_rectangle, distance_rectangle_point 15 15 from util import text_extents, text_align, text_multiline … … 28 28 c = context.cairo 29 29 nw = self._handles[NW] 30 c.rectangle( nw.x, nw.y, self.width, self.height)30 c.rectangle(0, 0, self.width, self.height) 31 31 if context.hovered: 32 32 c.set_source_rgba(.8,.8,1, .8) … … 50 50 r = (x0, y0, x1 - x0, y1 - y0) 51 51 por = point_on_rectangle(r, (x, y), border=True) 52 #print 'Point', r, (x, y), por53 return distance_rectangle_point(r, (x, y)), por52 p = distance_rectangle_point(r, (x, y)) 53 return p, por 54 54 55 55 … … 82 82 83 83 84 class FatLine(Item): 85 def __init__(self): 86 super(FatLine, self).__init__() 87 self._handles.extend((Handle(), Handle())) 88 89 90 def _set_height(self, height): 91 h1, h2 = self._handles 92 return h2.y + height 93 94 95 def _get_height(self): 96 h1, h2 = self._handles 97 return h2.y - h1.y 98 99 100 height = property(_get_height, _set_height) 101 102 103 def setup_canvas(self): 104 super(FatLine, self).setup_canvas() 105 h1, h2 = self._handles 106 h2.x = h1.x 107 add = self.canvas.solver.add_constraint 108 self._c1 = EqualsConstraint(a=h1.x, b=h2.x) 109 self._c2 = LessThanConstraint(smaller=h1.y, bigger=h2.y, delta=20) 110 add(self._c1) 111 add(self._c2) 112 113 114 def draw(self, context): 115 cr = context.cairo 116 cr.set_line_width(10) 117 cr.move_to(0, 0) 118 cr.line_to(0, self.height) 119 cr.stroke() 120 121 84 122 class ConnectingHandleTool(tool.HandleTool): 85 123 """ 86 124 This is a HandleTool which supports a simple connection algorithm, 87 using LineConstraint.125 using BalanceConstraint. 88 126 """ 89 127 … … 96 134 if not handle.connectable: 97 135 return 98 matrix_w2i = view.canvas.get_matrix_w2i99 matrix_i2w = view.canvas.get_matrix_i2w100 136 101 137 # Make glue distance depend on the zoom ratio (should be about 10 pixels) … … 105 141 for i in view.canvas.get_all_items(): 106 142 if not i is item: 107 ix, iy = matrix_w2i(i).transform_point(wx, wy) 143 #ix, iy = matrix_w2i(i).transform_point(wx, wy) 144 ix, iy = wx, wy 108 145 try: 109 146 distance, point = i.glue(item, handle, ix, iy) 110 # print distance, point111 147 # Transform distance to world coordinates 112 distance, dumy = matrix_i2w(i).transform_distance(distance, 0)148 #distance, dumy = matrix_i2w(i).transform_distance(distance, 0) 113 149 if distance <= glue_distance: 114 150 glue_distance = distance 115 glue_point = matrix_i2w(i).transform_point(*point)151 glue_point = point 116 152 glue_item = i 117 153 except AttributeError: 118 154 pass 119 155 if glue_point: 120 handle.x, handle.y = matrix_w2i(item).transform_point(*glue_point) 156 x, y = glue_point 157 handle.x, handle.y = glue_point 121 158 return glue_item 122 159 … … 131 168 """ 132 169 def side(handle, glued): 133 hx, hy = view.canvas.get_matrix_i2w(item).transform_point(handle.x, handle.y) 134 ax, ay = view.canvas.get_matrix_i2w(glued).transform_point(glued.handles()[0].x, glued.handles()[0].y) 135 bx, by = view.canvas.get_matrix_i2w(glued).transform_point(glued.handles()[2].x, glued.handles()[2].y) 170 handles = glued.handles() 171 hx, hy = handle.x, handle.y 172 ax, ay = handles[NW].x, handles[NW].y 173 bx, by = handles[SE].x, handles[SE].y 136 174 if abs(hx - ax) < 0.01: 137 side = 3175 return handles[NW], handles[SW] 138 176 elif abs(hy - ay) < 0.01: 139 side = 0177 return handles[NW], handles[NE] 140 178 elif abs(hx - bx) < 0.01: 141 side = 1179 return handles[NE], handles[SE] 142 180 else: 143 side = 2144 return side181 return handles[SW], handles[SE] 182 assert False 145 183 146 184 147 185 def handle_disconnect(): 148 186 try: 149 view.canvas.solver.remove_constraint(handle._connect_constraint) 187 view.canvas.solver.remove_constraint(handle._c1) 188 view.canvas.solver.remove_constraint(handle._c2) 150 189 except KeyError: 151 190 pass # constraint was alreasy removed … … 158 197 glue_item = self.glue(view, item, handle, wx, wy) 159 198 if glue_item and glue_item is handle.connected_to: 160 s = side(handle, glue_item)161 199 try: 162 view.canvas.solver.remove_constraint(handle._connect_constraint) 200 view.canvas.solver.remove_constraint(handle._c1) 201 view.canvas.solver.remove_constraint(handle._c2) 163 202 except KeyError: 164 pass # constraint was alreasy removed 165 handle._connect_constraint = LineConstraint(view.canvas, glue_item, glue_item.handles()[s], glue_item.handles()[(s+1)%4], item, handle) 166 view.canvas.solver.add_constraint(handle._connect_constraint) 203 pass # constraint was already removed 204 205 206 h1, h2 = side(handle, glue_item) 207 handle._c1 = BalanceConstraint(band=(h1.x, h1.x), v=handle.x) 208 handle._c2 = BalanceConstraint(band=(h2.y, h2.y), v=handle.y) 209 view.canvas.solver.add_constraint(handle._c1) 210 view.canvas.solver.add_constraint(handle._c2) 167 211 handle.disconnect = handle_disconnect 168 212 return … … 174 218 if glue_item: 175 219 if isinstance(glue_item, Box): 176 s = side(handle, glue_item) 220 h1, h2 = side(handle, glue_item) 221 177 222 # Make a constraint that keeps into account item coordinates. 178 handle._connect_constraint = LineConstraint(view.canvas, glue_item, glue_item.handles()[s], glue_item.handles()[(s+1)%4], item, handle) 179 view.canvas.solver.add_constraint(handle._connect_constraint) 223 handle._c1 = BalanceConstraint(band=(h1.x, h2.x), v=handle.x) 224 handle._c2 = BalanceConstraint(band=(h1.y, h2.y), v=handle.y) 225 view.canvas.solver.add_constraint(handle._c1) 226 view.canvas.solver.add_constraint(handle._c2) 227 180 228 handle.connected_to = glue_item 181 229 handle.disconnect = handle_disconnect … … 184 232 if handle.connected_to: 185 233 #print 'Handle.disconnect', view, item, handle 186 view.canvas.solver.remove_constraint(handle._connect_constraint) 234 view.canvas.solver.remove_constraint(handle._c1) 235 view.canvas.solver.remove_constraint(handle._c2) 187 236 188 237 gaphas/branches/hw/gaphas/item.py
r1540 r1551 348 348 eq = EqualsConstraint 349 349 lt = LessThanConstraint 350 h = self._handles 350 351 handles = self._handles 352 h_nw = handles[NW] 353 h_ne = handles[NE] 354 h_sw = handles[SW] 355 h_se = handles[SE] 356 357 w, h = self.width, self.height 358 x0, y0 = self._canvas.get_matrix_i2w(self, calculate=True).transform_point(0, 0) 359 h_nw.x = x0 360 h_nw.y = y0 361 h_se.x = x0 + w 362 h_se.y = y0 + h 363 351 364 add = self.canvas.solver.add_constraint 352 365 self._constraints = [ 353 add(eq(a=h[NW].y, b=h[NE].y)), 354 add(eq(a=h[SW].y, b=h[SE].y)), 355 add(eq(a=h[NW].x, b=h[SW].x)), 356 add(eq(a=h[NE].x, b=h[SE].x)), 357 # set h[NW] < h[SE] constraints, h[NE] and h[SW] positions will 358 # follow thanks to equality constraints above 359 # TODO: use LessThanConstraint.delta to calculate minimal size 360 add(lt(smaller=h[NW].x, bigger=h[SE].x)), 361 add(lt(smaller=h[NW].y, bigger=h[SE].y)), 362 ] 366 add(eq(a=h_nw.y, b=h_ne.y)), 367 add(eq(a=h_sw.y, b=h_se.y)), 368 add(eq(a=h_nw.x, b=h_sw.x)), 369 add(eq(a=h_ne.x, b=h_se.x)), 370 # set h_nw < h_se and h_sw < h_ne constraints 371 # with minimal size functionality 372 add(lt(smaller=h_nw.x, bigger=h_se.x, delta=10)), 373 add(lt(smaller=h_nw.y, bigger=h_se.y, delta=10)), 374 add(lt(smaller=h_sw.x, bigger=h_ne.x, delta=10)), 375 add(lt(smaller=h_ne.y, bigger=h_sw.y, delta=10)), 376 ] 363 377 364 378 # Immediately solve the constraints, ensuring the box is drawn okay 365 solve_for = (h [NE].y, h[SW].y, h[SW].x, h[NE].x)379 solve_for = (h_ne.y, h_sw.y, h_sw.x, h_ne.x) 366 380 for c, v in zip(self._constraints, solve_for): 367 381 c.solve_for(v) 382 368 383 369 384 def teardown_canvas(self): … … 389 404 390 405 391 def pre_update(self, context):392 """393 Make sure handles do not overlap during movement.394 Make sure the first handle (normally NW) is located at (0, 0).395 396 >>> from canvas import Canvas397 >>> c = Canvas()398 >>> e = Element()399 >>> c.add(e)400 >>> e.min_width = e.min_height = 0401 >>> c.update_now()402 >>> e._handles403 [<Handle object on (0, 0)>, <Handle object on (10, 0)>, <Handle object on (10, 10)>, <Handle object on (0, 10)>]404 >>> e._handles[0].x += 1405 >>> map(float, e._handles[0].pos)406 [1.0, 0.0]407 >>> e.pre_update(None)408 >>> e._handles409 [<Handle object on (0, 0)>, <Handle object on (9, 0)>, <Handle object on (9, 10)>, <Handle object on (-1, 10)>]410 """411 h_nw = self._handles[NW]412 x, y = map(float, h_nw.pos)413 if not x:414 x = float(self._handles[SW].x)415 if x:416 self.matrix.translate(x, 0)417 self._canvas.request_matrix_update(self)418 h_nw.x = 0419 for h in self._handles[1:4]:420 h.x -= x421 if not y:422 y = float(self._handles[NE].y)423 if y:424 self.matrix.translate(0, y)425 self._canvas.request_matrix_update(self)426 h_nw.y = 0427 for h in self._handles[1:4]:428 h.y -= y429 430 if self.width < self.min_width:431 self.width = self.min_width432 if self.height < self.min_height:433 self.height = self.min_height434 435 def update(self, context):436 """437 Do nothing during update.438 """439 pass440 441 406 def point(self, x, y): 442 407 """ … … 543 508 Setup constraints. In this case orthogonal. 544 509 """ 510 super(Line, self).setup_canvas() 545 511 self.orthogonal = self.orthogonal 546 512 … … 699 665 See Item.draw(context). 700 666 """ 667 m = self._canvas.get_matrix_w2i(self) 668 701 669 def draw_line_end(handle, angle, draw): 702 670 cr = context.cairo 703 671 cr.save() 704 672 try: 705 cr.translate( handle.x, handle.y)673 cr.translate(*m.transform_point(handle.x, handle.y)) 706 674 cr.rotate(angle) 707 675 draw(context) 708 676 finally: 709 677 cr.restore() 678 710 679 cr = context.cairo 711 680 cr.set_line_width(self.line_width) 712 681 draw_line_end(self._handles[0], self._head_angle, self.draw_head) 713 for h in self._handles[1:-1]: 714 cr.line_to(float(h.x), float(h.y)) 682 h = self._handles[0] 683 cr.move_to(*m.transform_point(h.x, h.y)) 684 for h in self._handles[1:]: 685 cr.line_to(*m.transform_point(h.x, h.y)) 715 686 h0, h1 = self._handles[-2:] 716 687 draw_line_end(self._handles[-1], self._tail_angle, self.draw_tail) gaphas/branches/hw/gaphas/painter.py
r1529 r1551 261 261 cairo.identity_matrix() 262 262 cairo.translate(*m.transform_point(h.x, h.y)) 263 cairo.translate(h.x, h.y) 263 264 cairo.rectangle(-4, -4, 9, 9) 264 265 cairo.fill() 265 266 finally: 266 267 cairo.restore() 268 267 269 268 270 def _draw_item(self, item, view, cairo, area=None): … … 317 319 cairo.identity_matrix() 318 320 cairo.set_antialias(ANTIALIAS_NONE) 319 cairo.translate( *m.transform_point(h.x, h.y))321 cairo.translate(h.x, h.y) 320 322 cairo.rectangle(-4, -4, 8, 8) 321 323 cairo.set_source_rgba(r, g, b, opacity) gaphas/branches/hw/gaphas/tool.py
r1518 r1551 339 339 # Move the item and schedule it for an update 340 340 i.matrix.translate(*get_matrix_w2i(i).transform_distance(dx, dy)) 341 for h in i.handles(): 342 h.x += dx 343 h.y += dy 341 344 canvas.request_matrix_update(i) 342 345 … … 377 380 if not h.movable: 378 381 continue 379 wx, wy = view.canvas.get_matrix_i2w(item).transform_point(h.x, h.y) 382 #wx, wy = view.canvas.get_matrix_i2w(item).transform_point(h.x, h.y) 383 wx, wy = h.x, h.y 380 384 x, y = view.transform_point_w2c(wx, wy) 381 385 if abs(x - event.x) < 6 and abs(y - event.y) < 6: … … 426 430 def move(self, view, item, handle, x, y): 427 431 """ 428 Move the handle to position (x,y). 429 This version already has some special behavior implemented for 430 gaphas.item.Element. The min_width and min_height properties of 431 Element are used to restrict the handles from overlapping each other. 432 """ 433 # Special behavior for Elements: 434 if isinstance(item, Element): 435 index = list(item.handles()).index(handle) 436 opposite = item.handles()[(index + 2) % 4] 437 438 if index == 0 or index == 3: 439 if opposite.x - x < item.min_width: 440 x = opposite.x - item.min_width 441 else: 442 if x - opposite.x < item.min_width: 443 x = opposite.x + item.min_width 444 445 if index == 0 or index == 1: 446 if opposite.y - y < item.min_height: 447 y = opposite.y - item.min_height 448 else: 449 if y - opposite.y < item.min_height: 450 y = opposite.y + item.min_height 451 452 handle.x = x 453 handle.y = y 432 Move the handle to position (x,y). If handle changed the position 433 of an item, then move the item, too. 434 """ 435 handle.x += x 436 handle.y += y 437 438 # calculate current position 439 matrix_w2i = view.canvas.get_matrix_w2i(item) 440 x1 = min(h.x for h in item.handles()) 441 y1 = min(h.y for h in item.handles()) 442 dx, dy = matrix_w2i.transform_point(x1, y1) 443 item.matrix.translate(dx, dy) 444 445 454 446 455 447 def glue(self, view, item, handle, wx, wy): … … 478 470 item, handle = self.find_handle(view, event) 479 471 if handle: 472 self.last_x, self.last_y = event.x, event.y 480 473 # Deselect all items unless CTRL or SHIFT is pressed 481 474 # or the item is already selected. … … 530 523 view.queue_draw_item(item) 531 524 532 # Calculate the distance the item has to be moved 525 dx, dy = view.transform_distance_c2w(event.x - self.last_x, 526 event.y - self.last_y) 533 527 wx, wy = view.transform_point_c2w(event.x, event.y) 534 x, y = canvas.get_matrix_w2i(item).transform_point(wx, wy)535 528 536 529 # Do the actual move: 537 self.move(view, item, handle, x,y)530 self.move(view, item, handle, dx, dy) 538 531 539 532 item.request_update() … … 544 537 finally: 545 538 pass 539 self.last_x, self.last_y = event.x, event.y 546 540 return True 547 541 else: … … 624 618 x, y = view.transform_point_c2w(x, y) 625 619 item.matrix.translate(x, y) 620 h = item.handles()[0] 621 h.x = x 622 h.y = y 626 623 return item 627 624
