[Skencil-commits] r682 - in skencil/branches/skencil-0.6: . Doc Doc/devguide Doc/usersguide Doc/usersguide/Images

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Jun 5 20:35:23 CEST 2006


Author: bh
Date: 2006-06-05 20:35:01 +0200 (Mon, 05 Jun 2006)
New Revision: 682

Added:
   skencil/branches/skencil-0.6/Doc/
   skencil/branches/skencil-0.6/Doc/Makefile
   skencil/branches/skencil-0.6/Doc/README
   skencil/branches/skencil-0.6/Doc/devguide/
   skencil/branches/skencil-0.6/Doc/devguide/architecture.xml
   skencil/branches/skencil-0.6/Doc/devguide/classes.xml
   skencil/branches/skencil-0.6/Doc/devguide/connector.xml
   skencil/branches/skencil-0.6/Doc/devguide/coordsys.xml
   skencil/branches/skencil-0.6/Doc/devguide/curveobj.xml
   skencil/branches/skencil-0.6/Doc/devguide/devguide.xml
   skencil/branches/skencil-0.6/Doc/devguide/fileformat.xml
   skencil/branches/skencil-0.6/Doc/devguide/plugins.xml
   skencil/branches/skencil-0.6/Doc/devguide/remarks.xml
   skencil/branches/skencil-0.6/Doc/devguide/ui.xml
   skencil/branches/skencil-0.6/Doc/devguide/undo.xml
   skencil/branches/skencil-0.6/Doc/usersguide/
   skencil/branches/skencil-0.6/Doc/usersguide/Images/
   skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateCurve.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateEllipse.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/CreatePoly.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateRect.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Delete.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Duplicate.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/EditMode.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/FlipHorizontal.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/FlipVertical.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/GridOn.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Group.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Image.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniEyeClosed.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniEyeOpen.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniPrintOff.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniPrintOn.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveOneDown.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveOneUp.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveToBottom.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveToTop.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/NewDocument.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Open.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Redo.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Save.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/SelectionMode.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Text.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Undo.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Ungroup.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/Zoom.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-left.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-right.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-up.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/bullet.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-conical.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-linear.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-radial.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/layers.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/selsize.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/seltrafo.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/sketch-logo.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/textpath.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/textpathrot.png
   skencil/branches/skencil-0.6/Doc/usersguide/Images/textpathskew.png
   skencil/branches/skencil-0.6/Doc/usersguide/concepts.xml
   skencil/branches/skencil-0.6/Doc/usersguide/configuration.xml
   skencil/branches/skencil-0.6/Doc/usersguide/quickint.xml
   skencil/branches/skencil-0.6/Doc/usersguide/scripting.xml
   skencil/branches/skencil-0.6/Doc/usersguide/usersguide.xml
Modified:
   skencil/branches/skencil-0.6/ChangeLog
Log:
Add the docbook version of the documentation.

Modified: skencil/branches/skencil-0.6/ChangeLog
===================================================================
--- skencil/branches/skencil-0.6/ChangeLog	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/ChangeLog	2006-06-05 18:35:01 UTC (rev 682)
@@ -1,3 +1,63 @@
+2006-06-05  Bernhard Herzog  <bh at intevation.de>
+
+	Add the docbook version of the documentation.
+
+	* Doc/Makefile, Doc/README: New.
+
+	* Doc/devguide/architecture.xml, Doc/devguide/classes.xml,
+	Doc/devguide/connector.xml, Doc/devguide/coordsys.xml,
+	Doc/devguide/curveobj.xml, Doc/devguide/devguide.xml,
+	Doc/devguide/fileformat.xml, Doc/devguide/plugins.xml,
+	Doc/devguide/remarks.xml, Doc/devguide/ui.xml,
+	Doc/devguide/undo.xml:
+	New.  docbook version of the developer's guide
+
+	* Doc/usersguide/concepts.xml, Doc/usersguide/configuration.xml,
+	Doc/usersguide/quickint.xml, Doc/usersguide/scripting.xml,
+	Doc/usersguide/usersguide.xml:
+	New.  docbook version of the user's guide
+
+	* Doc/usersguide/Images/CreateCurve.png,
+	Doc/usersguide/Images/CreateEllipse.png,
+	Doc/usersguide/Images/CreatePoly.png,
+	Doc/usersguide/Images/CreateRect.png,
+	Doc/usersguide/Images/Delete.png,
+	Doc/usersguide/Images/Duplicate.png,
+	Doc/usersguide/Images/EditMode.png,
+	Doc/usersguide/Images/FlipHorizontal.png,
+	Doc/usersguide/Images/FlipVertical.png,
+	Doc/usersguide/Images/GridOn.png, Doc/usersguide/Images/Group.png,
+	Doc/usersguide/Images/Image.png,
+	Doc/usersguide/Images/MiniEyeClosed.png,
+	Doc/usersguide/Images/MiniEyeOpen.png,
+	Doc/usersguide/Images/MiniPrintOff.png,
+	Doc/usersguide/Images/MiniPrintOn.png,
+	Doc/usersguide/Images/MoveOneDown.png,
+	Doc/usersguide/Images/MoveOneUp.png,
+	Doc/usersguide/Images/MoveToBottom.png,
+	Doc/usersguide/Images/MoveToTop.png,
+	Doc/usersguide/Images/NewDocument.png,
+	Doc/usersguide/Images/Open.png, Doc/usersguide/Images/Redo.png,
+	Doc/usersguide/Images/Save.png,
+	Doc/usersguide/Images/SelectionMode.png,
+	Doc/usersguide/Images/Text.png, Doc/usersguide/Images/Undo.png,
+	Doc/usersguide/Images/Ungroup.png, Doc/usersguide/Images/Zoom.png,
+	Doc/usersguide/Images/arrow-left.png,
+	Doc/usersguide/Images/arrow-right.png,
+	Doc/usersguide/Images/arrow-up.png,
+	Doc/usersguide/Images/bullet.png,
+	Doc/usersguide/Images/gradient-conical.png,
+	Doc/usersguide/Images/gradient-linear.png,
+	Doc/usersguide/Images/gradient-radial.png,
+	Doc/usersguide/Images/layers.png,
+	Doc/usersguide/Images/selsize.png,
+	Doc/usersguide/Images/seltrafo.png,
+	Doc/usersguide/Images/sketch-logo.png,
+	Doc/usersguide/Images/textpath.png,
+	Doc/usersguide/Images/textpathrot.png,
+	Doc/usersguide/Images/textpathskew.png:
+	New. Images for the user's guide.
+
 2006-03-18  Bernhard Herzog  <bh at intevation.de>
 
 	* Sketch/Graphics/document.py (EditDocument.CanConvertToCurve)

