Changeset 1597
- Timestamp:
- 07/08/07 11:38:16 (1 year ago)
- Files:
-
- gaphas/branches/hw/README.txt (modified) (2 diffs)
- gaphas/branches/hw/demo.py (modified) (1 diff)
- gaphas/branches/hw/demo_profile.py (modified) (1 diff)
- gaphas/branches/hw/gaphas/canvas.py (modified) (5 diffs)
- gaphas/branches/hw/gaphas/constraint.py (modified) (2 diffs)
- gaphas/branches/hw/gaphas/geometry.py (modified) (4 diffs)
- gaphas/branches/hw/gaphas/item.py (modified) (6 diffs)
- gaphas/branches/hw/gaphas/painter.py (modified) (3 diffs)
- gaphas/branches/hw/gaphas/tool.py (modified) (2 diffs)
- gaphas/branches/hw/gaphas/util.py (modified) (1 diff)
- gaphas/branches/hw/gaphas/view.py (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
gaphas/branches/hw/README.txt
r1179 r1597 87 87 The context contains: 88 88 89 parent: parent item of the item, or None90 children: child items of this item (do not need to force updates for those)91 89 cairo: a CairoContext, this can be used to calculate the dimensions of text 92 90 for example … … 106 104 view: the view we're drawing to 107 105 cairo: the CairoContext to draw to 108 parent: parent item of the item, or None109 children: child items of this item (do not need to force updates for those)110 106 selected: True if the item is actually selected in the view 111 107 focused: True if the item has the focus gaphas/branches/hw/demo.py
r1557 r1597 381 381 382 382 if __name__ == '__main__': 383 main() 384 383 import sys 384 if '-p' in sys.argv: 385 print 'Profiling...' 386 import hotshot, hotshot.stats 387 prof = hotshot.Profile('demo-gaphas.prof') 388 prof.runcall(main) 389 prof.close() 390 stats = hotshot.stats.load('demo-gaphas.prof') 391 stats.strip_dirs() 392 stats.sort_stats('time', 'calls') 393 stats.print_stats(20) 394 else: 395 main() 385 396 # vim: sw=4:et: gaphas/branches/hw/demo_profile.py
r1509 r1597 177 177 c.add(bb, parent=b) 178 178 179 for i in range(count): 180 bb = MyBox() 181 bb.width = bb.height = 15 182 x = int(i % 4) * 20 183 y = int(i / 4) * 20 184 bb.matrix.translate(5 + x, 100 + y) 185 c.add(bb) 186 179 187 t=MyText('Single line') 180 188 t.matrix.translate(70,70) gaphas/branches/hw/gaphas/canvas.py
r1558 r1597 365 365 """ 366 366 self._in_update = True 367 dirty_items = [] 367 368 # Order the dirty items, so they are updated bottom to top 369 dirty_items = [ item for item in reversed(self._tree.nodes) \ 370 if item in self._dirty_items ] 371 368 372 # dirty_items is a subset of dirty_matrix_items 369 373 dirty_matrix_items = set(self._dirty_matrix_items) … … 371 375 cairo_context = self._obtain_cairo_context() 372 376 373 # Order the dirty items, so they are updated bottom to top 374 dirty_items = ( item for item in reversed(self._tree.nodes) \ 375 if item in self._dirty_items ) 377 for item in dirty_matrix_items: 378 self._update_handles(item) 376 379 377 380 context_map = dict() 378 381 for item in dirty_items: 379 c = Context(parent=self._tree.get_parent(item), 380 children=self._tree.get_children(item), 381 cairo=cairo_context) 382 c = Context(cairo=cairo_context) 382 383 context_map[item] = c 383 384 try: … … 392 393 self._solver.solve() 393 394 394 # Order the dirty items, so they are updated bottom to top395 dirty_items = ( item for item in reversed(self._tree.nodes) \396 if item in self._dirty_items )397 398 395 dirty_matrix_items.update(self._dirty_matrix_items) 399 396 self.update_matrices() … … 403 400 c = context_map[item] 404 401 except KeyError: 405 c = Context(parent=self._tree.get_parent(item), 406 children=self._tree.get_children(item), 407 cairo=cairo_context) 402 c = Context(cairo=cairo_context) 408 403 try: 409 404 item.update(c) … … 475 470 request_resolve(h.x) 476 471 request_resolve(h.y) 472 477 473 478 474 if recursive: 479 475 for child in self._tree.get_children(item): 480 476 self.update_matrix(child) 477 478 def _update_handles(self, item): 479 """ 480 Update handle positions so the first handle is always located at (0, 0). 481 482 >>> from item import Element 483 >>> c = Canvas() 484 >>> e = Element() 485 >>> c.add(e) 486 >>> e.min_width = e.min_height = 0 487 >>> c.update_now() 488 >>> e.handles() 489 [<Handle object on (0, 0)>, <Handle object on (10, 0)>, <Handle object on (10, 10)>, <Handle object on (0, 10)>] 490 491 >>> e.handles()[0].x += 1 492 >>> map(float, e.handles()[0].pos) 493 [1.0, 0.0] 494 >>> c._update_handles(e) 495 >>> e.handles() 496 [<Handle object on (0, 0)>, <Handle object on (9, 0)>, <Handle object on (9, 10)>, <Handle object on (-1, 10)>] 497 498 >>> e.handles()[0].x += 1 499 >>> e.handles() 500 [<Handle object on (1, 0)>, <Handle object on (9, 0)>, <Handle object on (9, 10)>, <Handle object on (-1, 10)>] 501 >>> c._update_handles(e) 502 >>> e.handles() 503 [<Handle object on (0, 0)>, <Handle object on (8, 0)>, <Handle object on (8, 10)>, <Handle object on (-2, 10)>] 504 505 """ 506 handles = item.handles() 507 if not handles: 508 return 509 x, y = map(float, handles[0].pos) 510 if x: 511 item.matrix.translate(x, 0) 512 for h in handles: 513 h.x._value -= x 514 if y: 515 item.matrix.translate(0, y) 516 for h in handles: 517 h.y -= y 481 518 482 519 def register_view(self, view): gaphas/branches/hw/gaphas/constraint.py
r1551 r1597 124 124 else: 125 125 self.b.value = self.a.value 126 127 128 class CenterConstraint(Constraint): 129 """ 130 Simple Constraint, takes three arguments: 'a', 'b' and center. 131 When solved, the constraint ensures 'center' is located in the middle 132 of 'a' and 'b'. 133 134 >>> from solver import Variable 135 >>> a, b, center = Variable(1.0), Variable(3.0), Variable() 136 >>> eq = CenterConstraint(a, b, center) 137 >>> eq.solve_for(a) 138 >>> a 139 Variable(1, 20) 140 >>> center 141 Variable(2, 20) 142 >>> a.value = 10 143 >>> eq.solve_for(b) 144 >>> b 145 Variable(3, 20) 146 >>> center 147 Variable(6.5, 20) 148 """ 149 150 def __init__(self, a=None, b=None, center=None): 151 super(CenterConstraint, self).__init__(a, b, center) 152 self.a = a 153 self.b = b 154 self.center = center 155 156 def solve_for(self, var): 157 assert var in (self.a, self.b, self.center) 158 159 self.center.value = (self.a.value + self.b.value) / 2.0 126 160 127 161 … … 349 383 350 384 385 386 class BalanceConstraint(Constraint): 387 """ 388 Ensure that a variable @v is between values specified by @band 389 and in distance proportional from @band[0]. 390 391 Consider 392 >>> from solver import Variable, WEAK 393 >>> a, b, c = Variable(2.0), Variable(3.0), Variable(2.3, WEAK) 394 >>> bc = BalanceConstraint(band=(a,b), v=c) 395 >>> c.value = 2.4 396 >>> c 397 Variable(2.4, 10) 398 >>> bc.solve_for(c) 399 >>> a, b, c 400 (Variable(2, 20), Variable(3, 20), Variable(2.3, 10)) 401 402 Band does not have to be band[0] < band[1] 403 >>> a, b, c = Variable(3.0), Variable(2.0), Variable(2.45, WEAK) 404 >>> bc = BalanceConstraint(band=(a,b), v=c) 405 >>> c.value = 2.50 406 >>> c 407 Variable(2.5, 10) 408 >>> bc.solve_for(c) 409 >>> a, b, c 410 (Variable(3, 20), Variable(2, 20), Variable(2.45, 10)) 411 """ 412 413 def __init__(self, band=None, v=None): 414 super(BalanceConstraint, self).__init__(band[0], band[1], v) 415 self.band = band 416 b1, b2 = self.band 417 w = b2 - b1 418 if w != 0: 419 self.balance = (v - b1) / w 420 else: 421 self.balance = 0 422 self.v = v 423 424 425 def solve_for(self, var): 426 b1, b2 = self.band 427 w = b2 - b1 428 var.value = b1 + w * self.balance 429 430 431 351 432 if __name__ == '__main__': 352 433 import doctest, sys gaphas/branches/hw/gaphas/geometry.py
r1518 r1597 133 133 >>> r=Rectangle(5, 7, 20, 25) 134 134 >>> r + (0, 0) 135 Rectangle(0, 0, 25, 32) 135 Traceback (most recent call last): 136 ... 137 AttributeError: Can only add Rectangle or tuple (x, y, width, height), not (0, 0). 136 138 >>> r + (20, 30, 40, 50) 137 139 Rectangle(5, 7, 55, 73) … … 149 151 Traceback (most recent call last): 150 152 ... 151 AttributeError: Don't know how to handle <type 'str'> aap. Convert to a Rectangle first.152 """ 153 if isinstance(obj, Rectangle) or len(obj) == 4:153 AttributeError: Can only add Rectangle or tuple (x, y, width, height), not 'aap'. 154 """ 155 try: 154 156 x, y, width, height = obj 155 x1, y1 = x + width, y + height 156 elif len(obj) == 2: 157 # extend using a point 158 x, y = obj 159 width, height = 0, 0 160 x1, y1 = obj 161 else: 162 raise AttributeError, "Don't know how to handle %s %s." \ 163 " Convert to a Rectangle first." % (type(obj), obj) 157 except ValueError: 158 raise AttributeError, "Can only add Rectangle or tuple (x, y, width, height), not %s." % repr(obj) 159 x1, y1 = x + width, y + height 164 160 if self: 165 ox1, oy1 = self.x 1, self.y1161 ox1, oy1 = self.x + self.width, self.y + self.height 166 162 self.x = min(self.x, x) 167 163 self.y = min(self.y, y) … … 195 191 Traceback (most recent call last): 196 192 ... 197 AttributeError: Don't know how to handle <type 'str'> aap. Convert to a Rectangle first.198 """ 199 if isinstance(obj, Rectangle) or len(obj) == 4:193 AttributeError: Can only substract Rectangle or tuple (x, y, width, height), not 'aap'. 194 """ 195 try: 200 196 x, y, width, height = obj 201 x1, y1 = x + width, y + height202 else:203 raise AttributeError, "Don't know how to handle %s %s." \204 " Convert to a Rectangle first." % (type(obj), obj) 197 except ValueError: 198 raise AttributeError, "Can only substract Rectangle or tuple (x, y, width, height), not %s." % repr(obj) 199 x1, y1 = x + width, y + height 200 205 201 if self: 206 ox1, oy1 = self.x 1, self.y1202 ox1, oy1 = self.x + self.width, self.y + self.height 207 203 self.x = max(self.x, x) 208 204 self.y = max(self.y, y) … … 238 234 Traceback (most recent call last): 239 235 ... 240 AttributeError: Don't know how to handle <type 'str'> aap. Convert to a Rectangle or tuple first.241 """ 242 if isinstance(obj, Rectangle) or len(obj) == 4:236 AttributeError: Should compare to Rectangle, tuple (x, y, width, height) or point (x, y), not 'aap'. 237 """ 238 try: 243 239 x, y, width, height = obj 244 240 x1, y1 = x + width, y + width 245 e lif len(obj) == 2:241 except ValueError: 246 242 # point 247 x, y = obj248 x1, y1= obj249 else:250 raise AttributeError, "Don't know how to handle %s %s." \251 " Convert to a Rectangle or tuple first." % (type(obj),obj)243 try: 244 x, y = obj 245 x1, y1 = obj 246 except ValueError: 247 raise AttributeError, "Should compare to Rectangle, tuple (x, y, width, height) or point (x, y), not %s." % repr(obj) 252 248 return x >= self.x and x1 <= self.x1 and \ 253 249 y >= self.y and y1 <= self.y1 gaphas/branches/hw/gaphas/item.py
r1557 r1597 10 10 from matrix import Matrix 11 11 from geometry import distance_line_point, distance_rectangle_point 12 from solver import solvable, WEAK, NORMAL, STRONG 12 from solver import solvable, WEAK, NORMAL, STRONG, VERY_STRONG 13 13 from constraint import EqualsConstraint, LessThanConstraint 14 14 from state import observed, reversible_pair, reversible_property, disable_dispatching … … 237 237 def __init__(self, width=10, height=10): 238 238 super(Element, self).__init__() 239 self._handles = [ h(strength= STRONG) for h in [Handle]*4 ]239 self._handles = [ h(strength=VERY_STRONG) for h in [Handle]*4 ] 240 240 self._constraints = [] 241 241 self._min_width = 10 … … 251 251 20.0 252 252 >>> b._handles[NW].x 253 Variable(0, 30)253 Variable(0, 40) 254 254 >>> b._handles[SE].x 255 Variable(20, 30)255 Variable(20, 40) 256 256 """ 257 257 if width < self.min_width: … … 280 280 10.0 281 281 >>> b._handles[NW].y 282 Variable(0, 30)282 Variable(0, 40) 283 283 >>> b._handles[SE].y 284 Variable(10, 30)284 Variable(10, 40) 285 285 """ 286 286 if height < self.min_height: … … 329 329 True 330 330 >>> len(c.solver._constraints) 331 6331 8 332 332 >>> len(c.solver._marked_cons) 333 333 0 334 334 >>> c.solver.solve() 335 335 >>> len(c.solver._constraints) 336 6336 8 337 337 >>> len(c.solver._marked_cons) 338 338 0 … … 387 387 True 388 388 >>> len(c.solver._constraints) 389 6389 8 390 390 >>> b.teardown_canvas() 391 391 >>> len(c.solver._constraints) gaphas/branches/hw/gaphas/painter.py
r1556 r1597 81 81 the Item.draw() method. 82 82 """ 83 self.painter._draw_items(self. children,83 self.painter._draw_items(self._item.canvas.get_children(self._item), 84 84 self.view, 85 85 self.cairo, … … 101 101 cairo=cairo, 102 102 _area=area, 103 parent=view.canvas.get_parent(item), 104 children=view.canvas.get_children(item), 103 _item=item, 105 104 selected=(item in view.selected_items), 106 105 focused=(item is view.focused_item), … … 271 270 cairo = CairoBoundingBoxContext(cairo) 272 271 super(BoundingBoxPainter, self)._draw_item(item, view, cairo) 273 self._draw_handles(item, view, cairo) 274 view.set_item_bounding_box(item, cairo.get_bounds()) 272 bounds = cairo.get_bounds() 273 274 # Update bounding box with handles. 275 #transform_i2c = (view.canvas.get_matrix_i2w(item) * view._matrix).transform_point 276 transform_i2c = view.canvas.get_matrix_i2w(item).transform_point 277 for h in item.handles(): 278 cx, cy = transform_i2c(h.x, h.y) 279 bounds += (cx - 5, cy - 5, 9, 9) 280 281 bounds.expand(1) 282 view.set_item_bounding_box(item, bounds) 283 275 284 276 285 def _draw_items(self, items, view, cairo, area=None): gaphas/branches/hw/gaphas/tool.py
r1551 r1597 377 377 Find item's handle at (event.x, event.y) 378 378 """ 379 transform_point = view.canvas.get_matrix_i2w(item).transform_point 380 e_x, e_y = view.transform_point_c2w(event.x, event.y) 381 dx, dy = view.transform_distance_c2w(6, 6) 379 382 for h in item.handles(): 380 383 if not h.movable: 381 384 continue 382 #wx, wy = view.canvas.get_matrix_i2w(item).transform_point(h.x, h.y)385 #wx, wy = transform_point(h.x, h.y) 383 386 wx, wy = h.x, h.y 384 x, y = view.transform_point_w2c(wx, wy) 385 if abs(x - event.x) < 6 and abs(y - event.y) < 6: 387 if -dx < (wx - e_x) < dx and -dy < (wy - e_y) < dy: 386 388 return h 387 389 return None … … 531 533 532 534 item.request_update() 533 canvas.update_matrix(item)535 #canvas.update_matrix(item) 534 536 try: 535 537 if self._grabbed_handle.connectable: gaphas/branches/hw/gaphas/util.py
r1249 r1597 92 92 'bold' in font and cairo.FONT_WEIGHT_BOLD \ 93 93 or cairo.FONT_WEIGHT_NORMAL) 94 cr.set_font_size( int(font[-1]))94 cr.set_font_size(float(font[-1])) 95 95 96 96 gaphas/branches/hw/gaphas/view.py
r1529 r1597 390 390 self.canvas = canvas 391 391 392 # Set background to white. 393 self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#FFF')) 394 395 self._update_bounding_box = set() 396 392 397 def emit(self, *args, **kwargs): 393 398 """ … … 491 496 viewport_size=allocation.height) 492 497 498 @async(single=False, priority=PRIORITY_HIGH_IDLE) 499 def _idle_queue_draw_item(self, *items): 500 self.queue_draw_item(*items) 501 493 502 def queue_draw_item(self, *items): 494 503 """ … … 504 513 except KeyError: 505 514 pass # No bounds calculated yet? bummer. 506 #else:507 # #self.queue_draw_area(b.x - 1, b.y - 1,508 # # b.width + 2, b.height + 2)509 # self.queue_draw_area(b.x, b.y,510 # b.width, b.height)511 515 512 516 def queue_draw_area(self, x, y, w, h): … … 545 549 # Do not update items that require a full update (or are removed) 546 550 dirty_matrix_items = dirty_matrix_items.difference(dirty_items) 547 #dirty_items.update(dirty_matrix_items)548 #dirty_matrix_items.clear()549 551 550 552 removed_items = dirty_items.difference(self._canvas.get_all_items()) … … 583 585 self.dropzone_item = None 584 586 585 # Pseudo-draw586 cr = self.window.cairo_create()587 cr.rectangle(0,0,0,0)588 cr.clip()589 590 self.update_bounding_box(cr, dirty_items)591 592 for i in dirty_items:593 self.queue_draw_item(i)594 595 587 self.update_adjustments() 588 589 self._update_bounding_box.update(dirty_items) 590 596 591 finally: 597 592 self._dirty_items.clear() … … 623 618 area = event.area 624 619 x, y, w, h = area.x, area.y, area.width, area.height 625 self.window.draw_rectangle(self.style.white_gc, True,626 x, y, w, h)627 628 620 cr = self.window.cairo_create() 629 621 630 622 # Draw no more than nessesary. 631 623 cr.rectangle(x, y, w, h) 624 #print 'clip to', x, y, w, h 632 625 cr.clip() 626 627 update_bounding_box = self._update_bounding_box 628 if update_bounding_box: 629 try: 630 cr.save() 631 cr.rectangle(0, 0, 0, 0) 632 cr.clip() 633 try: 634 self.update_bounding_box(cr, update_bounding_box) 635 finally: 636 cr.restore() 637 self._idle_queue_draw_item(*update_bounding_box) 638 finally: 639 update_bounding_box.clear() 633 640 634 641 self._painter.paint(Context(view=self,
