Changeset 1637
- Timestamp:
- 07/16/07 08:26:30 (1 year ago)
- Files:
-
- gaphas/branches/hw/gaphas/canvas.py (modified) (4 diffs)
- gaphas/branches/hw/gaphas/constraint.py (modified) (2 diffs)
- gaphas/branches/hw/gaphas/examples.py (modified) (8 diffs)
- gaphas/branches/hw/gaphas/item.py (modified) (6 diffs)
- gaphas/branches/hw/gaphas/solver.py (modified) (1 diff)
- gaphas/branches/hw/gaphas/tests/test_canvas.py (added)
- gaphas/branches/hw/gaphas/tool.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
gaphas/branches/hw/gaphas/canvas.py
r1625 r1637 15 15 from gaphas.decorators import nonrecursive, async, PRIORITY_HIGH_IDLE 16 16 from state import observed, reversible_method, reversible_pair 17 from gaphas.constraint import Projector 17 18 18 19 … … 71 72 self._registered_views = set() 72 73 self._cache = WeakKeyDictionary() 74 75 self.proj = CanvasProjector(self) 73 76 74 77 solver = property(lambda s: s._solver) … … 497 500 # Make sure handles are marked (for constraint solving) 498 501 request_resolve = self._solver.request_resolve 499 for h in item.handles(): 500 request_resolve(h.x) 501 request_resolve(h.y) 502 for c in item.iconstraints(): 503 request_resolve(c) 502 504 503 505 if recursive: … … 597 599 598 600 601 602 class CanvasProjector(Projector): 603 def __init__(self, canvas): 604 super(CanvasProjector, self).__init__() 605 self._canvas = canvas 606 607 608 def _cproj(self, c, x=None, y=None, xy=None, **kw): 609 if x is not None: 610 for v, item in x.items(): 611 i2c = self._canvas.get_matrix_i2c(item).transform_point 612 v._value, _ = i2c(v._value, 0) 613 if y is not None: 614 for v, item in y.items(): 615 i2c = self._canvas.get_matrix_i2c(item).transform_point 616 _, v._value = i2c(0, v._value) 617 618 619 def _iproj(self, c, x=None, y=None, xy=None, **kw): 620 if x is not None: 621 for v, item in x.items(): 622 c2i = self._canvas.get_matrix_c2i(item).transform_point 623 v._value, _ = c2i(v._value, 0) 624 item.request_update() 625 if y is not None: 626 for v, item in y.items(): 627 c2i = self._canvas.get_matrix_c2i(item).transform_point 628 _, v._value = c2i(0, v._value) 629 item.request_update() 630 631 599 632 # Additional tests in @observed methods 600 633 __test__ = { gaphas/branches/hw/gaphas/constraint.py
r1634 r1637 490 490 491 491 492 def __call__(self, c, data):492 def __call__(self, c, *args, **kw): 493 493 """ 494 494 Decorator for Constraint.solve_for method to perform … … 498 498 f = c.solve_for 499 499 def wrapper(var): 500 self._cproj(c, data)500 self._cproj(c, *args, **kw) 501 501 f(var) 502 self._iproj(c, data)502 self._iproj(c, *args, **kw) 503 503 c.solve_for = wrapper 504 504 gaphas/branches/hw/gaphas/examples.py
r1625 r1637 45 45 """ 46 46 h = self._handles 47 hnw = h[NW] 48 hse = h[SE] 49 x0, y0 = float(hnw.x), float(hnw.y) 50 x1, y1 = float(hse.x), float(hse.y) 51 r = (x0, y0, x1 - x0, y1 - y0) 47 h_se = h[SE] 48 r = (0, 0, h_se.x, h_se.y) 52 49 por = point_on_rectangle(r, (x, y), border=True) 53 50 p = distance_rectangle_point(r, (x, y)) … … 172 169 inverse = Matrix(*view.matrix) 173 170 inverse.invert() 174 glue_distance, dummy = inverse.transform_distance(10, 0) 171 #glue_distance, dummy = inverse.transform_distance(10, 0) 172 glue_distance = 10 175 173 glue_point = None 176 174 glue_item = None 177 175 for i in view.canvas.get_all_items(): 178 176 if not i is item: 179 #ix, iy = matrix_w2i(i).transform_point(wx, wy)180 ix, iy = wx, wy177 v2i = view.get_matrix_v2i(i).transform_point 178 ix, iy = v2i(wx, wy) 181 179 try: 182 180 distance, point = i.glue(item, handle, ix, iy) … … 185 183 if distance <= glue_distance: 186 184 glue_distance = distance 187 glue_point = point 185 i2v = view.get_matrix_i2v(i).transform_point 186 glue_point = i2v(*point) 188 187 glue_item = i 189 188 except AttributeError: 190 189 pass 191 190 if glue_point: 192 x, y = glue_point193 handle.x, handle.y = glue_point191 v2i = view.get_matrix_v2i(item).transform_point 192 handle.x, handle.y = v2i(*glue_point) 194 193 return glue_item 195 194 … … 205 204 def side(handle, glued): 206 205 handles = glued.handles() 207 hx, hy = handle.x, handle.y 208 ax, ay = handles[NW].x, handles[NW].y 209 bx, by = handles[SE].x, handles[SE].y 206 hx, hy = view.get_matrix_i2v(item).transform_point(handle.x, handle.y) 207 ax, ay = view.get_matrix_i2v(glued).transform_point(handles[NW].x, handles[NW].y) 208 bx, by = view.get_matrix_i2v(glued).transform_point(handles[SE].x, handles[SE].y) 209 210 210 if abs(hx - ax) < 0.01: 211 return handles[NW], handles[SW] 211 return handles[NW], handles[SW], (hy - ay) / (by - ay) 212 212 elif abs(hy - ay) < 0.01: 213 return handles[NW], handles[NE] 213 return handles[NW], handles[NE], (hx - ax) / (bx - ax) 214 214 elif abs(hx - bx) < 0.01: 215 return handles[NE], handles[SE] 215 return handles[NE], handles[SE], (hy - ay) / (by - ay) 216 216 else: 217 return handles[SW], handles[SE] 217 return handles[SW], handles[SE], (hx - ax) / (bx - ax) 218 218 assert False 219 219 … … 221 221 def handle_disconnect(): 222 222 try: 223 view.canvas.solver.remove_constraint(handle._c1) 224 view.canvas.solver.remove_constraint(handle._c2) 223 item.remove_iconstraint(handle) 225 224 except KeyError: 226 225 pass # constraint was alreasy removed … … 240 239 241 240 242 h1, h2 = side(handle, glue_item) 241 assert False, 'not now!' 242 h1, h2, b = side(handle, glue_item) 243 243 handle._c1 = BalanceConstraint(band=(h1.x, h1.x), v=handle.x) 244 244 handle._c2 = BalanceConstraint(band=(h2.y, h2.y), v=handle.y) … … 254 254 if glue_item: 255 255 if isinstance(glue_item, Box): 256 h1, h2 = side(handle, glue_item)256 h1, h2, b = side(handle, glue_item) 257 257 258 258 # Make a constraint that keeps into account item coordinates. 259 handle._c1 = BalanceConstraint(band=(h1.x, h2.x), v=handle.x) 260 handle._c2 = BalanceConstraint(band=(h1.y, h2.y), v=handle.y) 261 view.canvas.solver.add_constraint(handle._c1) 262 view.canvas.solver.add_constraint(handle._c2) 259 c1 = BalanceConstraint(band=(h1.x, h2.x), v=handle.x, balance=b) 260 c2 = BalanceConstraint(band=(h1.y, h2.y), v=handle.y, balance=b) 261 view.canvas.proj(c1, x={h1.x: glue_item, h2.x: glue_item, handle.x: item}) 262 view.canvas.proj(c2, y={h1.y: glue_item, h2.y: glue_item, handle.y: item}) 263 item.add_iconstraint(handle, c1) 264 item.add_iconstraint(handle, c2) 263 265 264 266 handle.connected_to = glue_item … … 268 270 if handle.connected_to: 269 271 #print 'Handle.disconnect', view, item, handle 270 view.canvas.solver.remove_constraint(handle._c1) 271 view.canvas.solver.remove_constraint(handle._c2) 272 item.remove_iconstraint(handle) 272 273 273 274 gaphas/branches/hw/gaphas/item.py
r1620 r1637 126 126 self._matrix = Matrix() 127 127 self._handles = [] 128 self._constraints = [] 129 self._iconstraints = {} 130 131 132 def add_iconstraint(self, h, c): 133 if h not in self._iconstraints: 134 self._iconstraints[h] = set() 135 self._iconstraints[h].add(c) 136 self._canvas.solver.add_constraint(c) 137 138 139 def remove_iconstraint(self, h, c=None): 140 if c is None: # remove all handle's constraints 141 cons = self._iconstraints[h] 142 for c in cons: 143 self._canvas.solver.remove_constraint(c) 144 cons.clear() 145 else: 146 # remove specific constraint 147 self._canvas.solver.remove_constraint(c) 148 self._iconstraints[h].remove(c) 149 150 151 def iconstraints(self): 152 for cons in self._iconstraints.values(): 153 for c in cons: 154 yield c 155 128 156 129 157 @observed … … 149 177 "Canvas.add() and Canvas.remove().") 150 178 179 151 180 def setup_canvas(self): 152 181 """ … … 154 183 This method can be used to create constraints. 155 184 """ 156 pass 185 add = self.canvas.solver.add_constraint 186 for c in self._constraints: 187 add(c) 188 157 189 158 190 def teardown_canvas(self): … … 161 193 This method can be used to dispose constraints. 162 194 """ 195 super(Item, self).teardown_canvas() 163 196 for h in self.handles(): 164 197 h.disconnect() 198 199 for c in self._constraints: 200 self.canvas.solver.remove_constraint(c) 201 165 202 166 203 @observed … … 238 275 super(Element, self).__init__() 239 276 self._handles = [ h(strength=VERY_STRONG) for h in [Handle]*4 ] 240 self._constraints = [] 241 242 # create minimal size constraints277 278 eq = EqualsConstraint 279 lt = LessThanConstraint 243 280 handles = self._handles 244 281 h_nw = handles[NW] 282 h_ne = handles[NE] 283 h_sw = handles[SW] 245 284 h_se = handles[SE] 285 286 # create minimal size constraints 246 287 self._c_min_w = LessThanConstraint(smaller=h_nw.y, bigger=h_se.y, delta=10) 247 288 self._c_min_h = LessThanConstraint(smaller=h_nw.x, bigger=h_se.x, delta=10) 289 290 # setup constraints 291 self._constraints.extend([ 292 eq(a=h_nw.y, b=h_ne.y), 293 eq(a=h_nw.x, b=h_sw.x), 294 eq(a=h_se.y, b=h_sw.y), 295 eq(a=h_se.x, b=h_ne.x), 296 # set h_nw < h_se constraints 297 # with minimal size functionality 298 self._c_min_w, 299 self._c_min_h, 300 ]) 248 301 249 302 # set width/height when minimal size constraints exist 250 303 self.width = width 251 304 self.height = height 305 306 # immediately solve the constraints, ensuring the box is drawn okay 307 solve_for = (h_ne.y, h_sw.y, h_sw.x, h_ne.x) 308 for c, v in zip(self._constraints, solve_for): 309 c.solve_for(v) 252 310 253 311 … … 336 394 min_height = reversible_property(lambda s: s._c_min_h.delta, _set_min_height) 337 395 338 def setup_canvas(self):339 """340 >>> from canvas import Canvas341 >>> c=Canvas()342 >>> c.solver._constraints343 set([])344 >>> b = Element()345 >>> c.add(b)346 >>> b.canvas is c347 True348 >>> len(c.solver._constraints)349 8350 >>> len(c.solver._marked_cons)351 0352 >>> c.solver.solve()353 >>> len(c.solver._constraints)354 8355 >>> len(c.solver._marked_cons)356 0357 >>> b._handles[SE].pos = (25,30)358 >>> len(c.solver._marked_cons)359 4360 >>> c.solver.solve()361 >>> float(b._handles[NE].x)362 25.0363 >>> float(b._handles[SW].y)364 30.0365 """366 eq = EqualsConstraint367 lt = LessThanConstraint368 369 handles = self._handles370 h_nw = handles[NW]371 h_ne = handles[NE]372 h_sw = handles[SW]373 h_se = handles[SE]374 375 add = self.canvas.solver.add_constraint376 self._constraints = [377 add(eq(a=h_nw.y, b=h_ne.y)),378 add(eq(a=h_nw.x, b=h_sw.x)),379 add(eq(a=h_se.y, b=h_sw.y)),380 add(eq(a=h_se.x, b=h_ne.x)),381 # set h_nw < h_se constraints382 # with minimal size functionality383 add(self._c_min_w),384 add(self._c_min_h),385 ]386 387 # Immediately solve the constraints, ensuring the box is drawn okay388 solve_for = (h_ne.y, h_sw.y, h_sw.x, h_ne.x)389 for c, v in zip(self._constraints, solve_for):390 c.solve_for(v)391 392 396 393 def teardown_canvas(self):394 """395 Remove constraints created in setup_canvas().396 >>> from canvas import Canvas397 >>> c=Canvas()398 >>> c.solver._constraints399 set([])400 >>> b = Element()401 >>> c.add(b)402 >>> b.canvas is c403 True404 >>> len(c.solver._constraints)405 8406 >>> b.teardown_canvas()407 >>> len(c.solver._constraints)408 0409 """410 super(Element, self).teardown_canvas()411 for c in self._constraints:412 self.canvas.solver.remove_constraint(c)413 414 415 397 def point(self, x, y): 416 398 """ gaphas/branches/hw/gaphas/solver.py
r1631 r1637 350 350 351 351 352 def request_resolve(self, variable): 353 """ 354 Request resolving of the constraints for a variable. This does not 355 mark the variable itself as dirty. 356 """ 357 for c in variable._constraints: 358 if c not in self._marked_cons: 359 self._marked_cons.append(c) 352 def request_resolve(self, c): 353 """ 354 Request resolving of the constraint. 355 """ 356 self._marked_cons.append(c) 357 360 358 361 359 @observed gaphas/branches/hw/gaphas/tool.py
r1618 r1637 475 475 view = context.view 476 476 if self._grabbed_handle and self._grabbed_handle.connectable: 477 wx, wy = view.get_matrix_v2i(self._grabbed_item).transform_point(event.x, event.y)478 self.connect(view, self._grabbed_item, self._grabbed_handle, wx, wy)477 x, y = event.x, event.y 478 self.connect(view, self._grabbed_item, self._grabbed_handle, x, y) 479 479 finally: 480 480 context.view.queue_draw_item(context.view.hovered_item) … … 507 507 508 508 item.request_update() 509 #canvas.update_matrix(item)510 509 try: 511 510 if self._grabbed_handle.connectable: 512 self.glue(view, item, handle, x,y)511 self.glue(view, item, handle, event.x, event.y) 513 512 finally: 514 513 pass