Added: skencil/branches/skencil-0.6/Doc/Makefile
===================================================================
--- skencil/branches/skencil-0.6/Doc/Makefile	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/Makefile	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,30 @@
+
+# all:	usersguide devguide
+
+# usersguide devguide:
+# 	cd $@; $(MAKE)
+
+
+XSLTPROC=xsltproc
+XSLT_HTML_PARAMS=--stringparam base.dir html/ \
+	--stringparam use.id.as.filename 1
+XSLT_STYLESHEET=http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl
+
+HTMLINDEX=html/index.html
+
+HTML=html/index.html
+
+all: usersguide/$(HTML) devguide/$(HTML)
+
+usersguide/$(HTML): usersguide/*.xml
+devguide/$(HTML): devguide/*.xml
+
+%/$(HTML):
+	cd $*; \
+	rm -rf html ; \
+	$(XSLTPROC) $(XSLT_HTML_PARAMS) $(XSLT_STYLESHEET) $*.xml; \
+	test -d Images && (test -d html && cd html && ln -s ../Images/) || true
+
+clean:
+	cd usersguide; rm -rf html
+	cd devguide; rm -rf html


Property changes on: skencil/branches/skencil-0.6/Doc/Makefile
___________________________________________________________________
Name: svn:eol-style
   + native

Added: skencil/branches/skencil-0.6/Doc/README
===================================================================
--- skencil/branches/skencil-0.6/Doc/README	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/README	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,37 @@
+Skencil documentation
+=====================
+
+The skencil documentation consists of two main parts:
+
+  User's Guide        user documentation
+
+  Developer's Guide   documentation of Skencil's internals for developers 
+                      and script authors
+
+
+Building the documentation
+--------------------------
+
+The documentation is written in DocBook XML and converted to HTML by
+docbook-xslt and xsltproc.  On a debian sarge system you have to install
+the packages docbook-xml, docbook-xsl and xsltproc.
+
+With the relevant software installed and configured, it should be enough
+to simply run make in this directory.  Afterwards, the HTML-version of
+the documentation should be in usersguide/html/ and devguide/html/
+respectively.
+
+
+Documentation conventions
+-------------------------
+
+Some conventions to keep in mind when modifying the documentation:
+
+  - The documents are split into several HTML files with one file being
+    generated for every chapter and sect1 element.  The names of the
+    HTML files are derived from the id's of those elements.  Therefore,
+    all chapter and sect1 elements should have an id attribute.  Also,
+    the id of all sect1 elements of a chapter should have the same
+    prefix which is derived from the chapter's id.  E.g. the scripting
+    chapter has the id "script" and all id's of the sect1's in the
+    chapter start with "script-".


Property changes on: skencil/branches/skencil-0.6/Doc/README
___________________________________________________________________
Name: svn:eol-style
   + native

Added: skencil/branches/skencil-0.6/Doc/devguide/architecture.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/architecture.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/architecture.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,100 @@
+<chapter id="architecture"><title>The Design of Skencil</title>
+  <para>
+    Skencil is written almost completely in Python, an object oriented
+    interpreted programming language. Python can easily be extended by
+    modules written in C to increase performance and Skencil uses this
+    fact to implement some time critical functions and Python objects in
+    C.
+  </para>
+  <para>
+    The source code of Skencil can be divided roughly into these parts:
+    <variablelist>
+      <varlistentry><term>User Interface</term>
+	<listitem>
+	  <para>
+	    Skencil currently uses the Tk Toolkit via the Tkinter module
+	    from the standard Python library. Skencil only uses some
+	    generic widgets like buttons, menus and scrollbars and none
+	    of the more sophisticated widgets like Tk's Text or Canvas
+	    widgets. The main widget where the drawing is displayed is a
+	    Tk widget that is almost entirely implemented in Python
+	    using a C-module that provides GCs, Pixmaps, Fonts etc as
+	    Python objects (This module is heavily based on the Xt
+	    module).
+	  </para>
+	  <para>
+	    Skencil also has some classes that provide a more abstract
+	    interface to generic GUI elements like buttons and menus
+	    that hopefully make it relatively simple to switch to
+	    another toolkit. In fact I already switched toolkits once,
+	    from Xt/Athena to Tk, which was simpler than I had
+	    expected...
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Graphics Devices</term>
+	<listitem>
+	  <para>
+	    Skencil defines several classes for drawing into a window or
+	    into a PostScript file that share a common, generic
+	    interface. This allows us to use the same code for drawing
+	    on the screen and for printing.
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Document- and Graphics Objects</term>
+	<listitem>
+	  <para>
+	    These objects represent entire documents and the parts
+	    thereof in an abstract way. This representation is
+	    independent of any particular output device or operating
+	    system.
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>File IO</term>
+	<listitem>
+	  <para>
+	    Skencil has classes and functions for reading drawings in
+	    several formats (well, just three as of this
+	    writing). Skencil of course defines its own special format
+	    and can read and write this. In addition, there is currently
+	    partial support for reading and writing SVG and Adobe
+	    Illustrator (AI) files, just to name a few.
+	  </para>
+	  <para>
+	    For reading bitmap graphics Skencil uses the Python Imaging
+	    Library so that it should be able to read everything that
+	    this library can read.
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Miscellaneous</term>
+	<listitem>
+	  <para>
+	    There are a variety of support modules that provide objects
+	    representing 2D points/vectors, rectangles, affine
+	    transformations, fonts and font-metrics, or code to handle
+	    postscript files and a generic
+	    <link linkend="connector">message passing mechanism</link>.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </para>
+  <para>
+    Skencil uses a variation of the model/view/controller concept. The
+    document and graphics object classes form the model which represents
+    the drawing in a device independent way and which can be manipulated
+    through a specific set of methods. The
+    class <literal>SketchCanvas</literal> serves both as the main view
+    and controller. It manages a window graphics device that is used to
+    display that drawing and it accepts user input in the form of mouse
+    and keyboard events and translates them into method invocations on
+    the document object.
+  </para>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/classes.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/classes.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/classes.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,974 @@
+<chapter id="classes"><title>The Document and Graphics Classes</title>
+  <para>
+    The document is represented by a tree of graphics objects. The
+    document consists of one or more layers. Each layer consists of zero
+    or more primitives or compound objects.
+  </para>
+  <para>
+    Primitives are the leaves of the tree and contain no other graphics
+    objects, examples are Rectangles or PolyBezier objects. Most
+    primitives can have line and fill properties (Text objects currently
+    can only have fill properties and image objects have neither fill
+    nor line properties).
+  </para>
+  <para>
+    Compound objects are graphics objects that contain other graphics
+    objects, examples are the ordinary Group or the BlendGroup.
+  </para>
+
+  <sect1 id="class-hierarchy"><title>Class Hierarchy</title>
+    <para>
+      <itemizedlist>
+	<listitem>
+	  <para><link linkend="class-Selectable"><classname>Selectable</classname></link></para>
+	  <itemizedlist>
+	    <listitem>
+	      <para><link linkend="class-GraphicsObject"><classname>GraphicsObject</classname></link>
+	      </para>
+	      <itemizedlist>
+		<listitem>
+		  <para><link linkend="class-Primitive"><classname>Primitive</classname></link></para>
+		  <itemizedlist>
+		    <listitem>
+		      <para>
+			<classname>PolyBezier</classname>
+		      </para>
+		    </listitem>
+		    <listitem>
+		      <para>
+			<classname>RectangularPrimitive</classname>
+		      </para>
+		      <itemizedlist>
+			<listitem>
+			  <para><classname>Ellipse</classname></para>
+			</listitem>
+			<listitem>
+			  <para>
+			    <link linkend="class-Rectangle"><classname>Rectangle</classname></link>
+			  </para>
+			</listitem>
+		      </itemizedlist>
+		    </listitem>
+		  </itemizedlist>
+		</listitem>
+		<listitem>
+		  <para>
+		    <link linkend="class-Compound"><classname>Compound</classname></link>
+		  </para>
+		  <itemizedlist>
+		    <listitem>
+		      <para><classname>EditableCompound</classname></para>
+		      <itemizedlist>
+			<listitem>
+			  <para><classname>Group</classname></para>
+			</listitem>
+			<listitem>
+			  <para><classname>Layer</classname></para>
+			  <itemizedlist>
+			    <listitem>
+			      <para><classname>SpecialLayer</classname></para>
+			      <itemizedlist>
+				<listitem>
+				  <para>
+				    <classname>GuideLayer</classname>
+				  </para>
+				</listitem>
+				<listitem>
+				  <para>
+				    <classname>GridLayer</classname>
+				  </para>
+				</listitem>
+			      </itemizedlist>
+			    </listitem>
+			  </itemizedlist>
+			</listitem>
+		      </itemizedlist>
+		    </listitem>
+		  </itemizedlist>
+		</listitem>
+	      </itemizedlist>
+	    </listitem>
+	    <listitem>
+	      <para><classname>EditSelect</classname></para>
+	      <itemizedlist>
+		<listitem>
+		  <para><classname>SelectAndDrag</classname></para>
+		  <itemizedlist>
+		    <listitem>
+		      <para><classname>Editor</classname></para>
+		      <itemizedlist>
+			<listitem>
+			  <para><classname>EllipseEditor</classname></para>
+			</listitem>
+			<listitem>
+			  <para><classname>PolyBezierEditor</classname></para>
+			</listitem>
+		      </itemizedlist>
+		    </listitem>
+		    <listitem>
+		      <para><classname>Creator</classname></para>
+		      <itemizedlist>
+			<listitem>
+			  <para><classname>RectangularCreator</classname></para>
+			  <itemizedlist>
+			    <listitem>
+			      <para><classname>EllipseCreator</classname></para>
+			    </listitem>
+			    <listitem>
+			      <para><classname>RectangleCreator</classname></para>
+			    </listitem>
+			  </itemizedlist>
+			</listitem>
+			<listitem>
+			  <para><classname>PolyBezierCreator</classname></para>
+			</listitem>
+		      </itemizedlist>
+		    </listitem>
+		  </itemizedlist>
+		</listitem>
+	      </itemizedlist>
+	    </listitem>
+	  </itemizedlist>
+	</listitem>
+      </itemizedlist>
+    </para>
+  </sect1>
+
+  <sect1 id="class-GraphicsObject">
+    <title>The class <classname>GraphicsObject</classname></title>
+    <para>
+      Base Classes: <link linkend="class-Bounded"><classname>Bounded</classname></link>, 
+      <link linkend="class-HierarchyNode"><classname>HierarchyNode</classname></link>,
+      <link linkend="class-Selectable"><classname>Selectable</classname></link>
+      and <link linkend="class-Protocols"><classname>Protocols</classname></link>.
+    </para>
+    <para>
+      The class <classname>GraphicsObject</classname> defines the
+      interface common to all graphics objects.
+    </para>
+    <para>
+      For convenience of implementation, and because their interfaces
+      are needed elsewhere in the class hierarchy as well, some parts of
+      this interface are defined by the base classes:
+    </para>
+    <para>
+      <variablelist>
+	<varlistentry>
+	  <term><link linkend="class-Bounded"><classname>Bounded</classname></link></term>
+	  <listitem>
+	    <para>
+	      provides instance variables for the vertical and
+	      horizontal dimensions of a graphics object and some
+	      related methods.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><link linkend="class-HierarchyNode"><classname>HierarchyNode</classname></link></term>
+	  <listitem>
+	    <para>
+	      provides the default behavior for all methods related to
+	      the management of the object hierarchy in the document.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><link linkend="class-Selectable"><classname>Selectable</classname></link></term>
+	  <listitem>
+	    <para>
+	      defines the generic interface and default behavior for
+	      selection.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><link linkend="class-Protocols"><classname>Protocols</classname></link></term>
+	  <listitem>
+	    <para>
+	      has some variables that describe the object's
+	      capabilities.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </para>
+
+    <sect2><title>Instance Variables</title>
+      <para>
+	<classname>GraphicsObject</classname> maintains no
+	instance variables of its own, but uses those managed by its
+	base classes.
+      </para>
+    </sect2>
+    <sect2>
+      <title>Methods</title>
+      <para>
+	Methods defined in <classname>GraphicsObject</classname>:
+      </para>
+      <para>
+	<variablelist>
+	  <varlistentry id="GraphicsObject.Blend">
+	    <term><literal>Blend(<parameter>other</parameter>, <parameter>frac1</parameter>, <parameter>frac2</parameter>)</literal></term>
+	    <listitem>
+	      <para>
+		Return the weighted average of
+		<parameter>self</parameter>
+		and <parameter>other</parameter>.
+		<parameter>frac1</parameter>
+		and <parameter>frac2</parameter> are the weights
+		(if <parameter>self</parameter> and
+		<parameter>other</parameter> were numbers this should
+		be <parameter>frac1</parameter>
+		* <parameter>self</parameter>
+		+ <parameter>frac2</parameter>
+		* <parameter>other</parameter>).
+	      </para>
+	      <para>
+		This method is used by the function
+		<function>Blend</function> in
+		<filename>blend.py</filename>.
+		If <parameter>self</parameter>
+		and <parameter>other</parameter> can't be blended,
+		raise the <literal>blend.Mismatch</literal>
+		exception. This is the default behavior.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry id="GraphicsObject.AsBezier">
+	    <term><literal>AsBezier()</literal></term>
+	    <listitem>
+	      <para>
+		Return self as a <classname>PolyBezier</classname>
+		object if possible.  If this is not possible,
+		return <literal>None</literal>.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+      <para>
+	The following methods are not implemented
+	in <classname>GraphicsObject</classname> directly, but must be
+	defined for every graphics object. The derived
+	classes <link
+	linkend="class-Primitive"><classname>Primitive</classname></link>
+	and <link
+	linkend="class-Compound"><classname>Compound</classname></link>
+	provide a default implementation for most objects.
+      </para>
+      <variablelist>
+	<varlistentry id="GraphicsObject.Transform">
+	  <term>
+	    <literal>Transform(<parameter>trafo</parameter>)</literal>
+	  </term>
+	  <listitem>
+	    <para>
+	      Apply the <link linkend="class-Trafo">transformation
+		object</link>
+	      <parameter>trafo</parameter> to self. Return undo info.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="GraphicsObject.Translate">
+	  <term>
+	    <literal>Translate(<parameter>offset</parameter>)</literal>
+	  </term>
+	  <listitem>
+	    <para>
+	      Translate (move) self by <parameter>offset</parameter>.
+	      <parameter>offset</parameter> is a
+	      <link linkend="class-Point">point object</link>.  Return
+	      undo info.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="GraphicsObject.DrawShape">
+	  <term><literal>DrawShape(<parameter>device</parameter> [, <parameter>clip</parameter>])</literal></term>
+	  <listitem>
+	    <para>
+	      Draw self on <parameter>device</parameter>.
+	      <parameter>device</parameter> is a graphics device.
+	    </para>
+	    <para>
+	      The optional parameter <parameter>clip</parameter> is only
+	      provided if the object is used as a clip mask. If it is
+	      provided its value is 1.  Objects that can be used as clip
+	      masks (their <literal>is_clip</literal> flag is true)
+	      request appropriate clipping from the graphics device.
+	      Objects that cannot be used as clip masks don't need to
+	      accept it.
+	    </para>
+	    <para>
+	      (Note: The clipping interface for the high level drawing
+	      operations of the graphics devices is somewhat
+	      experimental)
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="GraphicsObject.SaveToFile">
+	  <term>
+	    <literal>SaveToFile(<parameter>file</parameter>)</literal>
+	  </term>
+	  <listitem>
+	    <para>
+	      Save self to file. The
+	      argument <parameter>file</parameter> is currently an
+	      instance of the class <classname>SKSaver</classname> which
+	      provides special methods for the object types currently
+	      implemented in Skencil.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+  </sect1>
+
+  <sect1 id="class-Bounded">
+    <title>The class <classname>Bounded</classname></title>
+    <para>
+      In Skencil, each graphics object has a <emphasis>bounding
+	rectangle</emphasis> and a
+      <emphasis>coordinate rectangle</emphasis>. The sides of both
+      rectangles are parallel to the coordinate axes.
+    </para>
+    <para>
+      The bounding rectangle is a rectangle that contains the entire
+      object.  Any marks the object or its children leave on the paper
+      when printed lie in it. Ideally it should be the smallest such
+      rectangle, but in practice it is sometimes difficult and indeed
+      not always desirable to get exactly the smallest one. In any case,
+      the bounding rectangle must contain the entire object.
+    </para>
+    <para>
+      Skencil uses the bounding rect for three purposes: to decide,
+      which parts of the screen to redraw, as an aid when deciding which
+      objects to select and to compute the BoundingBox of an EPS-File.
+    </para>
+    <para>
+      The coordinate rectangle is the smallest rectangle that contains
+      the entire object without taking the line width into
+      account. Skencil uses this rectangle for layout purposes and as
+      the reference for interactive resize- and transformation
+      operations.
+    </para>
+    <para>
+      The coordinate rectangle of an object should always lie completely
+      inside of the bounding rectangle. Both rectangles may be (and for
+      many object types they are) identical.
+    </para>
+    <para>
+      Since <classname>Bounded</classname>'s variables are used for
+      layout calculations, it provides access to and default behavior
+      for the <emphasis>layout point</emphasis>. The layout point is the
+      point of an object that should lie exactly on the grid or on other
+      special points.
+    </para>
+    <para>
+      By default, the layout point is the lower left corner of the
+      coordinate rectangle. For images this is the lower left corner of
+      the image which is not identical to the default if the image was
+      transformed. For text objects with default justification, the
+      layout point is the origin of the first letter, which is on the
+      baseline, whereas the coordinate rectangle takes the descender
+      into account.
+    </para>
+
+    <sect2><title>Instance Variables</title>
+      <para>
+	<classname>Bounded</classname> provides the following instance
+	variables
+      </para>
+      <variablelist>
+	<varlistentry><term><literal>bounding_rect</literal>:</term>
+	  <listitem>
+	    <para>
+	      the bounding rectangle
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry><term><literal>coord_rect</literal>:</term>
+	  <listitem>
+	    <para>
+	      the coordinate rectangle
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+      <para>
+	These instance variables are public attributes. Skencil uses
+	<literal>bounding_rect</literal> to speed up the search for the
+	object a mouse click has hit (when the point the user clicked on
+	is outside of the bounding rect, the object cannot be hit). This
+	test is significantly faster when the bounding rectangle is read
+	directly from an attribute instead of accessed through a method
+	call.
+      </para>
+    </sect2>
+
+    <sect2><title>Methods</title>
+      <para>
+	<classname>Bounded</classname> implements lazy evaluation for
+	its public instance variables (<literal>bounding_rect</literal>
+	and <literal>coord_rect</literal>). When one of these variables
+	is not defined, <classname>Bounded</classname>'s
+	<link
+	linkend="Bounded.__getattr__"><function>__getattr__</function></link>
+	method invokes the
+	method <link
+	linkend="Bounded.update_rects"><function>update_rects</function></link>
+	to compute the rectangles and set the variables. To force
+	recomputation when these variables are read next, a derived
+	class may call
+	<link
+	   linkend="Bounded.del_lazy_attrs"><function>del_lazy_attrs</function></link>.
+      </para>
+      <para>
+	This lazy evaluation mechanism is not limited to the instance
+	variables mentioned above. <literal>__getattr__</literal>
+	consults the dictionary <literal>self._lazy_attrs</literal> to
+	determine, whether the requested attribute is a lazy attribute:
+	if <literal>self._lazy_attrs</literal> has the attribute as a
+	key the attribute is treated as a lazy attribute. The value
+	associated with that key must be the name of the method to call
+	to recompute the value of the attribute.
+	<literal>__getattr__</literal> calls this method and expects
+	that <literal>self</literal> has that attribute after the method
+	has run.
+      </para>
+      <para>
+	<literal>_lazy_attrs</literal> is a class variable
+	of <classname>Bounded</classname>. If a derived class needs
+	additional lazy attributes, it should create its own class
+	variable <literal>_lazy_attrs</literal> as a copy of its
+	base-class' <literal>_lazy_attrs</literal> and add the
+	appropriate keys:
+      </para>
+      <para>
+<programlisting>
+class MyObject(GraphicsObject):
+
+    _lazy_attrs = GraphicsObject._lazy_attrs.copy()
+    _lazy_attrs['my_lazy_attribute'] = 'update_my_lazy_attr'
+
+    # somewhere in the class definition:
+    def update_my_lazy_attr(self):
+	# compute the new value of my_lazy_attr...
+	# ... and finally:
+	self.my_lazy_attribute = new_value
+</programlisting>
+      </para>
+      <para>
+	Thus <classname>Bounded</classname>'s methods are:
+      </para>
+      <variablelist>
+	<varlistentry id="Bounded.del_lazy_attrs">
+	  <term><literal>del_lazy_attrs()</literal></term>
+	  <listitem>
+	    <para>
+	      Delete the "lazy" instance variables. Any attempt to
+	      access a lazy attribute later triggers its recomputation
+	      via the <literal>__getattr__</literal> method.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="Bounded.update_rects">
+	  <term><literal>update_rects()</literal></term>
+	  <listitem>
+	    <para>
+	      <literal>Bounded.__getattr__</literal> invokes this method
+	      whenever one of the attributes
+	      <literal>bounding_rect</literal>
+	      or <literal>coord_rect</literal> is not set.
+	    </para>
+	    <para>
+	      This method <emphasis>must</emphasis> be supplied by some
+	      derived class and it <emphasis>must</emphasis> compute
+	      both rectangles.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="Bounded.__getattr__">
+	  <term><literal>__getattr__(<parameter>attr</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      If <literal>self._lazy_attrs.has_key(attr)</literal> is
+	      true, invoke 
+	      <literal>getattr(self, self._lazy_attrs[attr])()</literal> 
+	      to recompute the attribute.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="Bounded.LayoutPoint">
+	  <term><literal>LayoutPoint()</literal></term>
+	  <listitem>
+	    <para>
+	      Return the layout point of self as
+	      a <link linkend="class-Point">point object</link>. Default
+	      is the lower left corner of
+	      <literal>self.coord_rect</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="Bounded.GetSnapPoints">
+	  <term><literal>GetSnapPoints()</literal></term>
+	  <listitem>
+	    <para>
+	      Return a list of <link linkend="class-Point">point
+	      objects</link> indicating the "hot spots" of the graphics
+	      object. These points are used when "Snapping to Objects"
+	      is active. The default implementation returns an empty
+	      list.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+  </sect1>
+
+  <sect1 id="class-HierarchyNode">
+    <title>The class <classname>HierarchyNode</classname></title>
+    <para>
+      In Skencil, a document consists of a hierarchy of objects. Each
+      object has at most one parent and belongs to at most one
+      document. That is, an object may not belong to any compound object
+      or document, but if it belongs to one, it cannot be part of two
+      compound objects or two documents.
+    </para>
+    <para>
+      An object in this hierarchy knows which parent and document it
+      belongs to.
+    </para>
+    <para>
+      The class <classname>HierarchyNode</classname> provides the
+      standard interface for managing this hierarchy and the references
+      to the parent and the document for child objects. The default
+      behavior for parents is defined by the
+      class <link
+      linkend="class-Compound"><classname>Compound</classname></link>.
+    </para>
+    <para>
+      No object derived from this class should override the methods
+      defined here except as documented.
+    </para>
+
+    <sect2><title>Instance Variables</title>
+      <para>
+	<classname>HierarchyNode</classname> uses the following
+	instance variables:
+      </para>
+      <variablelist>
+	<varlistentry><term><literal>parent</literal></term>
+	  <listitem>
+	    <para>
+	      The parent of the object. Since the parent also has a
+	      reference to its child this introduces a circular
+	      reference. Therefore we must make sure that these
+	      references are deleted when the document is destroyed.
+	      The <link
+	      linkend="HierarchyNode.Destroy"><function>Destroy</function></link>
+	      method takes care of this.
+	    </para>
+	    <para>
+	      If the object is not currently the child of a compound
+	      object this variable should be <literal>None</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry><term><literal>document</literal></term>
+	  <listitem>
+	    <para>
+	      The document the object belongs to. If the object has
+	      just been created and is not yet inserted into the
+	      document, or when the object is stored in the
+	      application's clipboard, this variable is
+	      <literal>None</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+      <para>
+	In general, if <literal>parent</literal> is
+	not <literal>None</literal>, <literal>document</literal>
+	should be the same as <literal>parent.document</literal>.
+      </para>
+    </sect2>
+
+    <sect2><title>Methods</title>
+      <para>
+	Methods defined in <classname>HierarchyNode</classname>
+	(incomplete):
+      </para>
+      <variablelist>
+	<varlistentry id="HierarchyNode.__init__">
+	  <term><function>__init__</function></term>
+	  <listitem>
+	    <para>
+	      A <classname>HierarchyNode</classname>'s
+	      <function>__init__</function> method (and that of all
+	      derived classes) must accept an optional keyword argument
+	      called <literal>duplicate</literal> with the default
+	      value <literal>None</literal> and it must be callable with
+	      just that argument. This is used by the standard <link
+	      linkend="HierarchyNode.Duplicate"><function>Duplicate</function></link>
+	      method.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="HierarchyNode.Destroy">
+	  <term><function>Destroy()</function></term>
+	  <listitem>
+	    <para>
+	      Called by the parent when the document is
+	      destroyed. This method should delete any circular
+	      references. A Compound object should call the
+	      <function>Destroy</function> method of each of its
+	      children.
+	    </para>
+	    <para>
+	      The default implementation just sets
+	      <literal>parent</literal> to <literal>None</literal>.
+	      Derived classes should extend this method if necessary.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="HierarchyNode.SetParent">
+	  <term>
+	    <function>SetParent(<parameter>parent</parameter>)</function>
+	  </term>
+	  <listitem>
+	    <para>
+	      Set self's instance variable <literal>parent</literal>
+	      to <parameter>parent</parameter>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="HierarchyNode.SetDocument">
+	  <term>
+	    <function>SetDocument(<parameter>document</parameter>)</function>
+	  </term>
+	  <listitem>
+	    <para>
+	      Set self's instance variable <literal>document</literal>
+	      to <parameter>document</parameter>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="HierarchyNode.Duplicate">
+	  <term><function>Duplicate()</function></term>
+	  <listitem>
+	    <para>
+	      Return a duplicate of self. The default implementation
+	      just returns
+	      <literal>self.__class__(duplicate = self)</literal>.
+	      Therefore, the class's constructor must be callable with
+	      a single keyword argument <literal>duplicate</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+  </sect1>
+
+  <sect1 id="class-Protocols">
+    <title>The class <classname>Protocols</classname></title>
+    <para>
+      While sharing a common interface, the various types of graphics
+      objects provide a variety of additional capabilities and
+      interfaces. The class <classname>Protocols</classname> defines
+      some flags that indicate the presence of certain standard
+      extensions. These flags are boolean class variables with names of
+      the form "<literal>is_</literal>*" or
+      "<literal>has_</literal>*". By default all of these flags are
+      false. Derived classes are expected to set the appropriate flags.
+    </para>
+    <para>
+      The standard flags are:
+    </para>
+    <variablelist>
+      <varlistentry>
+	<term><literal>has_properties</literal></term>
+	<listitem>
+	  <para>
+	    True, iff object can have properties. If true, the object
+	    must implement the
+	    methods <function>AddStyle</function>,
+	    <function>Properties</function>,
+	    <function>SetProperties</function>, 
+	    <function>ObjectChanged</function> and 
+	    <function>ObjectRemoved</function>.
+	  </para>
+	  <para>
+	    The class <link linkend="class-Primitive"><classname>Primitive</classname></link>
+	    provides this interface.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry><term><literal>has_fill</literal></term>
+	<listitem>
+	  <para>
+	    True, iff object can have fill properties. If true,
+	    <literal>has_properties</literal> must also be true. In
+	    addition, the object must implement the
+	    method <function>Filled</function> and the
+	    method <function>SetProperties</function> must
+	    accept the fill properties.
+	  </para>
+	  <para>
+	    The class <link linkend="class-Primitive"><classname>Primitive</classname></link>
+	    provides this interface.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry><term><literal>has_line</literal></term>
+	<listitem>
+	  <para>
+	    True, iff object can have line properties. If true,
+	    <literal>has_properties</literal> must also be true. In
+	    addition, the object must implement the
+	    method <function>LineWidth</function> and the
+	    method <function>SetProperties</function> must
+	    accept the line properties.
+	  </para>
+	  <para>
+	    The class <link linkend="class-Primitive"><classname>Primitive</classname></link>
+	    provides this interface.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry><term><literal>has_font</literal></term>
+	<listitem>
+	  <para>
+	    True, iff object can have a font. If
+	    true, <literal>has_properties</literal> must also be
+	    true. In addition, the
+	    method <function>SetProperties</function> must accept the
+	    font properties.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><literal>is_Bezier</literal></term>
+	<term><literal>is_Rectangle</literal></term>
+	<term><literal>is_Ellipse</literal></term>
+	<term><literal>is_Text</literal></term>
+	<term><literal>is_Image</literal></term>
+	<term><literal>is_Eps</literal></term>
+	<listitem>
+	  <para>
+	    Indicate the type of object.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><literal>is_Compound</literal></term>
+	<listitem>
+	  <para>
+	    True, iff the object is a compound object.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><literal>is_Group</literal></term>
+	<listitem>
+	  <para>
+	    True, iff the object is a group. A group is a compound
+	    object. A group object can
+	    be <emphasis>ungrouped</emphasis>, that is, the user can
+	    issue a command that replaces the group with its children,
+	    which become direct children of the group's parent. To this
+	    end, a group must provide the
+	    method <function>Ungroup</function>. (see the document
+	    method <function>UngroupSelected</function>)
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><literal>is_Blend</literal></term>
+	<listitem>
+	  <para>
+	    True, iff the object is a blend group.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><literal>is_curve</literal></term>
+	<listitem>
+	  <para>
+	    True, iff the object can be converted to a
+	    <classname>PolyBezier</classname> object. If true, the
+	    object must implement the methods <link
+	    linkend="GraphicsObject.AsBezier"><function>AsBezier</function></link>
+	    and <function>Paths</function>.
+	  </para>
+	  <para>
+	    Skencil treats the PolyBezier as a kind of "common
+	    denominator" for blending. For instance, if you try to blend
+	    a rectangle and an ellipse, both are converted to beziers
+	    and the beziers are blended.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><literal>is_clip</literal></term>
+	<listitem>
+	  <para>
+	    True, iff the object may be used as a clip mask. If true,
+	    the methods
+	    <link
+	    linkend="Selectable.Hit"><function>Hit</function></link>
+	    and <link
+	    linkend="GraphicsObject.DrawShape"><function>DrawShape</function></link>
+	    must accept an additional boolean
+	    parameter <literal>clip</literal> indicating whether the
+	    object is used as a clip mask.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect1>
+
+  <sect1 id="class-Selectable">
+    <title>The class <classname>Selectable</classname></title>
+    <para>
+      The class <classname>Selectable</classname> defines the interface
+      for objects that can be selected with the mouse. This includes
+      tests for whether the object is hit by a mouse click and methods
+      for the handles.
+    </para>
+
+    <sect2><title>The Selection Mechanism</title>
+      <para>
+	Yet to be written...
+      </para>
+    </sect2>
+
+    <sect2><title>Methods</title>
+      <para>
+	A <classname>Selectable</classname> object has these methods:
+      </para>
+      <variablelist>
+	<varlistentry id="Selectable.Hit">
+	  <term><!-- methdef -->Hit(<parameter>p</parameter>, <parameter>rect</parameter>, <parameter>device</parameter>
+	    [, <parameter>clip</parameter>])<!-- /methdef --></term>
+	  <listitem>
+	    <para>
+	      Return true if clicking at <parameter>p</parameter>
+	      (a <link linkend="class-Point">point object</link>) should
+	      select the object. The
+	      parameter <parameter>device</parameter> is a graphics
+	      device that can convert points
+	      between <link linkend="coordinatesystems">document
+	      coordinates and window coordinates</link>.
+	      <parameter>p</parameter> is always given in document
+	      coordinates.
+	    </para>
+	    <para>
+	      <parameter>rect</parameter> is a 
+	      <link linkend="class-Rect">rect object</link> in
+	      doc-coordinates that describes a small area
+	      around <parameter>p</parameter> (a few pixels wide). A
+	      point of the object should be considered "hit" if it lies
+	      inside this rectangle.
+	    </para>
+	    <para>
+	      The <parameter>device</parameter> parameter is necessary,
+	      because clicking on a special point should have some
+	      tolerance, so that "missing" by a few pixels still selects
+	      that point. Unfortunately, pixels are screen coordinates
+	      and the object's coordinates are document coordinates, so
+	      conversion between the two is sometimes necessary.
+	      <parameter>device</parameter> has some methods for this
+	      and also for testing if certain primitives are hit.
+	      Currently <parameter>device</parameter> is an instance
+	      of <classname>HitTestDevice</classname>.
+	    </para>
+	    <para>
+	      The optional parameter <parameter>clip</parameter> is only
+	      provided if the object is used as a clip mask. If it is
+	      provided its value is 1.  Objects that can be used as clip
+	      masks (their <literal>is_clip</literal> flag is true)
+	      should test whether <parameter>p</parameter> is inside of
+	      the object regardless of whether they are filled or
+	      not. Objects that cannot be used as clip masks don't need
+	      to accept it.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="Selectable.SelectSubobject">
+	  <term><function>SelectSubobject(<parameter>p</parameter>, <parameter>rect</parameter>, <parameter>device</parameter>[, <parameter>path</parameter>])</function></term>
+	  <listitem>
+	    <para>
+	      When the parent decides that one of its children (or one
+	      of the child's descendants) is to be selected (this is
+	      determined using the children's bounding rects and
+	      their <function>Hit</function> methods), it calls this
+	      method to ask the child for details.
+	    </para>
+	    <para>
+	      Normally, self should be returned (this is also the
+	      default behavior). To select a subobject, return selection
+	      info relative to self as a single tuple of selection
+	      info. (see selinfo.py)
+	    </para>
+	    <para>
+	      Compound objects like groups and layers override this
+	      method to let the user select their children.
+	    </para>
+	    <para>
+	      As in <link
+	      linkend="Selectable.Hit"><function>Hit</function></link>,
+	      <parameter>p</parameter> and <parameter>rect</parameter>
+	      describe a point and a small tolerance rectangle around
+	      it, and <parameter>device</parameter> is
+	      a <classname>HitTestDevice</classname>.  The optional
+	      argument <parameter>path</parameter> is useful only for
+	      compound objects but has to be accepted by all graphics
+	      objects.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+  </sect1>
+
+  <sect1 id="class-Primitive">
+    <title>The class <classname>Primitive</classname></title>
+    <para>
+    </para>
+  </sect1>
+
+  <sect1 id="class-Compound">
+    <title>The class <classname>Compound</classname></title>
+    <para>
+    </para>
+  </sect1>
+
+  <sect1 id="class-Rectangle">
+    <title>The class <classname>Rectangle</classname></title>
+    <para>
+      The class <classname>Rectangle</classname> represents the drawing
+      primitive of a parallelogram with optional rounded corners. When
+      drawn interactively the object is an axis aligned rectangle. After
+      applying affine transformations the rectangle may not be a
+      rectangle anymore, but it will remain a parallelogram.
+    </para>
+    <para>
+      In Skencil, a rectangle is represented by the affine
+      transformation necessary to map the unit square (opposite corners
+      (0, 0) and (1, 1)), to the parallelogram. This is an elegant and
+      convenient but also somewhat unusual representation.
+    </para>
+    <para>
+      The transformation is of course stored as
+      a <link linkend="class-Trafo">transformation object</link>.
+    </para>
+    <para>
+      The rounded corners are defined by two floating point numbers
+      radius1 and radius2. Both numbers define a radius of the ellipses
+      that make up the rounded corners of the unit square, radius1
+      defines the horizontal radius and radius2 the vertical
+      radius. Valid values lie in the range 0.0 &lt;= radius1,radius2
+      &lt;= 0.5.
+    </para>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/connector.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/connector.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/connector.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,293 @@
+<chapter id="connector"><title>Message Passing</title>
+  <para>
+    In a Model-View-Controller architecture like the one used in
+    Skencil, the model has to inform the views when the data has changed
+    and the views have to be updated. Often there can be several views
+    for one model object and it is desirable to implement the model in
+    such a way that it doesn't have to know how many and what types of
+    view there actually are at any one point in time. Still, the views
+    have to be informed by the model that they should update themselves
+    whenever the model changes. In Skencil this is achieved through a
+    generic message passing mechanism similar to the signals used in Qt
+    or GTK.
+  </para>
+
+  <sect1 id="connector-concepts"><title>Concepts</title>
+    <para>
+      <emphasis>Messages</emphasis> are generated by
+      <emphasis>publishers</emphasis> and consist of a
+      <emphasis>message type</emphasis> represented by a string and an
+      arbitrary number of arguments. The message type is also called
+      a <parameter>channel</parameter>.
+    </para>
+    <para>
+      Program parts that want to receive messages subscribe to a channel
+      of a particular publisher by passing a callable object, often a
+      bound instance method, and optionally some additional arguments to
+      the publisher.
+    </para>
+    <para>
+      When the publisher issues a message all subscribers of the relevat
+      channel of the publisher all called with the message arguments and
+      the additional subscriber specific arguments.
+    </para>
+    <para>
+      The heart of this mechanism is the <link
+      linkend="class-Connector"><classname>Connector</classname></link>
+      class, whose instances manage all connections between publishers
+      and subscribers. This way, a publisher that has no subscribers
+      does not use any resources.
+    </para>
+    <para>
+      The connector module has one global
+      <classname>Connector</classname> instance and some of its methods
+      are available as globals.
+    </para>
+    <para>
+      There are two additional classes for publisher objects. <link
+      linkend="class-Publisher"><classname>Publisher</classname></link>
+      provides methods to subscribe to and unsubscribe from channels of
+      the object. <link
+      linkend="class-QueueingPublisher"><classname>QueueingPublisher</classname></link>
+      allows the publisher to accumulate messages in a queue with
+      identical messages queued only once and release them all at once.
+    </para>
+    <para>
+      Most objects that send messages are derived from one of these
+      publisher objects and in most circumstances their methods are used
+      to connect to their channels. The connector is rarely used
+      directly.
+    </para>
+  </sect1>
+
+  <sect1 id="class-Connector">
+    <title>The Class <classname>Connector</classname></title>
+    <variablelist>
+      <varlistentry id="Connector.Connect">
+	<term><function>Connect(<parameter>publisher</parameter>, <parameter>channel</parameter>, <parameter>subscriber</parameter>, <parameter>args</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Connect the <parameter>subscriber</parameter>, i.e. a
+	    callable object and additional arguments
+	    <parameter>args</parameter>, to a
+	    <parameter>channel</parameter> of a
+	    <parameter>publisher</parameter>.
+	  </para>
+	  <para>
+	    The <parameter>publisher</parameter> can be any object,
+	    though most of the time it's a <link
+	    linkend="class-Publisher"><classname>Publisher</classname></link>
+	    instance.  Skencil uses the <literal>None</literal> object
+	    as a publisher for global messages.
+	  </para>
+	  <para>
+	    <parameter>args</parameter> are subscriber specific
+	    arguments as a tuple.
+	  </para>
+	  <para>
+	    The same subscriber may be registered multiple times but it
+	    is only stored once in the list of subscribers. Two
+	    subscribers are considered equal if the callable object and
+	    the arguments are equal.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Connector.Disconnect">
+	<term><function>Disconnect(<parameter>publisher</parameter>, <parameter>channel</parameter>, <parameter>subscriber</parameter>,
+	    <parameter>args</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Disconnect <parameter>subscriber</parameter> from
+	    <parameter>publisher</parameter>'s <parameter>channel</parameter>.
+	  </para>
+	  <para>
+	    The arguments have the same meaning as in <link
+	    linkend="Connector.Connect"><function>Connect</function></link>
+	    and again the combination of <parameter>subscriber</parameter>
+	    and <parameter>args</parameter> is used to identify one
+	    particular subscriber.
+	  </para>
+	  <para>
+	    If the subscriber isn't connected to the channel, raise a
+	    <literal>ConnectorError</literal> exception.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Connector.Issue">
+	<term><function>Issue(<parameter>publisher</parameter>, <parameter>channel</parameter>, *<parameter>args</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Issue a message on a <parameter>channel</parameter>
+	    of <parameter>publisher</parameter>.
+	  </para>
+	  <para>
+	    The third and all following arguments are passed through to
+	    all subscribers as message arguments. The arguments the
+	    subscribers are called with is the concatenation of the
+	    message arguments and the subscriber specific arguments.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Connector.RemovePublisher">
+	<term><function>RemovePublisher(<parameter>publisher</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Remove all subscribers from all channels of
+	    <emphasis>publisher</emphasis>. It is safe to call this in a
+	    __del__ method.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Connector.HasSubscribers">
+	<term><function>HasSubscribers(<parameter>publisher</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Return true iff <parameter>publisher</parameter> has any
+	    subscribers.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+    <para>
+      Note that the connector does not hold references to the publisher.
+      Publishers are identified by their id. This makes it possible to
+      automatically disconnect all subscribers of a publisher in a
+      publisher's __del__ method. This does not work however, if
+      e.g. the publisher is itself a subscriber because the connector
+      has to own the references to the subcribers.
+    </para>
+  </sect1>
+
+  <sect1 id="class-Publisher">
+    <title>The Class <classname>Publisher</classname></title>
+    <para>
+      The class <classname>Publisher</classname> serves as a base class
+      for classes that send messages. It provides convenience methods to
+      subscribe to and unsubscribe from channels. It also removes all
+      subscriptions automatically when instances are deleted through
+      the <function>__del__</function> method.
+    </para>
+    <variablelist>
+      <varlistentry id="Publisher.Subscribe">
+	<term><function>Subscribe(<parameter>channel</parameter>, <parameter>subscriber</parameter>, *<parameter>args</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Subscribe <parameter>subscriber</parameter> to
+	    self's <parameter>channel</parameter> with the rest of the
+	    positional arguments as the subscriber specific
+	    parameters. See <link
+	    linkend="Connector.Connect"><function>Connect</function></link>
+	    for more details.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Publisher.Unsubscribe">
+	<term><function>Unsubscribe(<parameter>channel</parameter>, <parameter>subscriber</parameter>, *<parameter>args</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Unsubscribe <parameter>subscriber</parameter> to
+	    self's <parameter>channel</parameter> with the rest of the
+	    positional arguments as the subscriber specific
+	    parameters. See <link
+	    linkend="Connector.Disconnect"><function>Disconnect</function></link>
+	    for more details.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Publisher.issue">
+	<term><function>issue(<parameter>channel</parameter>, *<parameter>args</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    If the instance variable ignore_issue is false, issue the
+	    message described by the second and the following arguments
+	    on channel <parameter>channel</parameter>, otherwise, do
+	    nothing.
+	  </para>
+	  <para>
+	    ignore_issue defaults to false. ignore_issue will be removed
+	    in 0.8.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Publisher.Destroy">
+	<term><function>Destroy()</function></term>
+	<listitem>
+	  <para>
+	    Remove all subscribers of all of self's channels. See <link
+	    linkend="Connector.RemovePublisher"><function>RemovePublisher</function></link>
+	    for more details.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Publisher.__del__">
+	<term><function>__del__()</function></term>
+	<listitem>
+	  <para>
+	    Remove all subscribers of all of self's channels. See <link
+	    linkend="Connector.RemovePublisher"><function>RemovePublisher</function></link>
+	    for more details.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect1>
+
+  <sect1 id="class-QueueingPublisher">
+    <title>The Class <classname>QueueingPublisher</classname></title>
+    <para>
+      Sometimes it's useful to put messages in a queue and issue them
+      all in one go after a complex operation is finished. The class
+      <classname>QueueingPublisher</classname> provides such a queue and
+      the following methods:
+    </para>
+    <variablelist>
+      <varlistentry id="QueueingPublisher.queue_message">
+	<term><function>queue_message(<parameter>channel</parameter>, *<parameter>args</parameter>)</function></term>
+	<listitem>
+	  <para>
+	    Put message for channel <parameter>channel</parameter> in
+	    the queue. The rest of the arguments are treated just as
+	    in <link
+	    linkend="Publisher.issue"><function>issue</function></link>
+	  </para>
+	  <para>
+	    If the messge is already queued remove it and put it at the
+	    end.  This is done to make certain that no channel gets
+	    called twice between two calls to flush_message_queue. If
+	    the order of channel invocation is important two or more
+	    queues should be used.
+	  </para>
+	  <para>
+	    Note, that this can be very inefficient if a lot of
+	    different messages are queued before the queue is flushed
+	    because each new message is compared with all messages in
+	    the queue sequentiually. A dictionary could speed this up
+	    considerably if the order in which the messages are issued
+	    isn't important and if the messages can be used as
+	    dictionary keys. Especially the latter is not always the
+	    case, so this isn't done by defalt.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="QueueingPublisher.flush_message_queue">
+	<term><function>flush_message_queue()</function></term>
+	<listitem>
+	  <para>
+	    Issue all queued messages until the queue is empty. The
+	    process is repeated because issueing messages might result
+	    in new messages being queued. This can theoretically result
+	    in an infinite loop.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="QueueingPublisher.clear_message_queue">
+	<term><function>clear_message_queue()</function></term>
+	<listitem>
+	  <para>
+	    Discard all queued messages.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/coordsys.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/coordsys.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/coordsys.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,995 @@
+<chapter id="coordinatesystems"><title>Coordinate Systems</title>
+  <para>
+    All coordinates used by the document and graphics objects are given
+    in the <emphasis>document coordinate system</emphasis>. This
+    coordinate system has its origin in the lower left corner of the
+    page; x increases to the right, y increases to the top. The unit for
+    these coordinates is the DTP-point (or PostScript-point), that is,
+    1/72 inch. Thus Skencil's document coordinate system is the same as
+    the default coordinate system of a PostScript
+    interpreter. Coordinates are stored as floats.
+  </para>
+  <para>
+    The page size is a user settable document property, usually "A4",
+    "letter" or something similar. Skencil can display the outline of
+    the page if desired to allow the user to position the drawing on the
+    page.
+  </para>
+  <para>
+    When displaying the document in a window, the canvas widget (to be
+    more precise, the graphics device object the canvas uses) converts
+    document coordinates to <emphasis>window coordinates</emphasis>.
+    These are the standard X-Window coordinates with the origin in the
+    top left corner of the window and x increasing to the right and y
+    increasing downwards. The unit is 1 pixel.
+  </para>
+  <para>
+    Skencil defines a few builtin objects to represent and manipulate
+    coordinates: Points, Rects and Transformations. All of the related
+    functions, objects and constants are exported by
+    the <literal>Sketch</literal> package.
+  </para>
+
+  <sect1 id="class-Point"><title><classname>Point</classname> Objects</title>
+    <para>
+      Point objects represent 2D points or vectors--depending on how you
+      interpret them; their internal representation is identical.
+    </para>
+    <para>
+      While such points could be represented by Python tuples, this
+      special object type requires less memory and overloads some
+      arithmetic operators. A point object is represented by two C
+      "float" numbers, one for each cartesian coordinate.
+    </para>
+    <para>
+      Point objects are immutable.
+    </para>
+    <sect2>
+      <title>Constructors</title>
+      <para>
+	There are two constructor functions:
+      </para>
+      <para>
+	<variablelist>
+	  <varlistentry id="function-Point">
+	    <term><function>Point(<parameter>x</parameter>, <parameter>y</parameter>)</function></term>
+	    <term><function>Point(<parameter>sequence</parameter>)</function></term>
+	    <listitem>
+	      <para>
+		Return a point object with the coordinates
+		<parameter>x</parameter> and <parameter>y</parameter>.
+		If called with one argument, the argument must be a
+		sequence of two numbers. This form is called a
+		<link linkend="PointSpec">PointSpec</link>
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry id="function-Polar">
+	    <term><function>Polar(<parameter>r</parameter>, <parameter>phi</parameter>)</function></term>
+	    <term><function>Polar(<parameter>phi</parameter>)</function></term>
+	    <listitem>
+	      <para>
+		Return a point object for the polar coordinates
+		<parameter>r</parameter> and <parameter>phi</parameter>.
+		If <parameter>r</parameter> is omitted, it defaults to 1.0.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+    </sect2>
+
+    <sect2><title>Attributes</title>
+      <para>
+	A point object has two (read only) attributes:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>x</literal></term>
+	  <listitem>
+	    <para>
+	      The X-coordinate of the point as a python float
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>y</literal></term>
+	  <listitem>
+	    <para>
+	      The Y-coordinate of the point as a python float
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Methods</title>
+      <para>
+	A point object has these methods:
+      </para>
+      <variablelist>
+	<varlistentry><term><literal>normalized()</literal></term>
+	  <listitem>
+	    <para>
+	      Return a unit vector pointing in the same direction. If
+	      the point's length is 0, raise a ZeroDivisionError.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry><term><literal>polar()</literal></term>
+	  <listitem>
+	    <para>
+	      Return a tuple
+	      <literal>(<parameter>r</parameter>, <parameter>phi</parameter>)</literal>
+	      containing the polar coordinates of the
+	      point. <parameter>phi</parameter> is in the range -pi to
+	      pi.  If <parameter>r</parameter> is 0, so
+	      is <parameter>phi</parameter>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Operators</title>
+      <para>
+	Point objects implement both the number and the sequence
+	protocol for Python objects. This allows the following
+	operations:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term>Number Protocol</term>
+	  <listitem>
+	    <variablelist>
+	      <varlistentry>
+		<term><literal>+<parameter>P</parameter></literal></term>
+		<listitem>
+		  <para>
+		    The same as <parameter>P</parameter>.
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal>-<parameter>P</parameter></literal></term>
+		<listitem>
+		  <para>
+		    The negated vector <parameter>P</parameter>. The
+		    same as
+		  </para>
+		  <para>
+		    <literal>Point(-<parameter>P</parameter>.x,
+		      -<parameter>P</parameter>.y)</literal>
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal><parameter>P1</parameter> + <parameter>P2</parameter></literal></term>
+		<listitem>
+		  <para>
+		    The sum of the vectors <parameter>P1</parameter>
+		    and <parameter>P2</parameter>. The same as
+		  </para>
+		  <para>
+		    <literal>Point(<parameter>P1</parameter>.x
+		      + <parameter>P2</parameter>.x, <parameter>P1</parameter>.y
+		      + <parameter>P2</parameter>.y)</literal>
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal><parameter>P1</parameter>
+		    - <parameter>P2</parameter></literal></term>
+		<listitem>
+		  <para>
+		    The difference of the
+		    vectors <parameter>P1</parameter>
+		    and <parameter>P2</parameter>. The same as
+		  </para>
+		  <para>
+		    <literal>Point(<parameter>P1</parameter>.x
+		      - <parameter>P2</parameter>.x, <parameter>P1</parameter>.y
+		      - <parameter>P2</parameter>.y)</literal>
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term>
+		  <literal><parameter>P1</parameter> * <parameter>P2</parameter></literal></term>
+		<listitem>
+		  <para>
+		    The dot product of the
+		    vectors <parameter>P1</parameter>
+		    and <parameter>P2</parameter>. The same as
+		  </para>
+		  <para>
+		    <literal><parameter>P1</parameter>.x * <parameter>P2</parameter>.x + <parameter>P1</parameter>.y * <parameter>P2</parameter>.y</literal>
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal><parameter>NUMBER</parameter> * <parameter>P</parameter></literal></term>
+		<term><literal><parameter>P</parameter> * <parameter>NUMBER</parameter></literal></term>
+		<listitem>
+		  <para>
+		    The same as
+		  </para>
+		  <para>
+		    <literal>Point(<parameter>NUMBER</parameter> * <parameter>P</parameter>.x, <parameter>NUMBER</parameter> * <parameter>P</parameter>.y)</literal>
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal><parameter>P</parameter> / <parameter>NUMBER</parameter></literal></term>
+		<listitem>
+		  <para>
+		    The same as
+		  </para>
+		  <para>
+		    <literal>Point(<parameter>P</parameter>.x / <parameter>NUMBER</parameter>, <parameter>P</parameter>.y / <parameter>NUMBER</parameter>)</literal>
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term>abs(<parameter>P</parameter>)</term>
+		<listitem>
+		  <para>
+		    The length of the
+		    vector <parameter>P</parameter>. The same as
+		    <literal>math.hypot(<parameter>P</parameter>.x, <parameter>P</parameter>.y)</literal>.
+		  </para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term>Sequence Protocol</term>
+	  <listitem>
+	    <variablelist>
+	      <varlistentry>
+		<term><literal>len(<parameter>P</parameter>)</literal></term>
+		<listitem>
+		  <para>
+		    Always returns 2.
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal><parameter>P</parameter>[<parameter>i</parameter>]</literal></term>
+		<listitem>
+		  <para>
+		    For <literal><parameter>i</parameter></literal>
+		    either 0 or 1, this is the same as
+		    <literal><parameter>P</parameter>.x</literal>
+		    or <literal><parameter>P</parameter>.y</literal>
+		    respectively. For other values
+		    of <parameter>i</parameter> raise an IndexError
+		    exception.
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal>tuple(<parameter>P</parameter>)</literal></term>
+		<listitem>
+		  <para>
+		    Return the coordinates of <parameter>P</parameter>
+		    as a tuple <literal>(<parameter>P</parameter>.x,
+		      <parameter>P</parameter>.y)</literal>.
+		  </para>
+		</listitem>
+	      </varlistentry>
+	      <varlistentry>
+		<term><literal>x, y = <parameter>P</parameter></literal></term>
+		<listitem>
+		  <para>
+		    Unpack the point 
+		    <literal><parameter>P</parameter></literal>. 
+		    Equivalent to 
+		    <literal>x, y = tuple(<parameter>P</parameter>)</literal>
+		  </para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+      <para>
+	<parameter>P</parameter>, <parameter>P1</parameter>
+	and <parameter>P2</parameter> are point
+	objects, <parameter>NUMBER</parameter> is any number that can be
+	converted to a float.
+      </para>
+      <para>
+	<literal>abs</literal>, <literal>tuple</literal>, <literal>len</literal>
+	and <literal>math.hypot</literal> are the standard Python
+	functions of that name.
+      </para>
+    </sect2>
+
+    <sect2><title>Constants</title>
+      <variablelist>
+	<varlistentry><term><literal>NullPoint</literal></term>
+	  <listitem>
+	    <para>
+	      This is <literal>Point(0, 0)</literal>
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry><term><literal>PointType</literal></term>
+	  <listitem>
+	    <para>
+	      The point type object.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2 id="PointSpec"><title>PointSpec</title>
+      <para>
+	While point objects are the standard representation for a point,
+	it is sometimes inconvenient (particularly if you are computing
+	the individual coordinates separately) to create a point object
+	just because a function requires that argument type. Therefore,
+	some functions also accept a <emphasis>PointSpec</emphasis>
+	instead.
+      </para>
+      <para>
+	An argument that is supposed to be a PointSpec can be either a
+	point object or any sequence of two numbers. Here, number means
+	any object that can be converted to a "double" in C. You could
+	use e. g. a tuple of floats or ints instead of a point object.
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="class-Rect"><title><classname>Rect</classname> Objects</title>
+    <para>
+      Rect objects, or rects for short, represent rectangular areas of
+      the drawing whose edges are parallel to the coordinate axes. They
+      are represented by four floats for the positions of the left,
+      bottom, right and top edges. Rects are kept in a normalized state
+      where the left coordinate a less than the right coordinate and the
+      bottom coordinate less than the top coordinate.
+    </para>
+    <para>
+      The <link linkend="class-Bounded">bounding rects and coord
+      rects</link> of the graphics objects are such rect objects.
+    </para>
+    <para>
+      Rect objects provide efficient methods for boolean operations
+      (union and intersection of rects) and tests for overlapping rects
+      and contained points.
+    </para>
+    <para>
+      There are two special rect objects: <literal>InfinityRect</literal> and
+      <literal>EmptyRect</literal>. <literal>InfinityRect</literal>
+      represents the entire 2D plane while <literal>EmptyRect</literal>
+      is an empty rect. These objects behave in special ways: both
+      overlap every other rect, <literal>InfinityRect</literal> contains
+      all points while <literal>EmptyRect</literal> contains no point,
+      and so on. The particular coordinates of these objects are
+      irrelevant.
+    </para>
+    <para>
+      Rect objects are immutable.
+    </para>
+    <para>
+      Note: these rect objects have nothing to do with the rectangle
+      primitive (apart from the fact that the rectangle primitive has a
+      bounding box...).
+    </para>
+
+    <sect2><title>Constructors</title>
+      <variablelist>
+	<varlistentry id="function-Rect">
+	  <term><function>Rect(<parameter>left</parameter>, <parameter>bottom</parameter>, <parameter>right</parameter>, <parameter>top</parameter>)</function></term>
+	  <term><function>Rect(<parameter>llcorner</parameter>, <parameter>urcorner</parameter>)</function></term>
+	  <listitem>
+	    <para>
+	      Return a new Rect object with the coordinates
+	      <parameter>left</parameter>, <parameter>bottom</parameter>,
+	      <parameter>right</parameter>
+	      and <parameter>top</parameter> or the opposite corners
+	      <parameter>llcorner</parameter>
+	      and <parameter>urcorner</parameter> given
+	      as <link linkend="class-Point">point objects</link>. The
+	      rectangle is automatically normalized, so you can
+	      swap <parameter>left</parameter>/<parameter>right</parameter>
+	      or
+	      <parameter>top</parameter>/<parameter>bottom</parameter>
+	      or choose any opposite corners.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="function-PointsToRect">
+	  <term>
+	    <function>PointsToRect(<parameter>sequence</parameter>)</function>
+	  </term>
+	  <listitem>
+	    <para>
+	      Return the smallest rect that contains all points in
+	      <parameter>sequence</parameter>. <parameter>sequence</parameter>
+	      must be a sequence of
+	      <link linkend="PointSpec">PointSpecs</link>.
+	      If <parameter>sequence</parameter> is empty
+	      return <literal>EmptyRect</literal>
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Attributes</title>
+      <para>
+	A rect object has four (read only) attributes:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>left</literal></term>
+	  <term><literal>bottom</literal></term>
+	  <term><literal>right</literal></term>
+	  <term><literal>top</literal></term>
+	  <listitem>
+	    <para>
+	      The left, bottom, right and top coordinate of the rect as
+	      python floats. For <literal>InfinityRect</literal>
+	      and <literal>EmptyRect</literal> these have no real
+	      meaning.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Methods</title>
+      <para>
+	A rect object has these methods (self refers to the rect whose
+	method is called):
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>contains_point(<parameter>PointSpec</parameter>)</literal></term>
+	  <term><literal>contains_point(<parameter>x</parameter>, <parameter>y</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return true, if the point given
+	      by <parameter>PointSpec</parameter>
+	      or <parameter>x</parameter> and <parameter>y</parameter>
+	      is inside of self, false otherwise.
+	    </para>
+	    <para>
+	      For <literal>InfinityRect</literal> this is always true,
+	      for <literal>EmptyRect</literal> always false.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>
+	    <literal>contains_rect(<parameter>r</parameter>)</literal>
+	  </term>
+	  <listitem>
+	    <para>
+	      Return true, if the rect <parameter>r</parameter> lies
+	      completely inside of self.  A rect contains itself.
+	    </para>
+	    <para>
+	      <literal>InfinityRect</literal> contains all other rects
+	      and <literal>EmptyRect</literal> is contained in all other
+	      rects.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term><literal>overlaps(<parameter>r</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return true if self and the rect <parameter>r</parameter>
+	      overlap. A rect overlaps itself.
+	    </para>
+	    <para>
+	      <literal>InfinityRect</literal>
+	      and <literal>EmptyRect</literal> overlap all other rects
+	      and each other.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term><literal>translated(<parameter>PointSpec</parameter>)</literal></term>
+	  <term><literal>translated(<parameter>x</parameter>, <parameter>y</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return self translated by the vector
+	      <parameter>PointSpec</parameter>
+	      or <parameter>x</parameter>
+	      and <parameter>y</parameter>. Equivalent to
+	    </para>
+	    <para>
+	      <literal>Rect(self.left + x, self.bottom + y, self.right + x, self.top + y)</literal>
+	    </para>
+	    <para>
+	      For <literal>InfinityRect</literal>
+	      and <literal>EmptyRect</literal>, return self.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>grown(<parameter>amount</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return a rect that is larger than self
+	      by <parameter>amount</parameter> in every
+	      direction. Equivalent to
+	    </para>
+	    <para>
+	      <literal>Rect(self.left - amount, self.bottom - amount,
+		self.right + amount, self.top + amount)</literal>
+	    </para>
+	    <para>
+	      For <literal>InfinityRect</literal>
+	      and <literal>EmptyRect</literal>, return self.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><literal>center()</literal></term>
+	  <listitem>
+	    <para>
+	      Return the center point of self as a point object.
+	    </para>
+	    <para>
+	      For <literal>InfinityRect</literal>
+	      and <literal>EmptyRect</literal>, return
+	      <literal>Point(0, 0)</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Operators</title>
+      <para>
+	Rect objects implement the sequence protocol for Python
+	objects. This allows the following operations:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>len(<parameter>rect</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Always returns 4.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal><parameter>rect</parameter>[<parameter>i</parameter>]</literal></term>
+	  <listitem>
+	    <para>
+	      If <literal><parameter>i</parameter></literal> is one of
+	      0, 1, 2 or 3, this is the same as
+	      <literal><parameter>rect</parameter>.left</literal>,
+	      <literal><parameter>rect</parameter>.bottom</literal>,
+	      <literal><parameter>rect</parameter>.right</literal>
+	      or <literal><parameter>rect</parameter>.top</literal>
+	      respectively.
+	    </para>
+	    <para>
+	      For other values of <parameter>i</parameter> raise an
+	      IndexError exception.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>tuple(<parameter>rect</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the coordinates of <parameter>rect</parameter> as a tuple
+	    </para>
+	    <para>
+	      <literal>(<parameter>rect</parameter>.left, 
+		<parameter>rect</parameter>.bottom, 
+		<parameter>rect</parameter>.right,
+		<parameter>rect</parameter>.top)</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>left, bottom, right, top = <parameter>rect</parameter></literal></term>
+	  <listitem>
+	    <para>
+	      Unpack the rect
+	      <literal><parameter>rect</parameter></literal>. 
+	      Equivalent to
+	    </para>
+	    <para>
+	      <literal>left, bottom, right, top = tuple(<parameter>rect</parameter>)</literal>
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+      <para>
+	<literal>rect</literal> is a rect object, <literal>len</literal>
+	is the builtin function.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Functions</title>
+      <variablelist>
+	<varlistentry id="function-UnionRects">
+	  <term><function>UnionRects(<parameter>rect1</parameter>, <parameter>rect2</parameter>)</function></term>
+	  <listitem>
+	    <para>
+	      Return the union of the rects <parameter>rect1</parameter>
+	      and <parameter>rect2</parameter>. The union is the
+	      smallest rect containing both rects.
+	    </para>
+	    <para>
+	      If one the arguments is <literal>InfinityRect</literal>
+	      return <literal>InfinityRect</literal>, if one of the
+	      arguments is <literal>EmptyRect</literal> return the other
+	      argument.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="function-IntersectRects">
+	  <term><function>IntersectRects(<parameter>rect1</parameter>, <parameter>rect2</parameter>)</function></term>
+	  <listitem>
+	    <para>
+	      Return the intersection of the rects
+	      <parameter>rect1</parameter>
+	      and <parameter>rect2</parameter>. The intersection is the
+	      largest rect contained in both rects.
+	    </para>
+	    <para>
+	      If one the arguments is <literal>EmptyRect</literal>
+	      return <literal>EmptyRect</literal>, if one of the
+	      arguments is <literal>InfinityRect</literal> return the
+	      other argument.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Constants</title>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>InfinityRect</literal></term>
+	  <listitem>
+	    <para>
+	      Represents the entire 2D plane.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>EmptyRect</literal></term>
+	  <listitem>
+	    <para>
+	      The empty rect.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>UnitRect</literal></term>
+	  <listitem>
+	    <para>
+	      <literal>Rect(0, 0, 1, 1)</literal>
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>RectType</literal></term>
+	  <listitem>
+	    <para>
+	      The rect type object.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+  </sect1>
+
+  <sect1 id="class-Trafo"><title>Transformation Objects</title>
+    <para>
+      A transformation object, a trafo object or trafo for short,
+      represents an affine 2D transformation. Such a transformation is
+      given by 6 numbers: <parameter>m11</parameter>,
+      <parameter>m21</parameter>, <parameter>m21</parameter>,
+      <parameter>m22</parameter>, <parameter>v1</parameter> and
+      <parameter>v2</parameter>. These coefficients are given in the
+      same order as for a PostScript transformation matrix.
+    </para>
+    <para>
+      To apply a trafo to an object you can simple call the trafo with
+      that object as argument. For details, see
+      the <link linkend="Trafo-operators">section "Operators"</link>
+      below.
+    </para>
+    <para>
+      Trafo objects are immutable.
+    </para>
+    <para>
+      If such a transformation <parameter>T</parameter> is applied to
+      the point (<parameter>x</parameter>, <parameter>y</parameter>) you
+      get
+    </para>
+    <para>
+<programlisting>
+            / x \   / m11 m12 \ / x \   / v1 \
+        T * |   | = |         | |   | + |    |
+            \ y /   \ m21 m22 / \ y /   \ v2 /
+</programlisting>
+    </para>
+    <para>
+      or, in homogeneous coordinates:
+    </para>
+    <para>
+<programlisting>
+            / x \   / m11 m12 v1 \ / x \
+            |   |   |            | |   |
+        T * | y | = | m21 m22 v2 | | y |
+            |   |   |            | |   |
+            \ 1 /   \ 0   0   1  / \ 1 /
+</programlisting>
+    </para>
+
+    <sect2><title>Constructors</title>
+      <para>
+	The following functions create trafo objects:
+      </para>
+      <variablelist>
+	<varlistentry id="function-Trafo">
+	  <term><function>Trafo(<parameter>m11</parameter>, <parameter>m21</parameter>, <parameter>m21</parameter>, <parameter>m22</parameter>, <parameter>v1</parameter>, <parameter>v2</parameter>)</function></term>
+	  <listitem>
+	    <para>
+	      The generic constructor: return the transformation given
+	      by the coordinates <parameter>m11</parameter>,
+	      <parameter>m21</parameter>, <parameter>m21</parameter>,
+	      <parameter>m22</parameter>, <parameter>v1</parameter>
+	      and <parameter>v2</parameter>. These coefficients are
+	      given in the same order as for a PostScript
+	      transformation matrix.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="function-Scale">
+	  <term><function>Scale(<parameter>factorx</parameter>[, <parameter>factory</parameter>])</function></term>
+	  <listitem>
+	    <para>
+	      Return a trafo object for a scaling by the
+	      factors <parameter>factorx</parameter> (in x-direction)
+	      and <parameter>factory</parameter> (in y-direction). If
+	      omitted, <parameter>factory</parameter> defaults to the
+	      value of <parameter>factorx</parameter>.
+	    </para>
+	    <para>
+	      Equivalent to
+	      <literal>Trafo(<parameter>factorx</parameter>, 0, 0, <parameter>factory</parameter>, 0, 0)</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="function-Translation">
+	  <term><function>Translation(<parameter>offset</parameter>)</function></term>
+	  <term><function>Translation(<parameter>offset_x</parameter>, <parameter>offset_y</parameter>)</function></term>
+	  <listitem>
+	    <para>
+	      Return a trafo object for a translation
+	      by <parameter>offset</parameter>
+	      (a <link linkend="PointSpec">PointSpec</link>) or
+	      (<parameter>offset_x</parameter>,
+	      <parameter>offset_y</parameter>).
+	      Equivalent to 
+	      <literal>Trafo(1, 0, 0, 1, <parameter>offset_x</parameter>,
+		<parameter>offset_y</parameter>)</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="function-Rotation">
+	  <term><function>Rotation(<parameter>angle</parameter>[, <parameter>center</parameter>])</function></term>
+	  <term><function>Rotation(<parameter>angle</parameter>[, <parameter>center_x</parameter>, <parameter>center_y</parameter>])</function></term>
+	  <listitem>
+	    <para>
+	      Return a trafo object for a rotation through the angle
+	      <parameter>angle</parameter> (counter clockwise in
+	      radians) about the center
+	      point <parameter>center</parameter> or
+	      (<parameter>center_x</parameter>, <parameter>center_y</parameter>).
+	      <parameter>center</parameter> must be a <link linkend="PointSpec">PointSpec</link>. If
+	      <parameter>center</parameter> is omitted it defaults to
+	      the origin.
+	    </para>
+	    <para>
+	      Equivalent to
+<programlisting>
+	s = sin(angle);
+	c = cos(angle);
+	offx = cx - c * center_x + s * center_y;
+	offy = cy - s * center_x - c * center_y;
+	Trafo(c, s, -s, c, offx, offy);
+</programlisting>
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Attributes</title>
+      <para>
+	A trafo object has six (read only) attributes:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>m11</literal></term>
+	  <term><literal>m21</literal></term>
+	  <term><literal>m12</literal></term>
+	  <term><literal>m22</literal></term>
+	  <term><literal>v1</literal></term>
+	  <term><literal>v2</literal></term>
+	  <listitem>
+	    <para>
+	      The coefficients of the trafo as python floats.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Methods</title>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>DocToWin(<parameter>point</parameter>)</literal></term>
+	  <term><literal>DocToWin(<parameter>x</parameter>, <parameter>y</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Transform the point and return the result as a tuple of ints.
+	      <parameter>point</parameter> is a
+	      <link linkend="PointSpec">PointSpec</link>.  This function
+	      is used to transform document coordinates to window
+	      coordinates, hence the name. (Normally, if you want to
+	      transform a point, you
+	      <link linkend="Trafo-operators">call the trafo object
+	      directly</link>)
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>DTransform(<parameter>point</parameter>)</literal></term>
+	  <term><literal>DTransform(<parameter>x</parameter>, <parameter>y</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Treat the point as a vector and transform it, that is, don't add
+	      <literal>v1</literal> and <literal>v2</literal>.
+	      <parameter>point</parameter> is
+	      a <link linkend="PointSpec">PointSpec</link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>inverse()</literal></term>
+	  <listitem>
+	    <para>
+	      Return the inverse transformation of self. If self cannot
+	      be inverted raise the <literal>SingularMatrix</literal>
+	      exception.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>coeff()</literal></term>
+	  <listitem>
+	    <para>
+	      Return the coefficients of the trafo as a tuple
+	      (<parameter>m11</parameter>, <parameter>m21</parameter>,
+	      <parameter>m21</parameter>, <parameter>m22</parameter>,
+	      <parameter>v1</parameter>, <parameter>v2</parameter>).
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>matrix()</literal></term>
+	  <listitem>
+	    <para>
+	      Return the matrix coefficients of the trafo
+	      (<literal>m11</literal>, ..., <literal>m22</literal>) as a
+	      tuple. The same as <literal>coeff()[:4]</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>offset()</literal></term>
+	  <listitem>
+	    <para>
+	      Return the translation coefficients as a point object.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2 id="Trafo-operators"><title>Operators</title>
+      <para>
+	Since a transformation is a mapping in the mathematical sense,
+	it is convenient to make trafo objects callable, so you can
+	treat them like functions or methods. Depending on the type of
+	the argument the results are different:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>trafo(<parameter>point</parameter>)</literal></term>
+	  <term><literal>trafo(<parameter>x</parameter>, <parameter>y</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the transformed point. Point can be
+	      any <link linkend="PointSpec">PointSpec</link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>trafo(<parameter>othertrafo</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the composition of both trafos.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>trafo(<parameter>rect</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the smallest <link linkend="class-Rect">rect
+		object</link> that contains the transformed corners of
+	      the rect object <parameter>rect</parameter>.
+	    </para>
+	    <para>
+	      <literal>InfinityRect</literal>
+	      and <literal>EmptyRect</literal> are returned unchanged.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Constants</title>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>Identity</literal></term>
+	  <listitem>
+	    <para>
+	      The identity transformation 
+	      (<literal>Trafo(1, 0, 0, 1, 0, 0)</literal>)
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>IdentityMatrix</literal></term>
+	  <listitem>
+	    <para>
+	      A tuple containing the coefficients of the identity
+	      matrix. The same as <literal>Identity.matrix()</literal>
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>TrafoType</literal></term>
+	  <listitem>
+	    <para>
+	      The trafo type object.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>SingularMatrix</literal></term>
+	  <listitem>
+	    <para>
+	      Exception raised by the <literal>inverse()</literal> method.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/curveobj.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/curveobj.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/curveobj.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,366 @@
+<chapter id="class-curveobject"><title>Curve Objects</title>
+  <para>
+    A curve object represents a single continuous curve. A curve is a
+    sequence of segments with each segment starting at the end point of
+    the preceding segment (except the first segment, of which only the
+    end point is used as the start point of the second segment).
+  </para>
+  <para>
+    There are two kinds of segments, line segments and bezier segments.
+  </para>
+  <para>
+    A line segment is defined by its end point, p, and it defines a
+    straight line from the preceding segment's end point to p.
+  </para>
+  <para>
+    A bezier segment consists of an end point, p, and two auxiliary
+    points, p1 and p2. It defines a bezier curve starting at the
+    preceding segment's end point, approximating p1 and p2 and ending at
+    p.
+  </para>
+  <para>
+    The end points of the segments are usually called
+    <emphasis>nodes</emphasis>. There are two special properties
+    associated with them.
+  </para>
+  <para>
+    The first property is the <emphasis>continuity</emphasis>. The
+    continuity can be "angle", "smooth" or "symmetrical". This results
+    in constraints in the editor when the user modifies a bezier
+    object's auxiliary points:
+  </para>
+  <variablelist>
+    <varlistentry><term>angle</term>
+      <listitem>
+	<para>
+	  No constraint.
+	</para>
+      </listitem>
+    </varlistentry>
+    <varlistentry><term>smooth</term>
+      <listitem>
+	<para>
+	  The node, the auxiliary points p2 of the node's segment, and
+	  p1 of the following segment must be collinear.
+	</para>
+      </listitem>
+    </varlistentry>
+    <varlistentry><term>symmetrical</term>
+      <listitem>
+	<para>
+	  The node, the auxiliary points p2 of the node's segment, and
+	  p1 of the following segment must be collinear and the node is
+	  the arithmetic mean of the two auxiliary points.
+	</para>
+      </listitem>
+    </varlistentry>
+  </variablelist>
+
+  <para>
+    The second property is only used during editing and has not effect
+    on the appearance of the curve. It is a flag that indicates whether
+    the node is selected or not.
+  </para>
+  <para>
+    Segments are numbered from zero, just like other sequences in
+    Python.
+  </para>
+
+  <sect2><title>Constructors</title>
+    <para>
+      <variablelist>
+	<varlistentry id="function-CreatePath">
+	  <term><function>CreatePath()</function></term>
+	  <listitem>
+	    <para>
+	      Return an empty curve object.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </para>
+  </sect2>
+
+  <sect2><title>Attributes</title>
+    <variablelist>
+      <varlistentry><term><literal>len</literal></term>
+	<listitem>
+	  <para>
+	    The number of segments. An empty curve has zero length, a
+	    curve with just one node has length 1.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry><term><literal>closed</literal></term>
+	<listitem>
+	  <para>
+	    True (1) if the curve is closed, false (0) otherwise.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect2>
+
+  <sect2><title>Methods</title>
+
+    <sect3><title>Segment Construction</title>
+      <para>
+	When an empty curve has been created, segments can be appended
+	using the functions listed in this section. The first segment of
+	a curve must be a line segment.
+      </para>
+      <variablelist>
+	<varlistentry id="curve.AppendLine">
+	  <term><literal>AppendLine(<parameter>p</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <term><literal>AppendLine(<parameter>x</parameter>, <parameter>y</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <listitem>
+	    <para>
+	      Append a line segment to self. <parameter>p</parameter>
+	      must be a <link linkend="PointSpec">PointSpec</link>.
+	    </para>
+	    <para>
+	      <parameter>cont</parameter> is the continuity at the end
+	      node and defaults to <literal>ContAngle</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.AppendBezier">
+	  <term><literal>AppendBezier(<parameter>p1</parameter>, <parameter>p2</parameter>, <parameter>p</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <term><!-- meth -->AppendBezier(<parameter>x1</parameter>, <parameter>y1</parameter>, <parameter>x2</parameter>, <parameter>y2</parameter>,
+	    <parameter>x</parameter>, <parameter>y</parameter>[, <parameter>cont</parameter>])<!-- /meth --></term>
+	  <listitem>
+	    <para>
+	      Append a bezier segment to
+	      self. <parameter>p</parameter>, <parameter>p1</parameter>,
+	      and <parameter>p2</parameter> must
+	      be <link linkend="PointSpec">PointSpecs</link>. The
+	      control points of the bezier segment are the current end
+	      point of the curve,
+	      <parameter>p1</parameter> and <parameter>p2</parameter>
+	      (which are only approximated)
+	      and <parameter>p</parameter>.
+	    </para>
+	    <para>
+	      <parameter>cont</parameter> is the continuity at the end
+	      node and defaults to <literal>ContAngle</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.AppendSegment">
+	  <term><literal>AppendSegment(CurveLine, (), <parameter>p</parameter>[, cont])</literal></term>
+	  <term><!-- meth -->AppendSegment(CurveBezier, (<parameter>p1</parameter>, <parameter>p2</parameter>), <parameter>p</parameter>[,
+	    <parameter>cont</parameter>])<!-- /meth --></term>
+	  <listitem>
+	    <para>
+	      Append a segment. If the first parameter
+	      is <literal>CurveLine</literal>, this method is equivalent
+	      to <literal>AppendLine(<parameter>p</parameter>, <parameter>cont</parameter>)</literal>,
+	      with <parameter>cont</parameter> defaulting
+	      to <literal>ContAngle</literal>.
+	    </para>
+	    <para>
+	      If the first parameter is <literal>CurveBezier</literal>,
+	      this method is equivalent to
+	      <literal>AppendLine(<parameter>p1</parameter>, <parameter>p2</parameter>, <parameter>p</parameter>, <parameter>cont</parameter>)</literal>,
+	      with <parameter>cont</parameter> defaulting
+	      to <literal>ContAngle</literal>.
+	    </para>
+	    <para>
+	      This method is mainly supplied as the opposite of the
+	      method <link
+	      linkend="curve.Segment"><function>Segment</function></link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect3>
+
+    <sect3><title>Querying the Curve Geometry</title>
+      <para>
+	The following methods usually take the index of a segment as
+	argument.  This index counts from 0 to <literal>len -
+	1</literal>. If the index is negative it counts from the end,
+	just like for other sequences.
+      </para>
+      <variablelist>
+	<varlistentry id="curve.Segment">
+	  <term><literal>Segment(<parameter>i</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the segment number <parameter>i</parameter> as a
+	      4-tuple.
+	    </para>
+	    <para>
+	      If the segment is a line segment the result is of the
+	      form:
+	    </para>
+	    <para>
+	      <literal>(CurveLine, (), <parameter>p</parameter>, <parameter>cont</parameter>)</literal>
+	    </para>
+	    <para>
+	      if it is a bezier segment the result has the form:
+	    </para>
+	    <para>
+	      <literal>(CurveBezier, (<parameter>p1</parameter>, <parameter>p2</parameter>), <parameter>p</parameter>, <parameter>cont</parameter>)</literal>
+	    </para>
+	    <para>
+	      The result is suitable as argument tuple
+	      to <link
+	      linkend="curve.AppendSegment"><function>AppendSegment</function></link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.Node">
+	  <term><literal>Node(<parameter>i</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the <parameter>i</parameter>th node as a point
+	      object.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.Continuity">
+	  <term><literal>Continuity(<parameter>i</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the continuity at node <parameter>i</parameter>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.SegmentType">
+	  <term><literal>SegmentType(<parameter>i</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Return the type of the <parameter>i</parameter>th segment
+	      (either <literal>CurveLine</literal>
+	      or <literal>CurveBezier</literal>).
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect3>
+
+    <sect3><title>Modifying a Curve Object</title>
+      <variablelist>
+	<varlistentry id="curve.SetLine">
+	  <term><literal>SetLine(<parameter>i</parameter>, <parameter>p</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <term><literal>SetLine(<parameter>i</parameter>, <parameter>x</parameter>, <parameter>y</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <listitem>
+	    <para>
+	      Replace the <parameter>i</parameter>th segment by a line
+	      segment. The arguments <parameter>p</parameter>,
+	      <parameter>x</parameter>, <parameter>y</parameter>
+	      and <parameter>cont</parameter> are used as in
+	      <link
+		 linkend="curve.AppendLine"><function>AppendLine</function></link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.SetBezier">
+	  <term><literal>SetBezier(<parameter>i</parameter>, <parameter>p1</parameter>, <parameter>p2</parameter>, <parameter>p</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <term><literal>SetBezier(<parameter>i</parameter>, <parameter>x1</parameter>, <parameter>y1</parameter>, <parameter>x2</parameter>, <parameter>y2</parameter>, <parameter>x</parameter>, <parameter>y</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <listitem>
+	    <para>
+	      Replace the <parameter>i</parameter>th segment by a bezier
+	      segment. The rest of the arguments are used as
+	      in <link
+	      linkend="curve.AppendBezier"><function>AppendBezier</function></link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.SetSegment">
+	  <term><literal>SetSegment(<parameter>i</parameter>, CurveLine, (), <parameter>p</parameter>[, cont])</literal></term>
+	  <term><literal>SetSegment(<parameter>i</parameter>, CurveBezier, (<parameter>p1</parameter>, <parameter>p2</parameter>), <parameter>p</parameter>[, <parameter>cont</parameter>])</literal></term>
+	  <listitem>
+	    <para>
+	      Replace the <parameter>i</parameter>th segment by the segment
+	      described by the rest of arguments, which are used as in
+	      <link
+		 linkend="curve.AppendSegment"><function>AppendSegment</function></link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.ClosePath">
+	  <term><literal>ClosePath()</literal></term>
+	  <listitem>
+	    <para>
+	      Close the curve.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.Transform">
+	  <term><literal>Transform(<parameter>trafo</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Apply the transformation <parameter>trafo</parameter> (a
+	      trafo object) to the path. The path is modified in place.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="curve.Translate">
+	  <term><literal>Translate(<parameter>offset</parameter>)</literal></term>
+	  <listitem>
+	    <para>
+	      Translate the path by offset, a point object. The path is
+	      modified in place.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect3>
+
+    <sect3><title>Managing the Selection</title>
+      <para>
+	<variablelist>
+	  <varlistentry id="curve.SegmentSelected">
+	    <term><literal>SegmentSelected(<parameter>i</parameter>)</literal></term>
+	    <listitem>
+	      <para>
+		Return true (1) if the <parameter>i</parameter>th
+		segment is selected, false (0) otherwise.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry id="curve.SelectSegment">
+	    <term><literal>SelectSegment(<parameter>i</parameter>, [<parameter>flag</parameter>])</literal></term>
+	    <listitem>
+	      <para>
+		Mark the <parameter>i</parameter>th segment as selected
+		if <parameter>flag</parameter> is true and as unselected
+		otherwise. <parameter>flag</parameter> defaults to true.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+    </sect3>
+  </sect2>
+
+  <sect2><title>Constants</title>
+    <para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>ContAngle</literal></term>
+	  <term><literal>ContSmooth</literal></term>
+	  <term><literal>ContSymmetrical</literal></term>
+	  <listitem>
+	    <para>
+	      The values for the continuity property of the nodes.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>CurveLine</literal></term>
+	  <term><literal>CurveBezier</literal></term>
+	  <listitem>
+	    <para>
+	      The two different segment types. Used
+	      for <link linkend="curve.AppendSegment"><function>AppendSegment</function></link>
+	      and <link linkend="curve.Segment"><function>Segment</function></link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </para>
+  </sect2>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/devguide.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/devguide.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/devguide.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book
+          PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+          "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+
+[
+   <!ENTITY architecture SYSTEM "architecture.xml">
+   <!ENTITY remarks SYSTEM "remarks.xml">
+   <!ENTITY coordsys SYSTEM "coordsys.xml">
+   <!ENTITY curveobj SYSTEM "curveobj.xml">
+   <!ENTITY classes SYSTEM "classes.xml">
+   <!ENTITY undo SYSTEM "undo.xml">
+   <!ENTITY plugins SYSTEM "plugins.xml">
+   <!ENTITY ui SYSTEM "ui.xml">
+   <!ENTITY connector SYSTEM "connector.xml">
+   <!ENTITY fileformat SYSTEM "fileformat.xml">
+]>
+<book>
+  <bookinfo>
+    <title>Skencil Developer's Guide</title>
+    <author><firstname>Bernhard</firstname><surname>Herzog</surname></author>
+  </bookinfo>
+
+  <chapter id="intro"><title>Introduction</title>
+    <para>
+      This document describes the implementation of at least some parts
+      of Skencil. It is meant for anyone who wants to find out how
+      Skencil is implemented, how to extend Skencil with new object
+      types or wants to contribute to Skencil.
+    </para>
+    <para>
+      I'll assume that you are familiar with Skencil from the user's
+      point of view and that you have some experience in Python
+      programming. If you don't know Python yet, have a look at the
+      Python tutorial (contained in the standard documentation for
+      Python which is distributed as a separate package)
+    </para>
+    <para>
+      Some of the topics discussed in this document might be of interest
+      to developers of other Python applications as well. In particular,
+      these topics are the <link linkend="undo">undo mechanism</link>
+      and the <link linkend="connector">connector module</link>
+    </para>
+    <para>
+      Note that since Skencil was originally called "Skencil" that older
+      name is still used internally in a lot of places, for example in
+      some identifiers in the code.
+    </para>
+  </chapter>
+
+  &architecture;
+  &remarks;
+  &coordsys;
+  &curveobj;
+  &classes;
+  &undo;
+  &plugins;
+  &ui;
+  &connector;
+  &fileformat;
+
+</book>

Added: skencil/branches/skencil-0.6/Doc/devguide/fileformat.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/fileformat.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/fileformat.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,163 @@
+<chapter id="fileformat"><title>File Format</title>
+  <para>
+    Skencil stores drawings in plain ASCII files using a line oriented
+    format. The main idea is that each line of an sk file looks like a
+    Python function call. Originally, this was just for convenience, as
+    the import filter just had to define all those functions in a
+    dictionary, and read and (r)eval each line.
+  </para>
+  <para>
+    That turned out to be quite slow, probably because each line is
+    compiled to bytecode and then executed just once. Skencil now uses a
+    parser written in C. This is much faster and doesn't have the
+    potential security problems of eval.
+  </para>
+  <para>
+    All function arguments are Python literals, ints, floats, strings
+    (delimited with single- or double-quotes, the usual \ escapes are
+    allowed, but no triple quoted strings or raw strings), tuples and
+    lists.  Keyword arguments are also allowed.
+  </para>
+  <para>
+    Boolean values are represented as the ints 0 or 1.
+  </para>
+  <para>
+    Colors are represented by float triples describing the RGB values,
+    each in the range 0..1 (e.g. red (1.0, 0.0, 0.0)).
+  </para>
+  <para>
+    All sk files start with '##Sketch' followed by two numbers, the
+    major and minor version number of the file format.
+  </para>
+  <para>
+    Lines starting with # are comments, empty lines are ignored.
+  </para>
+
+  <sect1 id="fileformat-structure"><title>Overall structure</title>
+    <para>
+      The first function in an sk-file is always 'document()'. This
+      function takes no parameters.
+    </para>
+    <para>
+      The next part defines global parameters like the page layout and
+      objects like styles.
+    </para>
+    <para>
+      After this follow the layers from bottom to top.
+    </para>
+  </sect1>
+
+  <sect1 id="fileformat-globals"><title>Globals</title>
+    <para>
+      Functions for global parameters:
+    </para>
+    <variablelist>
+      <varlistentry>
+	<term>layout(<parameter>format</parameter>, <parameter>orientation</parameter>)</term>
+	<listitem>
+	  <para>
+	    <parameter>format</parameter> is either the name of a
+	    predefined paper-format or a tuple
+	    (<parameter>width</parameter>, <parameter>height</parameter>)
+	    in pt. See Sketch/Lib/pagelayout.py for a list of predefined
+	    paper-formats.
+	  </para>
+	  <para>
+	    <parameter>orientation</parameter> is 0 for portrait or 1
+	    for landscape.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term>dstyle(<parameter>name</parameter>)</term>
+	<listitem>
+	  <para>
+	    Define the style named <parameter>name</parameter> (a
+	    string). The preceding functions define the properties of
+	    this style. See the section
+	    on <link linkend="fileformat-properties">properties</link>
+	    for details.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect1>
+
+  <sect1 id="fileformat-layers"><title>Layers</title>
+    <para>
+      There are three kinds of layers, <emphasis>normal layers</emphasis>,
+      <emphasis>grid layers</emphasis> and <emphasis>guide layers</emphasis>.
+    </para>
+    <para>
+      Normal layers and guide layers can contain other objects. All
+      objects defined after a layer function are part of that layer. A
+      layer is implicitly closed by another layer function or the end of
+      file.
+    </para>
+    <para>
+      The layer functions:
+    </para>
+    <variablelist>
+      <varlistentry>
+	<term>layer(<parameter>name</parameter>, <parameter>visible</parameter>, <parameter>printable</parameter>,
+	  <parameter>locked</parameter>, <parameter>outlined</parameter>, <parameter>outline_color</parameter>)</term>
+	<listitem>
+	  <para>
+	    Start a normal layer named <parameter>name</parameter> (a
+	    string). The booleans <parameter>visible</parameter>,
+	    <parameter>printable</parameter>, <parameter>locked</parameter>
+	    and <parameter>outlined</parameter> determine whether the
+	    layer is visible, printable, locked or only shown outlined.
+	  </para>
+	  <para>
+	    <parameter>outline_color</parameter> defines the color used
+	    for the outlines of the objects in the layer.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term>grid(<parameter>geometry</parameter>)</term>
+	<listitem>
+	  <para>
+	    Define the grid-layer. The <parameter>geometry</parameter>
+	    is a tuple of the form
+	    (<parameter>xorig</parameter>, <parameter>yorig</parameter>,
+	    <parameter>xwidth</parameter>, <parameter>ywidth</parameter>)
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term>guidelayer(<parameter>name</parameter>, <parameter>visible</parameter>, <parameter>printable</parameter>,
+	  <parameter>locked</parameter>, <parameter>outlined</parameter>, <parameter>outline_color</parameter>)</term>
+	<listitem>
+	  <para>
+	    Start the guide layer. The arguments are the same as for the
+	    normal layer, but the arguments 
+	    <parameter>printable</parameter>
+	    and <parameter>outlined</parameter> will be ignored and set
+	    to 0 and 1 respectively.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect1>
+
+  <sect1 id="fileformat-objects"><title>Objects</title>
+    <sect2>
+      <title>Primitives</title>
+      <para>
+	Primitives 
+      </para>
+    </sect2>
+    <sect2>
+      <title>Compound Objects</title>
+      <para>
+      </para>
+    </sect2>
+  </sect1>
+  <sect1 id="fileformat-properties">
+    <title>Properties</title>
+    <para>
+    </para>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/plugins.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/plugins.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/plugins.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,1028 @@
+<chapter id="plugins"><title>Plugins</title>
+  <para>
+    Plugins provide a way to extend Skencil with external modules that
+    can be maintained independently from Skencil itself. Plugin modules
+    can define import and export filters for new file formats or they
+    can define new object types.
+  </para>
+  <para>
+    For this to work, Skencil has to provide a standardized interface to
+    these modules to allow them to create and manipulate graphics
+    objects.  In addition, there has to be some fall-back method if
+    someone loads a document containing objects defined by a plugin into
+    an installation where that particular plugin is not available.
+  </para>
+
+  <sect1 id="plugin-config"><title>Plugin Configuration</title>
+    <para>
+      On startup, Skencil searches for plugins on the <emphasis>plugin
+	path</emphasis>. Every Python source file found is scanned for
+      configuration information.  Later, when the the plugin is needed
+      it is imported.
+    </para>
+    <para>
+      The plugin path is a list of directories stored in
+      <literal>Sketch.config.plugin_path</literal>. The directory names
+      should be absolute pathnames. Skencil uses a notation borrowed
+      from the kpathsea library (which is used by many TeX programs to
+      search files):
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  If a directory name ends in a slash ('/') search in that
+	  directory and in the directories immediately contained in it.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  If a directory name ends with two slashes ('//') search in
+	  that directory and recursively in all subdirectories.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  Else, search only in that directory
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      The configuration information is a series of Python statements
+      (assignments), each on its own line, between the lines
+      '<literal>###Sketch Config</literal>' and
+      '<literal>###End</literal>'.
+    </para>
+    <para>
+      One of the assignments must be to a variable named
+      "<literal>type</literal>". This specifies the type of the plugin
+      (import filter, plugin object, etc.).
+    </para>
+    <para>
+      Another variable that may be used in the future, is
+      '<literal>version</literal>' which will be used to specify the
+      version of the plugin-config conventions used (not the version of
+      the plugin itself).
+    </para>
+    <para>
+      Other variable names are type dependent.
+    </para>
+    <para>
+      Each of the lines may be commented out.
+    </para>
+    <para>
+      Example:
+<programlisting>
+###Sketch Config
+#type = Import
+#class_name = 'SKLoader'
+#rx_magic = '^##Sketch 1 *(?P&lt;minor&gt;[0-9]+)'
+#tk_file_type = ('Skencil/Sketch Document', '.sk')
+format_name = 'SK-1'
+###End
+</programlisting>
+    </para>
+    <para>
+      Skencil uses this method--instead of importing every plugin module
+      and requiring that they register themselves with the plugin
+      manager--to avoid loading unnecessary modules.
+    </para>
+    <para>
+      Implementation Note: currently Skencil reads the lines between
+      '###Sketch Config' and '###End' into a single string (after
+      removing the initial '#'s if present) and exec's it with a globals
+      dictionary containing the predefined plugin types and an empty
+      locals dictionary which receives all the variables. A consequence
+      of this approach is that it is currently possible to use arbitrary
+      Python statements and not just assignments. Don't rely on this, it
+      could be changed in the future.
+    </para>
+  </sect1>
+
+  <sect1 id="plugin-import"><title>Import Filters</title>
+    <para>
+      Skencil uses import filters to read vector drawings from files.
+    </para>
+
+    <sect2 id="plugin-import-config"><title>Configuration Variables</title>
+      <para>
+	For import filter configuration, Skencil uses the following
+	variables:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>type</literal></term>
+	  <listitem>
+	    <para>
+	      The type must be <literal>Import</literal>. This
+	      identifier is defined in the globals() dictionary.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="plugin-import-conf:class_name">
+	  <term><literal>class_name</literal></term>
+	  <listitem>
+	    <para>
+	      A string containing the name of a Python class defined in
+	      the module. See below for the interface this class has to
+	      provide.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="plugin-import-conf:rx_magic">
+	  <term><literal>rx_magic</literal></term>
+	  <listitem>
+	    <para>
+	      A string containing a regular expression suitable for the
+	      re module. This regular expression is matched against the
+	      first line of the file. if it matches, the import
+	      mechanism assumes that the filter understands the file's
+	      format and then procedes to use that filter to load the
+	      file. So, if possible, this regular expression should
+	      match those files the filter can handle and only those.
+	    </para>
+	    <para>
+	      While this method of identifying files is not really
+	      sufficient to handle all file types, it works well enough
+	      for now. In the future we will probably have to extend
+	      this mechanism.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>tk_file_type</literal></term>
+	  <listitem>
+	    <para>
+	      A tuple containing two elements. The first is the name of
+	      the file format presented to the user in the file open
+	      dialog. The second element is eithe a string or a tuple of
+	      strings. Each of the strings defines a file name extension
+	      used for that filename.
+	    </para>
+	    <para>
+	      Examples:
+	    </para>
+	    <para>
+	      <literal>#tk_file_type = ('Skencil Document', '.sk')</literal>
+	    </para>
+	    <para>
+	      <literal>#tk_file_type = ('PostScript file', ('.ps', '.eps'))</literal>
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="plugin-import-conf:unload">
+	  <term><literal>unload</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      A boolean. True means that the filter module should be
+	      unloaded after use, false means that it shouldn't be
+	      unloaded. If the module is unloaded it will be imported
+	      again the next time the filter is needed. Infrequently
+	      used filters should set this to true, frequently used
+	      filters (like the filter for Skencil's own format) should
+	      set it to true.
+	    </para>
+	    <para>
+	      If omitted, it defaults to false.
+	    </para>
+	    <para>
+	      It's a good idea to set this variable to true at least
+	      while developing a filter because that way the filter will
+	      be automatically reloaded when the source file changes.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>format_name</literal></term>
+	  <listitem>
+	    <para>
+	      The name of the format as a string. This name is currently
+	      used internally to find out whether a document was loaded
+	      from a file in Skencil's format or from a different format
+	      (in the latter case "Save" is treated like "Save As...",
+	      i.e. the user has to provide a filename).
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>standard_messages</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      A boolean indicating whether the messages in the plugin
+	      are standard messages that are defined in Skencil's
+	      message catalogs.  For third-party plugins this should be
+	      omitted.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>The Class Interface</title>
+
+      <sect3><title>External Interface</title>
+	<para>
+	  The interface a loader class presents to the document loading
+	  mechanism is quite simple. The loading mechanism works roughly
+	  as follows:
+	</para>
+	<orderedlist>
+	  <listitem>
+	    <para>
+	      Read the first line of the file
+	    </para>
+	  </listitem>
+	  <listitem>
+	    <para>
+	      Match it in turn against all the regular expressions
+	      defined for import filter plugins (defined by
+	      the <link linkend="plugin-import-conf:rx_magic">rx_magic
+	      variable</link>).
+	    </para>
+	  </listitem>
+	  <listitem>
+	    <para>
+	      If a match is found, instantiate the plugin's class
+	      (defined by the <link linkend="plugin-import-conf:class_name">class_name
+		variable</link>) with three positional
+	      parameters <parameter>file</parameter>,
+	      <parameter>filename</parameter> and
+	      <parameter>match</parameter>.
+	      <parameter>file</parameter> is the open input file object,
+	      positioned just after the first line.
+	      <parameter>filename</parameter> is the name of the file.
+	      <parameter>match</parameter> is the match-object returned
+	      from regular expression match.  If possible, filters
+	      should read the input file sequentially and not use
+	      seeks. Skencil automatically pipes gzipped files through
+	      gzip and in that case the file object is actually a pipe,
+	      so seeks would be impossible. If a filter needs to access
+	      the first line it can do so by using
+	      <parameter>match</parameter>.string or by defing suitable
+	      groups in the regular expression.
+	    </para>
+	  </listitem>
+	  <listitem>
+	    <para>
+	      Call the instance's Load() method (without arguments).
+	      This method does the actual work and returns an instance
+	      of the document class.
+	    </para>
+	  </listitem>
+	  <listitem>
+	    <para>
+	      Call the instance's Messages() method without arguments.
+	      The return value is expected to be a list of strings with
+	      messages that are usually presented to the user by the UI.
+	    </para>
+	  </listitem>
+	  <listitem>
+	    <para>
+	      If the <link linkend="plugin-import-conf:unload">unload
+		configuration variable</link> is true, unload the
+		plugin's module.
+	    </para>
+	  </listitem>
+	</orderedlist>
+      </sect3>
+
+      <sect3><title>Common Base Classes</title>
+	<para>
+	  To make things easier, Skencil defines some base classes that
+	  plugins can
+	  inherit, <classname>LoaderWithComposites</classname> and,
+	  derived from that, <link
+	  linkend="class-GenericLoader"><classname>GenericLoader</classname></link>
+	  and <classname>SimplifiedLoader</classname>, derived in turn
+	  from <classname>GenericLoader</classname>.
+	</para>
+
+	<sect4 id="class-GenericLoader">
+	  <title><classname>GenericLoader</classname></title>
+	  <para>
+	    The class <classname>GenericLoader</classname> provides a
+	    default implementation of the constructor, a mechanism for
+	    warning and error messages and methods to easily create
+	    standard objects like rectangles, ellipses and groups.
+	  </para>
+	  <para>
+	    <classname>GenericLoader</classname> defines these methods:
+	  </para>
+	  <variablelist>
+	    <varlistentry id="GenericLoader.__init__">
+	      <term><function>__init__(<parameter>file</parameter>, <parameter>filename</parameter>, <parameter>match</parameter>)</function></term>
+	      <listitem>
+		<para>
+		  Assign the arguments to <literal>self.file</literal>,
+		  <literal>self.filename</literal> and
+		  <literal>self.match</literal> respectively.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry id="GenericLoader.document">
+	      <term><function>document()</function></term>
+	      <listitem>
+		<para>
+		  Start the construction of a document. This method must
+		  be called before any other of the object creation
+		  methods are called.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry id="GenericLoader.layer">
+	      <term><function>layer([<parameter>name</parameter>])</function></term>
+	      <listitem>
+		<para>
+		  Start a new layer. This method must be called after
+		  calling <link
+		  linkend="GenericLoader.document"><function>document</function></link>
+		  and before any of the other object creation methods.
+		</para>
+		<para>
+		  <parameter>name</parameter> is the name of the
+		  layer. If omitted, it defaults to "Layer 1".
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry id="GenericLoader.begin_group">
+	      <term><function>begin_group()</function></term>
+	      <listitem>
+		<para>
+		  Start a new group. Groups can be arbitrarily
+		  nested. Each call to <function>begin_group</function>
+		  must have a corresponding call to
+		  <link
+		     linkend="GenericLoader.end_group"><function>end_group</function></link>.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry id="GenericLoader.end_group">
+	      <term><function>end_group()</function></term>
+	      <listitem>
+		<para>
+		  End the current group.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry id="GenericLoader.rectangle">
+	      <term><!-- methdef -->rectangle(<parameter>m11</parameter>, <parameter>m21</parameter>,
+		<parameter>m12</parameter>, <parameter>m22</parameter>, <parameter>v1</parameter>, <parameter>v2</parameter>[, <parameter>radius1</parameter> = 0][,
+		<parameter>radius2</parameter> =
+		0])<!-- /methdef --></term>
+	      <listitem>
+		<para>
+		  Create a new rectangle object and append it to the
+		  current compound object.
+		</para>
+		<para>
+		  The first six positional parameters
+		  (<parameter>m11</parameter>,
+		  <parameter>m21</parameter>,
+		  <parameter>m12</parameter>, 
+		  <parameter>m22</parameter>,
+		  <parameter>v1</parameter>, <parameter>v2</parameter>)
+		  define a transformation matrix that transforms the
+		  unit square (opposite corners (0,0) and (1,1))
+		  onto the rectangle.
+		</para>
+		<para>
+		  <parameter>radius1</parameter> and
+		  <parameter>radius2</parameter> define the rounded
+		  corners.
+		</para>
+		<para>
+		  For more details see the documentation for the
+		  class <link
+		  linkend="class-Rectangle"><classname>Rectangle</classname></link>
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry id="GenericLoader.ellipse">
+	      <term><!-- methdef -->ellipse(<parameter>m11</parameter>, <parameter>m21</parameter>,
+		<parameter>m12</parameter>, <parameter>m22</parameter>, <parameter>v1</parameter>, <parameter>v2</parameter>[,
+		<parameter>start_angle</parameter> = 0.0][, <parameter>end_angle</parameter> = 0.0][,
+		<parameter>arc_type</parameter> = ArcPieSlice])<!-- /methdef --></term>
+	      <listitem>
+		<para>
+		  Create a new ellipse object and append it to the
+		  current compound object.
+		</para>
+		<para>
+		  The first six positional parameters
+		  (<parameter>m11</parameter>,
+		  <parameter>m21</parameter>,
+		  <parameter>m12</parameter>,
+		  <parameter>m22</parameter>, 
+		  <parameter>v1</parameter>, <parameter>v2</parameter>)
+		  define a transformation matrix that transforms the
+		  unit circle (center (0,0) and radius 1) onto the
+		  ellipse.
+		</para>
+		<para>
+		  <parameter>start_angle</parameter>
+		  and <parameter>end_angle</parameter>, if given, define
+		  the start end end angles for pie slices, arc and
+		  chords.
+		</para>
+		<para>
+		  <parameter>arc_type</parameter> defines whether and
+		  how the arc of an incomplete ellipse is closed. Valid
+		  values are <literal>ArcArc</literal>,
+		  <literal>ArcPieSlice</literal>
+		  and <literal>ArcChord</literal>. These constants are
+		  defined in <literal>Sketch.const</literal>
+		</para>
+		<para>
+		  For more details see the documentation for the
+		  class <classname>Ellipse</classname>
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry id="GenericLoader.bezier">
+	      <term><function>bezier(<parameter>paths</parameter>)</function></term>
+	      <listitem>
+		<para>
+		  Create a new b&eacute;zier object in the current
+		  compound object.
+		</para>
+		<para>
+		  <parameter>paths</parameter> must be a tuple
+		  of <link linkend="class-curveobject">curve
+		    objects</link>.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</sect4>
+      </sect3>
+    </sect2>
+  </sect1>
+
+  <sect1 id="plugin-export"><title>Export Filters</title>
+    <para>
+      Skencil uses export filters to write documents to files.
+    </para>
+
+    <sect2>
+      <title>Configuration Variables</title>
+      <para>
+	For export filter configuration, Skencil uses the following
+	variables:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>type</literal></term>
+	  <listitem>
+	    <para>
+	      The type must be <literal>Export</literal>. This
+	      identifier is defined in the globals() dictionary.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>tk_file_type</literal></term>
+	  <term><literal>unload</literal> (optional)</term>
+	  <term><literal>format_name</literal></term>
+	  <listitem>
+	    <para>
+	      These variables have the same meaning
+	      as <link linkend="plugin-import-config">in an import
+	      filter</link>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>extensions</literal></term>
+	  <listitem>
+	    <para>
+	      A string with the standard file extension of the export
+	      format.  Alternatively this can be a tuple of file
+	      extension strings.
+	    </para>
+	    <para>
+	      Skencil uses the file extension to find the export filter.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>standard_messages</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      A boolean indicating whether the messages in the plugin
+	      are standard messages that are defined in Skencil's
+	      message catalogs.  For third-party plugins this should be
+	      omitted.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>External Interface</title>
+      <para>
+	Given a document object and a filename for the output file,
+	Skencil does the following to find an export filter and to
+	export the drawing:
+      </para>
+      <orderedlist>
+	<listitem>
+	  <para>
+	    Take the extension of the output filename and find the
+	    export filter that uses that extension.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    Load the module of the plugin
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    Call the module's <function>save</function> function.
+	  </para>
+	</listitem>
+      </orderedlist>
+    </sect2>
+
+    <sect2><title>The <function>save</function> function</title>
+      <para>
+	The function <function>save</function> is the main entry point
+	for an export plugin. It is called with four positional
+	parameters <parameter>document</parameter>, <parameter>file</parameter>,
+	<parameter>filename</parameter>
+	and <parameter>options</parameter>.
+      </para>
+      <para>
+	<parameter>document</parameter> is the document that is to be
+	saved. <parameter>file</parameter> is the output file object
+	open for writing and <parameter>filename</parameter> is the
+	corresponding filename. Finally, <parameter>options</parameter>
+	is a dictionary with (user specified) options. Currently,
+	<parameter>options</parameter> is always an empty dictinary as
+	there is no way yet to specify such options.
+      </para>
+    </sect2>
+
+    <sect2><title>Implementation Strategy</title>
+      <para>
+	Apart from the <function>save</function> function entry point
+	Skencil requires very little from the plugin. The only other
+	thing it expects is that the plugin traverses the object tree by
+	itself and uses the interface provided by
+	the <link
+	linkend="class-Protocols"><classname>Protocols</classname></link>
+	class to distinguish the different object types.
+      </para>
+      <para>
+	In the following, the svg export filter serves as the basis for
+	a a brief outline of this technique.
+      </para>
+      <para>
+	Both the svg and the ai filter use the same basic approach. They
+	implement the filter as a class and use an instance of that
+	class to do the work:
+      </para>
+      <para>
+<programlisting>
+def save(document, file, filename, options = {}):
+    saver = SVGSaver(file, filename, document, options)
+    saver.Save()
+    saver.close()
+</programlisting>
+      </para>
+      <para>
+	The interesting parts happen in the class. The constructor
+	doesn't do much, it just saves the parameters in instance
+	variables:
+<programlisting>
+class SVGSaver:
+
+    def __init__(self, file, filename, document, options):
+        self.file = file
+        self.filename = filename
+        self.document = document
+        self.options = options
+</programlisting>
+      </para>
+      <para>
+	The Save method is where the real work begins.  First it
+	writes a kind of file header:
+<programlisting>
+    def Save(self):
+        self.file.write('&lt;?xml version="1.0" standalone="yes"?&gt;\n')
+        left, bottom, right, top = self.document.BoundingRect()
+        width = right - left
+        height = top - bottom
+        self.trafo = Trafo(1, 0, 0, -1, -left, top)
+        self.file.write('&lt;svg width="%g" height="%g"' % (width, height))
+        self.file.write('>\n')
+</programlisting>
+      </para>
+      <para>
+	The document method <function>BoundingRect</function> returns
+	the bounding rectangle of the entire document
+      </para>
+      <para>
+	After the header it loops over all the layers in the document...
+<programlisting>
+        for layer in self.document.Layers():
+</programlisting>
+      </para>
+      <para>
+	...and if the layer is not a special layer, such as grid or
+	guide layers, and if the layer is printable...
+      </para>
+<programlisting>
+            if not layer.is_SpecialLayer and layer.Printable():
+</programlisting>
+      <para>
+	... save the layer as a group:
+      </para>
+<programlisting>
+                self.BeginGroup()
+                self.save_objects(layer.GetObjects())
+                self.EndGroup()
+</programlisting>
+      <para>
+	<function>GetObjects()</function> returns a list of all objects
+	in the layer. All compound objects have this method. In the SVG
+	filter, the <function>BeginGroup</function>
+	and <function>EndGroup</function> methods write
+	the <literal>&lt;g&gt;</literal>
+	and <literal>&lt;/g&gt;</literal> tags that mark groups in SVG.
+      </para>
+      <para>
+	Finally, the trailer to close the <literal>&lt;svg&gt;</literal>
+	tag.
+<programlisting>
+        self.file.write('&lt;/svg&gt;')
+</programlisting>
+      </para>
+      <para>
+	The next interesting method is save_objects. It loops over the
+	list of objects...
+<programlisting>
+    def save_objects(self, objects):
+        for object in objects:
+</programlisting>
+        ...and if the object is a compound object...
+<programlisting>
+            if object.is_Compound:
+</programlisting>
+        ...save it as a group
+<programlisting>
+                self.BeginGroup()
+                self.save_objects(object.GetObjects())
+                self.EndGroup()
+</programlisting>
+      </para>
+      <para>
+	otherwise, if the object is a bezier object, a rectangle or an
+	ellipse...
+<programlisting>
+            elif object.is_Bezier or object.is_Rectangle or object.is_Ellipse:
+</programlisting>
+        ...save the object as bezier curves.
+<programlisting>
+                self.PolyBezier(object.Paths(), object.Properties(),
+                                object.bounding_rect)
+</programlisting>
+      </para>
+      <para>
+	The <function>Paths</function> method returns a tuple
+	of <link linkend="class-curveobject">path
+	objects</link>. <function>Properties</function> returns an
+	object that has members like <literal>fill_pattern</literal>
+	and <literal>line_width</literal> that define the properties of
+	the object.
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="plugin-objects"><title>Plugin Objects</title>
+    <para>
+      Plugin objects provide a way to define new types of
+      objects. Plugin objects can define how the user interacts with
+      them and they can be saved to and loaded from sk files. The design
+      of plugin objects takes the problem of loading files containing
+      plugin objects that a particular Skencil installation doesn't know
+      about into account.
+    </para>
+    <para>
+      An example of a plugin object is the regular polygon object that
+      comes with Skencil.
+    </para>
+
+    <sect2><title>Design Philosophy</title>
+      <para>
+	The idea behind plugin objects is that they're groups of builtin
+	objects with some special attributes and behavior on top of
+	that.
+      </para>
+      <para>
+	What a plugin object looks like is completely defined by the
+	children.  This is the key to being able to load drawings with
+	unknown plugin objects. Because the children are builtin objects
+	Skencil can display and print them without problems by treating
+	them more or less as ordinary groups.
+      </para>
+    </sect2>
+
+    <sect2><title>Saving and Loading a Plugin Object</title>
+      <para>
+	A plugin object is saved as a special compound object together
+	with all its children. When Skencil reads an sk file with a
+	plugin object that it doesn't know about it can still treat is
+	like a normal group and since all drawing is done by the
+	children it can still display and print it.
+      </para>
+      <para>
+	Skencil is actually a bit smarter than that. It doesn't turn
+	unknown plugin objects into normal groups, it turns them into an
+	UnknownPlugin object that remembers which class the object
+	belongs to and what parameters were used. As long as the object
+	isn't changed it is saved as a plugin object again.
+      </para>
+    </sect2>
+    <sect2><title>Configuration Variables</title>
+      <para>
+	For plugin object configuration, Skencil uses the following
+	variables:
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term><literal>type</literal></term>
+	  <listitem>
+	    <para>
+	      The type must be <literal>PluginCompound</literal>. This
+	      identifier is defined in the globals() dictionary.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="plugin-object-conf:class_name">
+	  <term><literal>class_name</literal></term>
+	  <listitem>
+	    <para>
+	      A string containing the name of a Python class defined in
+	      the module. See below for the interface this class has to
+	      provide.
+	    </para>
+	    <para>
+	      Skencil uses the class_name to distinguish different
+	      plugin types and should therefore be unique. A future
+	      version of Skencil will probably use a different name for
+	      that purpose.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>menu_text</literal></term>
+	  <listitem>
+	    <para>
+	      The text to display in the menu as a string. In the 0.6.x,
+	      this text is used for the entry in the Edit->Create menu.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>standard_messages</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      A boolean indicating whether the messages in the plugin
+	      are standard messages that are defined in Skencil's
+	      message catalogs.  For third-party plugins this should be
+	      omitted.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="plugin-object-conf:parameters">
+	  <term><literal>parameters</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      A tuple of tuples describing the parameters of the
+	      object. This information is used to create a dialog that
+	      allows the user to set the parameters for new objects and
+	      modify those of existing objects.
+	    </para>
+	    <para>
+	      See below for more detail.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>factory</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      The name of a function that is to be called by the user
+	      interface code instead of the class to create a new
+	      object. The sk import filter always calls the class
+	      directly.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term><literal>uses_selection</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      If this boolean is true, the factory, if defined, or the
+	      class will be called with a list of objects as the only
+	      parameter.  These objects are the ones currently selected.
+	    </para>
+	    <para>
+	      When omitted, it defaults to 0.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="plugin-object-conf:custom_dialog">
+	  <term><literal>custom_dialog</literal> (optional)</term>
+	  <listitem>
+	    <para>
+	      The name of a dialog class that is to be used instead of
+	      the dialog automatically built from the parameters
+	      information.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2><title>Implementation of a Plugin Object</title>
+      <para>
+	Many plugin objects have some parameters that the user can set
+	and modify and that have to be saved and read in again.
+      </para>
+      <para>
+	For the user interface part, there are two mechanism to deal
+	with parameters. They can either be defined by
+	the <link
+	linkend="plugin-object-conf:parameters"><literal>parameters</literal></link>
+	configuration variable in which case Skencil automatically
+	builds a dialog from the description or the plugin can implement
+	a custom dialog and tell Skencil to use it with
+	the <link
+	linkend="plugin-object-conf:custom_dialog"><literal>custom_dialog</literal></link>
+	configuration variable.
+      </para>
+      <para>
+	The <literal>parameters</literal> variable has to be sequence of
+	pentuples each of which defines one parameter. The pentuple has
+	the form
+      </para>
+      <para>
+	<literal> (<parameter>name</parameter>, <parameter>type</parameter>, <parameter>default</parameter>, <parameter>range</parameter>, <parameter>label</parameter>)</literal>
+      </para>
+      <para>
+	where <emphasis>label</emphasis> is text suitable for a label in
+	the dialog box. <parameter>name</parameter> is the internal name
+	for that property. The constructor of the plugin object must
+	accept a keyword argument name. Also, the plugin object must
+	have a method <parameter>Capname</parameter> to read the current
+	value of that property and a method
+	<function>SetParameters</function> accepting a
+	dictionary of parameters and returning undo information.
+	<parameter>Capname</parameter> is a "Capitalized" version of
+	the lowercase name (if <parameter>name</parameter> is
+	"the_parameter", <parameter>Capname</parameter> is
+	"TheParameter")
+      </para>
+      <para>
+	<parameter>type</parameter> describes the type of the
+	parameter, <parameter>default</parameter> is the initial value
+	and <parameter>range</parameter> describes the valid values.
+      </para>
+      <para>
+	Supported types:
+      </para>
+      <para>
+	<informaltable>
+	  <tgroup cols="3">
+	    <thead>
+	      <row><entry>type</entry><entry>range</entry></row>
+	    </thead>
+	    <tbody>
+	      <row>
+		<entry>int</entry>
+		<entry>
+		  (<parameter>MIN</parameter>, <parameter>MAX</parameter>)
+		</entry>
+		<entry>
+		  the minimal and maximal
+		  value. <parameter>MIN</parameter>
+		  and/or <parameter>MAX</parameter> may be None
+		  indicating no limit (apart from the builtin limits).
+		</entry>
+	      </row>
+	      <row>
+		<entry>float</entry>
+		<entry>
+		  (<parameter>MIN</parameter>, <parameter>MAX</parameter>)
+		</entry>
+		<entry>
+		  same as for int
+		</entry>
+	      </row>
+	      <row>
+		<entry>length</entry>
+		<entry>
+		  (<parameter>MIN</parameter>, <parameter>MAX</parameter>)
+		</entry>
+		<entry>
+		  A length in pt. The user can change the unit.
+		</entry>
+	      </row>
+	      <row>
+		<entry>text</entry>
+		<entry>
+		  ignored
+		</entry>
+		<entry>
+		  A text string (the range should be None for now)
+		</entry>
+	      </row>
+	    </tbody>
+	  </tgroup>
+	</informaltable>
+      </para>
+      <para>
+	Saving of plugin objects works a little differently for sk-files
+	than for other, non-native file formats.
+      </para>
+      <para>
+	Export filters for non-native file formats treat plugin objects
+	just like groups. That means you don't have to do anything
+	special, but it also means that any extra information associated
+	with the plugin-object will be lost.
+      </para>
+      <para>
+	Saving to an sk-file is done by the 
+	<function>SaveToFile</function> method which is called with
+	an <classname>SKSaver</classname> instance, customarily
+	called <literal>file</literal>. <classname>SKSaver</classname>
+	is defined by the sksaver plugin. The plugin-object is expected
+	to first call <literal>file.BeginPluginCompound</literal> with
+	appropriate arguments, then to call each child's SaveToFile
+	method with <literal>file</literal> as the only argument and
+	finally <literal>file.EndPluginCompound</literal> with no
+	arguments.
+      </para>
+      <para>
+	<function>BeginPluginCompound</function> has the following syntax:
+      </para>
+      <variablelist>
+	<varlistentry id="SKSaver.BeginPluginCompound">
+	  <term>
+	    <function>BeginPluginCompound(<parameter>plugin_name</parameter> [, <parameter>arg1</parameter>, ...]
+	      [, <parameter>kwarg1</parameter> = <parameter>value1</parameter>, ...])</function>
+	  </term>
+	  <listitem>
+	    <para>
+	      Start a plugin compound object in the sk
+	      file. <parameter>plugin_name</parameter> has to be the
+	      same as the configuration
+	      variable <link
+	      linkend="plugin-object-conf:class_name">class_name</link>.
+	    </para>
+	    <para>
+	      All remaining arguments, whether positional or keyword
+	      arguments, should be builtin python types. They're written
+	      to the file as is. The keywords if used must be names of
+	      parameters if the configuration
+	      variable <link
+	      linkend="plugin-object-conf:parameters">parameters</link>
+	      is used.
+	    </para>
+	    <para>
+	      When the file is read in again the plugin class is called
+	      with these arguments to create the instance.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+
+    <sect2 id="class-PluginCompound">
+      <title>The class <classname>PluginCompound</classname></title>
+      <para>
+	To make implementation easier, Skencil provides a base class for
+	plugin objects. <classname>PluginCompound</classname> has a
+	default implementation of <function>SetParameters</function>
+	which assumes that the parameters are instance variables that
+	have the same name as the parameters.
+      </para>
+      <para>
+	Furthermore, it has an implementation
+	of <function>SaveToFile</function> that has to be extended by
+	the derived class. All the derived class has to do in its
+	implementation of <function>SaveToFile</function> is to call the
+	inherited method with the same arguments as the SKSaver
+	method <link
+	linkend="SKSaver.BeginPluginCompound"><function>BeginPluginCompound</function></link>
+	except the class name. The class name is expected to be in a
+	(class-)attribute called <literal>class_name</literal>.
+      </para>
+      <para>
+	For examples see the regular polygon and the LCD-text objects in
+	<filename>Plugin/Objects</filename>.
+      </para>
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/remarks.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/remarks.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/remarks.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,413 @@
+<chapter id="misc"><title>General Remarks</title>
+  <sect1 id="directorystructure"><title>Directory Structure</title>
+    <para>
+      The source is divided into the core sources, containing the basic
+      graphics classes, the UI code and some utility
+      modules. <link linkend="plugin-import">Import filters</link> and
+      other <link linkend="plugins">plugins</link> are maintained
+      outside of this core source. Other external packages provide
+      direct access to Xlib functions and objects
+      (<link linkend="dir-pax">Pax</link>) and stream filter objects
+      (<link linkend="dir-filter">Filter</link>).
+    </para>
+
+    <variablelist>
+      <varlistentry>
+	<term><filename>sketch-&lt;version&gt;/</filename></term>
+	<listitem>
+	  <para>
+	    The top level directory holds the main scripts
+	    <filename>sketch.py</filename>
+	    and <filename>sk2ps.py</filename>
+	  </para>
+	  <variablelist>
+	    <varlistentry>
+	      <term><filename>Sketch/</filename></term>
+	      <listitem>
+		<para>
+		  The top-level directory for the core sources. This
+		  works as a Python package which exports many of the
+		  commonly needed support and graphics objects (classes,
+		  functions, constants etc.).
+		</para>
+		<para>
+		  Ideally, the <literal>Sketch</literal> package should
+		  export every thing a "normal" plugin may need. This is
+		  not yet the case, as some interfaces are not very
+		  stable yet and may need to be redesigned. Once they
+		  have reached a certain level of stability, they will
+		  be moved into <literal>Sketch</literal>.
+		</para>
+
+		<variablelist>
+		  <varlistentry><term><filename>Base/</filename></term>
+		    <listitem>
+		      <para>
+			Contains the most fundamental modules such as
+			the modules for file IO, undo/redo, the plugin
+			manager and code for user preferences.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		  <varlistentry><term><filename>Modules/</filename></term>
+		    <listitem>
+		      <para>
+			The C-Modules.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		</variablelist>
+		<para>
+		  The modules in <literal>Base/</literal> and
+		  <literal>Modules/</literal> are accessible as
+		  <literal>Sketch.<parameter>modulename</parameter></literal>.
+		  These directories are not currently subpackages.
+		</para>
+		<variablelist>
+		  <varlistentry>
+		    <term><filename>Graphics/</filename></term>
+		    <listitem>
+		      <para>
+			The subpackage for the graphics modules.
+		      </para>
+		      <para>
+			It contains all of the builtin graphics classes:
+			primitives, compound objects, special effects
+			(blend/mask/...), the document object, ...
+		      </para>
+		      <para>
+			It also holds the graphics devices for drawing
+			into the window or PostScript file.
+		      </para>
+		      <para>
+			The <literal>Graphics</literal> modules are
+			accesible as
+			<literal>Sketch.Graphics.<parameter>modulename</parameter></literal>.
+			Many of the objects defined in Graphics
+			modules are exported directly by the Sketch
+			module.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		  <varlistentry>
+		    <term><filename>UI/</filename></term>
+		    <listitem>
+		      <para>
+			The subpackage for user interface related code.
+		      </para>
+		      <para>
+			Contains the user interface code including the
+			application object.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		  <varlistentry><term><filename>Lib/</filename></term>
+		    <listitem>
+		      <para>
+			A subpackage for some support modules that are
+			not really Skencil specific, such as a Type 1
+			font interpreter (simply extracts the outline
+			information) and a simple parser for PostScript
+			files adhering to the DSC.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		  <varlistentry><term><filename>Pixmaps/</filename></term>
+		    <listitem>
+		      <para>
+			Pixmap files used by Skencil.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		</variablelist>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term><filename>Plugins/</filename></term>
+	      <listitem>
+		<para>
+		  The subdirectories contain the various
+		  <link linkend="plugins">plugins</link>:
+		</para>
+		<variablelist>
+		  <varlistentry id="dir-plugins-filters">
+		    <term><filename>Filters/</filename></term>
+		    <listitem>
+		      <para>
+			Contains the <link linkend="plugin-import">import
+			filters</link> and export filters for SK-files
+			and other formats.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		  <varlistentry>
+		    <term><filename>Objects/</filename></term>
+		    <listitem>
+		      <para>
+			<link linkend="plugin-objects">Plugin objects</link>.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		</variablelist>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term><filename>Resources/</filename></term>
+	      <listitem>
+		<para>
+		  The subdirectories contain platform/UI independent
+		  resources:
+		</para>
+		<variablelist>
+		  <varlistentry>
+		    <term><filename>Fontmetrics/</filename></term>
+		    <listitem>
+		      <para>
+			Fontmetrics (<filename>*.afm</filename>) for
+			standard PostScript fonts and "font directory
+			files" (<filename>*.sfd</filename>) that
+			describe fonts for Skencil.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		  <varlistentry>
+		    <term><filename>Misc/</filename></term>
+		    <listitem>
+		      <para>
+			Files that define arrows
+			(<filename>*.arrow</filename>), dashes
+			(<filename>*.dashes</filename>), palettes
+			(<filename>*.spl</filename>) and Tk-resources.
+		      </para>
+		    </listitem>
+		  </varlistentry>
+		</variablelist>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry id="dir-pax">
+	      <term><filename>Pax/</filename></term>
+	      <listitem>
+		<para>
+		  Modules that allow Skencil direct access to Xlib. This
+		  is a heavily modified version of the Xt-module.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term id="dir-filter"><filename>Filter/</filename></term>
+	      <listitem>
+		<para>
+		  A module for stream filters. A stream filter behaves
+		  just like a (non seekable) file and comes in two
+		  variants: An encoding filter encodes the data written
+		  to it and writes the encoded data to a data target (a
+		  file or another filter); a decoding filter reads data
+		  from a data source (a file or another filter) and
+		  provides it in decoded form.
+		</para>
+		<para>
+		  These stream filters are modeled after the filters in
+		  PostScript Level 2.
+		</para>
+		<para>
+		  Don't confuse these filters with the Import filters in the 
+		  <link
+		  linkend="dir-plugins-filters"><filename>Plugins/Filters/</filename></link>
+		  directory (although import filters might use stream
+		  filters to decode the data).
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term><filename>Examples/</filename></term>
+	      <listitem>
+		<para>
+		  Some example drawings.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect1>
+
+  <sect1 id="namingconventions"><title>Naming Conventions</title>
+    <para>
+      Module names are <literal>lowercase</literal>.
+    </para>
+    <para>
+      Functions have identifiers that are either
+      <literal>lowercase_with_underscores</literal>
+      or <literal>Capitalized</literal>. This is a bit of a mess, but
+      generally the former should be preferred.
+    </para>
+    <para>
+      Variables, local or global, are
+      also <literal>lowercase_with_underscores</literal>.  Module
+      internal names (for functions, variables, etc.) shouldstart with
+      an underscore ("<literal>_</literal>") (this is a Python
+      convention that affects import statements and module
+      finalization).
+    </para>
+    <para>
+      Class names are <literal>Capitalized</literal>. Public methods are also
+      <literal>Capitalized</literal>, protected methods
+      are <literal>lowercase_with_underscores</literal>, private methods
+      start with two underscores (another Python convention).  Instance
+      variables are also <literal>lowercase_with_underscores</literal>.
+    </para>
+    <para>
+      Constants are often <literal>UPPERCASE</literal> (an exception are
+      the X-constants in <literal>Pax/X.py</literal>)
+    </para>
+    <para>
+      Python does not enforce encapsulation and the distinction between
+      public, protected and private methods and instance variables is
+      more or less a convention programmers are expected to adhere to.
+    </para>
+  </sect1>
+
+  <sect1 id="codingguidelines"><title>Coding Guidelines</title>
+    <para>
+      This <emphasis>not</emphasis> a "coding style" or something
+      similar you are required to adhere to, just some remarks on
+      writing maintainable and readable Python code (IMHO).
+    </para>
+    <sect2>
+      <title>Import statements</title>
+      <para>
+	Don't use <literal>from <parameter>module</parameter> import *</literal>
+      </para>
+      <para>
+	It is difficult to find out whether the code really depends on
+	objects exported by the module. Editing the source or moving
+	some parts of the code to other modules may result in code that
+	doesn't need that module any more, so the import statement
+	should be removed.
+      </para>
+      <para>
+	Using "<literal>import <parameter>module</parameter></literal>"
+	or "<literal>from <parameter>module</parameter>
+	import <parameter>foo</parameter>, <parameter>bar</parameter></literal>"
+	makes this easier.
+      </para>
+    </sect2>
+
+    <sect2><title>Multiple assignments</title>
+      <para>
+	Don't use multiple assignments.
+      </para>
+      <para>
+	Multiple assignments are assignments like this:
+      </para>
+      <para>
+<programlisting>
+  a, b = 0, 1
+</programlisting>
+      </para>
+      <para>
+	I think this is harder to read than
+      </para>
+      <para>
+<programlisting>
+  a = 0
+  b = 1
+</programlisting>
+      </para>
+      <para>
+	or, if you really want only one line,
+<programlisting>
+  a = 0; b = 1
+</programlisting>
+      </para>
+      <para>
+	In the current interpreter (Python 1.5.1) the multiple
+	assignment is even slower than two single assignments (for local
+	variables; the interpreter actually builds a tuple and unpacks
+	it immediately)
+      </para>
+      <para>
+	Multiple assignments are convenient, though, if the first
+	assignment has side effects influencing the second
+	assignment. If you want to swap the values of the
+	variables <literal>a</literal> and <literal>b</literal> you may
+	write
+<programlisting>
+  a, b = b, a
+</programlisting>
+      </para>
+      <para>
+	Note that even in this case the traditional idiom for swapping
+	variables, <literal>temp = a; a = b; b = temp</literal>
+	is <emphasis>faster</emphasis> than multiple assignment
+	(see <filename>Tools/swapbench.py</filename>).
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>
+	Truth Values, <literal>__getattr__</literal> and
+	<literal>__len__</literal>
+      </title>
+      <para>
+	In various places, instance or class attributes have the
+	value <literal>None</literal> to indictate that the attribute
+	has no particular value, while, if the attribute is set, its
+	value is an instance object (one such attribute is
+	<link linkend="class-HierarchyNode"><classname>HierarchyNode</classname></link>'s
+	attribute <literal>parent</literal>). Functions and methods
+	often return <literal>None</literal> instead of an instance
+	object for similar reasons.
+      </para>
+      <para>
+	There are more cases, and, indeed, the following applies
+	whenever you have an object that may be <literal>None</literal>
+	or an instance object.
+      </para>
+      <para>
+	In all these cases, you have to test whether the object you have
+	is <literal>None</literal> or not. It is tempting to write e.g.
+<programlisting>
+  if self.parent:
+      self.parent.SomePublicMethod()
+</programlisting>
+      </para>
+      <para>
+	Don't do that. Test whether the object <emphasis>is</emphasis>
+	<literal>None</literal>:
+<programlisting>
+  if self.parent is not None:
+      self.parent.SomePublicMethod()
+</programlisting>
+      </para>
+      <para>
+	There are two reasons for this:
+      </para>
+      <para>
+	Firstly, if the object is an instance object, Python tries to
+	determine if it is true or false by calling its
+	<literal>__nonzero__</literal> method and, if it doesn't have
+	that method, its <literal>__len__</literal> method. Now, most
+	objects in Skencil don't have these methods, so Python tries to
+	call the <literal>__getattr__</literal> method, which many
+	objects, including all graphics objects, have, twice,
+	for <literal>__nonzero__</literal>
+	and <literal>__len__</literal>.  This overhead can be avoided by
+	testing for identity with <literal>None</literal>.
+      </para>
+      <para>
+	Secondly, even if you know that the object has no
+	<literal>__len__</literal> or <literal>__nonzero__</literal>
+	methods (and, hence, is always considered "true"), it may have
+	them in future versions (the compound graphics objects might
+	implement the Python sequence protocol and, accordingly, the
+	<literal>__len__</literal> method). In that case, code that
+	simply tests whether the object is true would break, as the
+	object might be false even though it is <emphasis>not</emphasis>
+	<literal>None</literal>.
+      </para>
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/ui.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/ui.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/ui.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,59 @@
+<chapter id="ui"><title>User Interface</title>
+
+  <sect1 id="ui-commands">
+    <title>Commands</title>
+    <para>
+      <emphasis>Commands</emphasis> (or command objects), represent a
+      command that can be invoked by the user. Menu items and buttons
+      are not directly connected to methods of the canvas or the
+      document, but are connected to these commands.
+    </para>
+    <para>
+      A command object knows how to invoke the command (i.e. which
+      method of which object to call with which arguments) and how to
+      update itself.  This update is done by calling several
+      callbacks. The following attributes are updated:
+    </para>
+    <variablelist>
+      <varlistentry><term>Menu Name</term>
+	<listitem>
+	  <para>
+	    The text to display in a menu entry. The only commands that
+	    use this currently are Undo and Redo. They use it to
+	    indicate what action would be undone or redone.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry><term>Sensitivity</term>
+	<listitem>
+	  <para>
+	    Whether the command is available at the moment or not. Most
+	    commands have a callback for this because this attribute
+	    determines whether the associated widgets (menu items or
+	    buttons) are grayed out or not.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry><term>Value</term>
+	<listitem>
+	  <para>
+	    The value is used by check command objects to determine
+	    whether they are checked or not. In the current
+	    implementation this value is used as the value of a Tkinter
+	    IntVar which is associated with a widget (or menu item), so
+	    it should be true for "checked" and false for "unchecked".
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+    <para>
+      Whenever, during an update, at least one of the attributes change,
+      all menu items or other associated widgets are notified and also
+      updated.
+    </para>
+    <para>
+      A command object can be associated with any number of widgets or
+      menu items.
+    </para>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/devguide/undo.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/devguide/undo.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/devguide/undo.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,248 @@
+<chapter id="undo"><title>The Undo Mechanism</title>
+  <para>
+    Skencil allows the user to undo every operation that is performed on
+    a document. To achieve this, it needs to keep some information on
+    how to undo the operation. The fact that in Python objects are
+    dynamically typed and functions and (bound) methods are objects
+    allows us to store this information in a very simple and yet very
+    flexible way.
+  </para>
+  <para>
+    I'll call this information <emphasis>undo information</emphasis>,
+    or <emphasis>undoinfo</emphasis> for short.
+  </para>
+
+  <sect1 id="undo-creation"><title>Creation and Storage</title>
+    <para>
+      In Skencil, undoinfo is stored basically in a list in the
+      document object (actually in an instance of the
+      <classname>UndoRedo</classname> class owned by the document).
+    </para>
+    <para>
+      A document method that changes the document either creates the
+      undoinfo itself or requires that the functions and methods it
+      calls return the undoinfo. The latter case is the most common, as
+      most operations do not change the state of the document object
+      itself but the state of a layer or a primitive.
+    </para>
+    <para>
+      In fact, most functions that are expected to return undoinfo do
+      not perform the operation themselves, but call other methods and
+      simply pass the undoinfo they get from those methods back to their
+      caller.
+    </para>
+    <para>
+      Consider for example the method <function>SetProperties</function>
+      of a group object. A group object has no graphics properties of
+      its own, but setting, e. g., the fill pattern of a group will set
+      the fill pattern of all of the group's children (the objects
+      contained in the group). So its <function>SetProperties</function>
+      method calls the <function>SetProperties</function> method of each
+      of its children and stores the undo info it gets in a list. The
+      undoinfo it returns to its caller will basically say: "to undo the
+      operation you must undo everything in this list".
+    </para>
+  </sect1>
+  <sect1 id="undo-representation">
+    <title>Representation of Undoinfo</title>
+    <para>
+      In Skencil, undoinfo is stored as a tuple whose first element is a
+      callable object. The rest of the tuple are the arguments that the
+      callable object must be called with to actually do the undo:
+    </para>
+    <para>
+      <!-- def --><!-- thtag -->Undoinfo (1)<!-- /thtag -->
+    </para>
+    <para>
+      A tuple <literal>t</literal> is a tuple of undoinfo of an
+      operation, iff the Python expression
+      "<literal>apply(t[0],&nbsp;t[1:])</literal>" will undo the
+      operation.
+    </para>
+    <!-- /def -->
+    <para>
+      Example: The <function>SetRadius</function> method of the regular
+      polygon plugin:
+<programlisting>
+def SetRadius(self, radius):
+    undo = self.SetRadius, self.radius	# create undoinfo
+    self.radius = radius	# set the instance variable
+    # ... update internal data here ...
+    return undo			# finally, return undo info
+</programlisting>
+    </para>
+    <para>
+      Undoing <function>SetRadius</function> simply means to set the
+      radius back to the old one, that is, one has to call the
+      method <function>SetRadius</function> of the same object again,
+      only this time with the old radius as parameter. Thus the undoinfo
+      returned is "<literal>(self.SetRadius, self.radius)</literal>"
+      which is executed before <literal>self.radius</literal>
+      changes. Note, that in this example the internal data get
+      recomputed automatically during the undo.
+    </para>
+    <para>
+      Closer examination reveals that performing this undo returns again
+      some undoinfo. This new undo info tells us how to undo the undo!
+      This is the information we need to perform the "redo" operation,
+      the <emphasis>redoinfo</emphasis>.
+    </para>
+    <para>
+      That means, that if we refine the requirements of the tuple of
+      undoinfo just a little bit, we get the "redo" for free:
+    </para>
+    <para>
+      <!-- def --><!-- thtag -->Undoinfo (2)<!-- /thtag -->
+    </para>
+    <para>
+      A tuple <literal>t</literal> is a tuple of undoinfo of an
+      operation, iff <literal>apply(t[0],&nbsp;t[1:])</literal> undoes
+      the operation and returns redoinfo.
+    </para>
+    <!-- /def -->
+    <para>
+      As it turns out, in Skencil at least, this additional demand is
+      trivial to meet.
+    </para>
+  </sect1>
+
+  <sect1 id="undo-combine"><title>Combining Undoinfo</title>
+    <para>
+      The <function>SetFillStyle</function> method of
+      the <classname>Group</classname> class has to return undoinfo that
+      describes how to undo several operations at once. To achieve this,
+      one can define a function <function>UndoList</function> as
+      follows:
+    </para>
+    <para>
+<programlisting>
+def UndoList(infos):
+    undoinfo = map(Undo, infos)
+    undoinfo.reverse()
+    return (UndoList, undoinfo)
+</programlisting>
+    </para>
+    <para>
+      Here, <function>Undo</function> is a function that executes a
+      single undoinfo (defined in <literal>undo.py</literal>).
+    </para>
+    <para>
+      Given a list "<literal>infos</literal>" of
+      undoinfos, <literal>Group.SetFillStyle</literal> can
+      return <literal>(UndoList, infos)</literal>.
+    </para>
+    <para>
+      Calling <function>reverse</function>
+      in <function>UndoList</function> is essential, as some operations
+      must be undone in exactly the reverse order in which they were
+      performed.
+    </para>
+    <para>
+      For more complex cases where several undoinfos have to be executed
+      in a certain order one can easily define similar functions. See
+      for instance <function>UndoAfter</function>
+      in <literal>undo.py</literal>
+    </para>
+  </sect1>
+
+  <sect1 id="undo-api"><title>The Undo API</title>
+    <para>
+      The module <literal>undo.py</literal> implements most functions
+      and classes necessary for handling undo in Skencil.
+    </para>
+    <para>
+      The format for a single unit of undoinfo is as described above
+      with a single extension: The first item in the tuple may be a
+      string, in which case the second item is callable and the items
+      [2:] are the arguments.  The string is meant to provide a short
+      description of the operation, such as "Create Rectangle", that may
+      be displayed as a menu item like "Undo Create Rectangle".
+      Therefore, this string is only necessary at the top level undo
+      info, which is currently always created by the document object.
+    </para>
+    <para>
+      The public interface to undo handling in Skencil consists of the
+      following functions and objects which are exported by the
+      package <literal>Sketch</literal>.
+    </para>
+
+    <sect2><title>Constructors</title>
+      <para>
+	In many cases, methods that change graphics objects or are
+	otherwise expected to return undoinfo, simply create a tuple of
+	the correct format.
+      </para>
+      <para>
+	Example: The SetRadius method of the regular polygon Plugin:
+<programlisting>
+def SetRadius(self, radius):
+    undo = self.SetRadius, self.radius  # create undoinfo
+    self.radius = radius    # set the instance variable
+    self.compute_poly()     # update the polygon
+    self._changed()	    # notify interested objects that self changed,
+			    # and force update of bounding rects, etc.
+    return undo             # finally, return undo info
+</programlisting>
+      </para>
+      <para>
+	For compound objects and methods that need to combine several
+	pieces of undo info there are two special constructors:
+      </para>
+      <variablelist>
+	<varlistentry id="function-CreateListUndo">
+	  <term><function>CreateListUndo(<parameter>infos</parameter>)</function></term>
+	  <listitem>
+	    <para>
+	      Return undo info that combines the undo infos
+	      in <parameter>infos</parameter>. <parameter>infos</parameter>
+	      is expected to be a sequence of undo infos listed in the
+	      order in which the actions were performed. When the
+	      operation is undone they are executed in reverse order.
+	    </para>
+	    <para>
+	      <function>CreateListUndo</function> tries to simplify
+	      <parameter>infos</parameter>. It builds a new list by
+	      iterating over the items of <parameter>infos</parameter>
+	      and inlining list undo info (as created by
+	      <function>CreateListUndo</function>) and by discarding
+	      empty undo info (represented by the
+	      <link linkend="NullUndo">NullUndo</link> object, see
+	      below). If the resulting list is empty return
+	      <literal>NullUndo</literal>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry id="function-CreateMultiUndo">
+	  <term><function>CreateMultiUndo(<parameter>info1</parameter>[, <parameter>info2</parameter>[, ...]])</function></term>
+	  <listitem>
+	    <para>
+	      Return undoinfo that undoes <parameter>info1</parameter>, 
+	      <parameter>info2</parameter>, etc., in reverse order.
+	      This is implemented via <function>CreateListUndo</function>.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+      <para>
+	Sometimes it happens that nothing has to be undone:
+      </para>
+      <variablelist>
+	<varlistentry id="NullUndo">
+	  <term><literal>NullUndo</literal></term>
+	  <listitem>
+	    <para>
+	      <literal>NullUndo</literal> is an undo info tuple that
+	      does nothing. If a method needs to return undo info, but
+	      for some reason nothing needs to be undone, this object
+	      should be returned.
+	    </para>
+	    <para>
+	      The functions that combine undo info treat it specially by
+	      removing it from the list of undo infos.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateCurve.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateCurve.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateEllipse.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateEllipse.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreatePoly.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreatePoly.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateRect.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/CreateRect.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Delete.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Delete.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Duplicate.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Duplicate.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/EditMode.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/EditMode.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/FlipHorizontal.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/FlipHorizontal.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/FlipVertical.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/FlipVertical.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/GridOn.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/GridOn.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Group.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Group.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Image.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Image.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniEyeClosed.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniEyeClosed.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniEyeOpen.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniEyeOpen.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniPrintOff.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniPrintOff.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniPrintOn.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MiniPrintOn.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveOneDown.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveOneDown.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveOneUp.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveOneUp.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveToBottom.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveToBottom.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveToTop.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/MoveToTop.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/NewDocument.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/NewDocument.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Open.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Open.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Redo.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Redo.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Save.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Save.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/SelectionMode.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/SelectionMode.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Text.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Text.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Undo.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Undo.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Ungroup.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Ungroup.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/Zoom.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/Zoom.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-left.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-left.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-right.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-right.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-up.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/arrow-up.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/bullet.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/bullet.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-conical.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-conical.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-linear.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-linear.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-radial.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/gradient-radial.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/layers.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/layers.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/selsize.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/selsize.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/seltrafo.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/seltrafo.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/sketch-logo.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/sketch-logo.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/textpath.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/textpath.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/textpathrot.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/textpathrot.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/Images/textpathskew.png
===================================================================
(Binary files differ)


Property changes on: skencil/branches/skencil-0.6/Doc/usersguide/Images/textpathskew.png
___________________________________________________________________
Name: svn:mime-type
   + image/png

Added: skencil/branches/skencil-0.6/Doc/usersguide/concepts.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/usersguide/concepts.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/usersguide/concepts.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,313 @@
+<chapter id="concepts"><title>Concepts</title>
+  <para>
+    To use the full potential of Skencil, it is important to know some
+    fundamental concepts, such as the various kinds of objects that make
+    up a drawing and their relationship. This section introduces these
+    concepts and the terminology needed to talk about them. This
+    terminology is also used in the menus, the status bar and other
+    parts of Skencil's user interface.
+  </para>
+
+  <sect1 id="concept-objecttypes"><title>Object Types</title>
+    <para>
+      Skencil has two fundamentally different kinds of
+      objects: <emphasis>primitives</emphasis> and <emphasis>compound
+      objects</emphasis>.
+    </para>
+
+    <sect2 id="concept-primitives"><title>Primitives</title>
+      <para>
+	Primitives are the basic building blocks of a drawing. They are
+	the ones that actually leave marks on the paper. Among this kind
+	of object are the <!-- link
+	linkend="objects-rectangle"-->rectangle, the <!-- link
+	linkend="objects-bezier"-->b&eacute;zier curve (which also
+	serves as a polygon or even as a straight line) and <!-- link
+	linkend="objects-text"-->text object.
+      </para>
+      <para>
+	Most primitives can have <emphasis>fill properties</emphasis>
+	and <emphasis>line properties</emphasis>.  Properties are
+	discussed in more
+	detail <link linkend="concept-properties">below</link>.
+      </para>
+    </sect2>
+
+    <sect2 id="concept-compound"><title>Compound Objects</title>
+      <para>
+	<emphasis>Compound objects</emphasis> group several primitives
+	or other compound objects together into one object. As such,
+	compound objects are invisible, but the primitives contained in
+	them are not. Therefore, compound objects are mainly interesting
+	for editing purposes.
+      </para>
+      <para>
+	It is often convenient to group the primitives that form a
+	distinctive part of a drawing together into
+	a <emphasis><!--link linkend="objects-group"-->group</emphasis>.
+	For instance, in the sample file flags.sk each of the flags is a
+	group of several primitives (often just a few rectangles as many
+	of the flags consist of some stripes).  Whenever you click on
+	one of the flags the whole group is selected not just the
+	rectangle you clicked on. Thus, most of the time the group is
+	manipulated as a whole (there are ways to work on the parts of a
+	group without ungrouping them first, but that is an advanced
+	topic).
+      </para>
+      <para>
+	There are some compound objects that behave in a special
+	way. The only example at the moment is the 
+	<!--link linkend="objects-blendgroup"-->BlendGroup.  This group
+	consists of two (or more) control objects and a number of
+	objects that are linear interpolations of the control
+	objects. When you edit one of the control objects all
+	interpolated objects are updated automatically.
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="concept-structure"><title>Structure of a Drawing</title>
+    <para>
+      A drawing consists of
+      <link linkend="concept-primitives">primitives</link> organized
+      in <link linkend="concept-compound">compound objects</link>. The
+      entire drawing itself, the <emphasis>document</emphasis>, is a
+      compound object that contains all the others.
+    </para>
+    <para>
+      When speaking about the objects contained in a compound object,
+      it's convenient to use the terms parent and child. The compound
+      object is the <emphasis>parent</emphasis> of the object it
+      contains, the contained objects are the compound object's 
+      <emphasis>children</emphasis>.
+    </para>
+    <para>
+      The objects are always drawn in the same order with the objects
+      drawn later obscuring the ones drawn earlier in case of overlap.
+      One might also say that some objects lie on top of each other and
+      that objects are drawn from bottom to top. This is the model we
+      usually use and the reason for menu items such as "Move To Top".
+    </para>
+    <para>
+      The order in which the objects are drawn changes only when the
+      user explicitly chooses a command that does so. Moving an object
+      around or changing the <link linkend="fill-properties">fill
+      properties</link> does not change this order.
+    </para>
+
+    <sect2><title>Layers</title>
+      <para>
+	The top-level compound object,
+	the <emphasis>document</emphasis>, is always divided into
+	<emphasis>layers</emphasis>. Layers are the only kind of
+	children a document can have and the parent of a layer will
+	always be a document.
+      </para>
+      <para>
+	This means that normal objects such as primitives or other types
+	of compound objects are never contained directly in the document
+	object but are always, directly or indirectly, contained in a
+	layer.
+      </para>
+      <para>
+	The layer is a special compound object with some special
+	attributes.  These attributes control whether its children are
+	visible or not.
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="concept-properties"><title>Properties</title>
+    <para>
+      Primitives can have <emphasis>properties</emphasis> that define
+      how they are drawn.
+    </para>
+    <para>
+      <link linkend="fill-properties">Fill properties</link> define how
+      the area defined by a primitive is drawn. Often this is just a
+      single color, but Skencil offers some more variety in the form
+      of <link linkend="patterns">patterns</link>.
+    </para>
+    <para>
+      <link linkend="line-properties">Line properties</link> define how
+      the lines of a primitive are drawn. The most important line
+      properties are probably color, width and dashes.
+    </para>
+    <para>
+      A primitive can usually have both, fill and line properties, but
+      there is no need for a primitive to have any properties. You might
+      just want to draw the outline but not the interior of a rectangle,
+      for instance.
+    </para>
+    <para>
+      Some types of primitives even cannot have fill or line
+      properties. An <!-- link linkend="objects-image"-->image object
+      for instance has neither fill nor line properties and a text
+      object doesn't have a line attribute (currently at least) but has
+      an attribute that defines its font.
+    </para>
+    <para>
+      As an advanced feature, Skencil offers 
+      <emphasis><link linkend="dynamic-properties">dynamic
+      properties</link></emphasis>. These allow you to define logical
+      properties touse instead of physical properties. Whenever you
+      change the definition of a dynamic attribute, all objects that use
+      that attribute are automatically updated. This is similar to
+      logical markup versus physical markup in LaTeX or SGML.
+    </para>
+
+    <sect2 id="fill-properties"><title>Fill Properties</title>
+      <para>
+	<emphasis>Fill Properties</emphasis> define how the area of a
+	primitive is filled.
+      </para>
+      <para>
+	The simplest case is just a single color that fills the area
+	uniformly.  Skencil offers more variety than that, though, in
+	the form of patterns.  A single color is then viewed as a very
+	simple type of pattern.
+      </para>
+      <para>
+	A primitive may have empty fill properties or, phrased
+	differently, no fill properties. In this case the area of the
+	primitive is not changed all and the objects below the primitive
+	are not obscured. Only its line is still drawn if it has line
+	properties.
+      </para>
+
+      <sect3 id="patterns"><title>Patterns</title>
+	<para>
+	  Skencil currently offers three kinds of
+	  pattern: <link linkend="patterns-solid">solid</link>,
+	  <link linkend="patterns-gradient">gradient</link> 
+	  and <link linkend="patterns-hatching">hatching pattern</link>.
+	</para>
+
+	<sect4 id="patterns-solid"><title>Solid</title>
+	  <para>
+	    This is the simplest pattern: Just a single color that
+	    uniformly fills the area.
+	  </para>
+	</sect4>
+
+	<sect4 id="patterns-gradient"><title>Gradient</title>
+	  <para>
+	    A gradient is the interpolation between two or more
+	    colors. A gradient pattern can be either linear, radial or
+	    conical.
+	  </para>
+	  <para>
+	    <informaltable>
+	      <tgroup cols="3">
+		<tbody>
+		  <row>
+		    <entry>
+		      <inlinegraphic fileref="Images/gradient-linear.png"/> 
+		    </entry>
+		    <entry>
+		      <inlinegraphic fileref="Images/gradient-conical.png"/> 
+		    </entry>
+		    <entry>
+		      <inlinegraphic fileref="Images/gradient-radial.png"/> 
+		    </entry>
+		  </row>
+		  <row>
+		    <entry>Linear Gradient</entry>
+		    <entry>Conical Gradient</entry>
+		    <entry>Radial Gradient</entry>
+		  </row>
+		</tbody>
+	      </tgroup>
+	    </informaltable>
+	  </para>
+	</sect4>
+
+	<sect4 id="patterns-hatching"><title>Hatching</title>
+	  <para></para>
+	</sect4>
+      </sect3>
+    </sect2>
+
+    <sect2 id="line-properties"><title>Line Properties</title>
+      <para>
+	A primitive may either have no line properties (which means that
+	only its area is filled if it has an area and nonempty fill
+	properties) or one of each of the following properties:
+	<variablelist>
+	  <varlistentry>
+	    <term>Pattern</term>
+	    <listitem>
+	      <para>
+		Currently, this can only be a solid color or the empty
+		pattern. An empty pattern means that no line is drawn.
+		Future extensions will probably allow arbitrary
+		patterns.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>Width</term>
+	    <listitem>
+	      <para>
+		The line width. A width of zero means that the thinnest
+		possible line is drawn.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>Dashes</term>
+	    <listitem>
+	      <para>
+		Whether to draw a solid line or a dashed line. A line
+		can have arbitrary dash patterns.
+	      </para>
+	      <para>
+		Dash patterns are represented by a list of numbers such
+		as "5.0, 2.0, 1.0, 2.0". This list describes a pattern
+		of a drawn segment of 5 units long, followed by a gap of
+		2 units, followed by a drawn segment of 1 unit and
+		finally a gap of 2 units, after which the sequence
+		starts over. The unit used is the line width.  This
+		means that a thicker line has longer dashes and gaps.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>Join Style</term>
+	    <listitem>
+	      <para>
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>Cap Style</term>
+	    <listitem>
+	      <para>
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>Arrow Heads</term>
+	    <listitem>
+	      <para>
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+    </sect2>
+
+    <sect2 id="font-property"><title>Font</title>
+      <para/>
+    </sect2>
+
+    <sect2 id="dynamic-properties"><title>Dynamic Properties</title>
+      <para/>
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/usersguide/configuration.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/usersguide/configuration.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/usersguide/configuration.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,209 @@
+<chapter id="configuration"><title>Configuration</title>
+
+  <sect1 id="config-fonts"><title>Fonts</title>
+    <para>
+      Fonts are a somewhat complex matter in Linux and X. Skencil's main
+      output format for printing is PostScript. Because of that, Skencil
+      identifies fonts with their PostScript names and must know how to
+      get the appropriate metrics (these tell Skencil how to place the
+      individual letters for instance) and it must know X's name for the
+      font (to be able to show the text on the screen appropriately).
+    </para>
+    <para>
+      The information Skencil needs to map the PostScript names to
+      metric-filenames (.afm-files) and X font names is stored in
+      .sfd-files.
+    </para>
+
+    <sect2><title>sfd-Files</title>
+      <para>
+	An sfd-file maps font names to the filenames of the afm-files
+	and to various font attributes like weight and width and to two
+	strings that are used to build the font name for X.
+      </para>
+      <para>
+	For example, the line concerning the Courier font in
+	<filename>Resources/Fontmetrics/std.sfd</filename> is:
+      </para>
+      <para>
+<programlisting>
+  Courier,Courier,Roman,-adobe-Courier-medium-r-normal,iso8859-1,pcrr
+</programlisting>
+      </para>
+      <para>
+	This tells Skencil that the metrics file is pcrr.afm and that
+	the first part of the X font name is
+	-adobe-Courier-medium-r-normal and its last part is
+	iso8859-1. The parts missing from the X font name describe the
+	size and transformation which are automatically filled in by
+	Skencil.  Skencil assumes that fonts can be arbitrarily scaled
+	and transformed.  (The XFree servers often used on Linux have
+	this capability; other servers on other platforms may not)
+      </para>
+      <para>
+	If the font is not installed in the server (either the X-server
+	or the font server), or if it is installed under a different
+	name, Skencil will not be able to display the text.
+      </para>
+      <para>
+	On start-up, Skencil reads all sfd-files it finds in the
+	directories listed in its font-path.
+      </para>
+    </sect2>
+
+    <sect2><title>The font-path</title>
+      <para>
+	Skencil maintains a list of directories where it searches for
+	font-related files like sfd-files and metrics.  Note that this
+	is a skencil-specific font-path and has nothing to do with X's
+	font-path.
+      </para>
+      <para>
+	By default (as of version 0.6.2) the font-path consists of the
+	directories <filename>Resources/Fontmetrics</filename> (relative
+	to where Skencil is installed),
+	<filename>/usr/X11R6/lib/X11/fonts/Type1</filename> and
+	<filename>/usr/share/ghostscript/fonts</filename>.
+      </para>
+      <para>
+	If you need to add directories or otherwise modify the
+	font-path, you can do so in Skencil's start-up file,
+	<filename>~/.sketch/userhooks.py</filename>, which is executed
+	by Skencil if it exists.  E.g. to add a directory to the
+	font-path you could put this code into 
+	<filename>userhooks.py</filename>:
+      </para>
+      <para>
+<programlisting>
+from Sketch import config
+
+config.font_path.append('/usr/local/share/fonts/bitstream')
+</programlisting>
+      </para>
+      <para>
+	In case you're wondering, Skencil was originally called
+	"Sketch", hence the name of the directory and the python module
+	in the above code snippet.
+      </para>
+    </sect2>
+
+    <sect2><title>Adding Fonts</title>
+      <para>
+	If you install new Type 1 fonts on your system for use with
+	Skencil, you have to make them available to X and you have to
+	create an sfd-file for Skencil.
+      </para>
+      <para>
+	The X-specific part of this is described in the usual man-pages,
+	like mkfontdir(1) (for the format of fonts.scale and
+	fonts.alias), xset(1) (for ways to change the fontpath at
+	runtime), Xserver(1) (for general information about the X
+	server, including fonts) and XF86Config(5) (for the default
+	configuration of XFree86).
+      </para>
+      <para>
+	To help with the installation, Skencil comes with a script,
+	mkfontdb.py, that can create both Skencil's sfd-files and X's
+	fonts.scale files.  In my opinion it's a good idea to generate
+	both files with mkfontdb.py to make sure the X-font-names in
+	both files match, because Skencil won't be able to display the
+	fonts otherwise.
+      </para>
+      <para>
+	The easiest way to use mkfontdb.py is:
+      </para>
+      <para>
+<programlisting>
+mkfontdb.py &lt;dir&gt;
+</programlisting>
+      </para>
+      <para>
+	When invoked like this, mkfontdb.py reads the afm-files in the
+	directory &lt;dir&gt; and creates the two files fonts.scale and
+	std.sfd in the current directory. For more information about the
+	command line options run 'mkfontdb.py -h'.
+      </para>
+      <para>
+	A good way to install new Type 1 fonts on a Linux-system, in my
+	opinion, is to put the files (pfb/pfa and afm) into a separate
+	directory, e.g. <filename>/usr/local/share/fonts</filename> and
+	create fonts.scale and an sfd file in that directory, and append
+	it to X's font-path and Skencil's font-path.
+      </para>
+    </sect2>
+
+    <sect2><title>Installing Ghostscript's Type1 fonts for X.</title>
+      <para>
+	To use the standard PostScript fonts, I recommend installing the
+	appropriate Type1 fonts from the Ghostscript distribution. They
+	are high quality fonts and distributed under the GPL.
+      </para>
+      <para>
+	The following suggestions and instructions are mainly for
+	XFree86. I don't know in how far these are applicable to other
+	X-servers or other platforms than Linux.
+      </para>
+      <para>
+	<emphasis>WARNING:</emphasis> The following instructions
+	describe how to change the configuration files of XFree86. Be
+	careful and make backup copies of the files you modify so you
+	can restore them if something goes wrong.
+      </para>
+      <para>
+	Copy or symlink the necessary files from Ghostscript's fonts
+	directory to /usr/X11R6/lib/X11/fonts/Type1/ (or wherever you
+	have X). On my system this can be done from the Type1 directory
+	with:
+      </para>
+      <para>
+<programlisting>
+$ ln -s /usr/share/ghostscript/fonts/*l.pfb .
+</programlisting>
+      </para>
+      <para>
+	Append the file <filename>Doc/fonts.scale</filename> to
+	<filename>Type1/fonts.scale</filename>.  The first line in the
+	latter file contains a single number. This is the number of
+	fonts listed in that file. Update that number to reflect the
+	changes (if there are no blank lines or comments, this number is
+	the number of lines minus 1)
+      </para>
+      <para>
+	You may have noticed that the font names used in
+	<filename>Doc/fonts.scale</filename> don't match the ones in
+	in <filename>std.sfd</filename>.  The reason for this is that
+	fonts you have just installed aren't the original adobe
+	PostScript fonts. Instead, they were contributed to ghostscript
+	by a company called URW. To use the standard PostScript names to
+	refer to these fonts, append
+	<filename>Doc/fonts.alias</filename> to
+	<filename>/usr/X11/lib/X11/fonts/misc/fonts.alias</filename>. There
+	is no number to update here.
+      </para>
+      <para>
+	The file <filename>Doc/fonts.scale</filename> lists
+	Ghostscript's fonts with their own name and not with the name of
+	the Adobe fonts they can replace. The
+	file <filename>Doc/fonts.alias</filename> maps the adobe names
+	to these real names.
+      </para>
+      <para>
+	Now you have to run mkfontdir(1) to update the font database:
+      </para>
+      <para>
+<programlisting>
+$ mkfontdir
+</programlisting>
+      </para>
+      <para>
+	If your X-server is running already you have to tell it to
+	reread the font databases with xset(1):
+      </para>
+      <para>
+<programlisting>
+$ xset fp rehash
+</programlisting>
+      </para>
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/usersguide/quickint.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/usersguide/quickint.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/usersguide/quickint.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,889 @@
+<chapter id="quickintro"><title>Quick Overview</title>
+  <para>
+    Since the User's Manual is quite incomplete and even a bit outdated,
+    here is a quick guide to the main features of Skencil.
+  </para>
+
+  <sect1 id="quick-mainwindow"><title>The Main Window</title>
+    <para>
+      There's not much to say about the main window, since many of its
+      components are fairly standard, like
+      the <link linkend="quick-menu">menu and toolbar</link>.
+    </para>
+    <para>
+      The status bar at the bottom indicates the
+      current <link linkend="quick-modes">mode</link>, the current
+      magnification factor, the current position of the mouse pointer
+      (you can change the unit from the context menu) and some
+      information about the current selection.
+    </para>
+    <para>
+      The palette just above the status bar allows you to easily assign
+      a fill color (click the left mouse button) or a line color (middle
+      mouse button). It also has an experimental Drag&amp;Drop facility:
+      click on a color and drag the color to the pattern window in the
+      fill dialog or onto a color button.
+    </para>
+  </sect1>
+
+  <sect1 id="quick-menu"><title>Toolbar/Menu</title>
+    <para>
+      Here's a brief description of some menu commands. If the command
+      is also available as a button in the toolbar, the icon is also
+      shown.
+    </para>
+    <para>
+      Some commands are accessible via key strokes. The key sequence is
+      indicated in the menu. The notation for key strokes is described
+      in the section on <link linkend="quick-keystrokenotation">key
+      strokes</link>.
+    </para>
+
+    <variablelist>
+      <varlistentry><term>File Operations</term>
+	<listitem>
+	  <variablelist>
+	    <varlistentry>
+	      <term><inlinegraphic fileref="Images/Open.png"/> Open</term>
+	      <listitem>
+		<para>
+		  Load a file into Skencil. Skencil tries to determine
+		  the file type automatically. It recognizes its own
+		  format, XFig, Adobe Illustrator, CMX (an exchange
+		  format defined by Corel), SVG (the upcoming
+		  web-standard for vector graphics) and WMF files.
+		</para>
+		<para>
+		  The filters for the 'foreign' formats are not
+		  complete.  The XFig filter for instance has some
+		  problems with the ordering of objects (because of the
+		  "depth" feature) and ignores arrow heads and dashing.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term>Insert Document</term>
+	      <listitem>
+		<para>
+		  Insert the contents of a document as a group into
+		  the current document.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term><inlinegraphic fileref="Images/Save.png"/> Save</term>
+	      <listitem>
+		<para>
+		  Save the current file. If it was read from an
+		  SK-file (Skencil's own format) it is saved under the
+		  same name after Skencil has created a backup
+		  file. If it was not read from a file or the file was
+		  not an SK-file, you have to specify a filename.  In
+		  addition to its own format, Skencil can save
+		  drawings in a variety of other file formats
+		  including Illustrator, WMF, CGM and SVG.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term>Save As PostScript</term>
+	      <listitem>
+		<para>
+		  Save the current drawing into a PostScript file. The
+		  file conforms to the EPS specification.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Edit Commands</term>
+	<listitem>
+	  <variablelist id="quick-modebuttons">
+	    <varlistentry>
+	      <term><inlinegraphic fileref="Images/EditMode.png"/>
+		Edit Mode</term>
+	      <term><inlinegraphic fileref="Images/SelectionMode.png"/> 
+		Selection Mode</term>
+	      <listitem>
+		<para>
+		  Switch to one of Skencil's major modes,
+		  <link linkend="quick-modes"><emphasis>edit
+		      mode</emphasis> and <emphasis>selection
+		      mode</emphasis></link>.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term><inlinegraphic fileref="Images/Undo.png"/> Undo</term>
+	      <term><inlinegraphic fileref="Images/Redo.png"/> Redo</term>
+	      <listitem>
+		<para>
+		  Skencil allows you to undo every operation and
+		  maintains a virtually unlimited undo history. If you
+		  really want to limit the undo history, you can do so
+		  from the
+		  <!--link linkend="dialogs-preferences"-->preferences
+		  dialog (File/Options...).
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/Delete.png"/> Delete
+	      </term>
+	      <listitem>
+		<para>
+		  Delete the current object.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/Duplicate.png"/> Duplicate
+	      </term>
+	      <listitem>
+		<para>
+		  Create a duplicate of the current object just above
+		  the current object and select it. The duplicate is
+		  slightly offset. You can set the duplication offset
+		  in the
+		  <!-- link
+		       linkend="dialogs-preferences"-->preferences dialog.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>Effects</term>
+	<listitem>
+	  <variablelist>
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/FlipHorizontal.png"/> 
+		Flip Horizontal
+	      </term>
+	      <term>
+		<inlinegraphic fileref="Images/FlipVertical.png"/> 
+		Flip Vertical
+	      </term>
+	      <listitem>
+		<para>
+		  Flip the current object(s) horizontally (vertically)
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term>Remove Transformation</term>
+	      <listitem>
+		<para>
+		  Some objects have an intrinsic geometry, like text
+		  objects, where the geometry is defined by the font
+		  and the font size, and bitmap images or EPS
+		  files. Any transformations (rotations, reflections,
+		  ...) later applied are stored in the object. Remove
+		  Transformation reverts these objects to their
+		  natural size and orientation.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Rearranging the Stacking Order</term>
+	<listitem>
+	  <variablelist>
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/MoveToTop.png"/> 
+		Move To Top
+	      </term>
+	      <listitem>
+		<para>
+		  Move the current object to the top of its layer.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/MoveToBottom.png"/> 
+		Move To Bottom
+	      </term>
+	      <listitem>
+		<para>
+		  Move the current object to the bottom of its layer.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/MoveOneUp.png"/> 
+		Move One Up
+	      </term>
+	      <listitem>
+		<para>
+		  Swap the current object and the next higher one.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/MoveOneDown.png"/> 
+		Move One Down
+	      </term>
+	      <listitem>
+		<para>
+		  Swap the current object and the next lower one.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Grouping Objects</term>
+	<listitem>
+	  <variablelist>
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/Group.png"/> Group
+	      </term>
+	      <listitem>
+		<para>
+		  Replace the currently selected objects with a group
+		  containing these objects and select it.
+		</para>
+		<para>
+		  Grouped objects are usually manipulated as a whole,
+		  but if needed, you can
+		  <link linkend="quick-selectsubobjects">select
+		    individual objects</link> with the mouse or
+		  keyboard.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/Ungroup.png"/> Ungroup
+	      </term>
+	      <listitem>
+		<para>
+		  Replace the currently selected group with the
+		  objects it contains and select them.
+		</para>
+		<para>
+		  While Group creates only normal groups, this command
+		  can ungroup other
+		  <link linkend="quick-specialgroups">special
+		    groups</link> such as
+		  <!--link linkend="objects-blendgroup"-->blend
+		  groups
+		  or <!-- link linkend="objects-maskgroup"-->mask
+		  groups as well.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Viewing Commands</term>
+	<listitem>
+	  <variablelist>
+	    <varlistentry>
+	      <term><inlinegraphic fileref="Images/Zoom.png"/> Zoom</term>
+	      <listitem>
+		<para>
+		  After invoking the zoom command you can either
+		  <itemizedlist>
+		    <listitem>
+		      <para>
+			Zoom into a region.
+		      </para>
+		      <para>
+			Click and drag &lt;Button1&gt; to indicate a
+			rectangular area in the main window. This area
+			will be magnified such that it just fits into
+			the window.
+		      </para>
+		    </listitem>
+		    <listitem>
+		      <para>
+			Double the magnification 
+		      </para>
+		      <para>
+			Just click (and don't drag) &lt;Button1&gt; on
+			a point in the main window. This point will be
+			centered and the magnification factor doubled.
+		      </para>
+		    </listitem>
+		  </itemizedlist>
+		</para>
+		<para>
+		  The maximum zoom factor is 1600%.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry><term>Arranging Objects</term>
+	<listitem>
+	  <variablelist>
+	    <varlistentry><term>Convert To Curve</term>
+	      <listitem>
+		<para>
+		  Convert the current object to a b&eacute;zier
+		  object.  This works for b&eacute;ziers :-),
+		  rectangles, ellipses and text. (To convert text to
+		  b&eacute;ziers, Skencil must have access to the
+		  appropriate type1 font file (either .pfa or pfb)).
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/GridOn.png"/> Snap To Grid
+	      </term>
+	      <listitem>
+		<para>
+		  Turns the grid on (or off, if it's on). If gridding
+		  is on, objects will snap to grid points when they
+		  are edited.
+		</para>
+		<para>
+		  This command doesn't affect the visibility of the
+		  grid.  The visibility is controlled via
+		  the <!--link linkend="dialogs-layers"-->layer
+		  dialog. The grid is a special layer which is
+		  usually called "Grid".
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term>Snap To Objects</term>
+	      <listitem>
+		<para>
+		  If snapping to objects is active, dragged objects
+		  snap to the nearest special point of any other
+		  visible object. Special points are the nodes of a
+		  <!-- link linkend="objects-bezier"-->b&eacute;zier
+		  curveor the corners of a <!-- link
+						linkend="objects-rectangle"-->rectangle.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry><term>Snap To Guide Lines</term>
+	      <listitem>
+		<para>
+		  If snapping to guide lines is active, dragged
+		  objects snap to the nearest guide line or other
+		  objects on the <!-- link
+				      linkend="objects-guidelayer"-->guide layer.
+		</para>
+		<para>
+		  This command doesn't affect the visibility of the
+		  guide lines. The visibility can be controlled from
+		  the <!--link linkend="dialogs-layers"-->layer
+		  dialog. The guide layer is usually called
+		  "Guide Lines".
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry id="quick-create"><term>Creating Objects</term>
+	<listitem>
+	  <variablelist>
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/CreateRect.png"/> Rectangle
+	      </term>
+	      <listitem>
+		<para>
+		  Create a Rectangle by pressing the left mouse button
+		  and dragging the mouse. One corner of the newly
+		  created rectangle is where the button was pressed,
+		  the other where it was released. Holding
+		  &lt;Ctrl&gt; while dragging creates a square,
+		  holding &lt;Shift&gt; creates a rectangle or square
+		  centered on the starting point.
+		</para>
+		<para>
+		  In <link linkend="quick-modes"><emphasis>edit
+		      mode</emphasis></link>, you can drag the corners
+		  of a rectangle to create rounded corners.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/CreateEllipse.png"/>
+		Ellipse
+	      </term>
+	      <listitem>
+		<para>
+		  Create an Ellipse by pressing the left mouse button
+		  and dragging the mouse. Holding &lt;Ctrl&gt; while
+		  dragging creates a circle, holding &lt;Shift&gt;
+		  creates a ellipse or circle centered on the starting
+		  point.
+		</para>
+		<para>
+		  In <link linkend="quick-modes"><emphasis>edit
+		      mode</emphasis></link>, you can drag the handle
+		  of an ellipse to create arcs.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/CreateCurve.png"/> 
+		B&eacute;zier Curve
+	      </term>
+	      <listitem>
+		<para>
+		  Create a B&eacute;zier curve. This requires at least
+		  two click-drag-release cycles. The first cycle
+		  defines the start point of the curve and its
+		  tangent. The next cycles define the rest of the
+		  points and tangents in the same fashion. Click
+		  &lt;Button2&gt; or press Space to finish.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/CreatePoly.png"/> Polygon
+	      </term>
+	      <listitem>
+		<para>
+		  Create a polygon. The first click-drag-release cycle
+		  defines the first line segment. The next cycles
+		  define the rest of the segments. Click
+		  &lt;Button2&gt; or press Space to finish. The object
+		  created is actually a B&eacute;zier curve consisting
+		  only of straight lines.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term><inlinegraphic fileref="Images/Text.png"/> Text</term>
+	      <listitem>
+		<para>
+		  Create a text object by clicking where you want the
+		  text to be and type. If you click and drag you
+		  create rotated text.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<inlinegraphic fileref="Images/Image.png"/> 
+		Bitmap/EPS images
+	      </term>
+	      <listitem>
+		<para>
+		  This command opens a dialog box to let you specify
+		  the image file. After selecting the file, place the
+		  image on the page by clicking at the desired
+		  position. A dashed rectangle indicates the size and
+		  position.
+		</para>
+		<para>
+		  Skencil can load any image the Python Imaging
+		  Library (PIL) can read. EPS files are not read by
+		  the PIL, they are imported and printed
+		  unmodified. Skencil uses Ghostscript to render a
+		  preview image, so an EPS file looks like an ordinary
+		  bitmap image on the screen.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </sect1>
+
+  <sect1 id="quick-mousekbd"><title>Mouse and keyboard</title>
+
+    <sect2 id="quick-keystrokenotation">
+      <title>Notation of key strokes</title>
+      <para>
+	The notation of key strokes used in this manual and in the
+	menus is very similar to the one used in GNU-Emacs:
+      </para>
+
+      <informaltable>
+	<tgroup cols="2">
+	  <thead>
+	    <row><entry>Notation</entry><entry>Meaning</entry></row>
+	  </thead>
+	  <tbody>
+	    <row><entry>Space</entry><entry>space</entry></row>
+	    <row>
+	      <entry>Right, Left, Up, Down</entry>
+	      <entry>The cursor keys</entry>
+	    </row>
+	    <row>
+	      <entry>Prev, Next, Home, End</entry>
+	    </row>
+	    <row>
+	      <entry>&lt;Shift&gt; &lt;Ctrl&gt; &lt;Meta&gt;</entry>
+	      <entry>
+		The modifier keys Shift Control and Meta (which may be
+		the Alt key)
+	      </entry>
+	    </row>
+	    <row>
+	      <entry>&lt;Button1&gt;</entry>
+	      <entry>The left mouse button</entry>
+	    </row>
+	    <row>
+	      <entry>&lt;Button2&gt;</entry>
+	      <entry>The middle mouse button</entry>
+	    </row>
+	    <row>
+	      <entry>&lt;Button3&gt;</entry>
+	      <entry>The left mouse button</entry>
+	    </row>
+	    <row>
+	      <entry>C-d</entry>
+	      <entry>
+		&lt;Ctrl&gt; and lowercase "d", similarly S- for
+		&lt;Shift&gt; and M- for &lt;Meta&gt;
+	      </entry>
+	    </row>
+	  </tbody>
+	</tgroup>
+      </informaltable>
+
+      <para>
+	Unless otherwise noted, "Clicking" means a click with the left
+	mouse button.
+      </para>
+    </sect2>
+
+    <sect2 id="quick-modes"><title>Modes</title>
+      <para>
+	Most of the time, Skencil is on one of two major
+	modes: <emphasis>Selection Mode</emphasis> or <emphasis>Edit
+	  Mode</emphasis>. You can switch between these modes with Space
+	or the <link linkend="quick-modebuttons">toolbar</link>.
+      </para>
+      <para>
+	In selection mode, you can select objects
+	and <link linkend="quick-transform">move and transform</link>
+	them as a whole with the mouse.  Most commands operate on the
+	currently selected objects (see
+	also <link linkend="quick-mousekbd">Mouse and
+	  keyboard</link>). In edit mode, you can edit individual
+	aspects of an object, like the nodes of
+	a <!-- link linkend="objects-bezier"-->b&eacute;zier curve or
+	the text of a <!-- link linkend="objects-text"-->text object.
+      </para>
+      <para>
+	Sometimes, Skencil is in a temporary minor mode, for instance
+	when selecting a region for zooming, or
+	when <link linkend="quick-create">creating an object</link>.
+      </para>
+    </sect2>
+
+    <sect2><title>Selecting Objects</title>
+      <para>
+	To select...
+
+	<variablelist>
+	  <varlistentry>
+	    <term>...a single object:</term>
+	    <listitem>
+	      <para>
+		Click on it. It will become the new currently selected
+		object.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>...multiple objects:</term>
+	    <listitem>
+	      <para>
+		Click S-&lt;Button1&gt; on an object to add it to the
+		selected objects.
+	      </para>
+	      <para>
+		Click C-&lt;Button1&gt; on an object to deselect it.
+	      </para>
+	      <para>
+		You can also select multiple objects by
+		rubberbanding. Click and drag &lt;Button1&gt;, all
+		objects in the dashed rectangle will be
+		selected. Again, holding &lt;Shift&gt; or &lt;Ctrl&gt;
+		add or deselect the indicated objects.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry id="quick-selectsubobjects">
+	    <term>...an object in a group:</term>
+	    <listitem>
+	      <orderedlist>
+		<listitem>
+		  <para>Select the group.</para>
+		</listitem>
+		<listitem>
+		  <para>
+		    Click C-S-&lt;Button1&gt; on the sub-object.
+		  </para>
+		</listitem>
+	      </orderedlist>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+
+      <para>
+	You can also use the cursor keys to navigate through the
+	object hierarchy:
+      </para>
+      <para>
+	<informaltable>
+	  <tgroup cols="2">
+	    <tbody>
+	      <row>
+		<entry>M-Right</entry>
+		<entry>Select the next (higher) object</entry>
+	      </row>
+	      <row>
+		<entry>M-Left</entry>
+		<entry>Select the previous (next lower) object</entry>
+	      </row>
+	      <row>
+		<entry>M-Down</entry>
+		<entry>
+		  Select the first child (sub-object) of the current
+		  object
+		</entry>
+	      </row>
+	      <row>
+		<entry>M-Up</entry>
+		<entry>
+		  Select the parent of the current object (if the
+		  current object is a sub-object)
+		</entry>
+	      </row>
+	    </tbody>
+	  </tgroup>
+	</informaltable>
+      </para>
+    </sect2>
+
+    <sect2 id="quick-transform"><title>Manipulating Objects</title>
+      <para>
+	If you're in selection mode and you've just selected an
+	object, Skencil indicates this with 8
+	rectangular <emphasis>handles</emphasis> around the object:
+      </para>
+      <para>
+	<inlinegraphic fileref="Images/selsize.png"/>
+      </para>
+      <para>
+	Clicking on a handle and dragging it will resize the
+	object. Just clicking on the object and dragging the object,
+	moves the object.  Holding &lt;Ctrl&gt; while dragging
+	constrains the resize and move operations.
+      </para>
+      <para>
+	A single click (and no drag) on the object switches to
+	transformation mode:
+      </para>
+      <para>
+	<inlinegraphic fileref="Images/seltrafo.png"/>
+      </para>
+      <para>
+	Another single click switches back to the resize mode.
+      </para>
+    </sect2>
+  </sect1>
+
+
+  <sect1 id="quick-objecttypes"><title>Object Types</title>
+
+    <sect2 id="quick-specialgroups"><title>Special Effects</title>
+      <para>
+	Skencil currently has three special effects groups:
+      </para>
+
+      <sect3>
+	<title>Blend Groups</title>
+	<para>
+	  To create a blend group:
+	  <orderedlist>
+	    <listitem>
+	      <para>select the two objects you want to blend</para>
+	    </listitem>
+	    <listitem>
+	      <para>open the blend panel (Effects/Blend...)</para>
+	    </listitem>
+	    <listitem>
+	      <para>set the number of steps</para>
+	    </listitem>
+	    <listitem>
+	      <para>and press the Apply-button</para>
+	    </listitem>
+	  </orderedlist>
+	</para>
+	<para>
+	  If you later edit one of the control objects, the blend
+	  group will be updated automatically.
+	</para>
+	<para>
+	  For optimal results, the objects should have a similar
+	  structure: b&eacute;zier curves with the same number of
+	  nodes, groups with the same number of sub objects, etc.
+	</para>
+	<para>
+	  To create a blend group with more than two control objects,
+	  select the start or end object of an existing blend group
+	  and the new control object and press apply in the blend
+	  panel.
+	</para>
+	<para>
+	  It's a little awkward to change the number of steps in an
+	  interpolation with the blend panel if the blend group has
+	  more than two control objects (and therefore more than one
+	  interpolation). In that case, you have to select the
+	  interpolation itself by holding &lt;Ctrl&gt; and
+	  &lt;Shift&gt; while clicking on it.
+	</para>
+      </sect3>
+
+      <sect3><title>Mask Groups</title>
+	<para>
+	  A mask group is a special group where one object defines a
+	  clip mask for the rest of the group. If this object is
+	  e.g. an ellipse, all that is drawn of the other objects are
+	  the parts that overlap the ellipse.
+	</para>
+	<para>
+	  To create a mask group
+	  <orderedlist>
+	    <listitem>
+	      <para>Select the mask.</para>
+	    </listitem>
+	    <listitem>
+	      <para>Invoke Arrange/Move To Top</para>
+	    </listitem>
+	    <listitem>
+	      <para>Add the other objects to the selection.</para>
+	    </listitem>
+	    <listitem>
+	      <para>
+		Create the mask group via the menu Effects/Create Mask
+		Group
+	      </para>
+	    </listitem>
+	  </orderedlist>
+	</para>
+	<para>
+	  Note: The <emphasis>topmost</emphasis> of the selected
+	  objects will become the mask, regardless of the order in
+	  which you select them. (In versions prior to 0.5.3 it was
+	  the lowest object)
+	</para>
+	<para>
+	  If you want to edit the mask you can select it via the
+	  context menu (&lt;Button3&gt;).
+	</para>
+	<para>
+	  The mask has to be
+	  a <!-- link linkend="objects-rectangle" -->rectangle,
+	  an <!-- link linkend="objects-ellipse" -->ellipse,
+	  a <!-- link linkend="objects-bezier" -->b&eacute;zier curve
+	  or an <!-- link linkend="objects-image" -->image.
+	</para>
+      </sect3>
+
+      <sect3><title>Text on a Curve</title>
+	<para>
+	  In Skencil, you can align text along a curve:
+	  <informaltable frame="none">
+	    <tgroup cols="2">
+	      <colspec colname="1" />
+	      <colspec colname="2" />
+	      <tbody>
+		<row>
+		  <entry>
+		    <inlinegraphic fileref="Images/textpathrot.png"/>
+		  </entry>
+		  <entry>
+		    <inlinegraphic fileref="Images/textpathskew.png"/> 
+		  </entry>
+		</row>
+		<row>
+		  <entry namest="1" nameend="2">
+		    Text on a path can have either rotated letters
+		    (left) or skewed letters (right).
+		  </entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+
+	<para>
+	  To create this
+	  <orderedlist>
+	    <listitem>
+	      <para>
+		Select a text object and a curve
+		(a <!-- link linkend="objects-bezier"-->b&eacute;zier
+		curve, an
+		<!-- link linkend="objects-ellipse"-->ellipse or
+		a <!-- link linkend="objects-rectangle"-->rectangle)
+	      </para>
+	    </listitem>
+
+	    <listitem>
+	      <para>Choose Effects/Create Path Text from the menu.</para>
+	    </listitem>
+	  </orderedlist>
+	</para>
+
+	<para>
+	  To edit either the text object or the curve individually,
+	  select it via the context menu if the whole group is
+	  selected.
+	</para>
+	<para>
+	  This way, you can hide the curves by assigning empty fill
+	  and line patterns.
+	</para>
+      </sect3>
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/usersguide/scripting.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/usersguide/scripting.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/usersguide/scripting.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,923 @@
+<chapter id="script"><title>User Scripting</title>
+  <para>
+    Skencil lets you write scripts to automate tasks and add new
+    functionality. The programming language for these scripts is Python,
+    an interpreted, object oriented language.
+  </para>
+  <para>
+    This chapter explains how to write such scripts and how they end up
+    in the Scripts menu, so that you can invoke them. I'll assume that
+    you already know how to program in Python. If you don't know that
+    yet, have a look at <ulink url="http://www.python.org">Python's
+    web-page</ulink> for online documentation.
+  </para>
+  <para>
+    Some parts of this feature are still experimental and may change
+    substantially in newer releases, so watch the NEWS file and the
+    sample scripts in case this documentation is outdated.
+  </para>
+  <para>
+    Skencil itself is implemented almost completely in Python, so your
+    scripts have access to all areas of the application, including
+    internal data structures. This makes user scripts very powerful, but
+    it also means that they can mess around with Skencil's internals
+    with the result that Skencil might not be able to undo the changes
+    or even save the document. But don't worry, evading the traps is not
+    that difficult (I think) and this chapter tries to explain how to
+    avoid them.
+  </para>
+
+  <sect1 id="script-intro"><title>Introduction</title>
+
+    <sect2><title>Safe and Advanced Scripts</title>
+      <para>
+	As mentioned above user scripts in Skencil can cause data
+	loss. To make things easier for you in this regard, Skencil
+	supports two kinds of user scripts, <emphasis>safe
+	scripts</emphasis> and <emphasis>advanced scripts</emphasis>.
+      </para>
+      <para id="safe-script">
+	Safe scripts take care of undo handling for you and they
+	restrict what your script can actually do to keep you from
+	harm. The disadvantage of this approach is that you can't do
+	everything you might want to do with a safe script.
+      </para>
+      <para id="advanced-script">
+	The advanced script has no restrictions but it has to take care
+	of undo handling itself, which isn't difficult but has to be
+	done with care.
+      </para>
+    </sect2>
+    
+    <sect2><title>The Script Function</title>
+      <para>
+	Regardless of whether a script is a safe script or an advanced
+	script it is just a Python function that accepts a context
+	object as parameter.  The context is an instance with three
+	attributes:
+      </para>
+
+      <variablelist>
+	<varlistentry><term><literal>document</literal></term>
+	  <listitem>
+	    <para>The document for which the script was called.</para>
+	    <para>
+	      The document contains all objects that make up the drawing
+	      and it manages the selection.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><literal>application</literal></term>
+	  <listitem>
+	    <para>The application object.</para>
+	    <para>
+	      The application object has methods for setting and
+	      retrieving the application's clipboard and to pop-up
+	      message boxes and file dialogs.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><literal>main_window</literal></term>
+	  <listitem>
+	    <para>
+	      The top-level window containing the canvas widget that
+	      shows the current drawing. It has methods for loading and
+	      saving documents, among others.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+
+      <para>
+	A simple 'hello world' type script might look like this:
+
+<programlisting>
+def hello_world(context):
+    context.application.MessageBox(title = "My Script", 
+                                   message = "Hello World!")
+</programlisting>
+      </para>
+    </sect2>
+
+    <sect2><title>Registering Scripts</title>
+      <para>
+	The Script menu just shows all the scripts in
+	the <emphasis>script registry</emphasis>, so to have a script
+	appear in that menu, you have to put it into the registry.
+      </para>
+
+      <para>
+	The registry is managed in a subpackage Scripting of the
+	toplevel package Sketch (The name of the package is a leftover
+	from the time Skencil was called "Sketch", in case you're
+	wondering).  The function needed here
+	is <function>AddFunction</function> and is called like this:
+      </para>
+
+      <para>
+	<function>AddFunction(<parameter>name</parameter>, <parameter>title</parameter>, <parameter>function</parameter>)</function>
+      </para>
+
+      <variablelist>
+	<varlistentry><term><parameter>name</parameter></term>
+	  <listitem>
+	    <para>
+	      is a name for that script. This name should be unique, as
+	      the scripts are identified in the registry by this
+	      name. It doesn't have to be the same as the function name.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><parameter>title</parameter></term>
+	  <listitem>
+	    <para>The text of the menu entry.</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><parameter>function</parameter></term>
+	  <listitem>
+	    <para>
+	      the function that implements the script, e.g. hello_world
+	      above.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+
+      <para>
+	There are a few optional keyword arguments, one of which is
+	type.  The value of script_type must be either SafeScript (the
+	default) or AdvancedScript. Both values are defined in the
+	Scripting subpackage. The registry functions are covered in more
+	detail in the <link linkend="script-registry">script
+	registry</link> section.
+      </para>
+      <para>
+	As an example, registering the hello world script might look
+	like this:
+<programlisting>
+import Sketch.Scripting
+Sketch.Scripting.AddFunction("hello_world", "Hello World", hello_world)
+</programlisting>
+      </para>
+      <para>
+	First we import the package Sketch.Scripting and then we call
+	the AddFunction function.
+      </para>
+      <para>
+	For more information about the organization of Skencil's code
+	have a look at the <link linkend="script-skencilapi">API
+	overview</link>.
+      </para>
+    </sect2>
+
+    <sect2><title>The Startup Script</title>
+      <para>
+	The only thing left to do is to get some user supplied code to
+	run on startup, so it can define and register scripts. To do
+	that just create a file <filename>userhooks.py</filename> in the
+	directory <filename>~/.sketch/</filename>. If such a file exists
+	it is automatically executed when Skencil starts. More
+	precisely, the directory <filename>~/.sketch/</filename> is
+	inserted at the front of Python's modules search path and a
+	module <filename>userhooks.py</filename> is imported.
+      </para>
+      <para>
+	You can put arbitrary code in there not just scripts, but one
+	way to implement and register our hello_world script would be a
+	<filename>userhooks.py</filename> file like this:
+      </para>
+      <para>
+<programlisting>
+# example for ~/.sketch/userhooks.py
+
+def hello_world(context):
+context.application.MessageBox(title = "My Script", 
+                               message = "Hello World!")
+
+# register script
+import Sketch.Scripting
+Sketch.Scripting.AddFunction("hello_world", "Hello World", hello_world)
+</programlisting>
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="script-examplescripts"><title>The Example Scripts</title>
+    <para>
+      Skencil comes with a few example scripts in
+      the <filename>Scripts/</filename> directory. This directory works
+      as a Python package, so to import a script,
+      say <filename>abut_horizontal.py</filename> just execute import
+      Script.abut_horizontal in <filename>userhooks.py</filename>.
+    </para>
+    <para>
+      Each of the modules in <filename>Script/</filename> contains one
+      script and registers this script when it is imported.
+    </para>
+  </sect1>
+
+  <sect1 id="script-registry"><title>The Script Registry</title>
+    <para>
+      The script registry contains all user scripts and its contents are
+      used to create the Script menu. The script registry is implemented
+      in the (sub-)package Sketch.Scripting. Because the Scripting
+      package is not automatically imported by the Sketch package, you
+      have to import Sketch.Scripting explicitly before accessing the
+      registry functions.
+    </para>
+    <para>
+      Functions in the registry package:
+    </para>
+
+    <variablelist>
+      <varlistentry id="function-AddFunction">
+	<term>
+	  <function>AddFunction(<parameter>name</parameter>, <parameter>title</parameter>, <parameter>function</parameter>[, <parameter>kwargs</parameter>])</function>
+	</term>
+	<listitem>
+	  <para>
+	    Add the function function to the registry under the name
+	    name. name is used internally to identify the script and
+	    should be unique.
+	  </para>
+	  <para>
+	    The parameter <parameter>title</parameter> defines the text
+	    for the menu-entry.
+	  </para>
+	  <para>
+	    The function accepts these optional keyword arguments:
+	  </para>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>
+		<parameter>script_type</parameter> = <parameter>type</parameter>
+	      </term>
+	      <listitem>
+		<para>
+		  The type of the script. It can be either
+		  <literal>SafeScript</literal>
+		  or <literal>AdvancedScript</literal>. Both values
+		  are defined in the <literal>Scripting</literal>
+		  package. The default is
+		  <literal>SafeScript</literal>.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<parameter>menu</parameter> = <parameter>menu_spec</parameter>
+	      </term>
+	      <listitem>
+		<para>
+		  Defines the sub-menu the script should appear
+		  in. The <parameter>menu_spec</parameter> can be either
+		  a string or a tuple of strings. Each string is the
+		  title of a sub-menu.
+		</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>
+		<parameter>args</parameter> = <parameter>argtuple</parameter>
+	      </term>
+	      <listitem>
+		<para>
+		  Defines additional positional parameters passed to the
+		  script function after the context parameter.
+		  <parameter>argtuple</parameter> must be a tuple
+		  containing these arguments. It defaults to the empty
+		  tuple.
+		</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>
+      Example: Registering the <function>abut_horizontal</function>
+      script in the sub-menu "Arrange"
+    </para>
+    <para>
+<programlisting>
+Sketch.Scripting.AddFunction('abut_horizontal', 'Abut Horizontal',
+                             abut_horizontal, menu = 'Arrange')
+</programlisting>
+    </para>
+  </sect1>
+
+  <sect1 id="script-skencilapi"><title>Skencil's API</title>
+    <para>
+      If you want to write scripts for Skencil you have to know how to
+      access the objects in the document and how to manipulate
+      them. This section gives a brief introduction to the structure of
+      Skencil's modules and objects from script author's point of view.
+    </para>
+    <para>
+      A more detailed description of Skencil's internals can be found in
+      the Developer's Guide.
+    </para>
+
+    <sect2><title>Module Structure</title>
+      <para>
+	Skencil's code is organized in a hierarchy of packages. The
+	top-level package that contains all of Skencil's core components
+	is <literal>Sketch</literal>.  It directly contains references
+	to most of Skencil's graphics classes and functions.
+      </para>
+    </sect2>
+
+    <sect2><title>Conventions</title>
+      <para>
+	Skencil's objects have methods that are meant for public use and
+	methods for internal purposes. Naturally, a script is expected
+	to only use the public interface. Since Python has no builtin
+	distinction between public and private/protected methods we have
+	to rely on conventions.
+      </para>
+      <para>
+	Skencil uses a naming convention for this. Methods with
+	capitalized names, e.g. <function>SetRadius</function>, are
+	public methods and Methods with lowercase name,
+	e.g. <function>set_radius</function>, are protected.
+      </para>
+    </sect2>
+
+    <sect2><title>Undo Handling</title>
+      <para>
+	As pointed out above, advanced scripts have to deal with undo
+	information. This isn't difficult, but you have to know which
+	methods return undo information and what you have to do with it.
+      </para>
+      <para>
+	You only have to deal with undo info if you modify an object
+	that is part of a document. These objects include instances of
+	classes derived from <classname>GraphicsObject</classname>
+	(<!-- href ID=devguide at ClassHierararchy -->class hierarchy) and
+	the objects that define the properties of a graphics object,
+	like patterns.
+      </para>
+      <para>
+	All methods that modify such an object return an undo info
+	object. What this object looks like is irrelevant here, all you
+	need to know for now is that you have to pass it immediately on
+	to the document method <function>AddUndo</function>.
+      </para>
+      <para>
+	A typical example:
+<programlisting>
+context.document.AddUndo(object.Translate(offset))
+</programlisting>
+      </para>
+      <para>
+	The <!-- methref --><function>Translate</function> method
+	translates an object by offset, a
+	<!-- href ID=devguide at PointObject -->point object that stands
+	for a 2D-vector.
+      </para>
+      <para>
+	There are some exceptions to the rule that methods that modify
+	the document return undo info.
+      </para>
+      <para>
+	Firstly, the document methods that modify the selection, that
+	is, that modify which objects are selected not the selected
+	objects themselves, don't return undo info because changing the
+	selection is not considered changing the document.
+      </para>
+      <para>
+	Secondly, public document methods that modify the selected
+	objects themselves already take care of undo info
+	themselves. The reason for this is that they are called directly
+	as a result of a menu command, button or key-press event.
+      </para>
+      <para>
+	For more information about undo information in Skencil, have a
+	look at the <!-- href ID=devguide at UndoMechanism -->corresponding
+	section in the Developer's Guide.
+      </para>
+    </sect2>
+
+    <sect2><title>Further Information</title>
+      <para>
+	The example scripts in the <filename>Script</filename> directory
+	contain extensive comments on what's going on.
+      </para>
+      <para>
+	The Developer's Guide covers Skencil's internals in more
+	detail. Although it's incomplete it already contains a lot of
+	information about the structure of Skencil's sources, the class
+	hierarchy and some of the base classes, coordinate systems,
+	plugins and more.
+      </para>
+      <para>
+	And, of course: Use The Source, Luke!
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="script-tasks"><title>Common Tasks</title>
+    <para>
+      Unless otherwise noted, all functions and classes mentioned here
+      are directly accessible from the Sketch package. E.g. the
+      function <function>CreateRGBColor</function> is accessible either
+      with:
+<programlisting>
+import Sketch
+
+blue = Sketch.CreateRGBColor(0, 0, 1)
+</programlisting>
+    </para>
+    <para>
+      or
+    </para>
+    <para>
+<programlisting>
+from Sketch import CreateRGBColor
+
+blue = CreateRGBColor(0, 0, 1)
+</programlisting>
+    </para>
+
+    <sect2><title>Creating Objects</title>
+      <para>
+	Creating new objects for a drawing, usually takes three steps:
+      </para>
+      <orderedlist>
+	<listitem>
+	  <para>
+	    Create the object. This is described in this section.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    Set graphics properties like fill color or line width.  This
+	    is described
+	    <link linkend="script:changingproperties">below</link>.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>Insert the object into the document</para>
+	</listitem>
+      </orderedlist>
+      
+      <sect3><title>Primitives</title>
+	<sect4><title>Rectangles</title>
+	  <para>
+	    <function>Rectangle(<parameter>trafo</parameter>)</function>
+	  </para>
+	  <para>
+	    This function creates a rectangle object described by
+	    <parameter>trafo</parameter>.  <parameter>trafo</parameter>
+	    is an affine transformation (represented by a <!-- href
+	    ID=devguide at TrafoObject -->a transformation object that
+	    transforms the unit square into the desired rectangle.
+	  </para>
+	  <para>
+	    Transformation objects are created by the
+	    functions <function>Trafo</function>, <function>Scale</function>,
+	    <function>Rotation</function>
+	    and <function>Translation</function>.
+	  </para>
+	  <para>
+	    In the most common case where you want to create a rectangle
+	    with a specific width and height at a specific position (x, y)
+	    (the position of the lower left corner of the rectangle)
+	    and edges parallel to the edges of the page, you could
+	    create the rectangle like this:
+	  </para>
+	  <para>
+<programlisting>
+Rectangle(Trafo(width, 0, 0, height, x, y))
+</programlisting>
+	  </para>
+	  <para>
+	    or like this
+	  </para>
+	  <para>
+<programlisting>
+Rectangle(Translation(x, y)(Scale(width, height)))
+</programlisting>
+	  </para>
+	</sect4>
+
+	<sect4><title>Lines and Curves</title>
+	  <para>
+	    All line and curve-objects in Skencil are instances of the
+	    class <!-- classref --><classname>PolyBezier</classname>.
+	    Each <classname>PolyBezier</classname> object consists of
+	    one or more paths with each path consisting of one or more
+	    line or b&eacute;zier segments.
+	  </para>
+	  <para>
+	    To create a <classname>PolyBezier</classname> object you
+	    have to first create the paths and then
+	    the <classname>PolyBezier</classname> instance.  A path is
+	    created by starting with an empty path returned by the
+	    function <!-- funcref --><function>CreatePath</function> and
+	    then appending line- and curve-segments to construct the
+	    path.  How paths are constructed is covered in detail in
+	    the <!-- href ID=devguide at CurveObject -->corresponding
+	    section in the developer's guide.
+	  </para>
+	  <para>
+	    Once you have constructed your paths, you create the
+	    <classname>PolyBezier</classname> instance with:
+	  </para>
+	  <para>
+	    <literal>PolyBezier(<parameter>path_tuple</parameter>)</literal>
+	  </para>
+	  <para>
+	    The argument <parameter>path_tuple</parameter> must be a
+	    tuple of paths. If you have just one path path, you can use
+	    the expression <literal>(path,)</literal>.
+	  </para>
+	  <para>
+	    For an example, see the sample script
+	    <filename>create_star.py</filename>.
+	  </para>
+	</sect4>
+
+	<sect4><title>Text</title>
+	  <para>
+	    Skencil's text capabilities are still very simple. A text
+	    object consists of just one line of text in one font and
+	    size, hence the class is called
+	    <classname>SimpleText</classname>:
+	  </para>
+	  <para>
+	    <literal>SimpleText(<parameter>trafo</parameter>, <parameter>text</parameter>)</literal>
+	  </para>
+	  <para>
+	    Create a simple text object with the text
+	    string <parameter>text</parameter>. The position and
+	    orientation is given by <parameter>trafo</parameter>,
+	    a <!-- href ID=devguide at TrafoObject -->a transformation
+	    object.
+	  </para>
+	  <para>
+	    For an example, see the sample scripts
+	    <filename>create_text.py</filename>.
+	  </para>
+	</sect4>
+      </sect3>
+
+      <sect3><title>Compound Objects</title>
+
+	<sect4><title>Groups</title>
+	  <para>
+	    Creating a normal group is very simple. First, you have to
+	    construct a list of the objects to be contained in the
+	    group. Then you just call the constructor:
+	  </para>
+	  <para>
+	    <literal>Group(<parameter>children</parameter>)</literal>
+	  </para>
+	  <para>
+	    Create a group object with the objects in the list
+	    <parameter>children</parameter> as children. The children
+	    must not be contained in a document.
+	  </para>
+	  <para>
+	    If you want to create a group of objects that are already
+	    contained in the document, the easiest way is to make sure
+	    those objects are selected and then to call the document
+	    method <function>GroupSelected</function>.  Like all
+	    document methods this method takes care of undo itself.
+	  </para>
+	</sect4>
+      </sect3>
+
+      <sect3><title>Inserting the Object into the Document</title>
+	<para>
+	  You can insert an object into the document with this document
+	  method:
+	</para>
+	<variablelist>
+	  <varlistentry>
+	    <term>
+	      <function>Insert(<parameter>object</parameter>)</function>
+	    </term>
+	    <listitem>
+	      <para>
+		Insert the object <parameter>object</parameter> into the
+		document. The object becomes the topmost object in the
+		current layer. The selection is set to just this object.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </sect3>
+    </sect2>
+
+    <sect2>
+      <title>Manipulating Objects</title>
+      <para>
+	Once you have created a graphics object or you have a reference
+	to an object in the document, perhaps from the selection, you
+	can manipulate them in various ways. All methods that modify an
+	object in place return undo information which you have to pass
+	to the document's <function>AddUndo</function> method if your
+	script isan <link linkend="advanced-script">advanced
+	script</link>.
+      </para>
+
+      <sect3><title>Transformations</title>
+	<para>
+	  Objects have two methods that allow you move and transform
+	  them.
+	</para>
+	<para>
+	  <function>Translate(<parameter>offset</parameter>)</function>
+	</para>
+	<para>
+	  Move the object by <parameter>offset</parameter>.
+	  <parameter>offset</parameter> must be a <!-- href
+	  ID=devguide at PointObject -->point object. For an example, see
+	  the sample scripts
+	  <filename>abut_horizontal.py</filename> and
+	  <filename>abut_vertical.py</filename>.
+	</para>
+
+	<para>
+	  <function>Transform(<parameter>trafo</parameter>)</function>
+	</para>
+	<para>
+	  Apply the affine transformation <parameter>trafo</parameter>
+	  to the object.
+	</para>
+      </sect3>
+
+      <sect3 id="script:changingproperties">
+	<title>Changing Object Properties</title>
+	<para>
+	  Properties define how an object looks, i.e. they define the
+	  fill and line styles and fonts.
+	</para>
+	<para>
+	  The fill is defined by a pattern object. There are several
+	  kinds of pattern types:
+	</para>
+
+	<variablelist>
+	  <varlistentry><term><literal>EmptyPattern</literal></term>
+	    <listitem>
+	      <para>
+		The <parameter>EmptyPattern</parameter> is a predefined
+		object that means the object is not filled.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>
+	      <literal>SolidPattern(<parameter>color</parameter>)</literal>
+	    </term>
+	    <listitem>
+	      <para>
+		Return a solid pattern object for color
+		<parameter>color</parameter>. The solid pattern fills
+		the object uniformly.
+	      </para>
+	      <para>
+		color has to be a color object which can be created with
+		the following function:
+	      </para>
+	      <para>
+		<function>CreateRGBColor(<parameter>red</parameter>, <parameter>green</parameter>, <parameter>blue</parameter>)</function>
+	      </para>
+	      <para>
+		which returns a color object for the color given by the
+		RGB components <parameter>red</parameter>,
+		<parameter>green</parameter>, <parameter>blue</parameter>
+		which are floats in the range 0 - 1.
+	      </para>
+	      <para>
+		There are also some predefined color objects for some
+		standard colors. They are attributes of the
+		<literal>StandardColors</literal> object,
+		e.g. <literal>StandardColors.blue</literal> is blue.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+
+	<para>
+	  There are more pattern like gradients which I haven't
+	  documented yet.
+	</para>
+	<para>
+	  To set the properties of an object, call this method
+	</para>
+	<variablelist>
+	  <varlistentry>
+	    <term>
+	      <function>SetProperties(<parameter>keyword_arguments</parameter>)</function>
+	    </term>
+	    <listitem>
+	      <para>
+		Set the properties described by the keyword arguments
+		and return undo information. The accepted keyword
+		arguments are
+	      </para>
+
+	      <variablelist>
+		<varlistentry>
+		  <term><parameter>fill_pattern</parameter></term>
+		  <listitem>
+		    <para>
+		      The fill pattern. It can be of any pattern type.
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>fill_transform</parameter></term>
+		  <listitem>
+		    <para>
+		      A boolean (i.e. 0 or 1) that defines whether the
+		      pattern is transformed as well if the object is
+		      transformed.
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>line_pattern</parameter></term>
+		  <listitem>
+		    <para>
+		      The pattern for the outline. Must be either
+		      <literal>EmptyPattern</literal> or a
+		      <classname>SolidPattern</classname>. If it's
+		      <literal>EmptyPattern</literal>, no outline is drawn.
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>line_width</parameter></term>
+		  <listitem>
+		    <para>The line width as a float in pt.</para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>line_cap</parameter></term>
+		  <listitem>
+		    <para>
+		      The cap style. One of <literal>CapButt</literal>,
+		      <literal>CapRound</literal>
+		      or <literal>CapProjecting</literal>. These
+		      constants are defined in
+		      <literal>Sketch.const</literal>
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>line_join</parameter></term>
+		  <listitem>
+		    <para>
+		      The join style. One of <literal>JoinMiter</literal>,
+		      <literal>JoinRound</literal> or
+		      <literal>JoinBevel</literal>. These constants
+		      are defined in <literal>Sketch.const</literal>
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>line_dashes</parameter></term>
+		  <listitem>
+		    <para>
+		      The dash-pattern as a tuple of floats. The items
+		      of the tuple define the dashes and gaps terms of
+		      the line-width. The number of items in the tuple
+		      should be even.
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>line_arrow1</parameter></term>
+		  <term><parameter>line_arrow2</parameter></term>
+		  <listitem>
+		    <para>
+		      The arrow heads. Arrow heads are objects you can
+		      create with the function <function>Arrow</function>.
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>font</parameter></term>
+		  <listitem>
+		    <para>
+		      The font for a text object. The value must be a
+		      font object which you can get with the function
+		      <function>GetFont(<parameter>name</parameter>)</function>
+		      where name is the PostScript-name of the font.
+		    </para>
+		  </listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><parameter>font_size</parameter></term>
+		  <listitem>
+		    <para>The size of the font in pt.</para>
+		  </listitem>
+		</varlistentry>
+	      </variablelist>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </sect3>
+    </sect2>
+
+    <sect2><title>Managing the Selection</title>
+      <para>
+	In Skencil 0.6.x, the selection is managed by the document
+	object. You can use these document methods to query and change
+	the selection:
+      </para>
+
+      <variablelist>
+	<varlistentry>
+	  <term><function>HasSelection()</function></term>
+	  <listitem>
+	    <para>Return true if the selection is not empty.</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><function>CountSelected()</function></term>
+	  <listitem>
+	    <para>Return the number of selected objects.</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><function>SelectedObjects()</function></term>
+	  <listitem>
+	    <para>
+	      Return a list containing the currently selected objects.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><function>CurrentObject()</function></term>
+	  <listitem>
+	    <para>
+	      Return the currently selected object if exactly one object
+	      is selected, return <literal>None</literal> otherwise.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry><term><function>SelectNone()</function></term>
+	  <listitem>
+	    <para>Make the selection empty.</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term>
+	    <function>SelectObject(<parameter>object</parameter>[, <parameter>mode</parameter>])</function>
+	  </term>
+	  <listitem>
+	    <para>
+	      If <parameter>mode</parameter> is
+	      <literal>SelectSet</literal>, make object the selected
+	      object, otherwise, if mode is
+	      <literal>SelectAdd</literal>, add object to the
+	      selection. <parameter>mode</parameter>
+	      defaults <literal>to</literal> SelectSet.
+	    </para>
+	    <para>
+	      <parameter>object</parameter> may be a single object or a
+	      list of objects.
+	    </para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term>
+	    <function>DeselectObject(<parameter>object</parameter>)</function>
+	  </term>
+	  <listitem>
+	    <para>
+	      Remove <parameter>object</parameter> from the selection.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+
+    </sect2>
+  </sect1>
+</chapter>

Added: skencil/branches/skencil-0.6/Doc/usersguide/usersguide.xml
===================================================================
--- skencil/branches/skencil-0.6/Doc/usersguide/usersguide.xml	2006-06-01 15:34:15 UTC (rev 681)
+++ skencil/branches/skencil-0.6/Doc/usersguide/usersguide.xml	2006-06-05 18:35:01 UTC (rev 682)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book
+          PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+          "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+[
+   <!ENTITY quickint SYSTEM "quickint.xml">
+   <!ENTITY concepts SYSTEM "concepts.xml">
+   <!ENTITY configuration SYSTEM "configuration.xml">
+   <!ENTITY scripting SYSTEM "scripting.xml">
+
+]>
+<book>
+  <bookinfo>
+    <title>Skencil User's Guide </title>
+    <author><firstname>Bernhard</firstname><surname>Herzog</surname></author>
+    <abstract>
+      <para>
+	This is the User's Guide of the interactive drawing program
+	"Skencil".  It is quite incomplete, since I spend more time
+	coding than writing documentation (currently adding
+	functionality is more important), but some sections contain
+	useful information. You should should probably start with
+	the <link linkend="quickintro">quick introduction</link>
+	and <link linkend="configuration">configuration</link>.
+      </para>
+    </abstract>
+  </bookinfo>
+
+  <chapter id="intro"><title>Introduction</title>
+    <para>
+      Skencil is an interactive, object oriented drawing program. This
+      means that the drawing is composed of objects like rectangles,
+      lines or pieces of text. Skencil allows you to manipulate the
+      objects by moving them around, resizing them or changing their
+      color, etc.
+    </para>
+    <para>
+      This type of program is also called a <emphasis>vector drawing
+      program</emphasis> because it stores the objects internally as
+      coordinates. Apart from Skencil, there are some other (freeware)
+      programs of this type available, such as xfig or tgif and more
+      recently Sodipodi or Karbon, just to name a few.
+    </para>
+  </chapter>
+
+  &quickint;
+
+  &concepts;
+  
+  &configuration;
+
+  &scripting;
+
+</book>



More information about the Skencil-commits mailing list