Changeset 1001

Show
Ignore:
Timestamp:
09/07/06 00:28:11 (2 years ago)
Author:
arjanmol
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphas/trunk/ChangeLog

    r999 r1001  
    33        * item.py, canvas.py: item removal (with connected handles) solved, 
    44        use a callback method on the handle. 
     5        * demo.py, examples.py: Moved handle tool hacks into a nice example 
     6        handle tool class. 
    57 
    682006-09-06  Arjan Molenaar  <arjan_at_yirdis_dot_nl> 
  • gaphas/trunk/demo.py

    r999 r1001  
    1313import gtk 
    1414from gaphas import Canvas, View 
    15 from gaphas.examples import Box, Text 
     15from gaphas.examples import Box, Text, DefaultExampleTool 
    1616from gaphas.item import Line, NW, SE 
    1717from gaphas.tool import PlacementTool, HandleTool 
    18 from gaphas.constraint import LineConstraint 
    19 from gaphas.geometry import point_on_rectangle, distance_rectangle_point 
    20  
    21 DEFAULT_POINTER = gtk.gdk.LEFT_PTR 
    22  
    23  
    24 def handle_tool_glue(self, view, item, handle, wx, wy): 
    25     """MixIn method for HandleTool. It allows the tool to glue 
    26     to a Box or (other) Line item. 
    27     The distance from the item to the handle is determined in canvas 
    28     coordinates, using a 10 pixel glue distance. 
    29     """ 
    30     if not handle.connectable: 
    31         return 
    32     matrix_w2i = view.canvas.get_matrix_w2i 
    33     matrix_i2w = view.canvas.get_matrix_i2w 
    34  
    35     # Make glue distance depend on the zoom ratio (should be about 10 pixels) 
    36     glue_distance, dummy = view.transform_distance_c2w(10, 0) 
    37     glue_point = None 
    38     glue_item = None 
    39     for i in view.canvas.get_all_items(): 
    40         if not i is item: 
    41             ix, iy = matrix_w2i(i).transform_point(wx, wy) 
    42             try: 
    43                 distance, point = i.glue(item, handle, ix, iy) 
    44                 #print distance, point 
    45                 # Transform distance to world coordinates 
    46                 distance, dumy = matrix_i2w(i).transform_distance(distance, 0) 
    47                 if distance < glue_distance: 
    48                     glue_distance = distance 
    49                     glue_point = matrix_i2w(i).transform_point(*point) 
    50                     glue_item = i 
    51             except AttributeError: 
    52                 pass 
    53     if glue_point: 
    54         handle.x, handle.y = matrix_w2i(item).transform_point(*glue_point) 
    55     return glue_item 
    56  
    57 HandleTool.glue = handle_tool_glue 
    58  
    59  
    60 def handle_tool_connect(self, view, item, handle, wx, wy): 
    61     """Connect a handle to another item. 
    62  
    63     In this "method" the following assumptios are made: 
    64      1. The only item that accepts handle connections are the MyBox instances 
    65      2. The only items with connectable handles are Line's 
    66       
    67     """ 
    68     def side(handle, glued): 
    69         hx, hy = view.canvas.get_matrix_i2w(item).transform_point(handle.x, handle.y) 
    70         ax, ay = view.canvas.get_matrix_i2w(glued).transform_point(glued.handles()[0].x, glued.handles()[0].y) 
    71         bx, by = view.canvas.get_matrix_i2w(glued).transform_point(glued.handles()[2].x, glued.handles()[2].y) 
    72         if abs(hx - ax) < 0.01: 
    73             side = 3 
    74         elif abs(hy - ay) < 0.01: 
    75             side = 0 
    76         elif abs(hx - bx) < 0.01: 
    77             side = 1 
    78         else: 
    79             side = 2 
    80         return side 
    81  
    82     #print 'Handle.connect', view, item, handle, wx, wy 
    83     glue_item = self.glue(view, item, handle, wx, wy) 
    84     if glue_item and glue_item is handle.connected_to: 
    85         s = side(handle, glue_item) 
    86         view.canvas.solver.remove_constraint(handle._connect_constraint) 
    87         handle._connect_constraint = LineConstraint(view.canvas, glue_item, glue_item.handles()[s], glue_item.handles()[(s+1)%4], item, handle) 
    88         view.canvas.solver.add_constraint(handle._connect_constraint) 
    89         def handle_disconnect(): 
    90             view.canvas.solver.remove_constraint(handle._connect_constraint) 
    91             handle._connect_constraint = None 
    92         handle.disconnect = handle_disconnect 
    93         return 
    94  
    95     # drop old connetion 
    96     if handle.connected_to: 
    97         # remove constraints 
    98         try: 
    99             view.canvas.solver.remove_constraint(handle._connect_constraint) 
    100         except AttributeError: 
    101             pass # no _connect_constraints attribute 
    102         handle._connect_constraint = None 
    103         handle.connected_to = None 
    104  
    105     if glue_item: 
    106         if isinstance(glue_item, MyBox): 
    107             s = side(handle, glue_item) 
    108             # Make a constraint that keeps into account item coordinates. 
    109             handle._connect_constraint = LineConstraint(view.canvas, glue_item, glue_item.handles()[s], glue_item.handles()[(s+1)%4], item, handle) 
    110             view.canvas.solver.add_constraint(handle._connect_constraint) 
    111             handle.connected_to = glue_item 
    112  
    113  
    114 HandleTool.connect = handle_tool_connect 
    115  
    116  
    117 def handle_tool_disconnect(self, view, item, handle): 
    118     if handle.connected_to: 
    119         #print 'Handle.disconnect', view, item, handle 
    120         handle._connect_constraint.disabled = True 
    121  
    122 HandleTool.disconnect = handle_tool_disconnect 
    123  
    12418 
    12519class MyBox(Box): 
     
    12721    """ 
    12822 
    129     def glue(self, item, handle, x, y): 
    130         h = self._handles 
    131         hnw = h[NW] 
    132         hse = h[SE] 
    133         r = (float(hnw.x), float(hnw.y), float(hse.x), float(hse.y)) 
    134         por = point_on_rectangle(r, (x, y), border=True) 
    135         #print 'Point', r, (x, y), por 
    136         return distance_rectangle_point(r, (x, y)), por 
    137  
    138     def constrain(self, handle, x, y): 
    139         pass 
    14023 
    14124class MyLine(Line): 
     
    15336def create_window(canvas, zoom=1.0): 
    15437    view = View() 
    155      
     38    view.tool = DefaultExampleTool() 
     39 
    15640    w = gtk.Window() 
    15741    h = gtk.HBox() 
  • gaphas/trunk/gaphas/examples.py

    r945 r1001  
    99from item import NW, NE,SW, SE 
    1010from solver import solvable 
    11  
     11import tool 
     12from constraint import LineConstraint 
     13from geometry import point_on_rectangle, distance_rectangle_point 
    1214 
    1315class Box(Element): 
     
    3436        context.draw_children() 
    3537 
     38    def glue(self, item, handle, x, y): 
     39        """Special glue method used by the ConnectingHandleTool to find 
     40        a connection point. 
     41        """ 
     42        h = self._handles 
     43        hnw = h[NW] 
     44        hse = h[SE] 
     45        r = (float(hnw.x), float(hnw.y), float(hse.x), float(hse.y)) 
     46        por = point_on_rectangle(r, (x, y), border=True) 
     47        #print 'Point', r, (x, y), por 
     48        return distance_rectangle_point(r, (x, y)), por 
     49 
    3650 
    3751class Text(Item): 
     52    """Simple item shoring some text on the canvas. 
     53    """ 
    3854 
    3955    def __init__(self): 
     
    4965        return 0 
    5066 
     67 
     68class ConnectingHandleTool(tool.HandleTool): 
     69    """This is a HandleTool which supports a simple connection algerithm, 
     70    Using LineConstraint. 
     71    """ 
     72 
     73    def glue(self, view, item, handle, wx, wy): 
     74        """It allows the tool to glue to a Box or (other) Line item. 
     75        The distance from the item to the handle is determined in canvas 
     76        coordinates, using a 10 pixel glue distance. 
     77        """ 
     78        if not handle.connectable: 
     79            return 
     80        matrix_w2i = view.canvas.get_matrix_w2i 
     81        matrix_i2w = view.canvas.get_matrix_i2w 
     82 
     83        # Make glue distance depend on the zoom ratio (should be about 10 pixels) 
     84        glue_distance, dummy = view.transform_distance_c2w(10, 0) 
     85        glue_point = None 
     86        glue_item = None 
     87        for i in view.canvas.get_all_items(): 
     88            if not i is item: 
     89                ix, iy = matrix_w2i(i).transform_point(wx, wy) 
     90                try: 
     91                    distance, point = i.glue(item, handle, ix, iy) 
     92                    #print distance, point 
     93                    # Transform distance to world coordinates 
     94                    distance, dumy = matrix_i2w(i).transform_distance(distance, 0) 
     95                    if distance < glue_distance: 
     96                        glue_distance = distance 
     97                        glue_point = matrix_i2w(i).transform_point(*point) 
     98                        glue_item = i 
     99                except AttributeError: 
     100                    pass 
     101        if glue_point: 
     102            handle.x, handle.y = matrix_w2i(item).transform_point(*glue_point) 
     103        return glue_item 
     104 
     105    def connect(self, view, item, handle, wx, wy): 
     106        """Connect a handle to another item. 
     107 
     108        In this "method" the following assumptios are made: 
     109         1. The only item that accepts handle connections are the Box instances 
     110         2. The only items with connectable handles are Line's 
     111          
     112        """ 
     113        def side(handle, glued): 
     114            hx, hy = view.canvas.get_matrix_i2w(item).transform_point(handle.x, handle.y) 
     115            ax, ay = view.canvas.get_matrix_i2w(glued).transform_point(glued.handles()[0].x, glued.handles()[0].y) 
     116            bx, by = view.canvas.get_matrix_i2w(glued).transform_point(glued.handles()[2].x, glued.handles()[2].y) 
     117            if abs(hx - ax) < 0.01: 
     118                side = 3 
     119            elif abs(hy - ay) < 0.01: 
     120                side = 0 
     121            elif abs(hx - bx) < 0.01: 
     122                side = 1 
     123            else: 
     124                side = 2 
     125            return side 
     126 
     127 
     128        def handle_disconnect(): 
     129            try: 
     130                view.canvas.solver.remove_constraint(handle._connect_constraint) 
     131            except KeyError: 
     132                pass # constraint was alreasy removed 
     133            handle._connect_constraint = None 
     134            handle.connected_to = None 
     135            # Remove disconnect handler: 
     136            handle.disconnect = lambda: 0 
     137 
     138        #print 'Handle.connect', view, item, handle, wx, wy 
     139        glue_item = self.glue(view, item, handle, wx, wy) 
     140        if glue_item and glue_item is handle.connected_to: 
     141            s = side(handle, glue_item) 
     142            view.canvas.solver.remove_constraint(handle._connect_constraint) 
     143            handle._connect_constraint = LineConstraint(view.canvas, glue_item, glue_item.handles()[s], glue_item.handles()[(s+1)%4], item, handle) 
     144            view.canvas.solver.add_constraint(handle._connect_constraint) 
     145            handle.disconnect = handle_disconnect 
     146            return 
     147 
     148        # drop old connetion 
     149        if handle.connected_to: 
     150            handle.disconnect() 
     151 
     152        if glue_item: 
     153            if isinstance(glue_item, Box): 
     154                s = side(handle, glue_item) 
     155                # Make a constraint that keeps into account item coordinates. 
     156                handle._connect_constraint = LineConstraint(view.canvas, glue_item, glue_item.handles()[s], glue_item.handles()[(s+1)%4], item, handle) 
     157                view.canvas.solver.add_constraint(handle._connect_constraint) 
     158                handle.connected_to = glue_item 
     159                handle.disconnect = handle_disconnect 
     160 
     161    def disconnect(self, view, item, handle): 
     162        if handle.connected_to: 
     163            #print 'Handle.disconnect', view, item, handle 
     164            view.canvas.solver.remove_constraint(handle._connect_constraint) 
     165 
     166 
     167def DefaultExampleTool(): 
     168    """The default tool chain build from HoverTool, ItemTool and HandleTool. 
     169    """ 
     170    chain = tool.ToolChain() 
     171    chain.append(tool.HoverTool()) 
     172    chain.append(ConnectingHandleTool()) 
     173    chain.append(tool.ItemTool()) 
     174    chain.append(tool.TextEditTool()) 
     175    chain.append(tool.RubberbandTool()) 
     176    return chain 
     177 
     178 
    51179if __name__ == '__main__': 
    52180    import doctest 
  • gaphas/trunk/gaphas/tool.py

    r994 r1001  
    298298 
    299299class HandleTool(Tool): 
     300    """Tool for moving handles around. By default this tool does not provide 
     301    connecting handles to another item (see examples.ConnectingHandleTool for 
     302    an example). 
     303    """ 
    300304 
    301305    def __init__(self):