<?xml version="1.0"?>
<!-- vi:sw=2:tw=78
 -->
<!DOCTYPE book
  PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
      "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY DiaStrength SYSTEM "xml/dia-strength.xml">
<!ENTITY DiaVariable SYSTEM "xml/dia-variable.xml">
<!ENTITY DiaExport SYSTEM "xml/dia-export.xml">
<!ENTITY DiaExpression SYSTEM "xml/dia-expression.xml">
<!ENTITY DiaConstraint SYSTEM "xml/dia-constraint.xml">
<!ENTITY DiaSolver SYSTEM "xml/dia-solver.xml">
<!ENTITY DiaCanvasView SYSTEM "xml/dia-canvas-view.xml">
<!ENTITY DiaEvent SYSTEM "xml/dia-event.xml">
<!ENTITY DiaCanvasViewItem SYSTEM "xml/dia-canvas-view-item.xml">
<!ENTITY DiaCanvas SYSTEM "xml/dia-canvas.xml">
<!ENTITY DiaCanvasItem SYSTEM "xml/dia-canvas-item.xml">
<!ENTITY DiaCanvasGroup SYSTEM "xml/dia-canvas-group.xml">
<!ENTITY DiaCanvasGroupable SYSTEM "xml/dia-canvas-groupable.xml">
<!ENTITY DiaCanvasEditable SYSTEM "xml/dia-canvas-editable.xml">
<!ENTITY DiaHandleLayer SYSTEM "xml/dia-handle-layer.xml">
<!ENTITY DiaHandle SYSTEM "xml/dia-handle.xml">
<!ENTITY DiaShape SYSTEM "xml/dia-shape.xml">
<!ENTITY DiaShapeArt SYSTEM "xml/dia-shape-art.xml">
<!ENTITY DiaShapeX SYSTEM "xml/dia-shape-x.xml">
<!ENTITY DiaGeometry SYSTEM "xml/dia-geometry.xml">
<!ENTITY DiaCanvasLine SYSTEM "xml/dia-canvas-line.xml">
<!ENTITY DiaCanvasElement SYSTEM "xml/dia-canvas-element.xml">
<!ENTITY DiaCanvasBox SYSTEM "xml/dia-canvas-box.xml">
<!ENTITY DiaCanvasImage SYSTEM "xml/dia-canvas-image.xml">
<!ENTITY DiaCanvasText SYSTEM "xml/dia-canvas-text.xml">
<!ENTITY DiaTool SYSTEM "xml/dia-tool.xml">
<!ENTITY DiaUndoManager SYSTEM "xml/dia-undo-manager.xml">
<!ENTITY PythonDemoItem SYSTEM "../../python/demoitem.py">
]>

