Changeset 1803

Show
Ignore:
Timestamp:
08/01/07 00:35:21 (1 year ago)
Author:
arj..@yirdis.nl
Message:

updated (rst'ed) txt files.

Files:

Legend:

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

    r1766 r1803  
    66The basic idea is: 
    77 
    8  - Items (canvas items) should be used as "adapter" for model elements. 
    9    (not a real adapter since they are stateful). 
    10  - The canvas determines the tree structure (which items are children 
    11    of some other item is maintained by the canvas itself). 
    12  - of course the constraint solver is present. 
    13  - more modular: e.g. handle support could be swapped in and swapped out. 
    14  - rendering using Cairo. 
    15  
    16  
    17 To do 
    18 ===== 
    19  
    20 This is it as far as stage 1 is concerned. I have implemented: 
    21  v a render cycle. 
    22  v zoom and move functionality (canvas2world). 
    23  v scroll-bars work. 
    24  v a set of tools and a ToolChain (to chain them together). 
    25  v rubberband selection 
    26  
    27 Stage 2: 
    28  v check the code with pylint for strange things. 
    29  v line item 
    30  v placement tool 
    31  v connection protocol 
    32  v make update cycle independent from render (expose) event. 
    33     This is something we might do if the response is getting bad. 
    34  ? rotating and shearing for Element items. 
    35     Do we need this? 
    36  
    37 Stage 3: 
    38  v make double and triple click work. 
    39  v text edit tool (gtk.Edit in popup window?) 
    40  
    41 Stage n: 
    42  - Drop-zone tool 
    43      the idea is that for example you have a Package and when you drag 
    44      a Class into it it automatically makes the Package its owning element. 
    45  v undo management 
    46  
     8- Items (canvas items) should be used as "adapter" for model elements. 
     9  (not a real adapter since they are stateful). 
     10- The canvas determines the tree structure (which items are children 
     11  of some other item is maintained by the canvas itself). 
     12- of course the constraint solver is present. 
     13- more modular: e.g. handle support could be swapped in and swapped out. 
     14- rendering using Cairo. 
     15 
     16Gaphas is released under the terms of the GNU Library General Public License 
     17(LGPL). See the COPYING file for details. 
     18 
     19.. contents:: 
    4720 
    4821How it Works 
     
    6336 
    6437View (from view.py) is used to visualize a canvas. On a View, a Tool 
    65 (from tool.py) can be assigned, which will handle user input (button presses, 
     38(from tool.py) can be applied, which will handle user input (button presses, 
    6639key presses, etc.). Painters (from painter.py) are used to do the actual 
    6740drawing. This way it should be easy do draw to other media than the screen, 
     
    7346(Canvas.request_update()). The canvas performs an update by calling: 
    7447 
    75  1. Item.pre_update(context) 
    76  2. updating World-to-Item matrices, for fast transformation of coordinates 
    77     from the world to the items' coordinate system. 
    78     The w2i matrix is stored on the Item as Item._matrix_w2i. 
    79  3. solve constraints 
    80  4. normalize items by setting the coordinates of the first handle to (0, 0). 
    81  5. updating World-to-Item matrices again, just to be on the save side. 
    82  6. Item.post_update(context) 
    83  
    84 The idea is to do as much updating as possible in the (pre_)update() methods, 
    85 since they are called when the application is not handling user input. 
     481. Item.pre_update(context) for each item marked for update 
     492. Updating Canvas-to-Item matrices, for fast transformation of coordinates 
     50   from the canvas' to the items' coordinate system. 
     51   The c2i matrix is stored on the Item as Item._matrix_c2i. 
     523. Solve constraints. 
     534. Normalize items by setting the coordinates of the first handle to (0, 0). 
     545. Updating Canavs-to-Item matrices for items that have been changed by 
     55   normalizarion, just to be on the save side. 
     566. Item.post_update(context) for each item marked for update, including items 
     57   that have been marked during constraint solving. 
     58 
     59The idea is to do as much updating as possible in the {pre|post}_update() 
     60methods, since they are called when the application is not handling user input. 
    8661 
    8762The context contains: 
    8863 
    89  cairo:    a CairoContext, this can be used to calculate the dimensions of text 
    90            for example 
     64:cairo: a CairoContext, this can be used to calculate the dimensions of text 
     65        for example 
    9166 
    9267NOTE: updating is done from the canvas, items should not update sub-items. 
    9368 
    9469After an update, the Item should be ready to be drawn. 
     70 
     71Constraint solving 
     72------------------ 
     73A word about the constraint solver seems in place. It is one of the big 
     74features of this library after all. The Solver is able to solve constraints. 
     75Constraints can be applied to items (e.g. the Element item uses constraints to 
     76maintain it's recangular shape) and constraints can be created *between* items 
     77(for example a line that connects to a box). 
     78 
     79Constaints that apply to one item are pretty straight forward, as all variables 
     80live in the same coordinate system (of the item). The variables (in most cases 
     81a Handle's x and y coordinate) can simply be put in a constraint. 
     82 
     83When two items are connected to each other and constraints are created, a 
     84problem shows up: variables live in separate coordinate systems. To overcome 
     85this problem a Projection (from solver.py) has been defined. With a Projection 
     86instance, a variable can be "projected" on another coordinate system. In this 
     87case, where two items are connecting to each other, the Canvas' coordinate 
     88system is used. 
     89 
    9590 
    9691Drawing 
     
    10499The view context passed to the Items draw() method has the following properties: 
    105100 
    106  view:     the view we're drawing to 
    107  cairo:    the CairoContext to draw to 
    108  selected: True if the item is actually selected in the view 
    109  focused:  True if the item has the focus 
    110  hovered:  True if the mouse pointer if over the item. Only the top-most item 
     101:view:     the view we're drawing to 
     102:cairo:    the CairoContext to draw to 
     103:selected: True if the item is actually selected in the view 
     104:focused:  True if the item has the focus 
     105:hovered:  True if the mouse pointer if over the item. Only the top-most item 
    111106           is marked as hovered. 
    112  dropzone: The item is marked as drop zone. This happens then an item is 
     107:dropzone: The item is marked as drop zone. This happens then an item is 
    113108           dragged over the item and (if dropped) will become a child of 
    114109           this item. 
    115  draw_all: True if everything drawable on the item should be drawn (e.g. when 
     110:draw_all: True if everything drawable on the item should be drawn (e.g. when 
    116111           calculating the bounding boxes). 
    117112 
    118113The View automatically calculates the bounding box for the item, based on the 
    119 items drawn in the draw(context) function (this is only done once after each 
    120 Item.update()). The bounding box is in viewport coordinates. 
     114items drawn in the draw(context) function (this is only done when really 
     115necessary, e.g. after an update of the item). The bounding box is in viewport 
     116coordinates. 
    121117 
    122118The actual drawing is done by Painters (painter.py). A series of Painters have 
    123 been defined: one for handles, one for items
     119been defined: one for handles, one for items, etc
    124120 
    125121Tools 
     
    129125Tools can be chained together in order to provide more complex behavior. 
    130126 
    131 To mak eit easy a DefaultTool has been defined: a ToolChain instance with the 
     127To make it easy a DefaultTool has been defined: a ToolChain instance with the 
    132128tools added that are listed in the following sections. 
    133129 
    134130ToolChain 
    135 ~~~~~~~~~ 
    136 The ToolChain does not do anything by itself. It delegates to a set of tools 
    137 and keeps track of which tool has grabbed the focus. This happens most of the 
    138 time when the uses presses a mouse button. The tool requests a grab() and 
    139 all upcoming events (e.g. motion or button release events) are directly sent 
    140 to the focused tool. 
     131    The ToolChain does not do anything by itself. It delegates to a set of 
     132    tools and keeps track of which tool has grabbed the focus. This happens 
     133    most of the time when the uses presses a mouse button. The tool requests a 
     134    grab() and all upcoming events (e.g. motion or button release events) are 
     135    directly sent to the focused tool. 
    141136 
    142137HoverTool 
    143 ~~~~~~~~~ 
    144 A small and simple tool that does nothing more than making the item under the 
    145 mouse button the "hovered item". When such an item is drawn, its 
    146 context.hovered_item flag will be set to True. 
     138    A small and simple tool that does nothing more than making the item under 
     139    the mouse button the "hovered item". When such an item is drawn, its 
     140    context.hovered_item flag will be set to True. 
    147141 
    148142HandleTool 
    149 ~~~~~~~~~~ 
    150 The HandleTool is used to deal with handles. Handles can be dragged around. 
    151 Clicking on a handle automatically makes the underlaying item the focused item. 
     143    The HandleTool is used to deal with handles. Handles can be dragged around. 
     144    Clicking on a handle automatically makes the underlaying item the focused 
     145    item. 
    152146 
    153147ItemTool 
    154 ~~~~~~~~ 
    155 The item tool takes care of selecting items and dragging items around. 
     148    The item tool takes care of selecting items and dragging items around. 
    156149 
    157150TextEditTool 
    158 ~~~~~~~~~~~~ 
    159 This is a demo-tool, featuring a text-edit popup. 
     151    This is a demo-tool, featuring a text-edit popup. 
    160152 
    161153RubberbandTool 
    162 ~~~~~~~~~~~~~~ 
    163 The last toolin line is the rubberband tool. It's invoked when the mouse button 
    164 is pressed on a section of the view where no items or handles are present. It 
    165 allows the user to select items using a selection box (rubberband). 
     154    The last toolin line is the rubberband tool. It's invoked when the mouse 
     155    button is pressed on a section of the view where no items or handles are 
     156    present. It allows the user to select items using a selection box 
     157    (rubberband). 
    166158 
    167159 
     
    177169One of the problems you'll face is what to do when an item is removed from the 
    178170canvas and there are other items (lines) connected to. This problem can be 
    179 solved by providing a disconnect handler to the handle instance ones it is 
     171overcome by providing a disconnect handler to the handle instance ones it is 
    180172connected. A callable object (e.g. function) can be assigned to the handle. It 
    181173is called at the moment the item it's connected to is removed from the canvas. 
     
    201193 
    202194tree.py: 
    203        Central tree structure (no more CanvasGroupable) 
     195    Central tree structure (no more CanvasGroupable) 
    204196solver.py: 
    205        A constraint solver (infinite domain, based on diacanvas2's solver) 
     197    A constraint solver (infinite domain, based on diacanvas2's solver) 
    206198constraint.py: 
    207        Constraint implementation. 
     199    Constraint implementation. 
    208200geometry.py: 
    209        Matrix, Rectangle calculations. 
     201    Matrix, Rectangle calculations. 
    210202quadtree.py: 
    211         A QuadTree spacial index. Used in the View to pick items quickly. 
     203    A QuadTree spacial index. Used in the View to pick items quickly. 
    212204 
    213205Canvas classes: 
    214206 
    215207item.py: 
    216        Canvas item and handle 
     208    Canvas item and handle 
    217209canvas.py: 
    218        Canvas class 
     210    Canvas class 
    219211view.py: 
    220        Canvas view (renderer) class 
     212    Canvas view (renderer) class 
    221213tool.py: 
    222        Base class for Tools (which handle events on the view). 
     214    Base class for Tools (which handle events on the view). 
    223215 
    224216Other: 
    225217 
    226218examples.py: 
    227        Simple example classes. 
     219    Simple example classes. 
    228220 
    229221Guidelines 
    230 ---------- 
    231 Following the Python coding guidelines 
    232 <http://www.python.org/dev/peps/pep-0008/> indentation should be 4 spaces 
    233 (no tabs), function and method names should be lowercase_with_underscore(), 
    234 and files should contain a __version__ property, like this: 
     222========== 
     223Following the `Python coding guidelines`_ indentation should be 4 spaces 
     224(no tabs), function and method names should be ``lowercase_with_underscore()``, 
     225and files should contain a ``__version__`` property, like this:: 
    235226 
    236227  __version__ = "$Revision$" 
     
    240231 
    241232This inhibits that for each .py file, the svn:keywords property should be set 
    242 to "Revision HeadURL". This can be done manually
     233to ``Revision HeadURL``. This can be done manually:
    243234 
    244235  $ svn propset svn:keywords "Revision HeadURL" myfile.py 
    245236 
    246 or by configuring your ~/.subversion/config file to use auto-props: 
     237or by configuring your ~/.subversion/config file to use auto-props:: 
    247238 
    248239  [miscellany] 
     
    255246 
    256247 
     248.. _Python coding guidelines: http://www.python.org/dev/peps/pep-0008/ 
  • gaphas/trunk/state.txt

    r1716 r1803  
    77The state system consists of two parts: 
    88 
    9  1. A basic observer (the @observed decorator) 
    10  2. A reverter 
     91. A basic observer (the ``@observed`` decorator) 
     102. A reverter 
     11 
     12.. contents:: 
    1113 
    1214Observer 
    1315-------- 
    1416 
    15 The observer simply dispatches the function called (as <function ..>, not as 
    16 <unbound method..>!) to each handler registered in an observers list. 
     17The observer simply dispatches the function called (as ``<function ..>``, not as 
     18``<unbound method..>``!) to each handler registered in an observers list. 
    1719 
    1820    >>> from gaphas import state 
     
    5355    [] 
    5456 
    55 The @observed decorator can also be applied to properties, as is done in 
     57The ``@observed`` decorator can also be applied to properties, as is done in 
    5658gaphas/item.py's Handle class: 
    5759 
     
    7274What should you know: 
    7375 
    74  1. The observer always generates events based on 'function' calls. Even for 
    75     class method invokations. This is because, when calling a method (say 
    76     Tree.add) it's the im_func field is executed, which is a function type 
    77     object. 
    78  
    79  2. It's important to know if an event came from invoking a method or a simple 
    80     function. With methods, the first argument always is an instance. This can 
    81     be handy when writing an undo management systems in case multiple calls 
    82     from the same instance do not have to be registered (e.g. if a method 
    83     set_point() is called with exact coordinates (in stead of deltas), only the 
    84     first call to set_point needs to be remembered. 
     761. The observer always generates events based on 'function' calls. Even for 
     77   class method invokations. This is because, when calling a method (say 
     78   Tree.add) it's the im_func field is executed, which is a function type 
     79   object. 
     80 
     812. It's important to know if an event came from invoking a method or a simple 
     82   function. With methods, the first argument always is an instance. This can 
     83   be handy when writing an undo management systems in case multiple calls 
     84   from the same instance do not have to be registered (e.g. if a method 
     85   set_point() is called with exact coordinates (in stead of deltas), only the 
     86   first call to set_point needs to be remembered. 
    8587 
    8688 
     
    9092The reverser requires some registration. 
    9193 
    92  1. Property setters should be declared with reversible_property() 
    93  2. Method (or function) pairs that implement each others reverse operation 
    94     (e.g. add and remove) should be registered as reversible_pair()'s in the 
    95     reverser engine. 
    96     The reverser will construct a tuple (callable, arguments) which are send 
    97     to every handler registered in the subscribers list. Arguments is a dict(). 
    98  
    99 First thing to do is to actually enable the revert_handler
     941. Property setters should be declared with reversible_property() 
     952. Method (or function) pairs that implement each others reverse operation 
     96   (e.g. add and remove) should be registered as reversible_pair()'s in the 
     97   reverser engine. 
     98   The reverser will construct a tuple (callable, arguments) which are send 
     99   to every handler registered in the subscribers list. Arguments is a dict(). 
     100 
     101First thing to do is to actually enable the ``revert_handler``
    100102 
    101103    >>> state.observers.add(state.revert_handler) 
    102104 
    103105This handler is not enabled by default because: 
    104  1. it generates quite a bit of overhead if it isn't used anyway 
    105  2. you might want to add some additional filtering. 
     106 
     1071. it generates quite a bit of overhead if it isn't used anyway 
     1082. you might want to add some additional filtering. 
    106109 
    107110Point 2 may require some explanation. First of all observers have been added 
     
    129132applied to that function. 
    130133 
    131 The inverse operation is easiest performed by the function saveapply(). Of course 
    132 an inverse operation is emitting a change event too: 
     134The inverse operation is easiest performed by the function saveapply(). Of 
     135course an inverse operation is emitting a change event too: 
    133136 
    134137    >>> state.saveapply(*events.pop())                  # doctest: +ELLIPSIS 
     
    155158    >>> state.observers.remove(state.revert_handler) 
    156159 
    157 TODO 
    158 ---- 
    159  
    160 Function wrappers should have an extra property indicating if a function needs 
    161 to be dispatched or not. If it needs to be dispatched an extra flag should be 
    162 set. This will prevent the system from slowing down due to emitting signals that 
    163 are filtered out later on. 
    164  
    165160What is Observed  
    166161---------------- 
     
    170165to monitor the Matrix class (which is from Cairo). 
    171166 
    172  canvas.py: 
    173   Canvas: 
    174     add() and remove() 
    175  
    176  item.py: 
    177   Handle: 
    178     x, y, connectable, movable, visible, connected_to and disconnect properties 
    179   Item: 
    180     canvas and matrix properties 
    181   Element: 
    182     min_height and min_width properties 
    183   Line: 
    184     line_width, fuzziness, orthogonal and horizontal properties; 
    185     split_segment() and merge_segment() 
    186  
    187  solver.py: 
    188   Variable: 
    189     strength and value properties 
    190   Solver: 
    191     add_constraint() and remove_constraint()  
    192  
    193  tree.py: 
    194   Tree: 
    195     add() and remove() 
    196  
    197  matrix.py: 
    198   Matrix: 
    199     invert, translate, rotate and scale 
     167canvas.py: 
     168  Canvas: 
     169    add() and remove() 
     170 
     171item.py: 
     172  Handle: 
     173    x, y, connectable, movable, visible, connected_to and disconnect properties 
     174  Item: 
     175    canvas and matrix properties 
     176  Element: 
     177    min_height and min_width properties 
     178  Line: 
     179    line_width, fuzziness, orthogonal and horizontal properties; 
     180    split_segment() and merge_segment() 
     181 
     182solver.py: 
     183  Variable: 
     184    strength and value properties 
     185  Solver: 
     186    add_constraint() and remove_constraint()  
     187 
     188tree.py: 
     189  Tree: 
     190    add() and remove() 
     191 
     192matrix.py: 
     193  Matrix: 
     194   invert, translate, rotate and scale 
    200195 
    201196Testcases are described in undo.txt. 
  • gaphas/trunk/undo.txt

    r1716 r1803  
    99 
    1010See state.txt about how state is recorded. 
     11 
     12.. contents:: 
    1113 
    1214For this to work, some boilerplate has to be configured: 
     
    3638tree.py: Tree 
    3739------------- 
    38 Tree's add() and remove() methods are disabled by default. 
     40Tree's ``add()`` and ``remove()`` methods are disabled by default. 
    3941 
    4042    >>> from gaphas.tree import Tree 
     
    121123----------------- 
    122124Matrix is used by Item classes. 
    123     invert, translate, rotate and scale 
    124125 
    125126    >>> from gaphas.matrix import Matrix 
     
    192193    >>> canvas.add(item) 
    193194 
    194 The request_update() method is observed: 
     195The ``request_update()`` method is observed: 
    195196 
    196197    >>> len(undo_list) 
     
    200201    4 
    201202 
    202 On the canvas only add() and remove() are monitored: 
     203On the canvas only ``add()`` and ``remove()`` are monitored: 
    203204 
    204205    >>> canvas.get_all_items()                          # doctest: +ELLIPSIS 
     
    271272item.py: Handle 
    272273--------------- 
    273      x, y, connectable, movable, visible, connected_to and disconnect properties 
    274274Changing the Handle's position is reversible: 
    275275 
     
    316316while testing the Canvas class. 
    317317 
    318 The Matrix has been tested in section matrix.y: Matrix. 
     318The Matrix has been tested in section matrix.py: Matrix. 
    319319 
    320320item.py: Element 
    321321---------------- 
    322322 
    323 An element has min_height and min_width properties. 
     323An element has ``min_height`` and ``min_width`` properties. 
    324324 
    325325    >>> from gaphas import Element 
     
    343343------------- 
    344344 
    345 A line has the following properties: line_width, fuzziness, orthogonal and 
    346 horizontal. Each one of then is observed for changes: 
     345A line has the following properties: ``line_width``, ``fuzziness``, 
     346``orthogonal`` and ``horizontal``. Each one of then is observed for changes: 
    347347 
    348348    >>> from gaphas import Line 
     
    404404----------------- 
    405405 
    406 Solvers add_constraint() and remove_constraint() are observed.  
     406Solvers ``add_constraint()`` and ``remove_constraint()`` are observed.  
    407407 
    408408    >>> from gaphas.solver import Solver