Changeset 1597

Show
Ignore:
Timestamp:
07/08/07 11:38:16 (1 year ago)
Author:
wrobe..@pld-linux.org
Message:

- merge changes 1549:1598 from trunk

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphas/branches/hw/README.txt

    r1179 r1597  
    8787The context contains: 
    8888 
    89  parent:   parent item of the item, or None 
    90  children: child items of this item (do not need to force updates for those) 
    9189 cairo:    a CairoContext, this can be used to calculate the dimensions of text 
    9290           for example 
     
    106104 view:     the view we're drawing to 
    107105 cairo:    the CairoContext to draw to 
    108  parent:   parent item of the item, or None 
    109  children: child items of this item (do not need to force updates for those) 
    110106 selected: True if the item is actually selected in the view 
    111107 focused:  True if the item has the focus 
  • gaphas/branches/hw/demo.py

    r1557 r1597  
    381381 
    382382if __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() 
    385396# vim: sw=4:et: 
  • gaphas/branches/hw/demo_profile.py

    r1509 r1597  
    177177        c.add(bb, parent=b) 
    178178 
     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 
    179187    t=MyText('Single line') 
    180188    t.matrix.translate(70,70) 
  • gaphas/branches/hw/gaphas/canvas.py

    r1558 r1597  
    365365        """ 
    366366        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 
    368372        # dirty_items is a subset of dirty_matrix_items 
    369373        dirty_matrix_items = set(self._dirty_matrix_items) 
     
    371375            cairo_context = self._obtain_cairo_context() 
    372376 
    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) 
    376379 
    377380            context_map = dict() 
    378381            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) 
    382383                context_map[item] = c 
    383384                try: 
     
    392393            self._solver.solve() 
    393394 
    394             # Order the dirty items, so they are updated bottom to top 
    395             dirty_items = ( item for item in reversed(self._tree.nodes) \ 
    396                                  if item in self._dirty_items ) 
    397  
    398395            dirty_matrix_items.update(self._dirty_matrix_items) 
    399396            self.update_matrices() 
     
    403400                    c = context_map[item] 
    404401                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) 
    408403                try: 
    409404                    item.update(c) 
     
    475470            request_resolve(h.x) 
    476471            request_resolve(h.y) 
     472             
    477473 
    478474        if recursive: 
    479475            for child in self._tree.get_children(item): 
    480476                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 
    481518 
    482519    def register_view(self, view): 
  • gaphas/branches/hw/gaphas/constraint.py

    r1551 r1597  
    124124        else: 
    125125            self.b.value = self.a.value 
     126 
     127 
     128class 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 
    126160 
    127161 
     
    349383 
    350384 
     385 
     386class 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 
    351432if __name__ == '__main__': 
    352433    import doctest, sys 
  • gaphas/branches/hw/gaphas/geometry.py

    r1518 r1597  
    133133        >>> r=Rectangle(5, 7, 20, 25) 
    134134        >>> 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). 
    136138        >>> r + (20, 30, 40, 50) 
    137139        Rectangle(5, 7, 55, 73) 
     
    149151        Traceback (most recent call last): 
    150152          ... 
    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
    154156            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 
    164160        if self: 
    165             ox1, oy1 = self.x1, self.y1 
     161            ox1, oy1 = self.x + self.width, self.y + self.height 
    166162            self.x = min(self.x, x) 
    167163            self.y = min(self.y, y) 
     
    195191        Traceback (most recent call last): 
    196192          ... 
    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
    200196            x, y, width, height = obj 
    201             x1, y1 = x + width, y + height 
    202         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 
    205201        if self: 
    206             ox1, oy1 = self.x1, self.y1 
     202            ox1, oy1 = self.x + self.width, self.y + self.height 
    207203            self.x = max(self.x, x) 
    208204            self.y = max(self.y, y) 
     
    238234        Traceback (most recent call last): 
    239235          ... 
    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
    243239            x, y, width, height = obj 
    244240            x1, y1 = x + width, y + width 
    245         elif len(obj) == 2
     241        except ValueError
    246242            # point 
    247             x, y = obj 
    248             x1, y1 = obj 
    249         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) 
    252248        return x >= self.x and x1 <= self.x1 and \ 
    253249               y >= self.y and y1 <= self.y1 
  • gaphas/branches/hw/gaphas/item.py

    r1557 r1597  
    1010from matrix import Matrix 
    1111from geometry import distance_line_point, distance_rectangle_point 
    12 from solver import solvable, WEAK, NORMAL, STRONG 
     12from solver import solvable, WEAK, NORMAL, STRONG, VERY_STRONG 
    1313from constraint import EqualsConstraint, LessThanConstraint 
    1414from state import observed, reversible_pair, reversible_property, disable_dispatching 
     
    237237    def __init__(self, width=10, height=10): 
    238238        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 ] 
    240240        self._constraints = [] 
    241241        self._min_width = 10 
     
    251251        20.0 
    252252        >>> b._handles[NW].x 
    253         Variable(0, 30) 
     253        Variable(0, 40) 
    254254        >>> b._handles[SE].x 
    255         Variable(20, 30) 
     255        Variable(20, 40) 
    256256        """ 
    257257        if width < self.min_width: 
     
    280280        10.0 
    281281        >>> b._handles[NW].y 
    282         Variable(0, 30) 
     282        Variable(0, 40) 
    283283        >>> b._handles[SE].y 
    284         Variable(10, 30) 
     284        Variable(10, 40) 
    285285        """ 
    286286        if height < self.min_height: 
     
    329329        True 
    330330        >>> len(c.solver._constraints) 
    331         6 
     331        8 
    332332        >>> len(c.solver._marked_cons) 
    333333        0 
    334334        >>> c.solver.solve() 
    335335        >>> len(c.solver._constraints) 
    336         6 
     336        8 
    337337        >>> len(c.solver._marked_cons) 
    338338        0 
     
    387387        True 
    388388        >>> len(c.solver._constraints) 
    389         6 
     389        8 
    390390        >>> b.teardown_canvas() 
    391391        >>> len(c.solver._constraints) 
  • gaphas/branches/hw/gaphas/painter.py

    r1556 r1597  
    8181        the Item.draw() method. 
    8282        """ 
    83         self.painter._draw_items(self.children
     83        self.painter._draw_items(self._item.canvas.get_children(self._item)
    8484                                 self.view, 
    8585                                 self.cairo, 
     
    101101                                  cairo=cairo, 
    102102                                  _area=area, 
    103                                   parent=view.canvas.get_parent(item), 
    104                                   children=view.canvas.get_children(item), 
     103                                  _item=item, 
    105104                                  selected=(item in view.selected_items), 
    106105                                  focused=(item is view.focused_item), 
     
    271270        cairo = CairoBoundingBoxContext(cairo) 
    272271        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 
    275284 
    276285    def _draw_items(self, items, view, cairo, area=None): 
  • gaphas/branches/hw/gaphas/tool.py

    r1551 r1597  
    377377        Find item's handle at (event.x, event.y) 
    378378        """ 
     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) 
    379382        for h in item.handles(): 
    380383            if not h.movable: 
    381384                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) 
    383386            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: 
    386388                return h 
    387389        return None 
     
    531533             
    532534            item.request_update() 
    533             canvas.update_matrix(item) 
     535            #canvas.update_matrix(item) 
    534536            try: 
    535537                if self._grabbed_handle.connectable: 
  • gaphas/branches/hw/gaphas/util.py

    r1249 r1597  
    9292                        'bold' in font and cairo.FONT_WEIGHT_BOLD \ 
    9393                                        or cairo.FONT_WEIGHT_NORMAL) 
    94     cr.set_font_size(int(font[-1])) 
     94    cr.set_font_size(float(font[-1])) 
    9595 
    9696 
  • gaphas/branches/hw/gaphas/view.py

    r1529 r1597  
    390390        self.canvas = canvas 
    391391 
     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 
    392397    def emit(self, *args, **kwargs): 
    393398        """ 
     
    491496                                viewport_size=allocation.height) 
    492497 
     498    @async(single=False, priority=PRIORITY_HIGH_IDLE) 
     499    def _idle_queue_draw_item(self, *items): 
     500        self.queue_draw_item(*items) 
     501 
    493502    def queue_draw_item(self, *items): 
    494503        """ 
     
    504513            except KeyError: 
    505514                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) 
    511515 
    512516    def queue_draw_area(self, x, y, w, h): 
     
    545549        # Do not update items that require a full update (or are removed) 
    546550        dirty_matrix_items = dirty_matrix_items.difference(dirty_items) 
    547         #dirty_items.update(dirty_matrix_items) 
    548         #dirty_matrix_items.clear() 
    549551 
    550552        removed_items = dirty_items.difference(self._canvas.get_all_items()) 
     
    583585                self.dropzone_item = None 
    584586 
    585             # Pseudo-draw 
    586             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  
    595587            self.update_adjustments() 
     588 
     589            self._update_bounding_box.update(dirty_items) 
     590 
    596591        finally: 
    597592            self._dirty_items.clear() 
     
    623618        area = event.area 
    624619        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  
    628620        cr = self.window.cairo_create() 
    629621 
    630622        # Draw no more than nessesary. 
    631623        cr.rectangle(x, y, w, h) 
     624        #print 'clip to', x, y, w, h 
    632625        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() 
    633640 
    634641        self._painter.paint(Context(view=self,