<book id="index">
  <bookinfo>
    <title>DiaCanvas2 Reference Manual</title>
    <subtitle>Version 0.14.0</subtitle>
    <author><firstname>Arjan</firstname><surname>Molenaar</surname></author>

    <abstract>
      <para>This is the DiaCanvas2 reference manual. It contains information
	about how to use the DiaCanvas2. This documentation is written for
	people who want to start programming with DiaCanvas2.</para>
      <para>In <xref linkend="chap-DiaCanvas"/> the canvas model is discussed.
        In <xref linkend="chap-Solver"/> the usage and rationale behind the
	<link linkend="DiaSolver">DiaSolver</link> class is explained.
	The solver is used to keep connections between objects true.
	The third chapter tells you about some standard objects.
	Visualization is explained in <xref linkend="chap-Views"/>.
	A view will allow you to display the (abstract) contents
	of a DiaCanvas in a window. This will also tell you something about
	the default behavior of the canvas(-views). The
	<link linkend="chap-Geometry">last chapter</link> discusses
	some functions for determining distances and intersections of points,
	lines and rectangles.</para>
    </abstract>
  </bookinfo>

  <chapter id="chap-DiaCanvas">
    <!-- TODO:
	- DiaCanvasItem is stateless, special case: DiaCanvasItemClass::event()
	- composite objects.
	- describe handling of events (1st grabbed item, then focus_item, and
	  at last the event underneath the mouse cursor.
    -->
    <title>The Canvas</title>

    <para>DiaCanvas is a GNOME widget tailored to applications that draw a 
      diagram, in the wider sense of the word. DiaCanvas has a Visio like
      appearance and supports the GNOME anti-alias canvas.</para>
    
    <para>DiaCanvas2 uses the model/view/controller paradigm to make it possible
      to create multiple views of one object and to separate visualization data
      from the (more simple) data model. <link linkend="DiaCanvas">DiaCanvas
      </link> is the base class for the canvas model. A canvas contains a set of
      <link linkend="DiaCanvasItem">DiaCanvasItem</link>s.
      The <link linkend="DiaCanvasView">DiaCanvasView</link> class is the
      visual counterpart of DiaCanvas. The <link linkend="DiaCanvasViewItem">
      DiaCanvasViewItem</link> is the visual counterpart of
      the <link linkend="DiaCanvasItem">DiaCanvasItem</link>,
      the object that contains information about an object
      on the canvas.</para>

    <para>A programmer should not need to worry about the views of the canvas.
      All the programmer needs to do is inherit from DiaCanvasItem to create
      a object that has more specialized functionality. The view will request
      the <link linkend="DiaShape">DiaShape</link> objects that describe
      the appearance. A shape is the most
      simple representation of a drawing primitive.
      For a line is would be a list of points, the line width, end point type
      and the color.</para>

    <para>DiaCanvasItems are stateless. A few functions are provided that
      can request the visibility status (normal, selected, focus, grabbed)
      from the active view.
      </para>

    <para>As of version 0.13, DiaCanvasItems do no longer handle events
      themselves. All events are hanlded by <link linkend="DiaTool">tools</link>. 
      A tool acts as a controler in the canvas: it receives user events and
      translates them to an action. Tools handle the movement of <link
      linkend="DiaHandle">handles</link>, the movement of items and the
      rubberband selection.</para>

    <para>Objects can be transformed in a generic way. This can be done by
      using an transformation matrix. If you have programmed with the
      <link linkend="GnomeCanvas">GnomeCanvas</link> this probably sounds
      familiar. For example if an object needs to be rotated, the
      matrix is assigned values to make the transformation possible. The object
      itself, however does not need to know that it is transformed, it
      creates its shapes the same way it would have done when the object was
      not rotated.</para>

    <para>The interface <link linkend="DiaCanvasGroupable">DiaCanvasGroupable
      </link>has a special meaning. Groupable objects have the ability to
      contain child objects visible to the view. The views use this
      interface to access those child objects. Objects exposed via the
      DiaCanvasGroupable interface can recieve events and can therefore
      be selected individually. The <link linkend="DiaCanvasGroup">
      DiaCanvasGroup</link> class realizes this interface. Items can be
      assembled by using multiple <link linkend="DiaCanvasItemFlags">
      composite</link> items.</para>

    <para>Another interface, <link
      linked="DiaCanvasEditable">DiaCanvasEditable</link>, can be used to make
      text editable on the canvas. The default tools will check if an item
      supports this interface whenever the item is double-clicked. The
      DiaCanvasItem may then return a <link linkend="DiaShapeText">text
      shape</link> that will then be edited.</para>

    <para>An object usually has a bunch of handles. A handle
      (<link linkend="DiaHandle">DiaHandle</link>) is
      an object used to manipulate the DiaCanvasItem. For a line the handles
      can be used to move the different points on the line (every point is
      represented by a handle). A rectangle might have a handle on every corner,
      this makes it easy to resize the rectangle.</para>

    <para>DiaHandle objects are always drawn on top of the objects. This way
      you can guess where an object is, even if it is hidden by another object.
      </para>

    <para>Like all diagrams an item can be connected to another.
      In DiaCanvas2 those relations are held true by means of a linear
      constraint solver. If a line connects to a rectangle object
      (e.g. a box), an equation is created that will position the line's
      handle on the side of the rectangle. If the rectangle is moved,
      the line also moves (or at least the line's handle). Please read
      the chapter about the <link linkend="chap-Solver">constraint solver</link>
      for more information.</para>

    <figure>
      <title>UML model of the DiaCanvas model</title>
      <graphic fileref="diacanvas.png" format="gif"></graphic>
    </figure>

    &DiaCanvas;
    &DiaCanvasGroupable;
    &DiaCanvasEditable;
    &DiaCanvasItem;
    &DiaCanvasGroup;
    &DiaShape;
    &DiaHandle;
    &DiaUndoManager;
    &DiaExport;
  </chapter>

  <chapter id="chap-Solver">
    <title>Linear Constraint Solver</title>

    <para>Creating a diagram is no fun if the different objects on the
      canvas can not create relations with each other.</para>

    <para>The easiest way (at first) seems to hard code the behavior that is
      desirable when objects need to have a relation with each other. This
      is a quite limited approach, since it is hard to tailor the objects
      behavior to the expectations of the user. It is also hard to verify
      if the code works correctly under all circumstances, since the code
      is scattered among a lot of different classes.</para>

    <para>When using a constraint solver instead we can solve a bunch of
      problems at once:
      <orderedlist>
	<listitem>
	  <para>We are free to create any relation between any object on
	    the canvas.</para>
	  </listitem>
	<listitem>
	  <para>All constraints on the canvas can easily be verified at
	    once.</para>
	  </listitem>
	<listitem>
	  <para>Stability: no strange behavior can be expected as long as
	    the constraints are constructed properly.</para>
	  </listitem>
	</orderedlist>
      </para>

    <para>It is easy to assign new values to a bunch of objects and then
      solve all constraints at once. This is desirable in an interactive
      environment where speed is a prerequisite.</para>

    <para>Every variable is assigned a strength. When solving constraints the
      weakest variable in an equation will be adjusted to make the equation
      true.</para>

    <para>DiaCanvas2 features a small constraint solver based on
      GObject. The big advantage is that you can send signals between
      the different parts of the constraint solver, this will keep the
      code clean.</para>

    <para>The solver consists of three classes:
      <variablelist>
	<varlistentry>
	  <term><link linkend="DiaVariable">DiaVariable</link></term>
	  <listitem>
	    <para>A DiaVariable hold a variable value. If the value changes
	      the <quote>changed_internal</quote> signal is emitted. This
	      signal is emitted every time the variable is assigned a
	      new value. The DiaVariable also has a <quote>changed</quote>
	      signal. This signal is emitted if its value is changed by the
	      constraint solver. You usually want to connect to this
	      signal.</para>
	    </listitem>
	  </varlistentry>
	<varlistentry>
	  <term><link linkend="DiaConstraint">DiaConstraint</link></term>
	  <listitem>
	    <para>A Constraint consists of an linear expression. For this
	      purpose a helper class "DiaExpression" is created. An
	      expression is an array of <emphasis>variable * constant</emphasis>
	      pairs. This will result in an expression like:
	      <emphasis>a*x + b*y +c = 0</emphasis>.
	      A constraint will react on DiaVariable's
	      <quote>changed_internal </quote> signal by emitting
	      <quote>need_resolve</quote>.</para>
	    </listitem>
	  </varlistentry>
	<varlistentry>
	  <term><link linkend="DiaSolver">DiaSolver</link></term>
	  <listitem>
	    <para>The solver is the most interesting class of all: this is where
	      the actual work is done. You can add constraints to the solver.
	      The solver will connect to the constraints
	      <quote>need_resolve</quote> signal. If a constraint emits the
	      <quote>need_resolve</quote> signal the constraint will be marked.
	      If the <link linkend="dia-solver-resolve">resolve</link>
	      function is called the solver tries to
	      satisfy all constraints. This is done by looking for the
	      weakest variable in the constraint. If weakest variable is
	      already edited the constraint is not resolved again.</para>
	    </listitem>
	  </varlistentry>
	</variablelist>
      </para>

    <figure>
      <title>UML model of the DiaSolver</title>
      <graphic fileref="diasolver.png" format="gif"></graphic>
    </figure>

    &DiaStrength;
    &DiaVariable;
    &DiaExpression;
    &DiaConstraint;
    &DiaSolver;
  </chapter>

  <chapter id="chap-Objects">
    <title>Standard objects</title>
    <para>
      </para>
    &DiaCanvasLine;
    &DiaCanvasElement;
    &DiaCanvasBox;
    &DiaCanvasImage;
    &DiaCanvasText;
  </chapter>

  <chapter id="chap-Views">
    <title>Visualization and Interaction</title>

    <para>Once you have created a <link linkend="DiaCanvas">DiaCanvas</link>
      it is likely that you want
      to display it on the screen. This is done by creating a
      <link linkend="DiaCanvasView">DiaCanvasView</link> object. The
      DiaCanvasView is used to interact with the object.</para>

    <para>Once you create a DiaCanvasView, a <link linkend="DiaCanvasViewItem">
      DiaCanvasViewItem</link> is created
      for every <link linkend="DiaCanvasItem">DiaCanvasItem</link> in the
      DiaCanvas (notice the difference: with
      or without <quote>View</quote>). The DiaCanvasViewItem objects will render
      the information found while iterating the <link linkend="DiaShape">
      DiaShape</link> objects. A view can be either
      LibArt based (with anti-aliasing) or X based. The X based implementation
      might work a little faster, but on a not-too-old computer you will hardly
      notice the difference.</para>

    <para>In order to increase usability, the render information used by the
      view items will be stored. Every view item will have it's own render data
      of a DiaShape.</para>

    <para>Once you have a nice DiaCanvasView on your screen  it is likely that
      you want to interact with it. We can split the user interaction in four
      parts:
      <orderedlist>
	<listitem>
	  <para>Actions on the item itself.</para></listitem>
	<listitem>
	  <para>Actions on the handles of an item.</para></listitem>
	<listitem>
	  <para>Actions involving multiple items on the canvas.</para>
	  </listitem>
	<listitem>
	  <para>View related actions.</para></listitem>
      </orderedlist></para>

    <para>Actions on the item are mainly button presses, motion events and
      button release events. The object should not worry about being selected
      or not, those kinds of state changes are taken care of by the view.
      The object should grab the focus if it wants to receive all user actions
      (this is usually the case when a mouse button is pressed).
      </para>

    <para>Actions on the handles are not handled by the item. A special object
      (DiaHandleLayer) takes care of the handles. There is one exception: when
      a handle is moved the handle owner (a DiaCanvasItem) is asked whether
      or not it is allowed to do a certain motion by calling the
      <link linkend="DiaCanvasItemClass">DiaCanvasItemClass</link>::<link linkend="DiaCanvasItem-handle-motion">handle_motion</link>() callback function.</para>

    <para>If a handle is pressed the owner object will get the focus. The
      <link linkend="DiaHandleLayer">DiaHandleLayer</link> does not know
      about any special action that should take
      place when a certain key modifier is pressed. For example
      <link linkend="DiaCanvasElement">DiaCanvasElement</link>
      like objects will rotate when a corner handle is moved and the CONTROL
      key is pressed and shear when a center handle is moved. This behavior
      is dictated by the DiaCanvasItem rather than the DiaHandleLayer.</para>

    <para>The only case where more than one object is involved is when multiple
      objects are selected and the objects are moved. It is the DiaCanvasItem
      that has the focus who initiates the move: by calling
      dia_canvas_item_move_interactive() all selected objects on the active
      view are moved.</para>

    <para>View related actions consist of selecting objects and deselecting
      objects. If the SHIFT button is held, no objects will be deselected.
      Pressing the CONTROL key while selecting objects will toggle the
      selection.</para>
      
    <figure>
      <title>UML model of the DiaCanvasView</title>
      <graphic fileref="diacanvasview.png" format="gif"></graphic>
    </figure>

    &DiaCanvasView;
    &DiaCanvasViewItem;
    &DiaTool;
    &DiaHandleLayer;
    &DiaShapeArt;
    &DiaShapeX;
  </chapter>

  <chapter id="chap-Geometry">
    <title>DiaCanvas2 Geometric Functions</title>
    <para>Function related to points and rectangles.</para>
    &DiaGeometry;
  </chapter>

  <chapter id="chap-Python">
    <title>Python bindings</title>
    <para>DiaCanvas supports Python bindings. This is nice. A typical Python
    program looks like this:</para>
    <programlisting>
#!/usr/bin/env python
                                                                                
import pygtk
pygtk.require('2.0')
import gtk
import diacanvas
                                                                                
canvas = diacanvas.Canvas()
box = diacanvas.CanvasBox()
box.set(border_width=0.3, color=diacanvas.color(200, 100, 100, 128))
canvas.root.add(box)
box.move(20, 20)
                                                                                
window = gtk.Window()
view = diacanvas.CanvasView(canvas=canvas)
view.show()
window.add(view)
window.connect("destroy", gtk.mainquit)
window.show()
                                                                                
gtk.main()
    </programlisting>

    <para>The Python DiaCanvas2 module is split up in one main module
    (diacanvas) and two submodules (shape and geometry). The diacanvas module
    contains the main canvas stuff, like Canvas, CanvasItem and CanvasView.
    The shape module is interesting if you want to create your own canvas
    items in Python, so is the geometry module.</para>

    <para>In Python we do not have special types for points, rectangles and
    transformation matrixes, instead we use a simple tuple:</para>
    <informaltable colsep="1" frame="topbot" rowsep="0" shortentry="0">
      <tgroup align="left" cols="2">
	<tbody>
	  <row>
	    <entry><link linkend="DiaPoint">DiaPoint</link></entry>
	    <entry>Tuple (x, y)</entry>
	  </row>
	  <row>
	    <entry><link linkend="DiaRectangle">DiaRectangle</link></entry>
	    <entry>Tuple (left, top, right, bottom)</entry>
	  </row>
	  <row>
	    <entry>gdouble[6] (affine matrix)</entry>
	    <entry>Tuple (a0, a1, a2, a3, a4, a5)</entry>
	  </row>
	</tbody>
      </tgroup>
    </informaltable>
    <para>
    There are a few methods that have been renamed or otherwise modified to
    suite Python:</para>

    <informaltable colsep="1" frame="topbot" rowsep="0" shortentry="0">
      <tgroup align="left" cols="2">
	<thead>
	  <row>
	    <entry>C function</entry>
	    <entry>Python method</entry>
	  </row>
	</thead>
	<tbody>
	  <row>
	    <entry><link linkend="dia-canvas-item-connect">dia_canvas_item_connect</link> (item, handle): boolean</entry>
	    <entry>DiaCanvasItem.connect_handle (self, handle): boolean</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-canvas-item-disconnect">dia_canvas_item_disconnect</link> (item, handle): boolean</entry>
	    <entry>DiaCanvasItem.disconnect_handle (self, handle): boolean</entry>
	  </row>
	  <row>
	    <entry><link linkend="DIA-SET-FLAGS">DIA_SET_FLAGS</link> (item, flags)</entry>
	    <entry>DiaCanvasItem.set_flags (self, flags)</entry>
	  </row>
	  <row>
	    <entry><link linkend="DIA-UNSET-FLAGS">DIA_UNSET_FLAGS</link> (item, flags)</entry>
	    <entry>DiaCanvasItem.unset_flags (self, flags)</entry>
	  </row>
	  <row>
	    <entry><link linkend="DIA-COLOR-A">DIA_COLOR_A</link> (r, g, b, a): int</entry>
	    <entry>color (r, g, b, a=255): int</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-shape-text-cursor-from-pos">dia_shape_text_cursor_from_pos</link> (shape, pos, *cursor): in</entry>
	    <entry>shape.Text.cursor_from_pos (self, pos): (in, cursor)</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-handle-get-pos-i">dia_handle_get_pos_i</link> (handle, *x, *y)</entry>
	    <entry>Handle.get_pos_i (self): (x, y)</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-handle-get-pos-w">dia_handle_get_pos_w</link> (handle, *x, *y)</entry>
	    <entry>Handle.get_pos_w (self): (x, y)</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-canvas-snap-to-grid">dia_canvas_snap_to_grid</link> (canvas, *x, *y)</entry>
	    <entry>Canvas.snap_to_grid (self, x, y): (x, y)</entry>
	  </row>
	  <row>
	    <entry><link
	    linkend="dia-canvas-glue-handle">dia_canvas_glue_handle</link> (canvas, handle, dest_x, dest_y, *glue_x, *glue_y, *item): dist</entry>
	    <entry>Canvas.glue_handle (self, handle, dest_x, dest_y): (dist, (glue_x, glue_y), item)</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-canvas-item-affine-w2i">dia_canvas_item_affine_w2i</link> (item, affine)</entry>
	    <entry>DiaCanvasItem.affine_w2i(self): affine</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-canvas-item-affine-i2w">dia_canvas_item_affine_i2w</link> (item, affine)</entry>
	    <entry>DiaCanvasItem.affine_i2w(self): affine</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-canvas-item-affine-point-w2i">dia_canvas_item_affine_point_w2i</link> (item, *x, *y)</entry>
	    <entry>DiaCanvasItem.affine_point_w2i (self, x, y): (x, y)</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-canvas-item-affine-point-i2w">dia_canvas_item_affine_point_i2w</link> (item, *x, *y)</entry>
	    <entry>DiaCanvasItem.affine_point_i2w (self, x, y): (x, y)</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-rectangle-add-point">dia_rectangle_add_point</link> (rect, point)</entry>
	    <entry>geometry.rectangle_add_point (rect, point): new_rect</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-distance-line-point">dia_distance_line_point</link> (line_start, line_end, point,
	      line_width, style, *point_on_line): distance</entry>
	    <entry>geometry.distance_line_point (line_start, line_end, point,
	      line_width, style): (distance, point_on_line)</entry>
	  </row>
	  <row>
	    <entry><link linkend="dia-intersection-line-line">dia_intersection_line_line</link> (s1, e1, s2, e2, *intersect):
	      boolean</entry>
	    <entry>geometry.intersection_line_line (s1, e1, s2, e2):
	      intersection point or <literal>None</literal></entry>
	  </row>
	  <row>
	    <entry><link
	    linkend="dia-intersection-line-rectangle">dia_intersection_line_rectangle</link>
	    (line_start, line_end, rect, intersect[2]): n_intersect</entry>
	    <entry>geometry.intersection_line_rectangle (start, end,
	    rect): (point1, point2)<footnote><para>If no intersections,
	    <literal>None</literal> is set in place of
	    <literal>point1</literal> and/or
	    <literal>point2</literal>.</para></footnote>
	    </entry>
	  </row>
	</tbody>
      </tgroup>
    </informaltable>

    <para>Some new methods and functions (and one new class) is defined:
    </para>
    <informaltable colsep="1" frame="topbot" rowsep="0" shortentry="0">
      <tgroup align="left" cols="2">
	<tbody>
	  <row>
	    <entry>DiaCanvasItem.set (self, name=value, ...)</entry>
	    <entry>Set multiple properties at once.</entry>
	  </row>
	  <row>
	    <entry>DiaCanvasItem.set_bounds (self, bounds)</entry>
	    <entry>Set the bounds of the canvas item.</entry>
	  </row>
	  <row>
	    <entry>DiaCanvasItem.shape_iter (self)</entry>
	    <entry>Get a Python iterator to the first shape to be rendered.
	    </entry>
	  </row>
	  <row>
	    <entry>set_callbacks(class)</entry>
	    <entry>Initialize the GObject class to forward calls to the python
	    object.</entry>
	  </row>
	  <row>
	    <entry>set_groupable(class)</entry>
	    <entry>Add the <link
	    linkend="DiaCanvasGroupable">CanvasGroupable</link> interface to
	    the class. You should inherit your class from CanvasGroupable
	    too.</entry>
	  </row>
	  <row>
	    <entry>set_editable(class)</entry>
	    <entry>Add the <link
	    linkend="DiaCanvasEditable">CanvasEditable</link> interface to
	    the class. You should inherit your class from CanvasEditable
	    too.</entry>
	  </row>
	  <row>
	    <entry>CanvasEditable</entry>
	    <entry>A abstract base class for the <link
	    linkend="DiaCanvasEditable">DiaCanvasEditable</link> interface.
	    You should call <literal>set_editable()</literal> too if you want
	    to use this interface.</entry>
	  </row>
	  <row>
	    <entry>CanvasGroupable</entry>
	    <entry>A wrapper class for the CanvasGroupable interface. This way
	    you can inherit from the interface too. You should call
	    <literal>set_groupable()</literal> too if you want to use
	    groupability in your canvas item.</entry>
	  </row>
	  <row>
	    <entry>CanvasGroupable.groupable_iter</entry>
	    <entry>Return an iterator which can be used to traverse the groups
	    children.</entry>
	  </row>
	</tbody>
      </tgroup>
    </informaltable>

    <sect1 renderas="sect2">
      <title>Creating canvas items in Python</title>
      <para>It is possible to create fully functional canvas items in Python.
      You have to define the callback methods in your python class and call
      <literal>set_callbacks()</literal> the first time you inherit from
      CanvasItem (or a predefined canvas item from the diacanvas module).
      Note that you have to call the parent's method from within
      your canvas item just like you do with normal python classes. All
      callback methods start with <literal>on_</literal> followed by their
      name. See <link linkend="DiaCanvasItem">DiaCanvasItem</link> for
      details.</para>
      <para>The following callbacks can be defined:</para>
      <informaltable colsep="1" frame="bottom" rowsep="0" shortentry="0">
	<tgroup align="left" cols="2">
	<tbody>
	  <row>
	    <entry>on_update (self, affine): None</entry>
	    <entry>Update the items state. You should try to do most of the
	    update actions in this function, since it is called when the
	    system is idle.</entry>
	  </row>
	  <row>
	    <entry>on_shape_iter(self): object</entry>
	    <entry>Return an iterator object that points to the first shape to
	    be rendered, e.g: <literal>iter([shape1, shape2])</literal>. You
	    can also use generators for this purpose (using the
	    <literal>yield</literal> statement). (Since 0.10.0)</entry>
	  </row>
	  <row>
	    <entry>on_point (self, x, y): distance</entry>
	    <entry>Return the distance from point (x, y) to the item.</entry>
	  </row>
	  <row>
	    <entry>on_move (self, x, y, interactive): None</entry>
	    <entry>Do something if the item moves. You might want to do a
	    <literal>CanvasItem.request_update()</literal> on any sub-items.
	    </entry>
	  </row>
	  <row>
	    <entry>on_handle_motion (self, handle, wx, wy, mask): None</entry>
	    <entry>Do something if a handle is moved.</entry>
	  </row>
	  <row>
	    <entry>on_event (self, event): boolean</entry>
	    <entry>Handle an event send to this item. It should return
	    <literal>1</literal> if the event is handles and
	    <literal>0</literal> otherwise.</entry>
	  </row>
	  <row>
	    <entry>on_glue (self, handle, wx, wy): (dist, (x, y))</entry>
	    <entry>This method is called if a connectable handle of another
	    canvas item is moved. It should return the distance to the item
	    (dist) and the point where the handle may connect (x,y).
	    (wx, wy) is the position where the handle is moved to in world
	    coordinates.</entry>
	  </row>
	  <row>
	    <entry>on_connect_handle (self, handle): boolean</entry>
	    <entry>A handle wants to connect to the item. Return
	    <literal>1</literal> if the handle is connected,
	    <literal>0</literal> otherwise.</entry>
	  </row>
	  <row>
	    <entry>on_disconnect_handle (self, handle): boolean</entry>
	    <entry>Like on_connect_handle(), but now the handle wants to
	    disconnect.</entry>
	  </row>
	</tbody>
	</tgroup>
      </informaltable>

      <sect2 renderas="sect3">
	<title>Grouping canvas items</title>
	<para>For canvas items to support grouping you should inherit your
	canvas item from <literal>CanvasGroupable</literal>. You should also
	set some groupability internals by calling
	<literal>set_groupable()</literal> on your canvas item class. Once you
	have done that you have to define the following methods:</para>
	<informaltable colsep="1" frame="topbot" rowsep="0" shortentry="0">
	  <tgroup align="left" cols="2">
	  <tbody>
	    <row>
	      <entry>on_groupable_add (self, item): boolean</entry>
	      <entry>Add an item to the canvas item. Should return
	      <literal>True</literal> on success, <literal>False</literal> on
	      failure.</entry>
	    </row>
	    <row>
	      <entry>on_groupable_remove (self, item): boolean</entry>
	      <entry>Idem, for removing items from the group.</entry>
	    </row>
	    <row>
	      <entry>on_groupable_iter(self): iter</entry>
	      <entry>Return an iterator object of the first item in the group.
	      You can return something like <literal>iter([item1,
	      item2])</literal> or create a generator object (using the
	      <literal>yield</literal> statement). (Since 0.10.0)</entry>
	    </row>
	    <row>
	      <entry>on_groupable_length (self): int</entry>
	      <entry>Return the amount of items held by the group.</entry>
	    </row>
	    <row>
	      <entry><literal>on_groupable_pos (self, item): int</literal></entry>
	      <entry>Return the position of item in the group list,
	      <literal>-1</literal> on failure.</entry>
	    </row>
	  </tbody>
	  </tgroup>
	</informaltable>
      </sect2>

      <sect2 renderas="sect3">
	<title>Editing text</title>
	<para>For text to be edited on a <link linkend="DiaCanvasView">
	DiaCanvasView</link>, a canvas item should support the
	<link linkend="DiaCanvasEditable">CanvasEditable</link> interface.
	Also call <literal>set_editable(class)</literal> to make the interface
	actually work.  Once you have done that you have to define the
	following methods:</para>
	<informaltable colsep="1" frame="topbot" rowsep="0" shortentry="0">
	  <tgroup align="left" cols="2">
	  <tbody>
	    <row>
	      <entry>on_editable_start_editing (self, shape)</entry>
	      <entry>Start editing of the text represented by the shape,
	      which must be a <link
	      linkend="DiaShapeText">diacanvas.shape.Text</link>.</entry>
	    </row>
	    <row>
	      <entry>on_editable_editing_done (self, shape, new_text)</entry>
	      <entry>Inform that the editing is finished.
	      <literal>shape</literal> is a <link
	      linkend="DiaShapeText">diacanvas.shape.Text</link> and
	      <literal>new_text</literal> is the text after it has been
	      edited.</entry>
	    </row>
	    <row>
	      <entry>on_editable_text_changed (self, shape, new_text)</entry>
	      <entry>Notify the canvas item that the text has changed.
	      <literal>shape</literal> is a <link
	      linkend="DiaShapeText">diacanvas.shape.Text</link> and
	      <literal>new_text</literal> is the text as it is edited.</entry>
	    </row>
	  </tbody>
	  </tgroup>
	</informaltable>
      </sect2>

      <sect2>
        <title>Example</title>

	<para>Here is an example of a canvas item created in Python. The item
	is derived from <classname>DiaCanvasElement</classname> and has one
	line on top and one one on the bottom. It also has a child item which
	can be used to edit some text.</para>
	<programlisting>
&PythonDemoItem;
	</programlisting>
      </sect2>
    </sect1>

  </chapter>
</book>


