Changeset 1551

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

- reimplemented tool's and item's code, so Handle.{x,y} are specified in

world coordinates

- thanks to above killed LineConstraint?, introduced BalanceConstraint? instead to

keep handle on a line (works in case of Element, needs more rethinking in
case of Line). BalanceConstraint? is completely decoupled from canvas code

- killed Element.pre_update, its functionality is generalized in

HandleTool?.move, which contains independent code for all items

- implemented Element.min_{width,height} using delta attribute of

LessThanConstraint? class (now, min size cannot be changed to be fixed
later)

- killed Handle.{x,y}.dirty() from canvas code, making solver existence

less miserable

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphas/branches/hw/demo.py

    r1532 r1551  
    2525import cairo 
    2626from gaphas import Canvas, GtkView, View 
    27 from gaphas.examples import Box, Text, DefaultExampleTool 
     27from gaphas.examples import Box, Text, FatLine, DefaultExampleTool 
    2828from gaphas.item import Line, NW, SE 
    2929from gaphas.tool import PlacementTool, HandleTool 
     
    296296 
    297297    b=MyBox() 
     298    h = b.handles()[0] 
     299    h.x = 20 
     300    h.y = 20 
    298301    b.min_width = 20 
    299302    b.min_height = 30 
    300     print 'box', b 
    301303    b.matrix=(1.0, 0.0, 0.0, 1, 20,20) 
    302304    b.width=b.height = 40 
    303305    c.add(b) 
    304306 
    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) 
    321332 
    322333    t=MyText('Single line') 
     
    325336 
    326337    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 
    328344    l.split_segment(0, 3) 
    329345    l.matrix.translate(30, 60) 
     346    print l, h[0].x, h[0].y, h[1].x, h[1].y 
    330347    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 
    332350 
    333351    off_y = 0 
  • gaphas/branches/hw/gaphas/canvas.py

    r1513 r1551  
    467467        item._canvas_matrix_w2i.invert() 
    468468 
    469         # Make sure handles are marked (for constraint solving) 
    470         for h in item.handles(): 
    471             h.x.dirty() 
    472             h.y.dirty() 
    473  
    474469        if recursive: 
    475470            for child in self._tree.get_children(item): 
  • gaphas/branches/hw/gaphas/constraint.py

    r1535 r1551  
    303303 
    304304 
    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 
     306class 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 
    425349 
    426350 
  • gaphas/branches/hw/gaphas/examples.py

    r1518 r1551  
    1111from solver import solvable 
    1212import tool 
    13 from constraint import LineConstraint 
     13from constraint import BalanceConstraint, LessThanConstraint, EqualsConstraint 
    1414from geometry import point_on_rectangle, distance_rectangle_point 
    1515from util import text_extents, text_align, text_multiline 
     
    2828        c = context.cairo 
    2929        nw = self._handles[NW] 
    30         c.rectangle(nw.x, nw.y, self.width, self.height) 
     30        c.rectangle(0, 0, self.width, self.height) 
    3131        if context.hovered: 
    3232            c.set_source_rgba(.8,.8,1, .8) 
     
    5050        r = (x0, y0, x1 - x0, y1 - y0) 
    5151        por = point_on_rectangle(r, (x, y), border=True) 
    52         #print 'Point', r, (x, y), por 
    53         return distance_rectangle_point(r, (x, y)), por 
     52        p = distance_rectangle_point(r, (x, y)) 
     53        return p, por 
    5454 
    5555 
     
    8282 
    8383 
     84class 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 
    84122class ConnectingHandleTool(tool.HandleTool): 
    85123    """ 
    86124    This is a HandleTool which supports a simple connection algorithm, 
    87     using LineConstraint. 
     125    using BalanceConstraint. 
    88126    """ 
    89127 
     
    96134        if not handle.connectable: 
    97135            return 
    98         matrix_w2i = view.canvas.get_matrix_w2i 
    99         matrix_i2w = view.canvas.get_matrix_i2w 
    100136 
    101137        # Make glue distance depend on the zoom ratio (should be about 10 pixels) 
     
    105141        for i in view.canvas.get_all_items(): 
    106142            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 
    108145                try: 
    109146                    distance, point = i.glue(item, handle, ix, iy) 
    110                     # print distance, point 
    111147                    # 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) 
    113149                    if distance <= glue_distance: 
    114150                        glue_distance = distance 
    115                         glue_point = matrix_i2w(i).transform_point(*point) 
     151                        glue_point = point 
    116152                        glue_item = i 
    117153                except AttributeError: 
    118154                    pass 
    119155        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 
    121158        return glue_item 
    122159 
     
    131168        """ 
    132169        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 
    136174            if abs(hx - ax) < 0.01: 
    137                 side = 3 
     175                return handles[NW], handles[SW] 
    138176            elif abs(hy - ay) < 0.01: 
    139                 side = 0 
     177                return handles[NW], handles[NE] 
    140178            elif abs(hx - bx) < 0.01: 
    141                 side = 1 
     179                return handles[NE], handles[SE] 
    142180            else: 
    143                 side = 2 
    144             return sid
     181                return handles[SW], handles[SE] 
     182            assert Fals
    145183 
    146184 
    147185        def handle_disconnect(): 
    148186            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) 
    150189            except KeyError: 
    151190                pass # constraint was alreasy removed 
     
    158197        glue_item = self.glue(view, item, handle, wx, wy) 
    159198        if glue_item and glue_item is handle.connected_to: 
    160             s = side(handle, glue_item) 
    161199            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) 
    163202            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) 
    167211            handle.disconnect = handle_disconnect 
    168212            return 
     
    174218        if glue_item: 
    175219            if isinstance(glue_item, Box): 
    176                 s = side(handle, glue_item) 
     220                h1, h2 = side(handle, glue_item) 
     221 
    177222                # 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 
    180228                handle.connected_to = glue_item 
    181229                handle.disconnect = handle_disconnect 
     
    184232        if handle.connected_to: 
    185233            #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) 
    187236 
    188237 
  • gaphas/branches/hw/gaphas/item.py

    r1540 r1551  
    348348        eq = EqualsConstraint 
    349349        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 
    351364        add = self.canvas.solver.add_constraint 
    352365        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        ] 
    363377 
    364378        # 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) 
    366380        for c, v in zip(self._constraints, solve_for): 
    367381            c.solve_for(v) 
     382 
    368383         
    369384    def teardown_canvas(self): 
     
    389404 
    390405 
    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 Canvas 
    397         >>> c = Canvas() 
    398         >>> e = Element() 
    399         >>> c.add(e) 
    400         >>> e.min_width = e.min_height = 0 
    401         >>> c.update_now() 
    402         >>> e._handles 
    403         [<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 += 1 
    405         >>> map(float, e._handles[0].pos) 
    406         [1.0, 0.0] 
    407         >>> e.pre_update(None) 
    408         >>> e._handles 
    409         [<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 = 0 
    419             for h in self._handles[1:4]: 
    420                 h.x -= x 
    421         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 = 0 
    427             for h in self._handles[1:4]: 
    428                 h.y -= y 
    429  
    430         if self.width < self.min_width: 
    431             self.width = self.min_width 
    432         if self.height < self.min_height: 
    433             self.height = self.min_height 
    434  
    435     def update(self, context): 
    436         """ 
    437         Do nothing during update. 
    438         """ 
    439         pass 
    440  
    441406    def point(self, x, y): 
    442407        """ 
     
    543508        Setup constraints. In this case orthogonal. 
    544509        """ 
     510        super(Line, self).setup_canvas() 
    545511        self.orthogonal = self.orthogonal 
    546512 
     
    699665        See Item.draw(context). 
    700666        """ 
     667        m = self._canvas.get_matrix_w2i(self) 
     668 
    701669        def draw_line_end(handle, angle, draw): 
    702670            cr = context.cairo 
    703671            cr.save() 
    704672            try: 
    705                 cr.translate(handle.x, handle.y
     673                cr.translate(*m.transform_point(handle.x, handle.y)
    706674                cr.rotate(angle) 
    707675                draw(context) 
    708676            finally: 
    709677                cr.restore() 
     678 
    710679        cr = context.cairo 
    711680        cr.set_line_width(self.line_width) 
    712681        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)) 
    715686        h0, h1 = self._handles[-2:] 
    716687        draw_line_end(self._handles[-1], self._tail_angle, self.draw_tail) 
  • gaphas/branches/hw/gaphas/painter.py

    r1529 r1551  
    261261                cairo.identity_matrix() 
    262262                cairo.translate(*m.transform_point(h.x, h.y)) 
     263                cairo.translate(h.x, h.y) 
    263264                cairo.rectangle(-4, -4, 9, 9) 
    264265                cairo.fill() 
    265266        finally: 
    266267            cairo.restore() 
     268 
    267269 
    268270    def _draw_item(self, item, view, cairo, area=None): 
     
    317319            cairo.identity_matrix() 
    318320            cairo.set_antialias(ANTIALIAS_NONE) 
    319             cairo.translate(*m.transform_point(h.x, h.y)
     321            cairo.translate(h.x, h.y
    320322            cairo.rectangle(-4, -4, 8, 8) 
    321323            cairo.set_source_rgba(r, g, b, opacity) 
  • gaphas/branches/hw/gaphas/tool.py

    r1518 r1551  
    339339                # Move the item and schedule it for an update 
    340340                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 
    341344                canvas.request_matrix_update(i) 
    342345 
     
    377380            if not h.movable: 
    378381                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 
    380384            x, y = view.transform_point_w2c(wx, wy) 
    381385            if abs(x - event.x) < 6 and abs(y - event.y) < 6: 
     
    426430    def move(self, view, item, handle, x, y): 
    427431        """ 
    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 
    454446 
    455447    def glue(self, view, item, handle, wx, wy): 
     
    478470        item, handle = self.find_handle(view, event) 
    479471        if handle: 
     472            self.last_x, self.last_y = event.x, event.y 
    480473            # Deselect all items unless CTRL or SHIFT is pressed 
    481474            # or the item is already selected. 
     
    530523            view.queue_draw_item(item) 
    531524 
    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) 
    533527            wx, wy = view.transform_point_c2w(event.x, event.y) 
    534             x, y = canvas.get_matrix_w2i(item).transform_point(wx, wy) 
    535528 
    536529            # Do the actual move: 
    537             self.move(view, item, handle, x, y) 
     530            self.move(view, item, handle, dx, dy) 
    538531             
    539532            item.request_update() 
     
    544537            finally: 
    545538                pass 
     539            self.last_x, self.last_y = event.x, event.y 
    546540            return True 
    547541        else: 
     
    624618        x, y = view.transform_point_c2w(x, y) 
    625619        item.matrix.translate(x, y) 
     620        h = item.handles()[0] 
     621        h.x = x 
     622        h.y = y 
    626623        return item 
    627624