Changeset 1161

Show
Ignore:
Timestamp:
03/14/07 23:56:20 (2 years ago)
Author:
arjanmol
Message:

Fixed bug in canvas add/remove undo, fixed typos in docs and added more tests. Version bump to 0.1.2.

Files:

Legend:

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

    r1094 r1161  
     12007-03-16  Arjan Molenaar  <arjan_at_yirdis_dot_nl> 
     2 
     3        * Implemented Undo system. State changes can be recorded and reverse 
     4        operations can be determined. 
     5 
     6[ for intermediate change log entries, see svn log ] 
     7 
    182006-12-05  Arjan Molenaar  <arjan_at_yirdis_dot_nl> 
    29 
  • gaphas/trunk/README.txt

    r1160 r1161  
    2121 v a render cycle. 
    2222 v zoom and move functionality (canvas2world). 
    23  v scrollbars work. 
     23 v scroll-bars work. 
    2424 v a set of tools and a ToolChain (to chain them together). 
    2525 v rubberband selection 
     
    3030 v placement tool 
    3131 v connection protocol 
    32  v make update cycle independant from render (expose) event. 
     32 v make update cycle independent from render (expose) event. 
    3333    This is something we might do if the response is getting bad. 
    3434 ? rotating and shearing for Element items. 
     
    4040 
    4141Stage n: 
    42  - Dropzone tool 
     42 - Drop-zone tool 
    4343     the idea is that for example you have a Package and when you drag 
    4444     a Class into it it automatically makes the Package its owning element. 
    45  - undo management 
     45 v undo management 
    4646 
    4747 
     
    5353 
    5454An Item can have a set of Handle's (also from item.py) which can be used to 
    55 manipulate the item (although this is not nessesary). Each item has it's own 
     55manipulate the item (although this is not necessary). Each item has it's own 
    5656coordinate system (a (0, 0) point). Item.matrix is the transformation 
    5757relative to the parent item of the Item, as defined in the Canvas. 
     
    5959The Canvas also contains a constraint Solver (from solver.py) that can be used 
    6060to solve mathematical dependencies between items (such as Handles that should 
    61 be alligned). 
     61be aligned). 
    6262 
    6363View (from view.py) is used to visualize a canvas. On a View, a Tool 
     
    108108 parent:   parent item of the item, or None 
    109109 children: child items of this item (do not need to force updates for those) 
    110  selected: True if the item is acutally selected in the view 
     110 selected: True if the item is actually selected in the view 
    111111 focused:  True if the item has the focus 
    112112 hovered:  True if the mouse pointer if over the item. Only the top-most item 
     
    149149==== 
    150150 
    151 Gaphas has a simple build-in system for registring changes in it's classes and 
     151Gaphas has a simple build-in system for registering changes in it's classes and 
    152152notifying the application. This code resides in state.py. 
    153153 
  • gaphas/trunk/demo.py

    r1160 r1161  
    22""" 
    33A simple demo app. 
     4 
     5It sports a small canvas and some trivial operations: 
     6 
     7 - Add a line/box 
     8 - Zoom in/out 
     9 - Split a line segment 
     10 - Delete focused item 
     11 - Record state changes 
     12 - Play back state changes (= undo !) With visual updates 
     13 - Exports to SVG and PNG 
     14 
    415""" 
    516 
     
    161172        for event in apply_me: 
    162173            saveapply(*event) 
     174            # Visualize each event: 
     175            while gtk.events_pending(): 
     176                gtk.main_iteration() 
    163177 
    164178    b.connect('clicked', on_clicked) 
  • gaphas/trunk/gaphas/canvas.py

    r1160 r1161  
    9393 
    9494    reversible_pair(add, remove, 
    95                     bind1={'parent': lambda self, node: self.get_parent(node) }) 
     95                    bind1={'parent': lambda self, item: self.get_parent(item) }) 
    9696 
    9797    def remove_connections_to_item(self, item): 
  • gaphas/trunk/gaphas/item.py

    r1160 r1161  
    422422 
    423423    Properties: 
    424      - fuzzyness (0.0..n): an extra margin that should be taken into account 
     424     - fuzziness (0.0..n): an extra margin that should be taken into account 
    425425         when calculating the distance from the line (using point()). 
    426426     - orthogonal (bool): wherther or not the line should be orthogonal 
     
    441441 
    442442        self._line_width = 2 
    443         self._fuzzyness = 0 
     443        self._fuzziness = 0 
    444444        self._orthogonal = [] 
    445445        self._horizontal = False 
     
    453453 
    454454    @observed 
    455     def _set_fuzzyness(self, fuzzyness): 
    456         self._fuzzyness = fuzzyness 
    457  
    458     fuzzyness = reversible_property(lambda s: s._fuzzyness, _set_fuzzyness) 
     455    def _set_fuzziness(self, fuzziness): 
     456        self._fuzziness = fuzziness 
     457 
     458    fuzziness = reversible_property(lambda s: s._fuzziness, _set_fuzziness) 
    459459 
    460460    @observed 
     
    649649        h = self._handles 
    650650        distance, point, segment = self.closest_segment(x, y) 
    651         return max(0, distance - self.fuzzyness) 
     651        return max(0, distance - self.fuzziness) 
    652652 
    653653    def draw_head(self, context): 
  • gaphas/trunk/gaphas/view.py

    r1157 r1161  
    679679    doctest.testmod() 
    680680 
    681  
    682681# vim: sw=4:et: 
  • gaphas/trunk/setup.py

    r1145 r1161  
    88setup( 
    99    name='gaphas', 
    10     version='0.1.1', 
     10    version='0.1.2', 
    1111    description='Gaphas is a GTK+ based diagramming widget', 
    1212    long_description="""\ 
    1313Gaphas is a GTK+ based diagramming widget written in Python. 
    1414It is the logical successor of the DiaCanvas library. 
     15 
     16GTK+ and PyGTK is required. 
    1517""", 
    1618 
  • gaphas/trunk/state.txt

    r1160 r1161  
    2020    >>> tree = Tree() 
    2121 
    22 For this demonistration let's use the Tree class (which contains an add/remove 
     22For this demonstration let's use the Tree class (which contains an add/remove 
    2323method pair). It's methods are not dispatched by default though (because they're 
    2424only used in the Canvas class. So first dispatching should be enabled: 
     
    8888 1. Property setters should be declared with reversible_property() 
    8989 2. Method (or function) pairs that implement each others reverse operation 
    90     (e.g. add and remove) should be registeres as reversible_pair()'s in the 
     90    (e.g. add and remove) should be registered as reversible_pair()'s in the 
    9191    reverser engine. 
    9292    The reverser will construct a tuple (callable, arguments) which are send 
     
    101101 2. you might want to add some additional filtering. 
    102102 
    103 Point 2 may require some explaination. First of all observers have been added 
     103Point 2 may require some explanation. First of all observers have been added 
    104104to almost every method that involves a state change. As a result multiple 
    105105(conflicting) revert actions may be generated (e.g. Canvas.add calls Tree.add, 
     
    125125applied to that function. 
    126126 
    127 The inverse operation is easiest performed by the function saveapply. Of course 
     127The inverse operation is easiest performed by the function saveapply(). Of course 
    128128an inverse operation is emitting a change event too: 
    129129 
     
    156156Function wrappers should have an extra property indicating if a function needs 
    157157to be dispatched or not. If it needs to be dispatched an extra flag should be 
    158 set. This will prevent the system from slowing down due to emiting signals that 
     158set. This will prevent the system from slowing down due to emitting signals that 
    159159are filtered out later on. 
    160160 
     
    174174     x, y, connectable, movable, visible, connected_to and disconnect properties 
    175175   Item: 
    176      canvas and matric properties 
     176     canvas and matrix properties 
    177177   Element: 
    178178     min_height and min_width properties 
    179179   Line: 
    180      line_width, fuzzyness, orthogonal and horizontal properties; 
     180     line_width, fuzziness, orthogonal and horizontal properties; 
    181181     split_segment() and merge_segment() 
    182182 
     
    195195    invert, translate, rotate and scale 
    196196 
    197 Testcases are described in test_state.txt. 
     197Testcases are described in undo.txt. 
    198198 
  • gaphas/trunk/undo.txt

    r1160 r1161  
    6767rotate(radians): 
    6868 
     69    >>> def matrix_approx(m): 
     70    ...     a = [] 
     71    ...     for i in tuple(m): 
     72    ...         if -1e-10 < i < 1e-10: i=0 
     73    ...         a.append(i) 
     74    ...     return tuple(a) 
     75 
    6976    >>> m.rotate(0.5) 
    7077    >>> m 
    7178    Matrix(0.877583, 0.479426, -0.479426, 0.877583, 0, 0) 
    7279    >>> undo() 
    73     >>> m 
    74     Matrix(1, 2.58022e-17, 2.58022e-17, 1, 0, 0) 
     80    >>> matrix_approx(m) 
     81    (1.0, 0, 0, 1.0, 0, 0) 
    7582 
    7683Okay, nearly, close enough IMHO... 
     
    8693    Matrix(0.585055, -0.319617, 0.319617, 0.585055, -10.2168, -2.01515) 
    8794    >>> undo() 
    88     >>> m 
    89     Matrix(1, 5.37489e-17, -8.52201e-17, 1, 1.77636e-15, 0) 
     95    >>> matrix_approx(m) 
     96    (1.0, 0, 0, 1.0, 0, 0) 
    9097 
    9198Again, rotate does not result in an exact match, but it's close enough. 
     
    96103canvas.py: Canvas 
    97104----------------- 
    98  
    99 On the canvas only add() and remove() are monitored: 
    100105 
    101106    >>> from gaphas import Canvas, Item 
     
    105110    >>> item = Item() 
    106111    >>> canvas.add(item) 
     112 
     113The request_update() method is observed: 
     114 
     115    >>> len(undo_list) 
     116    3 
     117    >>> canvas.request_update(item) 
     118    >>> len(undo_list) 
     119    4 
     120 
     121On the canvas only add() and remove() are monitored: 
     122 
    107123    >>> canvas.get_all_items()                          # doctest: +ELLIPSIS 
    108124    [<gaphas.item.Item object at 0x...>] 
     
    125141    [] 
    126142 
    127 The request_update() method is observed too: 
    128  
    129     >>> canvas.request_update(item) 
    130     >>> len(undo_list) 
    131     1 
     143Parent-child relationships are restored as well: 
     144 
     145    TODO! 
     146    >>> child = Item() 
     147    >>> canvas.add(child, parent=item) 
     148    >>> child.canvas is canvas 
     149    True 
     150    >>> canvas.get_parent(child) is item 
     151    True 
     152    >>> canvas.get_all_items()                          # doctest: +ELLIPSIS 
     153    [<gaphas.item.Item object at 0x...>, <gaphas.item.Item object at 0x...>] 
     154    >>> undo() 
     155    >>> child.canvas is None 
     156    True 
     157    >>> canvas.get_all_items()                          # doctest: +ELLIPSIS 
     158    [<gaphas.item.Item object at 0x...>] 
     159    >>> child in canvas.get_all_items() 
     160    False 
     161 
     162Now redo the previous undo action: 
     163 
     164    >>> undo_list[:] = redo_list[:] 
     165    >>> undo() 
     166    >>> child.canvas is canvas 
     167    True 
     168    >>> canvas.get_parent(child) is item 
     169    True 
     170    >>> canvas.get_all_items()                          # doctest: +ELLIPSIS 
     171    [<gaphas.item.Item object at 0x...>, <gaphas.item.Item object at 0x...>] 
     172 
    132173 
    133174NOTE: If remove() is invoked recursively (e.i. when the to-be removed item has 
     
    214255------------- 
    215256 
    216 A line has the following properties: line_width, fuzzyness, orthogonal and 
     257A line has the following properties: line_width, fuzziness, orthogonal and 
    217258horizontal. Each one of then is observed for changes: 
    218259 
    219260    >>> from gaphas import Line 
    220261    >>> l = Line() 
    221     >>> l.line_width, l.fuzzyness, l.orthogonal, l.horizontal 
     262    >>> l.line_width, l.fuzziness, l.orthogonal, l.horizontal 
    222263    (2, 0, False, False) 
    223264 
     
    225266 
    226267    >>> l.line_width = 4 
    227     >>> l.fuzzyness = 2 
     268    >>> l.fuzziness = 2 
    228269    >>> l.orthogonal = True 
    229270    >>> l.horizontal = True 
    230     >>> l.line_width, l.fuzzyness, l.orthogonal, l.horizontal 
     271    >>> l.line_width, l.fuzziness, l.orthogonal, l.horizontal 
    231272    (4, 2, True, True) 
    232273 
     
    234275 
    235276    >>> undo() 
    236     >>> l.line_width, l.fuzzyness, l.orthogonal, l.horizontal 
     277    >>> l.line_width, l.fuzziness, l.orthogonal, l.horizontal 
    237278    (2, 0, False, False) 
    238279 
     
    242283    >>> l.handles() 
    243284    [<Handle object on (0, 0)>, <Handle object on (10, 10)>] 
     285 
     286This is our basis for further testing. 
     287 
     288    >>> del undo_list[:] 
    244289 
    245290    >>> l.split_segment(0)