[Skencil-commits] r727 - skencil/branches/skencil-0.6/src/Sketch/Graphics

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Sep 22 23:52:33 CEST 2010


Author: igor_n
Date: 2010-09-22 23:52:28 +0200 (Wed, 22 Sep 2010)
New Revision: 727

Modified:
   skencil/branches/skencil-0.6/src/Sketch/Graphics/arrow.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/base.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/bezier.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/blend.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/blendgroup.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/clone.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/color.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/compound.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/dashes.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/document.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/ellipse.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/eps.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/external.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/font.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/gradient.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/graphics.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/group.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/guide.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/handle.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/image.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/layer.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/maskgroup.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/pagelayout.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/papersize.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/pattern.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/plugobj.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/properties.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/psdevice.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/rectangle.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/selection.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/selinfo.py
   skencil/branches/skencil-0.6/src/Sketch/Graphics/text.py
Log:
mixed indents are removed

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/arrow.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/arrow.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/arrow.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -33,7 +33,7 @@
 class Arrow:
 
     def __init__(self, path, closed = 0):
-	self.path = CreatePath()
+        self.path = CreatePath()
         if type(path) in (ListType, TupleType):
             for segment in path:
                 if len(segment) == 2:
@@ -42,26 +42,26 @@
                     apply(self.path.AppendBezier, segment)
         else:
             self.path = path
-	if closed:
-	    self.path.load_close()
+        if closed:
+            self.path.load_close()
 
     def BoundingRect(self, pos, dir, width):
         try:
             angle = atan2(dir.y, dir.x)
         except ValueError:
             angle = 0
-	if width < 1.0:
-	    width = 1.0
-	s = width * sin(angle)
-	c = width * cos(angle)
-	trafo = Trafo(c, s, -s, c, pos.x, pos.y)
-	return self.path.accurate_rect(trafo)
+        if width < 1.0:
+            width = 1.0
+        s = width * sin(angle)
+        c = width * cos(angle)
+        trafo = Trafo(c, s, -s, c, pos.x, pos.y)
+        return self.path.accurate_rect(trafo)
 
     def Draw(self, device, rect = None):
-	if self.path.closed:
-	    device.FillBezierPath(self.path, rect)
-	else:
-	    device.DrawBezierPath(self.path, rect)
+        if self.path.closed:
+            device.FillBezierPath(self.path, rect)
+        else:
+            device.DrawBezierPath(self.path, rect)
 
     def Paths(self):
         return (self.path,)
@@ -70,28 +70,28 @@
         return self.path.closed
 
     def SaveRepr(self):
-	path = map(lambda t: t[:-1], self.path.get_save())
-	return (path, self.path.closed)
+        path = map(lambda t: t[:-1], self.path.get_save())
+        return (path, self.path.closed)
 
     def __hash__(self):
-	return hash(id(self.path))
+        return hash(id(self.path))
 
     def __cmp__(self, other):
-	if __debug__:
-	    pdebug(None, 'Arrow.__cmp__, %s', other)
-	if isinstance(other, self.__class__):
-	    return cmp(self.path, other.path)
-	return cmp(id(self), id(other))
+        if __debug__:
+            pdebug(None, 'Arrow.__cmp__, %s', other)
+        if isinstance(other, self.__class__):
+            return cmp(self.path, other.path)
+        return cmp(id(self), id(other))
 
 
 def read_arrows(filename):
     arrows = []
     def arrow(path, closed, list = arrows):
-	list.append(Arrow(path, closed))
+        list.append(Arrow(path, closed))
     dict = {'arrow': arrow}
 
     read_resource_file(filename, '##Sketch Arrow 0',
-		       _("%s is not an arrow definition file"), dict)
+                       _("%s is not an arrow definition file"), dict)
 
     return arrows
 
@@ -100,11 +100,11 @@
 def StandardArrows():
     global std_arrows
     if std_arrows is None:
-	filename = os.path.join(config.std_res_dir, config.preferences.arrows)
-	try:
-	    std_arrows = read_arrows(filename)
-	except:
-	    warn_tb(USER, _("Error trying to read arrows from %s\n"
+        filename = os.path.join(config.std_res_dir, config.preferences.arrows)
+        try:
+            std_arrows = read_arrows(filename)
+        except:
+            warn_tb(USER, _("Error trying to read arrows from %s\n"
                             "Using builtin defaults"), filename)
-	    std_arrows = []
+            std_arrows = []
     return std_arrows

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/base.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/base.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/base.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -100,42 +100,42 @@
 
 
     def __init__(self):
-	# not needed here, but if some derived class wants to call the
-	# base class constructor...
-	pass
+        # not needed here, but if some derived class wants to call the
+        # base class constructor...
+        pass
 
     def DragStart(self, p):
-	# Start the drag at P. Initialize the instance variables. Set
-	# dragging to true.
-	# XXX: document the meaning of the return value
-	self.drawn = 0		# the object is not visible yet
-	self.dragging = 1
-	self.drag_start = p
-	self.drag_cur = p
-	self.off = NullPoint
-	return self.off
+        # Start the drag at P. Initialize the instance variables. Set
+        # dragging to true.
+        # XXX: document the meaning of the return value
+        self.drawn = 0		# the object is not visible yet
+        self.dragging = 1
+        self.drag_start = p
+        self.drag_cur = p
+        self.off = NullPoint
+        return self.off
 
     def DragMove(self, p):
-	# The pointer has moved to p. Compute the new offset.
-	self.off = p - self.drag_start
-	self.drag_cur = p
+        # The pointer has moved to p. Compute the new offset.
+        self.off = p - self.drag_start
+        self.drag_cur = p
 
 
     def MouseMove(self, p, state):
-	# XXX add documentation for this
-	if state & self.drag_mask:
-	    self.off = p - self.drag_start
-	    self.drag_cur = p
+        # XXX add documentation for this
+        if state & self.drag_mask:
+            self.off = p - self.drag_start
+            self.drag_cur = p
 
     def DragStop(self, p):
-	# The drag stopped at p. Update drag_cur and off for the last
-	# time, and set dragging to false.
-	self.dragging = 0
-	self.off = p - self.drag_start
-	self.drag_cur = p
+        # The drag stopped at p. Update drag_cur and off for the last
+        # time, and set dragging to false.
+        self.dragging = 0
+        self.off = p - self.drag_start
+        self.drag_cur = p
 
     def DragCancel(self):
-	self.dragging = 0
+        self.dragging = 0
 
     # The rest of Draggable's methods deal with drawing the object in
     # `dragged' form (usually an outline) on the screen. The output
@@ -173,17 +173,17 @@
     # DrawDragged is called directly.
 
     def DrawDragged(self, device, partially):
-	pass
+        pass
 
     def Show(self, device, partially = 0):
-	if not self.drawn:
-	    self.DrawDragged(device, partially)
-	self.drawn = 1
+        if not self.drawn:
+            self.DrawDragged(device, partially)
+        self.drawn = 1
 
     def Hide(self, device, partially = 0):
-	if self.drawn:
-	    self.DrawDragged(device, partially)
-	self.drawn = 0
+        if self.drawn:
+            self.DrawDragged(device, partially)
+        self.drawn = 0
 
 #
 # Class Selectable
@@ -195,56 +195,56 @@
 class Selectable:
 
     def __init__(self):
-	# only needed for derived classes.
-	pass
+        # only needed for derived classes.
+        pass
 
     def Hit(self, p, rect, device):
-	return None
+        return None
 
     def SelectSubobject(self, p, rect, device, path = None, *rest):
-	return self
+        return self
 
     def GetObjectHandle(self, multiple):
-	# Return a single point marking an important point of the
-	# object. This point is highlighted by a small rectangle in the
-	# canvas to indicate that the object is selected. Alternatively,
-	# a list of such points can be returned to mark several points,
-	# but that feature should only be used by compound objects.
-	#
-	# If multiple is false, self is the only object selected. If
-	# it's true, there may be more than one selected object.
-	return []
+        # Return a single point marking an important point of the
+        # object. This point is highlighted by a small rectangle in the
+        # canvas to indicate that the object is selected. Alternatively,
+        # a list of such points can be returned to mark several points,
+        # but that feature should only be used by compound objects.
+        #
+        # If multiple is false, self is the only object selected. If
+        # it's true, there may be more than one selected object.
+        return []
 
 
 class EditSelect(Selectable):
 
     def SelectPoint(self, p, rect, device, mode = SelectSet):
-	# Select (sub)object at P. If something is selected, return
-	# true, false otherwise.
-	return 0
+        # Select (sub)object at P. If something is selected, return
+        # true, false otherwise.
+        return 0
 
     def SelectHandle(self, handle, mode = SelectSet):
-	pass
+        pass
 
     def SelectRect(self, rect, mode = SelectSet):
-	# select (sub-)object(s) in RECT
-	pass
+        # select (sub-)object(s) in RECT
+        pass
 
     def GetHandles(self):
-	# In edit mode, this method will be called to get a list of
-	# handles. A handle should be shown at every `hot' spot of the
-	# object (e.g. the nodes of a PolyBezier). Handles are described
-	# by tuples which can be easily created by the functions in
-	# handle.py
-	return []
+        # In edit mode, this method will be called to get a list of
+        # handles. A handle should be shown at every `hot' spot of the
+        # object (e.g. the nodes of a PolyBezier). Handles are described
+        # by tuples which can be easily created by the functions in
+        # handle.py
+        return []
 
 
 
 class SelectAndDrag(Draggable, EditSelect):
 
     def __init__(self):
-	Draggable.__init__(self)
-	Selectable.__init__(self)
+        Draggable.__init__(self)
+        Selectable.__init__(self)
 
     def CurrentInfoText(self):
         # return a string describing the current state of the object
@@ -266,12 +266,12 @@
     is_Creator          = 0
 
     has_edit_mode = 0	# true if object has an edit mode. If true, the
-			# Editor() method must be implemented
+                        # Editor() method must be implemented
 
     is_curve = 0	# true, if object can be represented by and
-			# converted to a PolyBezier object. If true, the
-			# AsBezier() and Paths() methods must be
-			# implemented
+                        # converted to a PolyBezier object. If true, the
+                        # AsBezier() and Paths() methods must be
+                        # implemented
     is_clip = 0
 
     has_fill		= 0	# True, iff object can have fill properties
@@ -283,7 +283,7 @@
     is_Rectangle	= 0
     is_Ellipse		= 0
     is_Text		= 0	# Text objects must have a Font() method
-				# returning a font.
+                                # returning a font.
     is_SimpleText       = 0
     is_PathTextGroup    = 0 
     is_PathTextText     = 0     # The text part of a path text group
@@ -335,51 +335,51 @@
 class Bounded:
 
     _lazy_attrs = {'coord_rect' : 'update_rects',
-		   'bounding_rect' : 'update_rects'}
+                   'bounding_rect' : 'update_rects'}
 
     def __init__(self):
-	pass
+        pass
 
     def del_lazy_attrs(self):
-	for key in self._lazy_attrs.keys():
-	    try:
-		delattr(self, key)
-	    except:
-		pass
+        for key in self._lazy_attrs.keys():
+            try:
+                delattr(self, key)
+            except:
+                pass
 
     def update_rects(self):
-	# compute the various bounding rects and other attributes that
-	# use `lazy evaluation'. This method MUST be implemented by
-	# derived classes. It MUST set self.bounding_rect and
-	# self.coord_rect and other attributes where appropriate.
-	pass
+        # compute the various bounding rects and other attributes that
+        # use `lazy evaluation'. This method MUST be implemented by
+        # derived classes. It MUST set self.bounding_rect and
+        # self.coord_rect and other attributes where appropriate.
+        pass
 
     def __getattr__(self, attr):
-	# if a lazy attribute is accessed, compute it.
-	method = self._lazy_attrs.get(attr)
-	if method:
-	    getattr(self, method)()
-	    # now it should work... use self.__dict__ directly to avoid
-	    # recursion if the method is buggy
-	    try:
-		return self.__dict__[attr]
-	    except KeyError, msg:
-		warn(INTERNAL, '%s did not compute %s for %s.',
-		     method, attr, self)
-	if attr[:2] == attr[-2:] == '__':
-	    #if attr in ('__nonzero__', '__len__'):
-	    #	 print_stack()
-	    pass
-	else:
-	    warn(INTERNAL, "%s instance doesn't have an attribute %s",
-		 self.__class__, attr)
-	raise AttributeError, attr
+        # if a lazy attribute is accessed, compute it.
+        method = self._lazy_attrs.get(attr)
+        if method:
+            getattr(self, method)()
+            # now it should work... use self.__dict__ directly to avoid
+            # recursion if the method is buggy
+            try:
+                return self.__dict__[attr]
+            except KeyError, msg:
+                warn(INTERNAL, '%s did not compute %s for %s.',
+                     method, attr, self)
+        if attr[:2] == attr[-2:] == '__':
+            #if attr in ('__nonzero__', '__len__'):
+            #	 print_stack()
+            pass
+        else:
+            warn(INTERNAL, "%s instance doesn't have an attribute %s",
+                 self.__class__, attr)
+        raise AttributeError, attr
 
     def LayoutPoint(self):
-	return Point(self.coord_rect.left, self.coord_rect.bottom)
+        return Point(self.coord_rect.left, self.coord_rect.bottom)
 
     def GetSnapPoints(self):
-	return []
+        return []
 
 #
 # Class HierarchyNode
@@ -394,84 +394,84 @@
 class HierarchyNode:
 
     def __init__(self, duplicate = None):
-	if duplicate is not None:
-	    self.document = duplicate.document
-	    if duplicate.was_untied:
-		self.was_untied = duplicate.was_untied
+        if duplicate is not None:
+            self.document = duplicate.document
+            if duplicate.was_untied:
+                self.was_untied = duplicate.was_untied
 
     def __del__(self):
-	if self.document:
-	    self.document.connector.RemovePublisher(self)
+        if self.document:
+            self.document.connector.RemovePublisher(self)
 
     def Destroy(self):
-	# remove all circular references here...
-	# May be extended by derived classes.
-	self.parent = None
+        # remove all circular references here...
+        # May be extended by derived classes.
+        self.parent = None
 
     parent = None
     def SetParent(self, parent):
-	self.parent = parent
+        self.parent = parent
 
     def depth(self):
-	if self.parent is not None:
-	    return self.parent.depth() + 1
-	return 1
+        if self.parent is not None:
+            return self.parent.depth() + 1
+        return 1
 
     def SelectionInfo(self):
-	if self.parent is not None:
-	    return self.parent.SelectionInfo(self)
+        if self.parent is not None:
+            return self.parent.SelectionInfo(self)
 
     document = None	# the document self belongs to
 
     def SetDocument(self, doc):
-	self.document = doc
-	if doc is not None and self.was_untied:
-	    self.TieToDocument()
-	    del self.was_untied
+        self.document = doc
+        if doc is not None and self.was_untied:
+            self.TieToDocument()
+            del self.was_untied
 
     def UntieFromDocument(self):
-	# this will be called when self is being stored in the clipboard
-	# (CopyForClipboard/CutForClipboard), but before self.document
-	# becomes None. Disconnect will not be called in this case.
-	# May be extended by derived classes.
-	self.was_untied = 1
+        # this will be called when self is being stored in the clipboard
+        # (CopyForClipboard/CutForClipboard), but before self.document
+        # becomes None. Disconnect will not be called in this case.
+        # May be extended by derived classes.
+        self.was_untied = 1
 
     def TieToDocument(self):
-	# this will be called when self is being inserted into the
-	# document from the clipboard, after self.document has been set.
-	# Connect will not be called in this case.
-	# May be extended by derived classes.
-	pass
+        # this will be called when self is being inserted into the
+        # document from the clipboard, after self.document has been set.
+        # Connect will not be called in this case.
+        # May be extended by derived classes.
+        pass
 
     def Subscribe(self, channel, func, *args):
-	# XXX: what do we do if document has not been set (yet)
-	if self.document is not None:
-	    self.document.connector.Connect(self, channel, func, args)
+        # XXX: what do we do if document has not been set (yet)
+        if self.document is not None:
+            self.document.connector.Connect(self, channel, func, args)
 
     def Unsubscribe(self, channel, func, *args):
-	if self.document is not None:
-	    self.document.connector.Disconnect(self, channel, func, args)
+        if self.document is not None:
+            self.document.connector.Disconnect(self, channel, func, args)
 
     def Issue(self, channel, *args):
-	if self.document is not None:
-	    apply(self.document.connector.Issue, (self, channel,) + args)
+        if self.document is not None:
+            apply(self.document.connector.Issue, (self, channel,) + args)
 
     def issue_changed(self):
-	self.Issue(CHANGED, self)
-	if self.parent is not None:
-	    self.parent.ChildChanged(self)
+        self.Issue(CHANGED, self)
+        if self.parent is not None:
+            self.parent.ChildChanged(self)
 
     def Connect(self):
-	# May be extended by derived classes.
-	pass
+        # May be extended by derived classes.
+        pass
 
     def Disconnect(self):
-	# May be extended by derived classes.
-	pass
+        # May be extended by derived classes.
+        pass
 
     def Duplicate(self):
-	# return a duplicate of self
-	return self.__class__(duplicate = self)
+        # return a duplicate of self
+        return self.__class__(duplicate = self)
 
 
 
@@ -495,72 +495,72 @@
     script_access = {}
 
     def __init__(self, duplicate = None):
-	Selectable.__init__(self)
-	HierarchyNode.__init__(self, duplicate = duplicate)
+        Selectable.__init__(self)
+        HierarchyNode.__init__(self, duplicate = duplicate)
 
     def ChildChanged(self, child):
-	# in compound objects, this method is called by the child
-	# whenever it changes (normally via the issue_changed method)
-	pass
+        # in compound objects, this method is called by the child
+        # whenever it changes (normally via the issue_changed method)
+        pass
 
     def __cmp__(self, other):
-	return cmp(id(self), id(other))
+        return cmp(id(self), id(other))
 
     def _changed(self):
-	self.del_lazy_attrs()
-	self.issue_changed()
-	return (self._changed,)
+        self.del_lazy_attrs()
+        self.issue_changed()
+        return (self._changed,)
 
     def SetLowerLeftCorner(self, corner):
-	# move self so that self's lower left corner is at CORNER. This
-	# used when interactively placing an object
-	rect = self.coord_rect
-	ll = Point(rect.left, rect.bottom)
-	return self.Translate(corner - ll)
+        # move self so that self's lower left corner is at CORNER. This
+        # used when interactively placing an object
+        rect = self.coord_rect
+        ll = Point(rect.left, rect.bottom)
+        return self.Translate(corner - ll)
 
     def RemoveTransformation(self):
-	# Some objects accumulate the transformation applied by
-	# Transform() and apply them every time the object is displayed
-	# Restore this transformation to Identity.
-	return NullUndo
+        # Some objects accumulate the transformation applied by
+        # Transform() and apply them every time the object is displayed
+        # Restore this transformation to Identity.
+        return NullUndo
     script_access['RemoveTransformation'] = SCRIPT_UNDO
 
     def AsBezier(self):
-	# Return self as bezier if possible. See is_curve above.
-	return None
+        # Return self as bezier if possible. See is_curve above.
+        return None
     script_access['AsBezier'] = SCRIPT_OBJECT
 
     def Paths(self):
-	# Return a tuple of curve objects describing the outline of self
-	# if possible. The curve objects can be the ones used internally
-	# by self. The calling code is expected not to modify the curve
-	# objects in place.
+        # Return a tuple of curve objects describing the outline of self
+        # if possible. The curve objects can be the ones used internally
+        # by self. The calling code is expected not to modify the curve
+        # objects in place.
         # See is_curve above.
-	return None
+        return None
     script_access['Paths'] = SCRIPT_GET
 
     def Blend(self, other, frac1, frac2):
-	# Return the weighted average of SELF and OTHER. FRAC1 and FRAC2
-	# are the weights (if SELF and OTHER were numbers this should be
-	# FRAC1 * SELF + FRAC2 * OTHER).
-	#
-	# This method is used by the function Blend() in blend.py. If
-	# SELF and OTHER can't be blended, raise the blend.MismatchError
-	# exception. This is also the default behaviour.
-	raise MismatchError
+        # Return the weighted average of SELF and OTHER. FRAC1 and FRAC2
+        # are the weights (if SELF and OTHER were numbers this should be
+        # FRAC1 * SELF + FRAC2 * OTHER).
+        #
+        # This method is used by the function Blend() in blend.py. If
+        # SELF and OTHER can't be blended, raise the blend.MismatchError
+        # exception. This is also the default behaviour.
+        raise MismatchError
     script_access['Blend'] = SCRIPT_OBJECT
 
     def Snap(self, p):
-	# Determine the point Q on self's outline closest to P and
-	# return a tuple (abs(Q - P), Q)
-	return (1e100, p)
+        # Determine the point Q on self's outline closest to P and
+        # return a tuple (abs(Q - P), Q)
+        return (1e100, p)
     script_access['Snap'] = SCRIPT_GET
 
     def ObjectChanged(self, obj):
-	return 0
+        return 0
 
     def ObjectRemoved(self, obj):
-	return NullUndo
+        return NullUndo
 
     # Add some inherited method's script access flags
     script_access['coord_rect'] = SCRIPT_GET
@@ -582,33 +582,33 @@
     creation_text = 'Create Object'
 
     def __init__(self, start):
-	self.start = start
+        self.start = start
 
     def EndCreation(self):
-	# This method will be called when the object was being created
-	# interactively using more than one click-drag-release cycle,
-	# and the user has finished. This method is needed by the
-	# PolyBezier primitive for instance.
-	#
-	# Return true if creation was successful, false otherwise.
-	return 1
+        # This method will be called when the object was being created
+        # interactively using more than one click-drag-release cycle,
+        # and the user has finished. This method is needed by the
+        # PolyBezier primitive for instance.
+        #
+        # Return true if creation was successful, false otherwise.
+        return 1
 
     def ContinueCreation(self):
-	# called during interactive creation when the user releases the
-	# mouse button. Return true, if the object may need another
-	# click-drag-release cycle, false for objects that are always
-	# complete after one cycle. (XXX the `true' return value is
-	# interpreted in a special way, see the PolyBezier primitive)
-	#
-	# XXX: Should we distinguish more cases? A rectangle for example
-	# is always complete after one click-drag-release cycle. A
-	# PolyBezier object needs at least two cycles but accepts any
-	# number of additional cycles. A polygon (with straight lines)
-	# needs at least one. We might return a value that indicates
-	# whether the user *must* supply additional points, whether it's
-	# optional or whether the object is complete and the user
-	# *cannot* add points.
-	return None
+        # called during interactive creation when the user releases the
+        # mouse button. Return true, if the object may need another
+        # click-drag-release cycle, false for objects that are always
+        # complete after one cycle. (XXX the `true' return value is
+        # interpreted in a special way, see the PolyBezier primitive)
+        #
+        # XXX: Should we distinguish more cases? A rectangle for example
+        # is always complete after one click-drag-release cycle. A
+        # PolyBezier object needs at least two cycles but accepts any
+        # number of additional cycles. A polygon (with straight lines)
+        # needs at least one. We might return a value that indicates
+        # whether the user *must* supply additional points, whether it's
+        # optional or whether the object is complete and the user
+        # *cannot* add points.
+        return None
 
 class Editor(SelectAndDrag):
 
@@ -618,22 +618,22 @@
     context_commands = ()
 
     def __init__(self, object):
-	self.object = object
+        self.object = object
 
     def __getattr__(self, attr):
-	return getattr(self.object, attr)
+        return getattr(self.object, attr)
 
     def Destroy(self):
-	# called by the edit mode selection when the editor it not
-	# needed anymore.
-	pass
+        # called by the edit mode selection when the editor it not
+        # needed anymore.
+        pass
 
     def ChangeRect(self):
-	# ChangeRect indicates the area that is going to change during
-	# the current click-drag-release cycle. It is safe to make this
-	# equal to bounding_rect. This rectangle is used to determine
-	# which parts of the window have to be redrawn.
-	return self.bounding_rect
+        # ChangeRect indicates the area that is going to change during
+        # the current click-drag-release cycle. It is safe to make this
+        # equal to bounding_rect. This rectangle is used to determine
+        # which parts of the window have to be redrawn.
+        return self.bounding_rect
 
 
 #
@@ -655,123 +655,123 @@
     script_access = GraphicsObject.script_access.copy()
 
     def __init__(self, properties = None, duplicate = None):
-	GraphicsObject.__init__(self, duplicate = duplicate)
-	if duplicate is not None:
-	    self.properties = duplicate.properties.Duplicate()
-	    if duplicate.tie_info:
-		self.tie_info = duplicate.tie_info
-	else:
-	    if properties is not None:
-		self.properties = properties
-	    else:
-		self.properties = PropertyStack()
+        GraphicsObject.__init__(self, duplicate = duplicate)
+        if duplicate is not None:
+            self.properties = duplicate.properties.Duplicate()
+            if duplicate.tie_info:
+                self.tie_info = duplicate.tie_info
+        else:
+            if properties is not None:
+                self.properties = properties
+            else:
+                self.properties = PropertyStack()
 
     def Destroy(self):
-	GraphicsObject.Destroy(self)
+        GraphicsObject.Destroy(self)
 
     def UntieFromDocument(self):
-	info = self.properties.Untie()
-	if info:
-	    self.tie_info = info
-	GraphicsObject.UntieFromDocument(self)
+        info = self.properties.Untie()
+        if info:
+            self.tie_info = info
+        GraphicsObject.UntieFromDocument(self)
 
     def TieToDocument(self):
-	if self.tie_info:
-	    self.properties.Tie(self.document, self.tie_info)
-	    del self.tie_info
+        if self.tie_info:
+            self.properties.Tie(self.document, self.tie_info)
+            del self.tie_info
 
     def Transform(self, trafo, rects = None):
-	# Apply the affine transformation trafo to all coordinates and
-	# the properties.
-	undo = self.properties.Transform(trafo, rects)
-	if undo is not NullUndo:
-	    return self.properties_changed(undo)
-	return undo
+        # Apply the affine transformation trafo to all coordinates and
+        # the properties.
+        undo = self.properties.Transform(trafo, rects)
+        if undo is not NullUndo:
+            return self.properties_changed(undo)
+        return undo
 
     def Translate(self, offset):
-	# Move all points by OFFSET. OFFSET is an SKPoint instance.
-	return NullUndo
+        # Move all points by OFFSET. OFFSET is an SKPoint instance.
+        return NullUndo
 
     def DrawShape(self, device):
-	# Draw the object on device. Here we just set the properties.
-	device.SetProperties(self.properties, self.bounding_rect)
+        # Draw the object on device. Here we just set the properties.
+        device.SetProperties(self.properties, self.bounding_rect)
 
     # The following functions manage the properties
 
     def set_property_stack(self, properties):
-	self.properties = properties
+        self.properties = properties
     load_SetProperties = set_property_stack
 
     def properties_changed(self, undo):
-	if undo is not NullUndo:
-	    return (UndoAfter, undo, self._changed())
-	return undo
+        if undo is not NullUndo:
+            return (UndoAfter, undo, self._changed())
+        return undo
 
     def AddStyle(self, style):
-	return self.properties_changed(self.properties.AddStyle(style))
+        return self.properties_changed(self.properties.AddStyle(style))
     script_access['AddStyle'] = SCRIPT_UNDO
 
     def Filled(self):
-	return self.properties.HasFill()
+        return self.properties.HasFill()
     script_access['Filled'] = SCRIPT_GET
 
     def Properties(self):
-	return self.properties
+        return self.properties
     script_access['Properties'] = SCRIPT_OBJECT
 
     def SetProperties(self, if_type_present = 0, **kw):
-	if if_type_present:
-	    # change properties of that type if properties of that are
-	    # already present.
-	    prop_types = properties.property_types
-	    LineProperty = properties.LineProperty
-	    FillProperty = properties.FillProperty
-	    FontProperty = properties.FontProperty
-	    types = map(prop_types.get, kw.keys())
-	    if LineProperty in types and not self.properties.HasLine():
-		for key in kw.keys():
-		    if prop_types[key] == LineProperty:
-			del kw[key]
-	    if FillProperty in types and not self.properties.HasFill():
-		for key in kw.keys():
-		    if prop_types[key] == FillProperty:
-			del kw[key]
-	    if FontProperty in types and not self.properties.HasFont():
-		for key in kw.keys():
-		    if prop_types[key] == FontProperty:
-			del kw[key]
-	return self.properties_changed(apply(self.properties.SetProperty, (),
-					     kw))
+        if if_type_present:
+            # change properties of that type if properties of that are
+            # already present.
+            prop_types = properties.property_types
+            LineProperty = properties.LineProperty
+            FillProperty = properties.FillProperty
+            FontProperty = properties.FontProperty
+            types = map(prop_types.get, kw.keys())
+            if LineProperty in types and not self.properties.HasLine():
+                for key in kw.keys():
+                    if prop_types[key] == LineProperty:
+                        del kw[key]
+            if FillProperty in types and not self.properties.HasFill():
+                for key in kw.keys():
+                    if prop_types[key] == FillProperty:
+                        del kw[key]
+            if FontProperty in types and not self.properties.HasFont():
+                for key in kw.keys():
+                    if prop_types[key] == FontProperty:
+                        del kw[key]
+        return self.properties_changed(apply(self.properties.SetProperty, (),
+                                             kw))
     script_access['SetProperties'] = SCRIPT_UNDO
 
     def LineWidth(self):
-	if self.properties.HasLine:
-	    return self.properties.line_width
-	return 0
+        if self.properties.HasLine:
+            return self.properties.line_width
+        return 0
     script_access['LineWidth'] = SCRIPT_GET
 
     def ObjectChanged(self, obj):
-	if self.properties.ObjectChanged(obj):
-	    rect = self.bounding_rect
-	    self.del_lazy_attrs()
-	    self.document.AddClearRect(UnionRects(rect, self.bounding_rect))
-	    self.issue_changed()
-	    return 1
-	return 0
+        if self.properties.ObjectChanged(obj):
+            rect = self.bounding_rect
+            self.del_lazy_attrs()
+            self.document.AddClearRect(UnionRects(rect, self.bounding_rect))
+            self.issue_changed()
+            return 1
+        return 0
 
     def ObjectRemoved(self, obj):
-	return self.properties.ObjectRemoved(obj)
+        return self.properties.ObjectRemoved(obj)
 
 
     def set_blended_properties(self, blended, other, frac1, frac2):
-	blended.set_property_stack(Blend(self.properties, other.properties,
-					 frac1, frac2))
+        blended.set_property_stack(Blend(self.properties, other.properties,
+                                         frac1, frac2))
 
 
     def SaveToFile(self, file):
-	# save object to file. Must be extended by the subclasses. Here,
-	# we just save the properties.
-	self.properties.SaveToFile(file)
+        # save object to file. Must be extended by the subclasses. Here,
+        # we just save the properties.
+        self.properties.SaveToFile(file)
 
 
 #
@@ -783,102 +783,102 @@
 class RectangularObject:
 
     def __init__(self, trafo = None, duplicate = None):
-	if duplicate is not None:
-	    self.trafo = duplicate.trafo
-	else:
-	    if not trafo:
-		self.trafo = Identity
-	    else:
-		self.trafo = trafo
+        if duplicate is not None:
+            self.trafo = duplicate.trafo
+        else:
+            if not trafo:
+                self.trafo = Identity
+            else:
+                self.trafo = trafo
 
     def Trafo(self):
         return self.trafo
 
     def LayoutPoint(self, *rest):
-	# accept arguments to use this function as GetObjectHandle
-	return self.trafo.offset()
+        # accept arguments to use this function as GetObjectHandle
+        return self.trafo.offset()
 
     GetObjectHandle = LayoutPoint
 
     def Translate(self, offset):
-	return self.Transform(Translation(offset))
+        return self.Transform(Translation(offset))
 
     def set_transformation(self, trafo):
-	undo = (self.set_transformation, self.trafo)
-	self.trafo = trafo
-	self._changed()
-	return undo
+        undo = (self.set_transformation, self.trafo)
+        self.trafo = trafo
+        self._changed()
+        return undo
 
     def Transform(self, trafo):
-	trafo = trafo(self.trafo)
-	return self.set_transformation(trafo)
+        trafo = trafo(self.trafo)
+        return self.set_transformation(trafo)
 
     def Blend(self, other, p, q):
-	if other.__class__ == self.__class__:
-	    blended = self.__class__(BlendTrafo(self.trafo, other.trafo, p, q))
-	    self.set_blended_properties(blended, other, p, q)
-	    return blended
-	raise MismatchError
+        if other.__class__ == self.__class__:
+            blended = self.__class__(BlendTrafo(self.trafo, other.trafo, p, q))
+            self.set_blended_properties(blended, other, p, q)
+            return blended
+        raise MismatchError
 
 
 class RectangularPrimitive(RectangularObject, Primitive):
 
     def __init__(self, trafo = None, properties = None, duplicate = None):
-	RectangularObject.__init__(self, trafo, duplicate = duplicate)
-	Primitive.__init__(self, properties = properties,
-			   duplicate = duplicate)
+        RectangularObject.__init__(self, trafo, duplicate = duplicate)
+        Primitive.__init__(self, properties = properties,
+                           duplicate = duplicate)
 
     def Transform(self, trafo, transform_properties = 1):
-	undostyle = undo = NullUndo
-	try:
-	    rect = self.bounding_rect
-	    undo = RectangularObject.Transform(self, trafo)
-	    if transform_properties:
-		rects = (rect, self.bounding_rect)
-		undostyle = Primitive.Transform(self, trafo, rects = rects)
-	    return CreateMultiUndo(undostyle, undo)
-	except:
-	    Undo(undo)
-	    Undo(undostyle)
-	    raise
+        undostyle = undo = NullUndo
+        try:
+            rect = self.bounding_rect
+            undo = RectangularObject.Transform(self, trafo)
+            if transform_properties:
+                rects = (rect, self.bounding_rect)
+                undostyle = Primitive.Transform(self, trafo, rects = rects)
+            return CreateMultiUndo(undostyle, undo)
+        except:
+            Undo(undo)
+            Undo(undostyle)
+            raise
 
     def Translate(self, offset):
-	return self.Transform(Translation(offset), transform_properties = 0)
+        return self.Transform(Translation(offset), transform_properties = 0)
 
 
 class RectangularCreator(Creator):
 
     def __init__(self, start):
-	Creator.__init__(self, start)
-	self.trafo = Trafo(1, 0, 0, 1, start.x, start.y)
+        Creator.__init__(self, start)
+        self.trafo = Trafo(1, 0, 0, 1, start.x, start.y)
 
     def ButtonDown(self, p, button, state):
-	Creator.DragStart(self, p)
+        Creator.DragStart(self, p)
 
     def apply_constraint(self, p, state):
-	if state & ConstraintMask:
-	    trafo = self.trafo
+        if state & ConstraintMask:
+            trafo = self.trafo
             w, h = p - self.drag_start
-	    if w == 0:
-		w = 0.00001
-	    a = h / w
-	    if a > 0:
-		sign = 1
-	    else:
-		sign = -1
-	    if abs(a) > 1.0:
-		h = sign * w
-	    else:
-		w = sign * h
-	    p = self.drag_start + Point(w, h)
-	return p
+            if w == 0:
+                w = 0.00001
+            a = h / w
+            if a > 0:
+                sign = 1
+            else:
+                sign = -1
+            if abs(a) > 1.0:
+                h = sign * w
+            else:
+                w = sign * h
+            p = self.drag_start + Point(w, h)
+        return p
 
     def MouseMove(self, p, state):
-	p = self.apply_constraint(p, state)
-	Creator.MouseMove(self, p, state)
+        p = self.apply_constraint(p, state)
+        Creator.MouseMove(self, p, state)
 
     def ButtonUp(self, p, button, state):
-	p = self.apply_constraint(p, state)
-	Creator.DragStop(self, p)
-	x, y = self.off
-	self.trafo = Trafo(x, 0, 0, y, self.trafo.v1, self.trafo.v2)
+        p = self.apply_constraint(p, state)
+        Creator.DragStop(self, p)
+        x, y = self.off
+        self.trafo = Trafo(x, 0, 0, y, self.trafo.v1, self.trafo.v2)

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/bezier.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/bezier.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/bezier.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -49,9 +49,9 @@
 
 def undo_path(undo, path):
     if undo is not None:
-	return apply(getattr(path, undo[0]), undo[1:])
+        return apply(getattr(path, undo[0]), undo[1:])
     else:
-	return undo
+        return undo
 
 class PolyBezier(Primitive):
 
@@ -63,214 +63,214 @@
     script_access = Primitive.script_access.copy()
 
     def __init__(self, paths = None, properties = None, duplicate = None):
-	if duplicate is not None:
-	    if paths is None:
-		paths = []
-		for path in duplicate.paths:
-		    paths.append(path.Duplicate())
-		self.paths = tuple(paths)
-	    else:
-		# This special case uses the properties kwarg now, I
-		# hope.
-		warn(INTERNAL, 'Bezier object created with paths and duplicte')
-		print_stack()
-		if type(paths) != type(()):
-		    paths = (paths,)
-		self.paths = paths
-	elif paths is not None:
-	    if type(paths) != type(()):
-		paths = (paths,)
-	    self.paths = paths
-	else:
-	    self.paths = (CreatePath(),)
+        if duplicate is not None:
+            if paths is None:
+                paths = []
+                for path in duplicate.paths:
+                    paths.append(path.Duplicate())
+                self.paths = tuple(paths)
+            else:
+                # This special case uses the properties kwarg now, I
+                # hope.
+                warn(INTERNAL, 'Bezier object created with paths and duplicte')
+                print_stack()
+                if type(paths) != type(()):
+                    paths = (paths,)
+                self.paths = paths
+        elif paths is not None:
+            if type(paths) != type(()):
+                paths = (paths,)
+            self.paths = paths
+        else:
+            self.paths = (CreatePath(),)
 
-	Primitive.__init__(self, properties = properties, duplicate=duplicate)
+        Primitive.__init__(self, properties = properties, duplicate=duplicate)
 
     def Hit(self, p, rect, device, clip = 0):
-	for path in self.paths:
-	    if path.hit_point(rect):
-		return 1
-	return device.MultiBezierHit(self.paths, p, self.properties,
-				     clip or self.Filled(),
-				     ignore_outline_mode = clip)
+        for path in self.paths:
+            if path.hit_point(rect):
+                return 1
+        return device.MultiBezierHit(self.paths, p, self.properties,
+                                     clip or self.Filled(),
+                                     ignore_outline_mode = clip)
 
     def do_undo(self, undo_list):
-	undo = map(undo_path, undo_list, self.paths)
-	self._changed()
-	return (self.do_undo, undo)
+        undo = map(undo_path, undo_list, self.paths)
+        self._changed()
+        return (self.do_undo, undo)
 
     def Transform(self, trafo):
-	undo = []
-	undostyle = NullUndo
-	try:
-	    rect = self.bounding_rect
-	    for path in self.paths:
-		undo.append(path.Transform(trafo))
-	    self._changed()
-	    undo = (self.do_undo, undo)
-	    self.update_rects() # calling update_rects directly is a bit faster
-	    undostyle = Primitive.Transform(self, trafo,
-					    rects = (rect, self.bounding_rect))
-	    return CreateMultiUndo(undostyle, undo)
-	except:
-	    Undo(undostyle)
-	    if type(undo) != type(()):
-		undo = (self.do_undo, undo)
-	    Undo(undo)
-	    raise
+        undo = []
+        undostyle = NullUndo
+        try:
+            rect = self.bounding_rect
+            for path in self.paths:
+                undo.append(path.Transform(trafo))
+            self._changed()
+            undo = (self.do_undo, undo)
+            self.update_rects() # calling update_rects directly is a bit faster
+            undostyle = Primitive.Transform(self, trafo,
+                                            rects = (rect, self.bounding_rect))
+            return CreateMultiUndo(undostyle, undo)
+        except:
+            Undo(undostyle)
+            if type(undo) != type(()):
+                undo = (self.do_undo, undo)
+            Undo(undo)
+            raise
 
     def Translate(self, offset):
-	for path in self.paths:
-	    path.Translate(offset)
-	self._changed()
-	return self.Translate, -offset
+        for path in self.paths:
+            path.Translate(offset)
+        self._changed()
+        return self.Translate, -offset
 
     def DrawShape(self, device, rect = None, clip = 0):
-	Primitive.DrawShape(self, device)
-	device.MultiBezier(self.paths, rect, clip)
+        Primitive.DrawShape(self, device)
+        device.MultiBezier(self.paths, rect, clip)
 
     def GetObjectHandle(self, multiple):
-	if self.paths:
-	    return self.paths[0].Node(0)
-	return Point(0, 0)
+        if self.paths:
+            return self.paths[0].Node(0)
+        return Point(0, 0)
 
     def GetSnapPoints(self):
-	points = []
-	for path in self.paths:
-	    points = points + path.NodeList()
-	return points
+        points = []
+        for path in self.paths:
+            points = points + path.NodeList()
+        return points
 
     def Snap(self, p):
-	found = [(1e100, p)]
-	for path in self.paths:
-	    t = path.nearest_point(p.x, p.y)
-	    if t is not None:
-		#print p, t
-		p2 = path.point_at(t)
-		found.append((abs(p - p2), p2))
-	return min(found)
+        found = [(1e100, p)]
+        for path in self.paths:
+            t = path.nearest_point(p.x, p.y)
+            if t is not None:
+                #print p, t
+                p2 = path.point_at(t)
+                found.append((abs(p - p2), p2))
+        return min(found)
 
     def update_rects(self):
-	if not self.paths:
-	    # this should never happen...
-	    self.coord_rect = self.bounding_rect = Rect(0, 0, 0, 0)
-	    return
+        if not self.paths:
+            # this should never happen...
+            self.coord_rect = self.bounding_rect = Rect(0, 0, 0, 0)
+            return
 
-	rect = self.paths[0].accurate_rect()
-	for path in self.paths[1:]:
-	    rect = UnionRects(rect, path.accurate_rect())
-	self.coord_rect = rect
-	if self.properties.HasLine():
-	    rect = self.add_arrow_rects(rect)
-	    self.bounding_rect = rect.grown(self.properties.GrowAmount())
-	else:
-	    self.bounding_rect = rect
+        rect = self.paths[0].accurate_rect()
+        for path in self.paths[1:]:
+            rect = UnionRects(rect, path.accurate_rect())
+        self.coord_rect = rect
+        if self.properties.HasLine():
+            rect = self.add_arrow_rects(rect)
+            self.bounding_rect = rect.grown(self.properties.GrowAmount())
+        else:
+            self.bounding_rect = rect
 
     def add_arrow_rects(self, rect):
-	if self.properties.HasLine():
-	    arrow1 = self.properties.line_arrow1
-	    arrow2 = self.properties.line_arrow2
-	    if arrow1 or arrow2:
-		width = self.properties.line_width
-		for path in self.paths:
-		    if not path.closed and path.len > 1:
-			if arrow1 is not None:
-			    type, controls, p3, cont = path.Segment(1)
-			    p = path.Node(0)
-			    if type == Bezier:
-				dir = p - controls[0]
-			    else:
-				dir = p - p3
-			    rect = UnionRects(rect,
-					      arrow1.BoundingRect(p,dir,width))
-			if arrow2 is not None:
-			    type, controls, p, cont = path.Segment(-1)
-			    if type == Bezier:
-				dir = p - controls[1]
-			    else:
-				dir = p - path.Node(-2)
-			    rect = UnionRects(rect,
-					      arrow2.BoundingRect(p,dir,width))
-	return rect
+        if self.properties.HasLine():
+            arrow1 = self.properties.line_arrow1
+            arrow2 = self.properties.line_arrow2
+            if arrow1 or arrow2:
+                width = self.properties.line_width
+                for path in self.paths:
+                    if not path.closed and path.len > 1:
+                        if arrow1 is not None:
+                            type, controls, p3, cont = path.Segment(1)
+                            p = path.Node(0)
+                            if type == Bezier:
+                                dir = p - controls[0]
+                            else:
+                                dir = p - p3
+                            rect = UnionRects(rect,
+                                              arrow1.BoundingRect(p,dir,width))
+                        if arrow2 is not None:
+                            type, controls, p, cont = path.Segment(-1)
+                            if type == Bezier:
+                                dir = p - controls[1]
+                            else:
+                                dir = p - path.Node(-2)
+                            rect = UnionRects(rect,
+                                              arrow2.BoundingRect(p,dir,width))
+        return rect
 
     def Info(self):
-	nodes = 0
-	for path in self.paths:
-	    nodes = nodes + path.len
-	    if path.closed:
-		nodes = nodes - 1
-	return _("PolyBezier (%(nodes)d nodes in %(paths)d paths)") \
-	       % {'nodes':nodes, 'paths':len(self.paths)}
+        nodes = 0
+        for path in self.paths:
+            nodes = nodes + path.len
+            if path.closed:
+                nodes = nodes - 1
+        return _("PolyBezier (%(nodes)d nodes in %(paths)d paths)") \
+               % {'nodes':nodes, 'paths':len(self.paths)}
 
     def set_paths(self, paths):
-	undo = (self.set_paths, self.paths)
-	self.paths = tuple(paths)
-	self._changed()
-	return undo
+        undo = (self.set_paths, self.paths)
+        self.paths = tuple(paths)
+        self._changed()
+        return undo
 
     SetPaths = set_paths
     def Paths(self):
-	return self.paths
+        return self.paths
 
     def PathsAsObjects(self):
-	result = []
-	for path in self.paths:
-	    object = self.__class__(paths = (path.Duplicate(),),
-				    properties = self.properties.Duplicate())
-	    result.append(object)
-	return result
+        result = []
+        for path in self.paths:
+            object = self.__class__(paths = (path.Duplicate(),),
+                                    properties = self.properties.Duplicate())
+            result.append(object)
+        return result
     script_access['PathsAsObjects'] = SCRIPT_OBJECTLIST
 
     def AsBezier(self):
-	# is `return self' enough ?
-	return self.Duplicate()
+        # is `return self' enough ?
+        return self.Duplicate()
 
     #
     #
     #
 
     def SaveToFile(self, file):
-	Primitive.SaveToFile(self, file)
-	file.PolyBezier(self.paths)
+        Primitive.SaveToFile(self, file)
+        file.PolyBezier(self.paths)
 
     def load_straight(self, *args):
-	apply(self.paths[-1].AppendLine, args)
+        apply(self.paths[-1].AppendLine, args)
 
     def load_curve(self, *args):
-	apply(self.paths[-1].AppendBezier, args)
+        apply(self.paths[-1].AppendBezier, args)
 
     def load_close(self, copy_cont_from_last = 0):
-	self.paths[-1].load_close(copy_cont_from_last)
+        self.paths[-1].load_close(copy_cont_from_last)
 
     def guess_continuity(self):
-	for path in self.paths:
-	    path.guess_continuity()
+        for path in self.paths:
+            path.guess_continuity()
 
     def load_IsComplete(self):
-	if self.paths[0].len < 2:
-	    # we need at least two nodes
-	    return 0
-	return 1
+        if self.paths[0].len < 2:
+            # we need at least two nodes
+            return 0
+        return 1
 
     def Blend(self, other, frac1, frac2):
-	if self.__class__ != other.__class__:
-	    try:
-		other = other.AsBezier()
-		if not other:
-		    raise MismatchError
-	    except AttributeError, value:
-		if value == 'AsBezier':
-		    raise MismatchError
-		else:
-		    raise
+        if self.__class__ != other.__class__:
+            try:
+                other = other.AsBezier()
+                if not other:
+                    raise MismatchError
+            except AttributeError, value:
+                if value == 'AsBezier':
+                    raise MismatchError
+                else:
+                    raise
 
         paths = BlendPaths(self.paths, other.paths, frac1, frac2)
-	blended = PolyBezier(paths = paths)
-	self.set_blended_properties(blended, other, frac1, frac2)
-	return blended
+        blended = PolyBezier(paths = paths)
+        self.set_blended_properties(blended, other, frac1, frac2)
+        return blended
 
     def Editor(self):
-	return PolyBezierEditor(self)
+        return PolyBezierEditor(self)
 
 
 
@@ -279,8 +279,8 @@
     creation_text = _("Create Curve")
 
     def __init__(self, start):
-	self.path = CreatePath()
-	Creator.__init__(self, start)
+        self.path = CreatePath()
+        Creator.__init__(self, start)
 
     def apply_constraints(self, p, state):
         if self.path.len > 0:
@@ -289,7 +289,7 @@
             node = self.drag_start
         else:
             return p
-        
+
         if state & ConstraintMask:
             radius, angle = (p - node).polar()
             pi12 = pi / 12
@@ -299,50 +299,50 @@
 
     def ButtonDown(self, p, button, state):
         p = self.apply_constraints(p, state)
-	if self.path.len == 0:
-	    self.path.AppendLine(p)
-	else:
-	    self.path.AppendBezier(self.drag_cur, p, p)
-	return self.DragStart(p)
+        if self.path.len == 0:
+            self.path.AppendLine(p)
+        else:
+            self.path.AppendBezier(self.drag_cur, p, p)
+        return self.DragStart(p)
 
     def MouseMove(self, p, state):
-	if not (state & Button1Mask):
-	    return
-	self.DragMove(self.apply_constraints(p, state))
+        if not (state & Button1Mask):
+            return
+        self.DragMove(self.apply_constraints(p, state))
 
     def ButtonUp(self, p, button, state):
-	if not (state & Button1Mask):
-	    return
+        if not (state & Button1Mask):
+            return
         p = self.apply_constraints(p, state)
-	self.DragStop(p)
-	if self.path.len > 1:
-	    type, (p1, p2), p, cont = self.path.Segment(-1)
-	    p2 = adjust_control_point(p2, p, self.drag_cur, ContSymmetrical)
-	    self.path.SetBezier(-1, p1, p2, p, ContSymmetrical)
+        self.DragStop(p)
+        if self.path.len > 1:
+            type, (p1, p2), p, cont = self.path.Segment(-1)
+            p2 = adjust_control_point(p2, p, self.drag_cur, ContSymmetrical)
+            self.path.SetBezier(-1, p1, p2, p, ContSymmetrical)
 
     def EndCreation(self):
-	return self.path.len > 1
+        return self.path.len > 1
 
     def AppendInteractive(self, p):
-	return self
+        return self
 
     def ContinueCreation(self):
-	return self.AppendInteractive
+        return self.AppendInteractive
 
     def DrawDragged(self, device, partially):
-	if not partially:
-	    self.path.draw_not_last(device.Bezier, device.Line)
-	device.DrawHandleLine(self.path.Node(-1), self.drag_cur)
-	device.DrawSmallRectHandle(self.drag_cur)
-	if self.path.len > 1:
-	    type, (p1, p2), p, cont = self.path.Segment(-1)
-	    p2 = adjust_control_point(p2, p, self.drag_cur, ContSymmetrical)
-	    device.Bezier(self.path.Node(-2), p1, p2, p)
-	    device.DrawHandleLine(p, p2)
-	    device.DrawSmallRectHandle(p2)
+        if not partially:
+            self.path.draw_not_last(device.Bezier, device.Line)
+        device.DrawHandleLine(self.path.Node(-1), self.drag_cur)
+        device.DrawSmallRectHandle(self.drag_cur)
+        if self.path.len > 1:
+            type, (p1, p2), p, cont = self.path.Segment(-1)
+            p2 = adjust_control_point(p2, p, self.drag_cur, ContSymmetrical)
+            device.Bezier(self.path.Node(-2), p1, p2, p)
+            device.DrawHandleLine(p, p2)
+            device.DrawSmallRectHandle(p2)
 
     def CreatedObject(self):
-	return PolyBezier(paths = (self.path,),
+        return PolyBezier(paths = (self.path,),
                           properties = DefaultGraphicsProperties())
 
 
@@ -352,9 +352,9 @@
     creation_text = _("Create Poly-Line")
 
     def __init__(self, start):
-	self.path = CreatePath()
+        self.path = CreatePath()
         self.was_dragged = 0
-	Creator.__init__(self, start)
+        Creator.__init__(self, start)
 
     def apply_constraints(self, p, state):
         if self.path.len > 0:
@@ -363,7 +363,7 @@
             node = self.drag_start
         else:
             return p
-        
+
         if state & ConstraintMask:
             radius, angle = (p - node).polar()
             pi12 = pi / 12
@@ -372,43 +372,43 @@
         return p
 
     def ButtonDown(self, p, button, state):
-	return self.DragStart(self.apply_constraints(p, state))
+        return self.DragStart(self.apply_constraints(p, state))
 
     def MouseMove(self, p, state):
-	if not (state & Button1Mask):
-	    return
+        if not (state & Button1Mask):
+            return
         self.was_dragged = 1
-	self.DragMove(self.apply_constraints(p, state))
+        self.DragMove(self.apply_constraints(p, state))
 
     def ButtonUp(self, p, button, state):
-	if not (state & Button1Mask):
-	    return
-	self.DragStop(self.apply_constraints(p, state))
+        if not (state & Button1Mask):
+            return
+        self.DragStop(self.apply_constraints(p, state))
         if self.was_dragged and self.path.len == 0:
             self.path.AppendLine(self.drag_start)
         self.path.AppendLine(self.drag_cur)
 
     def EndCreation(self):
-	return self.path.len > 1
+        return self.path.len > 1
 
     def AppendInteractive(self, p):
-	return self
+        return self
 
     def ContinueCreation(self):
-	return self.AppendInteractive
+        return self.AppendInteractive
 
     def DrawDragged(self, device, partially):
-	if self.path.len > 1:
-	    if not partially:
+        if self.path.len > 1:
+            if not partially:
                 device.DrawBezierPath(self.path)
         if self.path.len >= 1:
-	    device.Line(self.path.Node(-1), self.drag_cur)
+            device.Line(self.path.Node(-1), self.drag_cur)
         else:
             if self.was_dragged:
                 device.Line(self.drag_start, self.drag_cur)
 
     def CreatedObject(self):
-	return PolyBezier(paths = (self.path,),
+        return PolyBezier(paths = (self.path,),
                           properties = DefaultGraphicsProperties())
 
 SelCurvePoint = -1
@@ -419,12 +419,12 @@
     commands = []
 
     def __init__(self, object):
-	self.selected_path = -1
-	self.selected_idx = -1
-	self.selection_type = SelNone
-	self.other_segment = -1
-	Editor.__init__(self, object)
-	self.Deselect()
+        self.selected_path = -1
+        self.selected_idx = -1
+        self.selection_type = SelNone
+        self.other_segment = -1
+        Editor.__init__(self, object)
+        self.Deselect()
 
     def SelectPoint(self, p, rect, device, mode):
         self.deselect()
@@ -432,9 +432,9 @@
         for i in range(len(self.paths)):
             path = self.paths[i]
             t = path.nearest_point(p.x, p.y)
-	    if t is not None:
-		p2 = path.point_at(t)
-		found.append((abs(p - p2), i, t, p2))
+            if t is not None:
+                p2 = path.point_at(t)
+                found.append((abs(p - p2), i, t, p2))
         dist, i, t, p2 = min(found)
         self.selected_path = i
         self.selected_idx = t
@@ -466,63 +466,63 @@
             path.SelectSegment(segment, 0)
 
     def SelectRect(self, rect, mode = SelectSet):
-	selected = 0
-	for path in self.paths:
-	    selected = path.select_rect(rect, mode) or selected
+        selected = 0
+        for path in self.paths:
+            selected = path.select_rect(rect, mode) or selected
         self.selection_type = SelNodes
-	return selected
+        return selected
 
     def SelectAllNodes(self):
-	for path in self.paths:
-	    for i in range(path.len):
-		path.SelectSegment(i, 1)
+        for path in self.paths:
+            for i in range(path.len):
+                path.SelectSegment(i, 1)
     AddCmd(commands, SelectAllNodes, _("Select All Nodes"))
 
     def deselect(self):
-	for path in self.paths:
-	    path.deselect()
+        for path in self.paths:
+            path.deselect()
 
     def Deselect(self):
         self.deselect()
-	self.selected_path = -1
-	self.selected_idx = -1
-	self.selection_type = SelNone
+        self.selected_path = -1
+        self.selected_idx = -1
+        self.selection_type = SelNone
 
     def ButtonDown(self, p, button, state):
-	if self.selected_path >= 0:
-	    path = self.paths[self.selected_path]
-	    if self.selection_type == SelNodes:
-		start = path.Node(self.selected_idx)
-		self.DragStart(start)
-		return p - start
-	    elif self.selection_type == SelSegmentFirst:
-		segment = self.selected_idx
-		if segment > 1 \
-		   and path.SegmentType(segment - 1) == Bezier\
-		   and path.Continuity(segment - 1):
-		    self.other_segment = segment - 1
-		elif path.closed and segment == 1 \
-		     and path.SegmentType(-1) == Bezier\
-		     and path.Continuity(-1):
-		    self.other_segment = path.len - 1
-		else:
-		    self.other_segment = -1
-		p1 = path.Segment(segment)[1][0]
-		self.DragStart(p1)
-		return p - p1
-	    elif self.selection_type == SelSegmentLast:
-		segment = self.selected_idx
-		self.other_segment = -1
-		if path.Continuity(segment):
-		    if segment < path.len - 1 \
-		       and path.SegmentType(segment + 1) == Bezier:
-			self.other_segment = segment + 1
-		    elif path.closed and segment == path.len - 1 \
-			 and path.SegmentType(1) == Bezier:
-			self.other_segment = 1
-		p2 = path.Segment(segment)[1][1]
-		self.DragStart(p2)
-		return p - p2
+        if self.selected_path >= 0:
+            path = self.paths[self.selected_path]
+            if self.selection_type == SelNodes:
+                start = path.Node(self.selected_idx)
+                self.DragStart(start)
+                return p - start
+            elif self.selection_type == SelSegmentFirst:
+                segment = self.selected_idx
+                if segment > 1 \
+                   and path.SegmentType(segment - 1) == Bezier\
+                   and path.Continuity(segment - 1):
+                    self.other_segment = segment - 1
+                elif path.closed and segment == 1 \
+                     and path.SegmentType(-1) == Bezier\
+                     and path.Continuity(-1):
+                    self.other_segment = path.len - 1
+                else:
+                    self.other_segment = -1
+                p1 = path.Segment(segment)[1][0]
+                self.DragStart(p1)
+                return p - p1
+            elif self.selection_type == SelSegmentLast:
+                segment = self.selected_idx
+                self.other_segment = -1
+                if path.Continuity(segment):
+                    if segment < path.len - 1 \
+                       and path.SegmentType(segment + 1) == Bezier:
+                        self.other_segment = segment + 1
+                    elif path.closed and segment == path.len - 1 \
+                         and path.SegmentType(1) == Bezier:
+                        self.other_segment = 1
+                p2 = path.Segment(segment)[1][1]
+                self.DragStart(p2)
+                return p - p2
             elif self.selection_type == SelCurvePoint:
                 start = path.point_at(self.selected_idx)
                 segment = int(ceil(self.selected_idx))
@@ -554,14 +554,14 @@
                     elif path.closed and segment == 1:
                         prev = path.len - 1
                 self.other_segment = (prev, next)
-		self.DragStart(start)
-		return p - start
+                self.DragStart(start)
+                return p - start
 
     def apply_constraints(self, p, state):
         if state & ConstraintMask:
             if self.selection_type == SelNodes:
-		pi4 = pi / 4
-		off = p - self.drag_start
+                pi4 = pi / 4
+                off = p - self.drag_start
                 d = Polar(pi4 * round(atan2(off.y, off.x) / pi4))
                 p = self.drag_start + (off * d) * d
             elif self.selection_type in (SelSegmentFirst, SelSegmentLast):
@@ -575,48 +575,48 @@
                 angle = pi12 * floor(angle / pi12 + 0.5)
                 p = node + Polar(radius, angle)
         return p
-            
+
     def MouseMove(self, p, state):
         self.DragMove(self.apply_constraints(p, state))
 
     def ButtonUp(self, p, button, state):
         p = self.apply_constraints(p, state)
-	self.DragStop(p)
-	type = self.selection_type
-	if type == SelNodes:
-	    undo = []
-	    for path in self.paths:
-		if path.selection_count() > 0:
-		    undo.append(path.move_selected_nodes(self.off))
-		else:
-		    undo.append(None)
-	    if undo:
-		self._changed()
-		return (self.do_undo, undo)
-	elif type in (SelSegmentFirst, SelSegmentLast):
-	    idx = self.selected_path
-	    segment = self.selected_idx
-	    path = self.paths[idx].Duplicate()
-	    paths = self.paths[:idx] + (path,) + self.paths[idx + 1:]
-	    if type == SelSegmentFirst:
-		type, (p1, p2), node, cont = path.Segment(segment)
-		path.SetBezier(segment, self.drag_cur, p2, node, cont)
-		if self.other_segment >= 0:
-		    other = self.other_segment
-		    type, (p1, p2), node, cont = path.Segment(other)
-		    p2 = adjust_control_point(p2, node, self.drag_cur, cont)
-		    path.SetBezier(other, p1, p2, node, cont)
-		path.SelectSegment(segment - 1)
-	    elif type == SelSegmentLast:
-		type, (p1, p2), node, cont = path.Segment(segment)
-		path.SetBezier(segment, p1, self.drag_cur, node, cont)
-		if self.other_segment >= 0:
-		    other = self.other_segment
-		    type, (p1, p2), node2, cont2 = path.Segment(other)
-		    p1 = adjust_control_point(p1, node, self.drag_cur, cont)
-		    path.SetBezier(other, p1, p2, node2, cont2)
-		path.SelectSegment(segment)
-	    return self.set_paths(paths) # set_paths calls _changed()
+        self.DragStop(p)
+        type = self.selection_type
+        if type == SelNodes:
+            undo = []
+            for path in self.paths:
+                if path.selection_count() > 0:
+                    undo.append(path.move_selected_nodes(self.off))
+                else:
+                    undo.append(None)
+            if undo:
+                self._changed()
+                return (self.do_undo, undo)
+        elif type in (SelSegmentFirst, SelSegmentLast):
+            idx = self.selected_path
+            segment = self.selected_idx
+            path = self.paths[idx].Duplicate()
+            paths = self.paths[:idx] + (path,) + self.paths[idx + 1:]
+            if type == SelSegmentFirst:
+                type, (p1, p2), node, cont = path.Segment(segment)
+                path.SetBezier(segment, self.drag_cur, p2, node, cont)
+                if self.other_segment >= 0:
+                    other = self.other_segment
+                    type, (p1, p2), node, cont = path.Segment(other)
+                    p2 = adjust_control_point(p2, node, self.drag_cur, cont)
+                    path.SetBezier(other, p1, p2, node, cont)
+                path.SelectSegment(segment - 1)
+            elif type == SelSegmentLast:
+                type, (p1, p2), node, cont = path.Segment(segment)
+                path.SetBezier(segment, p1, self.drag_cur, node, cont)
+                if self.other_segment >= 0:
+                    other = self.other_segment
+                    type, (p1, p2), node2, cont2 = path.Segment(other)
+                    p1 = adjust_control_point(p1, node, self.drag_cur, cont)
+                    path.SetBezier(other, p1, p2, node2, cont2)
+                path.SelectSegment(segment)
+            return self.set_paths(paths) # set_paths calls _changed()
         elif self.selection_type == SelCurvePoint:
             idx = self.selected_path
             path = self.paths[idx].Duplicate()
@@ -663,51 +663,51 @@
             return self.set_paths(paths) # set_paths calls _changed()
 
     def DrawDragged(self, device, partially):
-	if self.selection_type == SelNodes:
-	    for path in self.paths:
-		path.draw_dragged_nodes(self.off, partially,
-					device.Bezier, device.Line)
-	elif self.selection_type == SelSegmentFirst:
-	    if not partially:
-		for path in self.paths:
-		    path.draw_unselected(device.Bezier, device.Line)
-	    path = self.paths[self.selected_path]
-	    segment = self.selected_idx
-	    node = path.Node(segment - 1)
-	    type, (p1, p2), node2, cont = path.Segment(segment)
-	    device.Bezier(node, self.drag_cur, p2, node2)
-	    device.DrawSmallRectHandle(self.drag_cur)
-	    device.DrawHandleLine(node, self.drag_cur)
-	    if self.other_segment >= 0:
-		other = self.other_segment
-		type, (p1, p2), node, cont = path.Segment(other)
-		p2 = adjust_control_point(p2, node, self.drag_cur, cont)
-		device.Bezier(path.Node(other - 1), p1, p2, node)
-		device.DrawSmallRectHandle(p2)
-		device.DrawHandleLine(node, p2)
-	elif self.selection_type == SelSegmentLast:
-	    if not partially:
-		for path in self.paths:
-		    path.draw_unselected(device.Bezier, device.Line)
-	    path = self.paths[self.selected_path]
-	    segment = self.selected_idx
-	    type, (p1, p2), node, cont = path.Segment(segment)
-	    device.Bezier(path.Node(segment - 1), p1, self.drag_cur, node)
-	    device.DrawSmallRectHandle(self.drag_cur)
-	    device.DrawHandleLine(node, self.drag_cur)
-	    if self.other_segment >= 0:
-		other = self.other_segment
-		type, (p1, p2), node2, cont2 = path.Segment(other)
-		p1 = adjust_control_point(p1, node, self.drag_cur, cont)
-		device.Bezier(node, p1, p2, node2)
-		device.DrawSmallRectHandle(p1)
-		device.DrawHandleLine(node, p1)
+        if self.selection_type == SelNodes:
+            for path in self.paths:
+                path.draw_dragged_nodes(self.off, partially,
+                                        device.Bezier, device.Line)
+        elif self.selection_type == SelSegmentFirst:
+            if not partially:
+                for path in self.paths:
+                    path.draw_unselected(device.Bezier, device.Line)
+            path = self.paths[self.selected_path]
+            segment = self.selected_idx
+            node = path.Node(segment - 1)
+            type, (p1, p2), node2, cont = path.Segment(segment)
+            device.Bezier(node, self.drag_cur, p2, node2)
+            device.DrawSmallRectHandle(self.drag_cur)
+            device.DrawHandleLine(node, self.drag_cur)
+            if self.other_segment >= 0:
+                other = self.other_segment
+                type, (p1, p2), node, cont = path.Segment(other)
+                p2 = adjust_control_point(p2, node, self.drag_cur, cont)
+                device.Bezier(path.Node(other - 1), p1, p2, node)
+                device.DrawSmallRectHandle(p2)
+                device.DrawHandleLine(node, p2)
+        elif self.selection_type == SelSegmentLast:
+            if not partially:
+                for path in self.paths:
+                    path.draw_unselected(device.Bezier, device.Line)
+            path = self.paths[self.selected_path]
+            segment = self.selected_idx
+            type, (p1, p2), node, cont = path.Segment(segment)
+            device.Bezier(path.Node(segment - 1), p1, self.drag_cur, node)
+            device.DrawSmallRectHandle(self.drag_cur)
+            device.DrawHandleLine(node, self.drag_cur)
+            if self.other_segment >= 0:
+                other = self.other_segment
+                type, (p1, p2), node2, cont2 = path.Segment(other)
+                p1 = adjust_control_point(p1, node, self.drag_cur, cont)
+                device.Bezier(node, p1, p2, node2)
+                device.DrawSmallRectHandle(p1)
+                device.DrawHandleLine(node, p1)
         elif self.selection_type == SelCurvePoint:
             path = self.paths[self.selected_path]
             segment = int(self.selected_idx)
             t = self.selected_idx - segment
             prevnode = path.Node(segment)
-            
+
             type, control, node, cont = path.Segment(segment + 1)
             if type == Bezier:
                 p1, p2 = control
@@ -760,10 +760,10 @@
         NodeHandle = handle.MakeNodeHandle
         ControlHandle = handle.MakeControlHandle
         LineHandle = handle.MakeLineHandle
-	handles = []
+        handles = []
         node_handles = []
         append = handles.append
-	for path_idx in range(len(self.paths)):
+        for path_idx in range(len(self.paths)):
             path = self.paths[path_idx]
             if path.len > 0:
                 if not path.closed:
@@ -787,33 +787,33 @@
         return handles + node_handles
 
     def Info(self):
-	selected = 0
-	idx = None
-	paths = self.paths
-	for i in range(len(paths)):
-	    path = paths[i]
-	    count = path.selection_count()
-	    if count > 0:
-		selected = selected + count
-		idx = i
-	if selected > 1:
-	    return _("%d nodes in PolyBezier") % selected
-	else:
-	    if idx is not None:
-		path = paths[idx]
-		for i in range(path.len):
-		    if path.SegmentSelected(i):
-			break
-		else:
-		    warn(INTERNAL, 'Strange selection count')
-		    return _("PolyBezier")
-		if i == 0:
-		    return _("First node of PolyBezier")
-		elif i == path.len - 1:
-		    return _("Last node of PolyBezier")
-		else:
-		    return _("1 node of PolyBezier")
-	    else:
+        selected = 0
+        idx = None
+        paths = self.paths
+        for i in range(len(paths)):
+            path = paths[i]
+            count = path.selection_count()
+            if count > 0:
+                selected = selected + count
+                idx = i
+        if selected > 1:
+            return _("%d nodes in PolyBezier") % selected
+        else:
+            if idx is not None:
+                path = paths[idx]
+                for i in range(path.len):
+                    if path.SegmentSelected(i):
+                        break
+                else:
+                    warn(INTERNAL, 'Strange selection count')
+                    return _("PolyBezier")
+                if i == 0:
+                    return _("First node of PolyBezier")
+                elif i == path.len - 1:
+                    return _("Last node of PolyBezier")
+                else:
+                    return _("1 node of PolyBezier")
+            else:
                 if self.selection_type == SelCurvePoint:
                     return _("Point on curve at position %.2f") \
                            % self.selected_idx
@@ -870,108 +870,108 @@
                     paths.append(path)
         return self.set_paths(paths)
     AddCmd(commands, OpenNodes, _("Cut Curve"), key_stroke = 'c',
-	   bitmap = pixmaps.BezierOpenNodes)
+           bitmap = pixmaps.BezierOpenNodes)
 
     def CloseNodes(self):
-	# find out if close is possible
-	two = 0
-	one = 0
-	for i in range(len(self.paths)):
-	    path = self.paths[i]
-	    selected = path.selection_count()
-	    if not selected:
-		continue
-	    if (path.closed and selected) or selected not in (1, 2):
-		return
-	    if selected == 1:
-		if path.SegmentSelected(0) or path.SegmentSelected(-1):
-		    one = one + 1
-		    continue
-		return
-	    else:
-		if path.SegmentSelected(0) and path.SegmentSelected(-1):
-		    two = two + 1
-		    continue
-		return
-	# now, close the nodes
-	if one == 2 and two == 0:
-	    paths = []
-	    append_to = None
-	    for path in self.paths:
-		if path.selection_count():
-		    if append_to:
-			# path is the second of the paths involved
-			end_node = append_to.Node(-1)
-			if path.SegmentSelected(0):
-			    for i in range(1, path.len):
-				type, p12, p, cont = path.Segment(i)
-				if end_node is not None and type == Bezier:
-				    p12 = (p12[0] + end_node - path.Node(0),
-					   p12[1])
-				    end_node = None
-				append_to.AppendSegment(type, p12, p, cont)
-			else:
-			    for i in range(path.len - 1, 0, -1):
-				type, p12, p3, cont = path.Segment(i)
-				if end_node is not None and type == Bezier:
-				    p12 = (p12[0],
-					   p12[1] + end_node - path.Node(-1))
-				    end_node = None
-				p = path.Node(i - 1)
-				if type == Bezier:
-				    p12 = (p12[1], p12[0])
-				append_to.AppendSegment(type, p12, p,
-							path.Continuity(i - 1))
-			continue
-		    else:
-			# path is the first of the paths involved
-			if path.SegmentSelected(0):
-			    # reverse the path
-			    append_to = CreatePath()
-			    p = path.Node(-1)
-			    append_to.AppendLine(p, ContAngle)
-			    for i in range(path.len - 1, 0, -1):
-				type, p12, p3, cont = path.Segment(i)
-				p = path.Node(i - 1)
-				if type == Bezier:
-				    p12 = (p12[1], p12[0])
-				append_to.AppendSegment(type, p12, p,
-							path.Continuity(i - 1))
-			    path = append_to
-			else:
-			    path = append_to = path.Duplicate()
-			append_to.SetContinuity(-1, ContAngle)
-		paths.append(path)
-	    undo = self.set_paths(paths)
-	elif one == 0 and two == 1:
-	    undo_list = []
-	    for path in self.paths:
-		if path.selection_count():
-		    undo_list.append(path.ClosePath())
-		else:
-		    undo_list.append(None)
-	    undo = (self.object.do_undo, undo_list)
-	    self._changed()
-	else:
-	    return
-	return undo
+        # find out if close is possible
+        two = 0
+        one = 0
+        for i in range(len(self.paths)):
+            path = self.paths[i]
+            selected = path.selection_count()
+            if not selected:
+                continue
+            if (path.closed and selected) or selected not in (1, 2):
+                return
+            if selected == 1:
+                if path.SegmentSelected(0) or path.SegmentSelected(-1):
+                    one = one + 1
+                    continue
+                return
+            else:
+                if path.SegmentSelected(0) and path.SegmentSelected(-1):
+                    two = two + 1
+                    continue
+                return
+        # now, close the nodes
+        if one == 2 and two == 0:
+            paths = []
+            append_to = None
+            for path in self.paths:
+                if path.selection_count():
+                    if append_to:
+                        # path is the second of the paths involved
+                        end_node = append_to.Node(-1)
+                        if path.SegmentSelected(0):
+                            for i in range(1, path.len):
+                                type, p12, p, cont = path.Segment(i)
+                                if end_node is not None and type == Bezier:
+                                    p12 = (p12[0] + end_node - path.Node(0),
+                                           p12[1])
+                                    end_node = None
+                                append_to.AppendSegment(type, p12, p, cont)
+                        else:
+                            for i in range(path.len - 1, 0, -1):
+                                type, p12, p3, cont = path.Segment(i)
+                                if end_node is not None and type == Bezier:
+                                    p12 = (p12[0],
+                                           p12[1] + end_node - path.Node(-1))
+                                    end_node = None
+                                p = path.Node(i - 1)
+                                if type == Bezier:
+                                    p12 = (p12[1], p12[0])
+                                append_to.AppendSegment(type, p12, p,
+                                                        path.Continuity(i - 1))
+                        continue
+                    else:
+                        # path is the first of the paths involved
+                        if path.SegmentSelected(0):
+                            # reverse the path
+                            append_to = CreatePath()
+                            p = path.Node(-1)
+                            append_to.AppendLine(p, ContAngle)
+                            for i in range(path.len - 1, 0, -1):
+                                type, p12, p3, cont = path.Segment(i)
+                                p = path.Node(i - 1)
+                                if type == Bezier:
+                                    p12 = (p12[1], p12[0])
+                                append_to.AppendSegment(type, p12, p,
+                                                        path.Continuity(i - 1))
+                            path = append_to
+                        else:
+                            path = append_to = path.Duplicate()
+                        append_to.SetContinuity(-1, ContAngle)
+                paths.append(path)
+            undo = self.set_paths(paths)
+        elif one == 0 and two == 1:
+            undo_list = []
+            for path in self.paths:
+                if path.selection_count():
+                    undo_list.append(path.ClosePath())
+                else:
+                    undo_list.append(None)
+            undo = (self.object.do_undo, undo_list)
+            self._changed()
+        else:
+            return
+        return undo
     AddCmd(commands, CloseNodes, _("Close Nodes"),
-	   bitmap = pixmaps.BezierCloseNodes)
+           bitmap = pixmaps.BezierCloseNodes)
 
     def SetContinuity(self, cont):
-	new_paths = []
-	for path in self.paths:
-	    if path.selection_count():
-		new_paths.append(set_continuity(path, cont))
-	    else:
-		new_paths.append(path)
-	return self.set_paths(new_paths)
+        new_paths = []
+        for path in self.paths:
+            if path.selection_count():
+                new_paths.append(set_continuity(path, cont))
+            else:
+                new_paths.append(path)
+        return self.set_paths(new_paths)
     AddCmd(commands, 'ContAngle', _("Angle"), SetContinuity,
-	   args = ContAngle, bitmap = pixmaps.BezierAngle, key_stroke = 'a')
+           args = ContAngle, bitmap = pixmaps.BezierAngle, key_stroke = 'a')
     AddCmd(commands, 'ContSmooth', _("Smooth"), SetContinuity,
-	   args = ContSmooth, bitmap = pixmaps.BezierSmooth, key_stroke = 's')
+           args = ContSmooth, bitmap = pixmaps.BezierSmooth, key_stroke = 's')
     AddCmd(commands, 'ContSymmetrical', _("Symmetrical"), SetContinuity,
-	   args = ContSymmetrical, bitmap = pixmaps.BezierSymm, key_stroke='y')
+           args = ContSymmetrical, bitmap = pixmaps.BezierSymm, key_stroke='y')
 
     def SegmentsToLines(self):
         if self.selection_type == SelCurvePoint:
@@ -986,9 +986,9 @@
                     new_paths.append(segments_to_lines(path))
                 else:
                     new_paths.append(path)
-	return self.set_paths(new_paths)
+        return self.set_paths(new_paths)
     AddCmd(commands, SegmentsToLines, _("Curve->Line"), key_stroke = 'l',
-	   bitmap = pixmaps.BezierCurveLine)
+           bitmap = pixmaps.BezierCurveLine)
 
     def SegmentsToCurve(self):
         if self.selection_type == SelCurvePoint:
@@ -1003,32 +1003,32 @@
                     new_paths.append(segments_to_beziers(path))
                 else:
                     new_paths.append(path)
-	return self.set_paths(new_paths)
+        return self.set_paths(new_paths)
     AddCmd(commands, SegmentsToCurve, _("Line->Curve"), key_stroke = 'b',
-	   bitmap = pixmaps.BezierLineCurve)
+           bitmap = pixmaps.BezierLineCurve)
 
     def DeleteNodes(self):
-	new_paths = []
-	for path in self.paths:
-	    if path.selection_count() > 0:
-		newpath = delete_segments(path)
-	    else:
-		newpath = path
-	    if newpath.len > 1:
-		new_paths.append(newpath)
-	    else:
-		# all nodes of path have been deleted
-		if __debug__:
-		    pdebug('bezier', 'path removed')
-	if new_paths:
-	    return self.set_paths(new_paths)
-	else:
-	    if __debug__:
-		pdebug('bezier', 'PolyBezier removed')
-	    self.document.DeselectObject(self.object)
-	    return self.parent.Remove(self.object)
+        new_paths = []
+        for path in self.paths:
+            if path.selection_count() > 0:
+                newpath = delete_segments(path)
+            else:
+                newpath = path
+            if newpath.len > 1:
+                new_paths.append(newpath)
+            else:
+                # all nodes of path have been deleted
+                if __debug__:
+                    pdebug('bezier', 'path removed')
+        if new_paths:
+            return self.set_paths(new_paths)
+        else:
+            if __debug__:
+                pdebug('bezier', 'PolyBezier removed')
+            self.document.DeselectObject(self.object)
+            return self.parent.Remove(self.object)
     AddCmd(commands, DeleteNodes, _("Delete Nodes"),
-	   bitmap = pixmaps.BezierDeleteNode, key_stroke = ('-', 'Delete'))
+           bitmap = pixmaps.BezierDeleteNode, key_stroke = ('-', 'Delete'))
 
     def InsertNodes(self):
         if self.selection_type == SelCurvePoint:
@@ -1045,39 +1045,39 @@
                     new_paths.append(insert_segments(path))
                 else:
                     new_paths.append(path)
-	return self.set_paths(new_paths)
+        return self.set_paths(new_paths)
     AddCmd(commands, InsertNodes, _("Insert Nodes"), key_stroke = '+',
-	   bitmap = pixmaps.BezierInsertNode)
+           bitmap = pixmaps.BezierInsertNode)
 
     def ChangeRect(self):
-	prop = self.properties
-	if prop.IsAlgorithmicFill() or prop.IsAlgorithmicLine() \
-	   or prop.line_arrow1 is not None or prop.line_arrow2 is not None \
+        prop = self.properties
+        if prop.IsAlgorithmicFill() or prop.IsAlgorithmicLine() \
+           or prop.line_arrow1 is not None or prop.line_arrow2 is not None \
            or self.selection_type == SelCurvePoint:
-	    return self.bounding_rect
+            return self.bounding_rect
 
-	filled = self.Filled()
-	pts = []
-	for path in self.paths:
-	    if path.selection_count():
-		for i in range(1, path.len):
-		    if path.SegmentSelected(i - 1) or path.SegmentSelected(i):
-			pts.append(path.Node(i - 1))
-			type, p12, p, cont = path.Segment(i)
-			if type == Bezier:
-			    p1, p2 = p12
-			    pts.append(p1)
-			    pts.append(p2)
-			pts.append(p)
-		if filled and not path.closed:
-		    if path.SegmentSelected(-1):
-			pts.append(path.Node(0))
-		    if path.SegmentSelected(0):
-			pts.append(path.Node(-1))
-	if pts:
-	    return PointsToRect(pts).grown(prop.GrowAmount())
-	else:
-	    return EmptyRect
+        filled = self.Filled()
+        pts = []
+        for path in self.paths:
+            if path.selection_count():
+                for i in range(1, path.len):
+                    if path.SegmentSelected(i - 1) or path.SegmentSelected(i):
+                        pts.append(path.Node(i - 1))
+                        type, p12, p, cont = path.Segment(i)
+                        if type == Bezier:
+                            p1, p2 = p12
+                            pts.append(p1)
+                            pts.append(p2)
+                        pts.append(p)
+                if filled and not path.closed:
+                    if path.SegmentSelected(-1):
+                        pts.append(path.Node(0))
+                    if path.SegmentSelected(0):
+                        pts.append(path.Node(-1))
+        if pts:
+            return PointsToRect(pts).grown(prop.GrowAmount())
+        else:
+            return EmptyRect
 
     context_commands = ('SelectAllNodes',)
 
@@ -1085,17 +1085,17 @@
 
 def adjust_control_point(p, node, control, continuity):
     if continuity == ContSymmetrical:
-	return 2 * node - control
+        return 2 * node - control
     elif continuity == ContSmooth:
-	try:
-	    d = (control - node).normalized()
-	    length = abs(p - node)
-	    return node - length * d
-	except ZeroDivisionError:
-	    # control == node
-	    return p
+        try:
+            d = (control - node).normalized()
+            length = abs(p - node)
+            return node - length * d
+        except ZeroDivisionError:
+            # control == node
+            return p
     else:
-	return p
+        return p
 
 def subdivide(p0, p1, p2, p3, t = 0.5):
     t2 = 1 - t
@@ -1112,53 +1112,53 @@
     newpath = CreatePath()
     selected = path.selection_count()
     if (path.closed and selected == path.len - 1) or selected == path.len:
-	return newpath
+        return newpath
     f13 = 1.0 / 3.0;	f23 = 2.0 / 3.0
     i = 0
     while path.SegmentSelected(i):
-	i = i + 1
+        i = i + 1
     if path.closed and i > 0:
-	if path.SegmentType(i) == Bezier:
-	    last_p2 = path.Segment(i)[1][1]
-	    last_type = Bezier
-	else:
-	    last_p2 = f23 * path.Node(i - 1) + f13 * path.Node(i)
-	    last_type = Line
+        if path.SegmentType(i) == Bezier:
+            last_p2 = path.Segment(i)[1][1]
+            last_type = Bezier
+        else:
+            last_p2 = f23 * path.Node(i - 1) + f13 * path.Node(i)
+            last_type = Line
     else:
-	last_p2 = None
+        last_p2 = None
     newpath.AppendLine(path.Node(i), path.Continuity(i))
 
     seg_p1 = None; seg_type = None
     for i in range(i + 1, path.len):
-	type, p12, p, cont = path.Segment(i)
-	if type == Bezier:
-	    p1, p2 = p12
-	if path.SegmentSelected(i):
-	    if seg_type is None:
-		seg_type = type
-		if type == Bezier:
-		    seg_p1 = p1
-		else:
-		    seg_p1 = f23 * path.Node(i - 1) + f13 * p
-	else:
-	    if seg_type is not None:
-		if type == Bezier or seg_type == Bezier:
-		    if type == Line:
-			p2 = f13 * path.Node(i - 1) + f23 * p
-		    newpath.AppendBezier(seg_p1, p2, p, cont)
-		else:
-		    newpath.AppendLine(p, cont)
-		seg_type = None
-	    else:
-		newpath.AppendSegment(type, p12, p, cont)
+        type, p12, p, cont = path.Segment(i)
+        if type == Bezier:
+            p1, p2 = p12
+        if path.SegmentSelected(i):
+            if seg_type is None:
+                seg_type = type
+                if type == Bezier:
+                    seg_p1 = p1
+                else:
+                    seg_p1 = f23 * path.Node(i - 1) + f13 * p
+        else:
+            if seg_type is not None:
+                if type == Bezier or seg_type == Bezier:
+                    if type == Line:
+                        p2 = f13 * path.Node(i - 1) + f23 * p
+                    newpath.AppendBezier(seg_p1, p2, p, cont)
+                else:
+                    newpath.AppendLine(p, cont)
+                seg_type = None
+            else:
+                newpath.AppendSegment(type, p12, p, cont)
     if path.closed:
-	if last_p2 is not None:
-	    if last_type == Bezier or seg_type == Bezier:
-		newpath.AppendBezier(seg_p1, last_p2, newpath.Node(0),
-				     newpath.Continuity(0))
-	    else:
-		newpath.AppendLine(newpath.Node(0), newpath.Continuity(0))
-	newpath.ClosePath()
+        if last_p2 is not None:
+            if last_type == Bezier or seg_type == Bezier:
+                newpath.AppendBezier(seg_p1, last_p2, newpath.Node(0),
+                                     newpath.Continuity(0))
+            else:
+                newpath.AppendLine(newpath.Node(0), newpath.Continuity(0))
+        newpath.ClosePath()
     return newpath
 
 def insert_segments(path):
@@ -1167,54 +1167,54 @@
     newpath.select_segment(0, path.SegmentSelected(0))
 
     for i in range(1, path.len):
-	type, p12, p, cont = path.Segment(i)
-	if path.SegmentSelected(i) and path.SegmentSelected(i - 1):
-	    if type == Line:
-		node = 0.5 * path.Node(i - 1) + 0.5 * path.Node(i)
-		newpath.AppendLine(node)
-		newpath.select_segment(-1)
-		newpath.AppendLine(path.Node(i))
-		newpath.select_segment(-1)
-	    else:
+        type, p12, p, cont = path.Segment(i)
+        if path.SegmentSelected(i) and path.SegmentSelected(i - 1):
+            if type == Line:
+                node = 0.5 * path.Node(i - 1) + 0.5 * path.Node(i)
+                newpath.AppendLine(node)
+                newpath.select_segment(-1)
+                newpath.AppendLine(path.Node(i))
+                newpath.select_segment(-1)
+            else:
                 if newpath.Continuity(-1) == ContSymmetrical:
                     newpath.SetContinuity(-1, ContSmooth)
                 p1, p2 = p12
-		p1, p2, node, p3, p4 = subdivide(path.Node(i - 1), p1, p2, p)
-		newpath.AppendBezier(p1, p2, node, ContSymmetrical)
-		newpath.select_segment(-1)
+                p1, p2, node, p3, p4 = subdivide(path.Node(i - 1), p1, p2, p)
+                newpath.AppendBezier(p1, p2, node, ContSymmetrical)
+                newpath.select_segment(-1)
                 if cont == ContSymmetrical:
                     cont = ContSmooth
-		newpath.AppendBezier(p3, p4, p, cont)
-		newpath.select_segment(-1)
-	else:
-	    newpath.AppendSegment(type, p12, p, cont)
-	    newpath.select_segment(-1, path.SegmentSelected(i))
+                newpath.AppendBezier(p3, p4, p, cont)
+                newpath.select_segment(-1)
+        else:
+            newpath.AppendSegment(type, p12, p, cont)
+            newpath.select_segment(-1, path.SegmentSelected(i))
     if path.closed:
-	newpath.ClosePath()
-	newpath.SetContinuity(-1, path.Continuity(-1))
+        newpath.ClosePath()
+        newpath.SetContinuity(-1, path.Continuity(-1))
     return newpath
 
 def copy_selection(path, newpath):
     for i in range(path.len):
-	newpath.select_segment(i, path.SegmentSelected(i))
+        newpath.select_segment(i, path.SegmentSelected(i))
 
 def segments_to_lines(path):
     newpath = CreatePath()
     newpath.AppendLine(path.Node(0))
     for i in range(1, path.len):
-	if path.SegmentSelected(i) and path.SegmentSelected(i - 1):
-	    if path.SegmentType(i) == Bezier:
-		cont = ContAngle
-		newpath.SetContinuity(-1, ContAngle)
-	    else:
-		cont = path.Continuity(i)
-	    newpath.AppendLine(path.Node(i), cont)
-	else:
-	    apply(newpath.AppendSegment, path.Segment(i))
+        if path.SegmentSelected(i) and path.SegmentSelected(i - 1):
+            if path.SegmentType(i) == Bezier:
+                cont = ContAngle
+                newpath.SetContinuity(-1, ContAngle)
+            else:
+                cont = path.Continuity(i)
+            newpath.AppendLine(path.Node(i), cont)
+        else:
+            apply(newpath.AppendSegment, path.Segment(i))
     if path.closed:
-	cont = newpath.Continuity(-1)
-	newpath.ClosePath()
-	newpath.SetContinuity(-1, cont)
+        cont = newpath.Continuity(-1)
+        newpath.ClosePath()
+        newpath.SetContinuity(-1, cont)
     copy_selection(path, newpath)
     return newpath
 
@@ -1223,23 +1223,23 @@
     newpath = CreatePath()
     newpath.AppendLine(path.Node(0))
     for i in range(1, path.len):
-	type, p12, p, cont = path.Segment(i)
-	if path.SegmentSelected(i) and path.SegmentSelected(i - 1):
-	    cont = path.Continuity(i)
-	    if type == Line:
-		node1 = path.Node(i - 1); node2 = path.Node(i)
-		p1 = f23 * node1 + f13 * node2
-		p2 = f13 * node1 + f23 * node2
-		cont = ContAngle
-	    else:
-		p1, p2 = p12
-	    newpath.AppendBezier(p1, p2, p, cont)
-	else:
-	    newpath.AppendSegment(type, p12, p, cont)
+        type, p12, p, cont = path.Segment(i)
+        if path.SegmentSelected(i) and path.SegmentSelected(i - 1):
+            cont = path.Continuity(i)
+            if type == Line:
+                node1 = path.Node(i - 1); node2 = path.Node(i)
+                p1 = f23 * node1 + f13 * node2
+                p2 = f13 * node1 + f23 * node2
+                cont = ContAngle
+            else:
+                p1, p2 = p12
+            newpath.AppendBezier(p1, p2, p, cont)
+        else:
+            newpath.AppendSegment(type, p12, p, cont)
     if path.closed:
-	cont = newpath.Continuity(-1)
-	newpath.ClosePath()
-	newpath.SetContinuity(-1, cont)
+        cont = newpath.Continuity(-1)
+        newpath.ClosePath()
+        newpath.SetContinuity(-1, cont)
     copy_selection(path, newpath)
     return newpath
 
@@ -1247,31 +1247,31 @@
     f13 = 1.0 / 3.0;	f23 = 2.0 / 3.0
     newpath = path.Duplicate()
     for i in range(1, path.len):
-	if path.SegmentSelected(i):
-	    newpath.SetContinuity(i, cont)
-	    if cont == ContAngle:
-		continue
-	    if newpath.SegmentType(i) != Bezier:
-		continue
-	    if i == path.len - 1:
-		if newpath.closed:
-		    other = 1
-		else:
-		    continue
-	    else:
-		other = i + 1
-	    if newpath.SegmentType(other) != Bezier:
-		continue
-	    type, (p1, p2), node, oldcont = newpath.Segment(i)
-	    type, (p3, p4), other_node, other_cont = newpath.Segment(other)
+        if path.SegmentSelected(i):
+            newpath.SetContinuity(i, cont)
+            if cont == ContAngle:
+                continue
+            if newpath.SegmentType(i) != Bezier:
+                continue
+            if i == path.len - 1:
+                if newpath.closed:
+                    other = 1
+                else:
+                    continue
+            else:
+                other = i + 1
+            if newpath.SegmentType(other) != Bezier:
+                continue
+            type, (p1, p2), node, oldcont = newpath.Segment(i)
+            type, (p3, p4), other_node, other_cont = newpath.Segment(other)
 
-	    d = p3 - p2
-	    if cont == ContSymmetrical:
-		d = 0.5 * d
-	    p2 = adjust_control_point(p2, node, node + d, cont)
-	    p3 = adjust_control_point(p3, node, node - d, cont)
-	    newpath.SetBezier(i, p1, p2, node, cont)
-	    newpath.SetBezier(other, p3, p4, other_node, other_cont)
+            d = p3 - p2
+            if cont == ContSymmetrical:
+                d = 0.5 * d
+            p2 = adjust_control_point(p2, node, node + d, cont)
+            p3 = adjust_control_point(p3, node, node - d, cont)
+            newpath.SetBezier(i, p1, p2, node, cont)
+            newpath.SetBezier(other, p3, p4, other_node, other_cont)
     return newpath
 
 
@@ -1345,7 +1345,7 @@
     copy_path(path1, path, 1, index, copy_selection = 0)
     apply(function, args)
     return result
-    
+
 def segment_to_line(path, at):
     index = int(at)
     if path.SegmentType(index + 1) == Bezier:
@@ -1368,7 +1368,7 @@
         newpath = CreatePath()
         copy_path(newpath, path, 0, index)
         f13 = 1.0 / 3.0;
-	f23 = 2.0 / 3.0
+        f23 = 2.0 / 3.0
         node1 = path.Node(index);
         node2 = path.Node(index + 1)
         p1 = f23 * node1 + f13 * node2
@@ -1382,14 +1382,14 @@
     else:
         newpath = path
     return newpath
-    
 
 
+
 def CombineBeziers(beziers):
     combined = beziers[0].Duplicate()
     paths = combined.paths
     for bezier in beziers[1:]:
-	paths = paths + bezier.paths
+        paths = paths + bezier.paths
     combined.paths = paths
     return combined
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/blend.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/blend.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/blend.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -27,42 +27,42 @@
 
 def Blend(obj1, obj2, frac1, frac2 = None):
     if frac2 is None:
-	frac2 = 1.0 - frac1
+        frac2 = 1.0 - frac1
     try:
-	return obj1.Blend(obj2, frac1, frac2)
+        return obj1.Blend(obj2, frac1, frac2)
     except MismatchError:
-	pass
+        pass
     try:
-	return obj2.Blend(obj1, frac2, frac1)
+        return obj2.Blend(obj1, frac2, frac1)
     except MismatchError:
-	pass
+        pass
     try:
-	from bezier import PolyBezier
-	if not isinstance(obj1,PolyBezier) and not isinstance(obj2,PolyBezier)\
-	   and obj1.is_curve and obj2.is_curve:
+        from bezier import PolyBezier
+        if not isinstance(obj1,PolyBezier) and not isinstance(obj2,PolyBezier)\
+           and obj1.is_curve and obj2.is_curve:
             paths = BlendPaths(obj1.Paths(), obj2.Paths(), frac1, frac2)
             properties = Blend(obj1.Properties(), obj2.Properties(),
                                frac1, frac2)
-	    return PolyBezier(paths = paths, properties = properties)
+            return PolyBezier(paths = paths, properties = properties)
     except AttributeError, value:
-	if str(value) != 'is_curve':
-	    raise
-    
+        if str(value) != 'is_curve':
+            raise
+
     return obj1.Duplicate()
 
 
 def BlendTrafo(t1, t2, frac1, frac2):
     return Trafo(frac1 * t1.m11 + frac2 * t2.m11,
-		 frac1 * t1.m21 + frac2 * t2.m21,
-		 frac1 * t1.m12 + frac2 * t2.m12,
-		 frac1 * t1.m22 + frac2 * t2.m22,
-		 frac1 * t1.v1  + frac2 * t2.v1,
-		 frac1 * t1.v2  + frac2 * t2.v2)
+                 frac1 * t1.m21 + frac2 * t2.m21,
+                 frac1 * t1.m12 + frac2 * t2.m12,
+                 frac1 * t1.m22 + frac2 * t2.m22,
+                 frac1 * t1.v1  + frac2 * t2.v1,
+                 frac1 * t1.v2  + frac2 * t2.v2)
 
 def BlendPaths(paths1, paths2, frac1, frac2):
-	length = min((len(paths1), len(paths2)))
-	paths = [None] * length
-	blend_paths = _sketch.blend_paths
-	for i in range(length):
-	    paths[i] = blend_paths(paths1[i], paths2[i], frac1, frac2)
-	return tuple(paths)
+    length = min((len(paths1), len(paths2)))
+    paths = [None] * length
+    blend_paths = _sketch.blend_paths
+    for i in range(length):
+        paths[i] = blend_paths(paths1[i], paths2[i], frac1, frac2)
+    return tuple(paths)

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/blendgroup.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/blendgroup.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/blendgroup.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -45,83 +45,83 @@
     is_BlendInterpolation = 1
 
     def __init__(self, steps = 2, start = None, end = None,
-		 duplicate = None):
-	if duplicate is not None:
-	    self.steps = duplicate.steps
-	    Compound.__init__(self, duplicate = duplicate)
-	else:
-	    self.steps = steps
-	    if start is not None:
-		Compound.__init__(self, self.compute_blend(start, end))
-	    else:
-		Compound.__init__(self)
+                 duplicate = None):
+        if duplicate is not None:
+            self.steps = duplicate.steps
+            Compound.__init__(self, duplicate = duplicate)
+        else:
+            self.steps = steps
+            if start is not None:
+                Compound.__init__(self, self.compute_blend(start, end))
+            else:
+                Compound.__init__(self)
 
     def SetParameters(self, steps):
-	if steps < 2:
-	    raise ValueError, 'steps must be >= 2'
-	if self.steps != steps:
-	    undo = (self.SetParameters, self.steps)
-	    self.steps = steps
-	    self.parent.RecomputeChild(self)
-	else:
-	    undo = NullUndo
-	return undo
+        if steps < 2:
+            raise ValueError, 'steps must be >= 2'
+        if self.steps != steps:
+            undo = (self.SetParameters, self.steps)
+            self.steps = steps
+            self.parent.RecomputeChild(self)
+        else:
+            undo = NullUndo
+        return undo
 
     def Steps(self):
-	return self.steps
+        return self.steps
 
     def Recompute(self, start, end):
-	self.set_objects(self.compute_blend(start, end))
+        self.set_objects(self.compute_blend(start, end))
 
     def compute_blend(self, start, end):
-	steps = self.steps
-	blended = []
-	for step in range(1, steps):
-	    fraction = float(step) / steps
-	    blend = Blend(start, end, fraction)
-	    blend.SetDocument(self.document)
-	    blend.SetParent(None)
-	    blended.append(blend)
-	blended.reverse()
-	return blended
+        steps = self.steps
+        blended = []
+        for step in range(1, steps):
+            fraction = float(step) / steps
+            blend = Blend(start, end, fraction)
+            blend.SetDocument(self.document)
+            blend.SetParent(None)
+            blended.append(blend)
+        blended.reverse()
+        return blended
 
     def set_objects(self, new_objs):
-	# called by __init__ and recompute
-	if self.document is not None:
-	    self.document.AddClearRect(self.bounding_rect)
-	for obj in self.objects:
-	    obj.Destroy()
-	self.objects = new_objs
-	self.del_lazy_attrs()
-	if self.document is not None:
-	    self.document.AddClearRect(self.bounding_rect)
-	self.issue_changed()
+        # called by __init__ and recompute
+        if self.document is not None:
+            self.document.AddClearRect(self.bounding_rect)
+        for obj in self.objects:
+            obj.Destroy()
+        self.objects = new_objs
+        self.del_lazy_attrs()
+        if self.document is not None:
+            self.document.AddClearRect(self.bounding_rect)
+        self.issue_changed()
 
     def SaveToFile(self, file):
-	if file.options.full_blend:
-	    file.BeginBlendInterpolation(self.steps)
-	    for obj in self.objects:
-		obj.SaveToFile(file)
-	    file.EndBlendInterpolation()
-	else:
-	    file.BlendInterpolation(self.steps)
+        if file.options.full_blend:
+            file.BeginBlendInterpolation(self.steps)
+            for obj in self.objects:
+                obj.SaveToFile(file)
+            file.EndBlendInterpolation()
+        else:
+            file.BlendInterpolation(self.steps)
 
     def AsGroup(self):
-	return Group(self.objects[:])
+        return Group(self.objects[:])
 
     def Transform(self, trafo):
-	if self.parent.changing_children:
-	    return Compound.Transform(self, trafo)
-	else:
-	    return NullUndo
+        if self.parent.changing_children:
+            return Compound.Transform(self, trafo)
+        else:
+            return NullUndo
 
     def Translate(self, offset):
-	if self.parent.changing_children:
-	    Compound.Translate(self, offset)
-	return NullUndo
+        if self.parent.changing_children:
+            Compound.Translate(self, offset)
+        return NullUndo
 
     def Info(self):
-	return _("Interpolation with %d steps") % self.steps
+        return _("Interpolation with %d steps") % self.steps
 
 
 class BlendGroup(Compound):
@@ -132,138 +132,138 @@
     allow_traversal = 1 # allow selection of subobjects via M-Down etc.
 
     def __init__(self, steps = 0, start = None, end = None, duplicate = None):
-	# Three different ways to instantiate this class:
-	#
-	# 1. Duplicating a BlendGroup: duplicate is not None.
-	#
-	# 2. Creating a BlendGroup from two normal graphics objects:
-	#    start and end are not None.
-	#
-	# 3. Creating a BlendGroup from an sk file: steps is 0.
+        # Three different ways to instantiate this class:
+        #
+        # 1. Duplicating a BlendGroup: duplicate is not None.
+        #
+        # 2. Creating a BlendGroup from two normal graphics objects:
+        #    start and end are not None.
+        #
+        # 3. Creating a BlendGroup from an sk file: steps is 0.
 
-	if duplicate is not None:
-	    # case 1
-	    Compound.__init__(self, duplicate = duplicate)
-	    #self.Connect()
-	elif start is not None:
-	    # case 2
-	    inter = BlendInterpolation(steps, start, end)
-	    Compound.__init__(self, [start, inter, end])
-	    #self.Connect()
-	else:
-	    # case 3
-	    Compound.__init__(self)
+        if duplicate is not None:
+            # case 1
+            Compound.__init__(self, duplicate = duplicate)
+            #self.Connect()
+        elif start is not None:
+            # case 2
+            inter = BlendInterpolation(steps, start, end)
+            Compound.__init__(self, [start, inter, end])
+            #self.Connect()
+        else:
+            # case 3
+            Compound.__init__(self)
 
     def load_AppendObject(self, object):
-	Compound.load_AppendObject(self, object)
-	length = len(self.objects)
-	if length > 2 and length & 1:
-	    # last object was a control object
-	    if len(self.objects[-2].objects) == 0:
-		self.objects[-2].Recompute(self.objects[-3], self.objects[-1])
+        Compound.load_AppendObject(self, object)
+        length = len(self.objects)
+        if length > 2 and length & 1:
+            # last object was a control object
+            if len(self.objects[-2].objects) == 0:
+                self.objects[-2].Recompute(self.objects[-3], self.objects[-1])
 
     def insert(self, obj, at):
-	undo_info = None
-	try:
-	    if type(at) != IntType or at > len(self.objects):
-		at = len(self.objects)
-	    self.objects.insert(at, obj)
-	    obj.SetDocument(self.document)
-	    obj.SetParent(self)
-	    obj.Connect()
-	    undo_info = (self.remove, at)
-	    self._changed()
-	    return undo_info
-	except:
-	    if undo_info is not None:
-		Undo(undo_info)
-	    raise
+        undo_info = None
+        try:
+            if type(at) != IntType or at > len(self.objects):
+                at = len(self.objects)
+            self.objects.insert(at, obj)
+            obj.SetDocument(self.document)
+            obj.SetParent(self)
+            obj.Connect()
+            undo_info = (self.remove, at)
+            self._changed()
+            return undo_info
+        except:
+            if undo_info is not None:
+                Undo(undo_info)
+            raise
 
     def remove(self, idx):
-	obj = self.objects[idx]
-	del self.objects[idx]
-	obj.Disconnect()
-	obj.SetParent(None)
-	self._changed()
-	return (self.insert, obj, idx)
+        obj = self.objects[idx]
+        del self.objects[idx]
+        obj.Disconnect()
+        obj.SetParent(None)
+        self._changed()
+        return (self.insert, obj, idx)
 
     def do_remove_child(self, idx):
-	undo = []
-	try:
-	    if idx % 2 == 0:
-		# a control object
-		if self.document is not None:
-		    undo.append(self.document.AddClearRect(self.bounding_rect))
-		if len(self.objects) > 3:
-		    if idx == 0:
-			undo.append(self.remove(1))
-			undo.append(self.remove(0))
-		    elif idx == len(self.objects) - 1:
-			undo.append(self.remove(idx))
-			undo.append(self.remove(idx - 1))
-		    else:
-			steps = self.objects[idx + 1].Steps() \
-				+ self.objects[idx - 1].Steps()
-			u = (UndoAfter, CreateMultiUndo(self.remove(idx + 1),
-							self.remove(idx)),
-			     self.objects[idx - 1].SetParameters(steps))
-			undo.append(u)
-		else:
-		    # remove one of only two control objects -> Remove self
-		    undo.append(self.parent.Remove(self))
-		return CreateListUndo(undo)
-	    else:
-		# XXX implement this case
-		raise ValueError, 'BlendGroup: cannot remove non control child'
-	except:
-	    Undo(CreateListUndo(undo))
-	    raise
+        undo = []
+        try:
+            if idx % 2 == 0:
+                # a control object
+                if self.document is not None:
+                    undo.append(self.document.AddClearRect(self.bounding_rect))
+                if len(self.objects) > 3:
+                    if idx == 0:
+                        undo.append(self.remove(1))
+                        undo.append(self.remove(0))
+                    elif idx == len(self.objects) - 1:
+                        undo.append(self.remove(idx))
+                        undo.append(self.remove(idx - 1))
+                    else:
+                        steps = self.objects[idx + 1].Steps() \
+                              + self.objects[idx - 1].Steps()
+                        u = (UndoAfter, CreateMultiUndo(self.remove(idx + 1),
+                                                        self.remove(idx)),
+                             self.objects[idx - 1].SetParameters(steps))
+                        undo.append(u)
+                else:
+                    # remove one of only two control objects -> Remove self
+                    undo.append(self.parent.Remove(self))
+                return CreateListUndo(undo)
+            else:
+                # XXX implement this case
+                raise ValueError, 'BlendGroup: cannot remove non control child'
+        except:
+            Undo(CreateListUndo(undo))
+            raise
 
     def RemoveSlice(self, min, max):
-	raise SketchInternalError('RemoveSlice not allowed for BlendGroup')
+        raise SketchInternalError('RemoveSlice not allowed for BlendGroup')
 
     def RemoveObjects(self, infolist):
-	if not infolist:
-	    return NullUndo
-	sliced = selinfo.list_to_tree_sliced(infolist)
-	sliced.reverse()
-	undo = [self.begin_change_children()]
-	try:
-	    for start, end in sliced:
-		if type(end) == IntType:
-		    # > 1 adjacent children of self. XXX implement this
-		    raise SketchInternalError('Deletion of multiple objects'
-					      ' of BlendGroups not yet'
-					      ' implemented')
-		elif type(end) == ListType:
-		    # remove grandchildren (children of child of self)
-		    if start % 2 == 0:
-			# control object changes. This should result in
-			# a recompute() automatically.
-			undo.append(self.objects[start].RemoveObjects(end))
-		    else:
-			pass
-		else:
-		    # a single child. If it's one of our control
-		    # objects, remove self
-		    undo.append(self.do_remove_child(start))
-	    undo.append(self.end_change_children())
-	    return CreateListUndo(undo)
-	except:
-	    Undo(CreateListUndo(undo))
-	    raise
+        if not infolist:
+            return NullUndo
+        sliced = selinfo.list_to_tree_sliced(infolist)
+        sliced.reverse()
+        undo = [self.begin_change_children()]
+        try:
+            for start, end in sliced:
+                if type(end) == IntType:
+                    # > 1 adjacent children of self. XXX implement this
+                    raise SketchInternalError('Deletion of multiple objects'
+                                              ' of BlendGroups not yet'
+                                              ' implemented')
+                elif type(end) == ListType:
+                    # remove grandchildren (children of child of self)
+                    if start % 2 == 0:
+                        # control object changes. This should result in
+                        # a recompute() automatically.
+                        undo.append(self.objects[start].RemoveObjects(end))
+                    else:
+                        pass
+                else:
+                    # a single child. If it's one of our control
+                    # objects, remove self
+                    undo.append(self.do_remove_child(start))
+            undo.append(self.end_change_children())
+            return CreateListUndo(undo)
+        except:
+            Undo(CreateListUndo(undo))
+            raise
 
     def permute_objects(self, permutation):
-	# for now, silently ignore this
-	return NullUndo
+        # for now, silently ignore this
+        return NullUndo
 
     def DuplicateObjects(self, infolist, offset):
-	# XXX: should allow duplication of the control objects by inserting
-	# them into the parent.
-	return [], NullUndo
+        # XXX: should allow duplication of the control objects by inserting
+        # them into the parent.
+        return [], NullUndo
 
     def ReplaceChild(self, child, object):
-	idx = self.objects.index(child)
+        idx = self.objects.index(child)
         if idx % 2 == 0:
             # the object is a control object
             undo = self.ReplaceChild, object, child
@@ -277,16 +277,16 @@
             raise SketchError('Cannot replace child')
 
     def SelectSubobject(self, p, rect, device, path = None, *rest):
-	idx = self.Hit(p, rect, device) - 1
-	obj = self.objects[idx]
-	if idx % 2 == 0:
-	    # a control object
-	    if path:
-		path_idx = path[0]
-		path = path[1:]
-		obj = obj.SelectSubobject(p, rect, device, path)
-	    elif path == ():
-		obj = obj.SelectSubobject(p, rect, device)
+        idx = self.Hit(p, rect, device) - 1
+        obj = self.objects[idx]
+        if idx % 2 == 0:
+            # a control object
+            if path:
+                path_idx = path[0]
+                path = path[1:]
+                obj = obj.SelectSubobject(p, rect, device, path)
+            elif path == ():
+                obj = obj.SelectSubobject(p, rect, device)
             info = selinfo.prepend_idx(idx, obj)
         else:
             # an interpolation object
@@ -294,110 +294,110 @@
                 info = self
             else:
                 info = selinfo.prepend_idx(idx, obj)
-	return info
+        return info
 
     def ForAllUndo(self, func):
-	# XXX: should we just change start and end and recompute?
-	self.begin_change_children()
-	undo = map(func, self.objects)
-	self.end_change_children(ignore_child_changes = 1)
-	idx = range(0, len(self.objects), 2)
-	undo = map(operator.getitem, [undo] * len(idx), idx)
-	return CreateListUndo(undo)
+        # XXX: should we just change start and end and recompute?
+        self.begin_change_children()
+        undo = map(func, self.objects)
+        self.end_change_children(ignore_child_changes = 1)
+        idx = range(0, len(self.objects), 2)
+        undo = map(operator.getitem, [undo] * len(idx), idx)
+        return CreateListUndo(undo)
 
     def begin_change_children(self):
-	self.child_has_changed = 0
-	return Compound.begin_change_children(self)
+        self.child_has_changed = 0
+        return Compound.begin_change_children(self)
 
     def end_change_children(self, ignore_child_changes = 0):
-	if self.child_has_changed and not ignore_child_changes:
-	    self.document.AddAfterHandler(self.recompute, (), self.depth())
-	self.child_has_changed = 0
-	return Compound.end_change_children(self)
+        if self.child_has_changed and not ignore_child_changes:
+            self.document.AddAfterHandler(self.recompute, (), self.depth())
+        self.child_has_changed = 0
+        return Compound.end_change_children(self)
 
     def ChildChanged(self, child):
-	idx = self.objects.index(child)
-	if idx % 2 == 0:
-	    if self.changing_children:
-		self.child_has_changed = 1
-	    else:
-		depth = self.depth(); recompute = self.recompute
-		if idx > 0:
-		    self.document.AddAfterHandler(recompute, (idx - 1,), depth)
-		if idx < len(self.objects) - 1:
-		    self.document.AddAfterHandler(recompute, (idx + 1,), depth)
-	else:
-	    Compound.ChildChanged(self, child)
-	self.del_lazy_attrs()
+        idx = self.objects.index(child)
+        if idx % 2 == 0:
+            if self.changing_children:
+                self.child_has_changed = 1
+            else:
+                depth = self.depth(); recompute = self.recompute
+                if idx > 0:
+                    self.document.AddAfterHandler(recompute, (idx - 1,), depth)
+                if idx < len(self.objects) - 1:
+                    self.document.AddAfterHandler(recompute, (idx + 1,), depth)
+        else:
+            Compound.ChildChanged(self, child)
+        self.del_lazy_attrs()
 
     def recompute(self, idx):
-	self.objects[idx].Recompute(self.objects[idx - 1], self.objects[idx+1])
+        self.objects[idx].Recompute(self.objects[idx - 1], self.objects[idx+1])
 
     def RecomputeChild(self, child):
-	self.recompute(self.objects.index(child))
+        self.recompute(self.objects.index(child))
 
     def SaveToFile(self, file):
-	file.BeginBlendGroup()
-	for obj in self.objects:
-	    obj.SaveToFile(file)
-	file.EndBlendGroup()
+        file.BeginBlendGroup()
+        for obj in self.objects:
+            obj.SaveToFile(file)
+        file.EndBlendGroup()
 
     def Info(self):
-	return _("BlendGroup with %d control objects") \
-	       % (len(self.objects) / 2 + 1)
+        return _("BlendGroup with %d control objects") \
+               % (len(self.objects) / 2 + 1)
 
     def CancelEffect(self):
-	self.unset_parent()
-	idx = range(0, len(self.objects), 2)
-	return map(operator.getitem, [self.objects] * len(idx), idx)
+        self.unset_parent()
+        idx = range(0, len(self.objects), 2)
+        return map(operator.getitem, [self.objects] * len(idx), idx)
 
     def SelectControl(self, relative, which):
-	idx = self.objects.index(relative)
-	if idx % 2 == 1:
-	    # an interpolation
-	    if which == SelectStart:
-		idx = idx - 1
-	    else:
-		idx = idx + 1
-	else:
-	    # a control
-	    if which == SelectStart:
-		if idx > 0:
-		    idx = idx - 2
-	    else:
-		if idx < len(self.objects) - 1:
-		    idx = idx + 2
-	self.document.SelectObject(self.objects[idx])
+        idx = self.objects.index(relative)
+        if idx % 2 == 1:
+            # an interpolation
+            if which == SelectStart:
+                idx = idx - 1
+            else:
+                idx = idx + 1
+        else:
+            # a control
+            if which == SelectStart:
+                if idx > 0:
+                    idx = idx - 2
+            else:
+                if idx < len(self.objects) - 1:
+                    idx = idx + 2
+        self.document.SelectObject(self.objects[idx])
 
     def ExtendBlend(self, start, end, steps):
-	idx = self.objects.index(start)
-	if idx == 0:
-	    inter = BlendInterpolation(steps, end, start)
-	    return CreateMultiUndo(self.insert(inter, 0),
-				   self.insert(end, 0))
-	elif idx == len(self.objects) - 1:
-	    inter = BlendInterpolation(steps, start, end)
-	    return CreateMultiUndo(self.insert(inter, None),
-				   self.insert(end, None))
+        idx = self.objects.index(start)
+        if idx == 0:
+            inter = BlendInterpolation(steps, end, start)
+            return CreateMultiUndo(self.insert(inter, 0),
+                                   self.insert(end, 0))
+        elif idx == len(self.objects) - 1:
+            inter = BlendInterpolation(steps, start, end)
+            return CreateMultiUndo(self.insert(inter, None),
+                                   self.insert(end, None))
 
     def Ungroup(self):
-	objects = []
-	for obj in self.objects:
-	    if obj.__class__ is BlendInterpolation:
-		objects.append(obj.AsGroup())
-	    else:
-		objects.append(obj)
-	return objects
+        objects = []
+        for obj in self.objects:
+            if obj.__class__ is BlendInterpolation:
+                objects.append(obj.AsGroup())
+            else:
+                objects.append(obj)
+        return objects
 
 
 def CreateBlendGroup(start, end, steps):
     if isinstance(start.parent, BlendGroup):
-	undo = start.parent.ExtendBlend(start, end, steps)
-	result = start.parent
+        undo = start.parent.ExtendBlend(start, end, steps)
+        result = start.parent
     elif isinstance(end.parent, BlendGroup):
-	undo = end.parent.ExtendBlend(end, start, steps)
-	result = end.parent
+        undo = end.parent.ExtendBlend(end, start, steps)
+        result = end.parent
     else:
-	result = BlendGroup(steps, start, end)
-	undo = NullUndo
+        result = BlendGroup(steps, start, end)
+        undo = NullUndo
     return result, undo

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/clone.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/clone.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/clone.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -38,117 +38,117 @@
     original = id(original)
     _clone_registry[original]= _clone_registry[original] - 1
     if _clone_registry[original] == 0:
-	del _clone_registry[original]
+        del _clone_registry[original]
 
 class Clone(Bounded, HierarchyNode):
 
     is_Clone = 1
 
     def __init__(self, original = None, duplicate = None):
-	HierarchyNode.__init__(self, duplicate = duplicate)
-	if original is not None and original.is_Clone:
-	    duplicate = original
-	    original = None
-	if duplicate is not None:
-	    self._original = duplicate._original
-	    self._center = duplicate._center
-	    self._offset = duplicate._offset
-	else:
-	    self._original = original
-	    self._center = self._original.coord_rect.center()
-	    self._offset = NullPoint
-	self.register()
+        HierarchyNode.__init__(self, duplicate = duplicate)
+        if original is not None and original.is_Clone:
+            duplicate = original
+            original = None
+        if duplicate is not None:
+            self._original = duplicate._original
+            self._center = duplicate._center
+            self._offset = duplicate._offset
+        else:
+            self._original = original
+            self._center = self._original.coord_rect.center()
+            self._offset = NullPoint
+        self.register()
 
     def register(self):
-	_register_clone(self._original)
-	self._original.Subscribe(CHANGED, self.orig_changed)
+        _register_clone(self._original)
+        self._original.Subscribe(CHANGED, self.orig_changed)
 
     def unregister(self):
-	self._original.Unsubscribe(CHANGED, self.orig_changed)
-	_unregister_clone(self._original)
+        self._original.Unsubscribe(CHANGED, self.orig_changed)
+        _unregister_clone(self._original)
 
     def __getattr__(self, attr):
-	if self._lazy_attrs.has_key(attr):
-	    return Bounded.__getattr__(self, attr)
-	#print 'Clone.__getattr__: from original:', attr
-	#if attr in ('__nonzero__', 'document'):
-	#    print_stack()
-	return getattr(self._original, attr)
+        if self._lazy_attrs.has_key(attr):
+            return Bounded.__getattr__(self, attr)
+        #print 'Clone.__getattr__: from original:', attr
+        #if attr in ('__nonzero__', 'document'):
+        #    print_stack()
+        return getattr(self._original, attr)
 
     def update_rects(self):
-	off = self._offset
-	self.bounding_rect = self._original.bounding_rect.translated(off)
-	self.coord_rect = self._original.coord_rect.translated(off)
+        off = self._offset
+        self.bounding_rect = self._original.bounding_rect.translated(off)
+        self.coord_rect = self._original.coord_rect.translated(off)
 
     def Translate(self, offset):
-	self._offset = self._offset + offset
-	self.del_lazy_attrs()
-	return self.Translate, -offset
+        self._offset = self._offset + offset
+        self.del_lazy_attrs()
+        return self.Translate, -offset
 
     def _set_offset(self, offset):
-	undo = (self._set_offset, self._offset)
-	self._offset = offset
-	self.del_lazy_attrs()
-	return undo
+        undo = (self._set_offset, self._offset)
+        self._offset = offset
+        self.del_lazy_attrs()
+        return undo
 
     def offset_center(self, offset):
-	undo = (self.offset_center, -offset)
-	self._center = self._center + offset
-	return undo
+        undo = (self.offset_center, -offset)
+        self._center = self._center + offset
+        return undo
 
     def Transform(self, trafo):
-	center = self._center + self._offset
-	offset = trafo(center) - center
-	if self.document is not None:
-	    self.document.AddAfterHandler(_transform,
-					  (self._original, trafo.matrix()), -1)
-	return self.offset_center(offset)
+        center = self._center + self._offset
+        offset = trafo(center) - center
+        if self.document is not None:
+            self.document.AddAfterHandler(_transform,
+                                          (self._original, trafo.matrix()), -1)
+        return self.offset_center(offset)
 
     def orig_changed(self, *args):
-	if self.document is not None:
-	    self.document.AddClearRect(self.bounding_rect)
-	self.del_lazy_attrs()
-	center = self._center
-	self._center = self._original.coord_rect.center()
-	self._offset = self._offset + center - self._center
-	if self.document is not None:
-	    self.document.AddClearRect(self.bounding_rect)
+        if self.document is not None:
+            self.document.AddClearRect(self.bounding_rect)
+        self.del_lazy_attrs()
+        center = self._center
+        self._center = self._original.coord_rect.center()
+        self._offset = self._offset + center - self._center
+        if self.document is not None:
+            self.document.AddClearRect(self.bounding_rect)
 
     def DrawShape(self, device, rect = None):
-	device.PushTrafo()
-	try:
-	    device.Translate(self._offset)
-	    self._original.DrawShape(device, rect)
-	finally:
-	    device.PopTrafo()
+        device.PushTrafo()
+        try:
+            device.Translate(self._offset)
+            self._original.DrawShape(device, rect)
+        finally:
+            device.PopTrafo()
 
     def Hit(self, p, rect, device):
-	off = -self._offset
-	return self._original.Hit(p + off, rect.translated(off), device)
+        off = -self._offset
+        return self._original.Hit(p + off, rect.translated(off), device)
 
 
     def Info(self):
-	return 'Clone of ' + self._original.Info()
+        return 'Clone of ' + self._original.Info()
 
 
     # overwrite Selectable methods
     def SelectSubobject(self, p, rect, device, path = None, *rest):
-	return self
+        return self
 
     def GetObjectHandle(self, multiple):
-	trafo = Translation(self._offset)
-	handle = self._original.GetObjectHandle(multiple)
-	if type(handle) == PointType:
-	    return trafo(handle)
-	else:
-	    return map(trafo, handle)
+        trafo = Translation(self._offset)
+        handle = self._original.GetObjectHandle(multiple)
+        if type(handle) == PointType:
+            return trafo(handle)
+        else:
+            return map(trafo, handle)
 
     # overwrite Bounded methods
     def LayoutPoint(self):
-	return self._original.LayoutPoint() + self._offset
+        return self._original.LayoutPoint() + self._offset
 
     def GetSnapPoints(self):
-	return map(Translation(self._offset), self._original.GetSnapPoints())
+        return map(Translation(self._offset), self._original.GetSnapPoints())
 
 
 def _transform(original, matrix):

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/color.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/color.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/color.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -35,7 +35,7 @@
     # only understands the old x specification with two hex digits per
     # component. e.g. `#00FF00'
     if s[0] != '#':
-	raise ValueError("Color %s dosn't start with a '#'" % s)
+        raise ValueError("Color %s dosn't start with a '#'" % s)
     r = atoi(s[1:3], 16) / 255.0
     g = atoi(s[3:5], 16) / 255.0
     b = atoi(s[5:7], 16) / 255.0
@@ -78,21 +78,21 @@
     colors = []
     color_idx = []
     failed = 0
-    
+
     shades_r, shades_g, shades_b, shades_gray = config.preferences.color_cube
     max_r = shades_r - 1
     max_g = shades_g - 1
     max_b = shades_b - 1
 
     for red in range(shades_r):
-	red = float_to_x(red / float(max_r))
-	for green in range(shades_g):
-	    green = float_to_x(green / float(max_g))
-	    for blue in range(shades_b):
-		blue = float_to_x(blue / float(max_b))
+        red = float_to_x(red / float(max_r))
+        for green in range(shades_g):
+            green = float_to_x(green / float(max_g))
+            for blue in range(shades_b):
+                blue = float_to_x(blue / float(max_b))
                 colors.append((red, green, blue))
     for i in range(shades_gray):
-	value = int((i / float(shades_gray - 1)) * max)
+        value = int((i / float(shades_gray - 1)) * max)
         colors.append((value, value, value))
 
     for red, green, blue in colors:
@@ -104,9 +104,9 @@
             failed = 1
 
     if failed:
-	warn(USER,
-	     _("I can't alloc all needed colors. I'll use a private colormap"))
-	warn(INTERNAL, "allocated colors without private colormap: %d",
+        warn(USER,
+             _("I can't alloc all needed colors. I'll use a private colormap"))
+        warn(INTERNAL, "allocated colors without private colormap: %d",
              len(filter(lambda i: i is None, color_idx)))
         if config.preferences.reduce_color_flashing:
             #print 'reduce color flashing'
@@ -121,7 +121,7 @@
             color_idx = []
             for red, green, blue in colors:
                 color_idx.append(cmap.AllocColor(red, green, blue)[0])
-               
+
     return cmap, color_idx
 
 _init_from_widget_done = 0
@@ -129,23 +129,23 @@
 def InitFromWidget(tkwin, root = None):
     global _init_from_widget_done, skvisual
     if _init_from_widget_done:
-	return
+        return
     if root:
-	visual = root.winfo_visual()
-	if visual == 'truecolor':
-	    skvisual = XVisual(tkwin.c_display(), tkwin.c_visual())
-	    #skvisual.set_gamma(config.preferences.screen_gamma)
-	    alloc_function = skvisual.get_pixel
-	if visual == 'pseudocolor' and root.winfo_depth() == 8:
-	    global global_colormap
-	    cmap = tkwin.colormap()
-	    newcmap, idxs = fill_colormap(cmap)
-	    if newcmap != cmap:
-		cmap = newcmap
-		tkwin.SetColormap(cmap)
+        visual = root.winfo_visual()
+        if visual == 'truecolor':
+            skvisual = XVisual(tkwin.c_display(), tkwin.c_visual())
+            #skvisual.set_gamma(config.preferences.screen_gamma)
+            alloc_function = skvisual.get_pixel
+        if visual == 'pseudocolor' and root.winfo_depth() == 8:
+            global global_colormap
+            cmap = tkwin.colormap()
+            newcmap, idxs = fill_colormap(cmap)
+            if newcmap != cmap:
+                cmap = newcmap
+                tkwin.SetColormap(cmap)
             shades_r, shades_g, shades_b, shades_gray \
-                      = config.preferences.color_cube
-	    skvisual = XVisual(tkwin.c_display(), tkwin.c_visual(),
-			     (shades_r, shades_g, shades_b, shades_gray, idxs))
-	    global_colormap = cmap
+                    = config.preferences.color_cube
+            skvisual = XVisual(tkwin.c_display(), tkwin.c_visual(),
+                               (shades_r, shades_g, shades_b, shades_gray, idxs))
+            global_colormap = cmap
     _init_from_widget_done = 1

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/compound.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/compound.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/compound.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -47,80 +47,80 @@
     allow_traversal = 0
 
     def __init__(self, objects = None, duplicate = None):
-	GraphicsObject.__init__(self, duplicate = duplicate)
-	if duplicate is not None:
-	    objects = []
-	    for obj in duplicate.objects:
-		objects.append(obj.Duplicate())
-	    self.objects = objects
-	elif objects:
-	    self.objects = objects
-	else:
-	    self.objects = []
-	self.changing_children = 0
-	self.set_parent()
+        GraphicsObject.__init__(self, duplicate = duplicate)
+        if duplicate is not None:
+            objects = []
+            for obj in duplicate.objects:
+                objects.append(obj.Duplicate())
+            self.objects = objects
+        elif objects:
+            self.objects = objects
+        else:
+            self.objects = []
+        self.changing_children = 0
+        self.set_parent()
 
     def Destroy(self):
-	self.destroy_objects()
-	GraphicsObject.Destroy(self)
+        self.destroy_objects()
+        GraphicsObject.Destroy(self)
 
     def destroy_objects(self):
-	for obj in self.objects:
-	    obj.Destroy()
-	self.objects = []
+        for obj in self.objects:
+            obj.Destroy()
+        self.objects = []
 
     def SetParent(self, parent):
-	if parent is self.parent:
-	    return
-	GraphicsObject.SetParent(self, parent)
-	if parent is not None:
-	    self.set_parent()
-	else:
-	    self.unset_parent()
+        if parent is self.parent:
+            return
+        GraphicsObject.SetParent(self, parent)
+        if parent is not None:
+            self.set_parent()
+        else:
+            self.unset_parent()
 
     def set_parent(self):
-	for child in self.objects:
-	    child.SetParent(self)
+        for child in self.objects:
+            child.SetParent(self)
 
     def unset_parent(self):
-	for child in self.objects:
-	    child.SetParent(None)
+        for child in self.objects:
+            child.SetParent(None)
 
     def SelectionInfo(self, child = None):
-	info = GraphicsObject.SelectionInfo(self)
-	if info and child is not None:
-	    path = info[0]
-	    return (path + (_sketch.IdIndex(self.objects, child),),
+        info = GraphicsObject.SelectionInfo(self)
+        if info and child is not None:
+            path = info[0]
+            return (path + (_sketch.IdIndex(self.objects, child),),
                     child)
-	return info
+        return info
 
     def ChildChanged(self, child):
-	self.del_lazy_attrs()
-	if self.changing_children:
-	    return
-	self.issue_changed()
+        self.del_lazy_attrs()
+        if self.changing_children:
+            return
+        self.issue_changed()
 
     def SetDocument(self, doc):
-	for obj in self.objects:
-	    obj.SetDocument(doc)
-	GraphicsObject.SetDocument(self, doc)
-	self.set_parent()
+        for obj in self.objects:
+            obj.SetDocument(doc)
+        GraphicsObject.SetDocument(self, doc)
+        self.set_parent()
 
     def disconnect_objects(self):
-	for obj in self.objects:
-	    obj.Disconnect()
+        for obj in self.objects:
+            obj.Disconnect()
 
     def Disconnect(self):
-	self.disconnect_objects()
-	self.unset_parent()
+        self.disconnect_objects()
+        self.unset_parent()
 
     def connect_objects(self):
-	for obj in self.objects:
-	    obj.Connect()
+        for obj in self.objects:
+            obj.Connect()
 
     def Connect(self):
-	self.set_parent()
-	self.connect_objects()
+        self.set_parent()
+        self.connect_objects()
 
     def set_objects(self, new_objs):
         if self.document is not None:
@@ -138,59 +138,59 @@
             self.document.AddClearRect(self.bounding_rect)
 
     def UntieFromDocument(self):
-	for obj in self.objects:
-	    obj.UntieFromDocument()
+        for obj in self.objects:
+            obj.UntieFromDocument()
 
     def TieToDocument(self):
-	for obj in self.objects:
-	    obj.TieToDocument()
+        for obj in self.objects:
+            obj.TieToDocument()
 
     def load_AppendObject(self, object):
-	self.objects.append(object)
+        self.objects.append(object)
 
     def load_Done(self):
-	pass
+        pass
 
     def __getitem__(self, idx):
-	if type(idx) == IntType:
-	    return self.objects[idx]
-	elif type(idx) == TupleType:
-	    if len(idx) > 1:
-		return self.objects[idx[0]][idx[1:]]
-	    elif len(idx) == 1:
-		return self.objects[idx[0]]
-	raise ValueError, 'invalid index %s' % `idx`
+        if type(idx) == IntType:
+            return self.objects[idx]
+        elif type(idx) == TupleType:
+            if len(idx) > 1:
+                return self.objects[idx[0]][idx[1:]]
+            elif len(idx) == 1:
+                return self.objects[idx[0]]
+        raise ValueError, 'invalid index %s' % `idx`
 
     def GetObjects(self):
-	# XXX should this return a copy of self.objects?
-	return self.objects
+        # XXX should this return a copy of self.objects?
+        return self.objects
 
     def del_lazy_attrs(self):
-	Bounded.del_lazy_attrs(self)
-	return (self.del_lazy_attrs,)
+        Bounded.del_lazy_attrs(self)
+        return (self.del_lazy_attrs,)
 
     def update_rects(self):
-	# XXX: should we raise an exception here if self.objects is empty?
-	boxes = map(lambda o: o.coord_rect, self.objects)
-	if boxes:
-	    self.coord_rect = reduce(UnionRects, boxes, boxes[0])
-	else:
-	    self.coord_rect = EmptyRect
+        # XXX: should we raise an exception here if self.objects is empty?
+        boxes = map(lambda o: o.coord_rect, self.objects)
+        if boxes:
+            self.coord_rect = reduce(UnionRects, boxes, boxes[0])
+        else:
+            self.coord_rect = EmptyRect
 
-	boxes = map(lambda o: o.bounding_rect, self.objects)
-	if boxes:
-	    self.bounding_rect = reduce(UnionRects, boxes, boxes[0])
-	else:
-	    self.bounding_rect = EmptyRect
+        boxes = map(lambda o: o.bounding_rect, self.objects)
+        if boxes:
+            self.bounding_rect = reduce(UnionRects, boxes, boxes[0])
+        else:
+            self.bounding_rect = EmptyRect
 
     def SelectSubobject(self, p, rect, device, path = None, *rest):
-	return self
+        return self
 
     def Insert(self, obj, at):
-	raise SketchError('Cannot insert in compound')
+        raise SketchError('Cannot insert in compound')
 
     def Remove(self, *args, **kw):
-	raise SketchError('Cannot remove from compound')
+        raise SketchError('Cannot remove from compound')
 
     RemoveSlice = Remove
     RemoveObjects = Remove
@@ -198,149 +198,149 @@
     ReplaceChild = Remove
 
     def MoveObjectsToTop(self, infolist):
-	raise SketchError('Cannot rearrange objects in compound')
+        raise SketchError('Cannot rearrange objects in compound')
 
     MoveObjectsToBottom = MoveObjectsToTop
     MoveObjectsDown = MoveObjectsToTop
     MoveObjectsUp = MoveObjectsToTop
     def move_objects_to_top(self, infolist, to_bottom = 0):
-	return infolist, NullUndo
+        return infolist, NullUndo
 
     def DuplicateObjects(self, infolist, offset):
-	raise SketchError('Cannot duplicate objects in compound')
+        raise SketchError('Cannot duplicate objects in compound')
 
     def ForAll(self, func):
-	self.changing_children = 1
-	try:
-	    return map(func, self.objects)
-	finally:
-	    self.changing_children = 0
+        self.changing_children = 1
+        try:
+            return map(func, self.objects)
+        finally:
+            self.changing_children = 0
 
     def WalkHierarchy(self, func):
-	for obj in self.objects:
-	    if obj.is_Compound:
-		obj.WalkHierarchy(func)
-	    else:
-		func(obj)
+        for obj in self.objects:
+            if obj.is_Compound:
+                obj.WalkHierarchy(func)
+            else:
+                func(obj)
 
     def begin_change_children(self):
-	self.changing_children = self.changing_children + 1
-	return (self.end_change_children,)
+        self.changing_children = self.changing_children + 1
+        return (self.end_change_children,)
 
     def end_change_children(self):
-	self.changing_children = self.changing_children - 1
-	if not self.changing_children:
-	    self._changed()
-	return (self.begin_change_children,)
+        self.changing_children = self.changing_children - 1
+        if not self.changing_children:
+            self._changed()
+        return (self.begin_change_children,)
 
     def ForAllUndo(self, func):
-	if self.objects:
-	    undo = [self.begin_change_children()]
-	    undo = undo + map(func, self.objects)
-	    undo.append(self.end_change_children())
-	    return CreateListUndo(undo)
-	else:
-	    return NullUndo
+        if self.objects:
+            undo = [self.begin_change_children()]
+            undo = undo + map(func, self.objects)
+            undo.append(self.end_change_children())
+            return CreateListUndo(undo)
+        else:
+            return NullUndo
 
     def FilterAll(self, func):
-	return filter(func, self.GetObjects())
+        return filter(func, self.GetObjects())
 
     def NumObjects(self):
-	return len(self.objects)
+        return len(self.objects)
 
     def Info(self):
-	return _("Compound with %d objects") % len(self.objects)
+        return _("Compound with %d objects") % len(self.objects)
 
     def AddStyle(self, style):
-	undo = self.ForAllUndo(lambda o, style = style: o.AddStyle(style))
-	return undo
+        undo = self.ForAllUndo(lambda o, style = style: o.AddStyle(style))
+        return undo
 
     def Properties(self):
-	return EmptyProperties
+        return EmptyProperties
 
     def SetProperties(self, **kw):
-	self.del_lazy_attrs()
-	func = lambda o, kw = kw: apply(o.SetProperties, (), kw)
-	undo = self.ForAllUndo(func)
-	return undo
+        self.del_lazy_attrs()
+        func = lambda o, kw = kw: apply(o.SetProperties, (), kw)
+        undo = self.ForAllUndo(func)
+        return undo
 
     def Hit(self, p, rect, device):
-	test = rect.overlaps
-	objects = self.objects
-	for obj_idx in range(len(objects) - 1, -1, -1):
-	    obj = objects[obj_idx]
-	    if test(obj.bounding_rect):
-		if obj.Hit(p, rect, device):
-		    return obj_idx + 1
-	return 0
+        test = rect.overlaps
+        objects = self.objects
+        for obj_idx in range(len(objects) - 1, -1, -1):
+            obj = objects[obj_idx]
+            if test(obj.bounding_rect):
+                if obj.Hit(p, rect, device):
+                    return obj_idx + 1
+        return 0
 
     def Transform(self, trafo):
-	self.del_lazy_attrs()
-	undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
-	return undo
+        self.del_lazy_attrs()
+        undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
+        return undo
 
     def Translate(self, offset):
-	undo = self.ForAllUndo(lambda o, p = offset: o.Translate(p))
-	return undo
+        undo = self.ForAllUndo(lambda o, p = offset: o.Translate(p))
+        return undo
 
     def DrawShape(self, device, rect = None):
-	if rect:
-	    test = rect.overlaps
-	    for o in self.objects:
-		if test(o.bounding_rect):
-		    o.DrawShape(device, rect)
-	else:
-	    for obj in self.objects:
-		obj.DrawShape(device)
+        if rect:
+            test = rect.overlaps
+            for o in self.objects:
+                if test(o.bounding_rect):
+                    o.DrawShape(device, rect)
+        else:
+            for obj in self.objects:
+                obj.DrawShape(device)
 
     def PickObject(self, point, rect, device):
-	objects = self.objects[:]
-	objects.reverse()
-	test = rect.overlaps
-	for obj in objects:
-	    if test(obj.bounding_rect):
-		if obj.is_Compound:
-		    result = obj.PickObject(point, rect, device)
-		    if result:
-			break
-		elif obj.Hit(point, rect, device):
-		    result =  obj
-		    break
-	else:
-	    result = None
+        objects = self.objects[:]
+        objects.reverse()
+        test = rect.overlaps
+        for obj in objects:
+            if test(obj.bounding_rect):
+                if obj.is_Compound:
+                    result = obj.PickObject(point, rect, device)
+                    if result:
+                        break
+                elif obj.Hit(point, rect, device):
+                    result =  obj
+                    break
+        else:
+            result = None
 
-	return result
+        return result
 
     def Blend(self, other, frac1, frac2):
-	try:
-	    objs = self.objects
-	    oobjs = other.objects
-	    blended = []
-	    for i in range(min(len(objs), len(oobjs))):
-		blended.append(Blend(objs[i], oobjs[i], frac1, frac2))
-	    return Compound(blended)
-	except:
-	    raise MismatchError
+        try:
+            objs = self.objects
+            oobjs = other.objects
+            blended = []
+            for i in range(min(len(objs), len(oobjs))):
+                blended.append(Blend(objs[i], oobjs[i], frac1, frac2))
+            return Compound(blended)
+        except:
+            raise MismatchError
 
     def GetObjectHandle(self, multiple):
-	return self.ForAll(lambda o: o.GetObjectHandle(1))
+        return self.ForAll(lambda o: o.GetObjectHandle(1))
 
 
     def SelectFirstChild(self):
-	if self.allow_traversal and self.objects:
-	    return self.objects[0]
+        if self.allow_traversal and self.objects:
+            return self.objects[0]
 
     def SelectLastChild(self):
-	if self.allow_traversal and self.objects:
-	    return self.objects[-1]
+        if self.allow_traversal and self.objects:
+            return self.objects[-1]
 
     def SelectNextChild(self, child, idx):
-	if self.allow_traversal and len(self.objects) > idx + 1:
-	    return self.objects[idx + 1]
+        if self.allow_traversal and len(self.objects) > idx + 1:
+            return self.objects[idx + 1]
 
     def SelectPreviousChild(self, child, idx):
-	if self.allow_traversal and len(self.objects) > idx - 1 and idx > 0:
-	    return self.objects[idx - 1]
+        if self.allow_traversal and len(self.objects) > idx - 1 and idx > 0:
+            return self.objects[idx - 1]
 
 
 class EditableCompound(Compound):
@@ -348,361 +348,361 @@
     allow_traversal = 1
 
     def SelectSubobject(self, p, rect, device, path = None, *rest):
-	test = rect.overlaps
-	if path is None:
-	    return self
-	if path:
-	    path_idx = path[0]
-	    path = path[1:]
-	else:
-	    path_idx = -1
-	    path = None
-	objects = self.objects
-	for obj_idx in range(len(objects) - 1, -1, -1):
-	    obj = objects[obj_idx]
-	    if test(obj.bounding_rect) and obj.Hit(p, rect, device):
-		if obj_idx == path_idx:
-		    result = obj.SelectSubobject(p, rect, device, path)
-		else:
-		    result = obj.SelectSubobject(p, rect, device)
-		return prepend_idx(obj_idx, result)
-	return None
+        test = rect.overlaps
+        if path is None:
+            return self
+        if path:
+            path_idx = path[0]
+            path = path[1:]
+        else:
+            path_idx = -1
+            path = None
+        objects = self.objects
+        for obj_idx in range(len(objects) - 1, -1, -1):
+            obj = objects[obj_idx]
+            if test(obj.bounding_rect) and obj.Hit(p, rect, device):
+                if obj_idx == path_idx:
+                    result = obj.SelectSubobject(p, rect, device, path)
+                else:
+                    result = obj.SelectSubobject(p, rect, device)
+                return prepend_idx(obj_idx, result)
+        return None
 
     def Insert(self, obj, at):
-	# Insert OBJ into the object hierarchy at the position described
-	# by AT. AT should be either an integer or a tuple of integers.
-	# OBJ can be a graphics object of a list of such objects.
-	#
-	# If AT is a tuple of 2 or more ints, self's child at AT[0] has
-	# to be a compound object and its Insert method is called with
-	# OBJ and AT[1:] as arguments.
-	#
-	# If AT is an int or a singleton of one int, insert OBJ at that
-	# position in self's children. If OBJ is a graphics object, this
-	# works just like a list objects insert method (insert(AT,
-	# OBJ)). If its a list of graphics objects this method
-	# effectively assigns that list to the slice AT:AT.
-	#
-	# As a side effect, this method calls the following methods of
-	# the inserted objects:
-	#
-	#	    obj.SetDocument(self.document)
-	#	    obj.SetParent(self)
-	#	    obj.Connect()
-	#
-	# Return a tuple (SELINFO, UNDO), where SELINFO is selection
-	# info for the inserted objects at their new positions, and UNDO
-	# is the appropriate undo info.
-	#
-	# If self is modified directly, issue a CHANGED message.
-	undo_info = None
-	try:
-	    if type(at) == TupleType and at:
-		if len(at) == 1:
-		    at = at[0]
-		else:
-		    child = at[0]
-		    at = at[1:]
-		    sel_info, undo_info = self.objects[child].Insert(obj, at)
-		    sel_info = prepend_idx(child, sel_info)
-		    return (sel_info, undo_info)
-	    if type(at) != IntType or at > len(self.objects):
-		at = len(self.objects)
-	    if type(obj) == InstanceType:
-		self.objects.insert(at, obj)
-		obj.SetDocument(self.document)
-		obj.SetParent(self)
-		obj.Connect()
-		sel_info = build_info(at, obj)
-		undo_info = (self.Remove, obj, at)
-	    else:
-		self.objects[at:at] = obj
-		for o in obj:
-		    # XXX: should we have undo info for these:
-		    o.SetDocument(self.document)
-		    o.SetParent(self)
-		    o.Connect()
-		sel_info = select_range(at, obj)
-		undo_info = (self.RemoveSlice, at, at + len(obj))
-	    self._changed()
-	    return (sel_info, undo_info)
-	except:
-	    if undo_info is not None:
-		Undo(undo_info)
-	    raise
+        # Insert OBJ into the object hierarchy at the position described
+        # by AT. AT should be either an integer or a tuple of integers.
+        # OBJ can be a graphics object of a list of such objects.
+        #
+        # If AT is a tuple of 2 or more ints, self's child at AT[0] has
+        # to be a compound object and its Insert method is called with
+        # OBJ and AT[1:] as arguments.
+        #
+        # If AT is an int or a singleton of one int, insert OBJ at that
+        # position in self's children. If OBJ is a graphics object, this
+        # works just like a list objects insert method (insert(AT,
+        # OBJ)). If its a list of graphics objects this method
+        # effectively assigns that list to the slice AT:AT.
+        #
+        # As a side effect, this method calls the following methods of
+        # the inserted objects:
+        #
+        #	    obj.SetDocument(self.document)
+        #	    obj.SetParent(self)
+        #	    obj.Connect()
+        #
+        # Return a tuple (SELINFO, UNDO), where SELINFO is selection
+        # info for the inserted objects at their new positions, and UNDO
+        # is the appropriate undo info.
+        #
+        # If self is modified directly, issue a CHANGED message.
+        undo_info = None
+        try:
+            if type(at) == TupleType and at:
+                if len(at) == 1:
+                    at = at[0]
+                else:
+                    child = at[0]
+                    at = at[1:]
+                    sel_info, undo_info = self.objects[child].Insert(obj, at)
+                    sel_info = prepend_idx(child, sel_info)
+                    return (sel_info, undo_info)
+            if type(at) != IntType or at > len(self.objects):
+                at = len(self.objects)
+            if type(obj) == InstanceType:
+                self.objects.insert(at, obj)
+                obj.SetDocument(self.document)
+                obj.SetParent(self)
+                obj.Connect()
+                sel_info = build_info(at, obj)
+                undo_info = (self.Remove, obj, at)
+            else:
+                self.objects[at:at] = obj
+                for o in obj:
+                    # XXX: should we have undo info for these:
+                    o.SetDocument(self.document)
+                    o.SetParent(self)
+                    o.Connect()
+                sel_info = select_range(at, obj)
+                undo_info = (self.RemoveSlice, at, at + len(obj))
+            self._changed()
+            return (sel_info, undo_info)
+        except:
+            if undo_info is not None:
+                Undo(undo_info)
+            raise
 
     def _insert_with_undo(self, obj, at):
-	# The same as the Insert method but return only the undo info.
-	return self.Insert(obj, at)[1]
+        # The same as the Insert method but return only the undo info.
+        return self.Insert(obj, at)[1]
 
     def do_remove_child(self, idx):
-	obj = self.objects[idx]
-	del self.objects[idx]
-	obj.Disconnect()
-	obj.SetParent(None)
-	self._changed()
-	return (self._insert_with_undo, obj, idx)
+        obj = self.objects[idx]
+        del self.objects[idx]
+        obj.Disconnect()
+        obj.SetParent(None)
+        self._changed()
+        return (self._insert_with_undo, obj, idx)
 
     def Remove(self, obj, idx = None):
-	if type(idx) == TupleType:
-	    if len(idx) == 1:
-		idx = idx[0]
-	    else:
-		return self.objects[idx[0]].Remove(obj, idx[1:])
-	if idx is None:
-	    idx = self.objects.index(obj)
-	elif self.objects[idx] is not obj:
-	    raise ValueError, 'Compound.Remove(): invalid index'
-	return self.do_remove_child(idx)
+        if type(idx) == TupleType:
+            if len(idx) == 1:
+                idx = idx[0]
+            else:
+                return self.objects[idx[0]].Remove(obj, idx[1:])
+        if idx is None:
+            idx = self.objects.index(obj)
+        elif self.objects[idx] is not obj:
+            raise ValueError, 'Compound.Remove(): invalid index'
+        return self.do_remove_child(idx)
 
     def RemoveSlice(self, min, max):
-	objs = self.objects[min:max]
-	self.objects[min:max] = []
-	for obj in objs:
-	    obj.Disconnect()
-	    obj.SetParent(None)
-	self._changed()
-	return (self._insert_with_undo, objs, min)
+        objs = self.objects[min:max]
+        self.objects[min:max] = []
+        for obj in objs:
+            obj.Disconnect()
+            obj.SetParent(None)
+        self._changed()
+        return (self._insert_with_undo, objs, min)
 
     def RemoveObjects(self, infolist):
-	if not infolist:
-	    return NullUndo
-	sliced = list_to_tree_sliced(infolist)
-	sliced.reverse() # important!
-	undo = [self.begin_change_children()]
-	try:
-	    for start, end in sliced:
-		if type(end) == IntType:
-		    undo.append(self.RemoveSlice(start, end))
-		elif type(end) == ListType:
-		    undo.append(self.objects[start].RemoveObjects(end))
-		else:
-		    undo.append(self.Remove(end, start))
-	    undo.append(self.end_change_children())
-	    return CreateListUndo(undo)
-	except:
-	    Undo(CreateListUndo(undo))
-	    raise
+        if not infolist:
+            return NullUndo
+        sliced = list_to_tree_sliced(infolist)
+        sliced.reverse() # important!
+        undo = [self.begin_change_children()]
+        try:
+            for start, end in sliced:
+                if type(end) == IntType:
+                    undo.append(self.RemoveSlice(start, end))
+                elif type(end) == ListType:
+                    undo.append(self.objects[start].RemoveObjects(end))
+                else:
+                    undo.append(self.Remove(end, start))
+            undo.append(self.end_change_children())
+            return CreateListUndo(undo)
+        except:
+            Undo(CreateListUndo(undo))
+            raise
 
     def ReplaceChild(self, child, object):
-	# replace self's child child with object. Return undo info
-	idx = self.objects.index(child)
-	self.objects[idx] = object
-	object.SetParent(self)
-	object.SetDocument(self.document)
-	child.SetParent(None)
-	self._changed()
-	return (self.ReplaceChild, object, child)
+        # replace self's child child with object. Return undo info
+        idx = self.objects.index(child)
+        self.objects[idx] = object
+        object.SetParent(self)
+        object.SetDocument(self.document)
+        child.SetParent(None)
+        self._changed()
+        return (self.ReplaceChild, object, child)
 
     def permute_objects(self, permutation):
-	# permutation must be a list of ints and len(permutation) must be
-	# equal to len(self.objects). permutation[i] is the index of the
-	# object that is moved to index i in the result.
-	objects = self.objects
-	length = len(objects)
-	identity = range(length)
-	if permutation == identity:
-	    return NullUndo
-	if len(objects) != len(permutation):
-	    raise ValueError, 'len(permutation) != len(self.objects)'
+        # permutation must be a list of ints and len(permutation) must be
+        # equal to len(self.objects). permutation[i] is the index of the
+        # object that is moved to index i in the result.
+        objects = self.objects
+        length = len(objects)
+        identity = range(length)
+        if permutation == identity:
+            return NullUndo
+        if len(objects) != len(permutation):
+            raise ValueError, 'len(permutation) != len(self.objects)'
 
-	result = map(operator.getitem, [objects] * length, permutation)
-	inverse = [0] * length
-	map(operator.setitem, [inverse] * length, permutation, identity)
-	self.objects = result
-	self._changed()
-	return (self.permute_objects, inverse)
+        result = map(operator.getitem, [objects] * length, permutation)
+        inverse = [0] * length
+        map(operator.setitem, [inverse] * length, permutation, identity)
+        self.objects = result
+        self._changed()
+        return (self.permute_objects, inverse)
 
     def move_objects_to_top(self, infolist, to_bottom = 0):
-	# Implement the public methods MoveToTop (if to_bottom is false)
-	# and MoveToBottom (if to_bottom is true).
-	sliced = list_to_tree_sliced(infolist)
-	sliced.reverse()
+        # Implement the public methods MoveToTop (if to_bottom is false)
+        # and MoveToBottom (if to_bottom is true).
+        sliced = list_to_tree_sliced(infolist)
+        sliced.reverse()
 
-	undo = [self.begin_change_children()]
-	selection = []
-	idxs = []
-	permutation = range(len(self.objects))
-	try:
-	    for start, end in sliced:
-		if type(end) == IntType:
-		    # a contiguous range of self's children (start:end)
-		    idxs[:0] = permutation[start:end]
-		    del permutation[start:end]
-		elif type(end) == ListType:
-		    # children of self.objects[start]
-		    child = self.objects[start]
-		    sel, undo_info = child.move_objects_to_top(end, to_bottom)
-		    if undo_info is not NullUndo:
-			undo.append(undo_info)
-		    selection = selection + prepend_idx(start, sel)
-		else:
-		    # a single object (self.object[start])
-		    idxs.insert(0, start)
-		    del permutation[start]
+        undo = [self.begin_change_children()]
+        selection = []
+        idxs = []
+        permutation = range(len(self.objects))
+        try:
+            for start, end in sliced:
+                if type(end) == IntType:
+                    # a contiguous range of self's children (start:end)
+                    idxs[:0] = permutation[start:end]
+                    del permutation[start:end]
+                elif type(end) == ListType:
+                    # children of self.objects[start]
+                    child = self.objects[start]
+                    sel, undo_info = child.move_objects_to_top(end, to_bottom)
+                    if undo_info is not NullUndo:
+                        undo.append(undo_info)
+                    selection = selection + prepend_idx(start, sel)
+                else:
+                    # a single object (self.object[start])
+                    idxs.insert(0, start)
+                    del permutation[start]
 
-	    if idxs:
-		# direct children of self are involved: apply the
-		# permutation
-		if to_bottom:
-		    permutation = idxs + permutation
-		else:
-		    permutation = permutation + idxs
-		undo_info = self.permute_objects(permutation)
-		if undo_info is not NullUndo:
-		    undo.append(undo_info)
-	    # finished:
-	    undo.append(self.end_change_children())
-	    if len(undo) <= 2:
-		# We haven't really done anything (undo has length 2),
-		# so we just pass the selection info back unchanged
-		selection = infolist
-		undo = NullUndo
-	    else:
-		# We have done something, so figure out the new
-		# selection info
-		undo = CreateListUndo(undo)
+            if idxs:
+                # direct children of self are involved: apply the
+                # permutation
+                if to_bottom:
+                    permutation = idxs + permutation
+                else:
+                    permutation = permutation + idxs
+                undo_info = self.permute_objects(permutation)
+                if undo_info is not NullUndo:
+                    undo.append(undo_info)
+            # finished:
+            undo.append(self.end_change_children())
+            if len(undo) <= 2:
+                # We haven't really done anything (undo has length 2),
+                # so we just pass the selection info back unchanged
+                selection = infolist
+                undo = NullUndo
+            else:
+                # We have done something, so figure out the new
+                # selection info
+                undo = CreateListUndo(undo)
 
-		if to_bottom:
-		    selection = selection \
-				+ select_range(0, self.objects[:len(idxs)])
-		else:
-		    min = len(self.objects) - len(idxs)
-		    selection = selection \
-				+ select_range(min, self.objects[min:])
-	    return (selection, undo)
-	except:
-	    # Ooops, something's gone wrong. Undo everything we've done
-	    # so far... (hmm, this currently fails to undo everything if
-	    # undo.append(undo_info) fails... (the undo_info involved
-	    # would be lost))
-	    Undo(CreateListUndo(undo))
-	    raise
+                if to_bottom:
+                    selection = selection \
+                              + select_range(0, self.objects[:len(idxs)])
+                else:
+                    min = len(self.objects) - len(idxs)
+                    selection = selection \
+                              + select_range(min, self.objects[min:])
+            return (selection, undo)
+        except:
+            # Ooops, something's gone wrong. Undo everything we've done
+            # so far... (hmm, this currently fails to undo everything if
+            # undo.append(undo_info) fails... (the undo_info involved
+            # would be lost))
+            Undo(CreateListUndo(undo))
+            raise
 
     def MoveObjectsToTop(self, infolist):
-	return self.move_objects_to_top(infolist)
+        return self.move_objects_to_top(infolist)
 
     def MoveObjectsToBottom(self, infolist):
-	return self.move_objects_to_top(infolist, to_bottom = 1)
+        return self.move_objects_to_top(infolist, to_bottom = 1)
 
     def MoveObjectsDown(self, infolist):
-	sliced = list_to_tree_sliced(infolist)
-	undo = [self.begin_change_children()]
-	selection = []
-	permutation = range(len(self.objects))
-	objects = self.objects
-	try:
-	    for start, end in sliced:
-		if type(end) == IntType:
-		    if start > 0:
-			temp = permutation[start:end]
-			del permutation[start:end]
-			permutation[start - 1:start - 1] = temp
-			selection = selection +select_range(start - 1,
-							    objects[start:end])
-		    else:
-			selection = selection +select_range(start,
-							    objects[start:end])
+        sliced = list_to_tree_sliced(infolist)
+        undo = [self.begin_change_children()]
+        selection = []
+        permutation = range(len(self.objects))
+        objects = self.objects
+        try:
+            for start, end in sliced:
+                if type(end) == IntType:
+                    if start > 0:
+                        temp = permutation[start:end]
+                        del permutation[start:end]
+                        permutation[start - 1:start - 1] = temp
+                        selection = selection +select_range(start - 1,
+                                                            objects[start:end])
+                    else:
+                        selection = selection +select_range(start,
+                                                            objects[start:end])
 
-		elif type(end) == ListType:
-		    sel, undo_info = objects[start].MoveObjectsDown(end)
-		    if undo_info is not NullUndo:
-			undo.append(undo_info)
-		    selection = selection + prepend_idx(start, sel)
-		else:
-		    if start > 0:
-			del permutation[start]
-			permutation.insert(start - 1, start)
-			selection.append(build_info(start - 1, objects[start]))
-		    else:
-			selection.append(build_info(start, objects[start]))
+                elif type(end) == ListType:
+                    sel, undo_info = objects[start].MoveObjectsDown(end)
+                    if undo_info is not NullUndo:
+                        undo.append(undo_info)
+                    selection = selection + prepend_idx(start, sel)
+                else:
+                    if start > 0:
+                        del permutation[start]
+                        permutation.insert(start - 1, start)
+                        selection.append(build_info(start - 1, objects[start]))
+                    else:
+                        selection.append(build_info(start, objects[start]))
 
-	    undo_info = self.permute_objects(permutation)
-	    if undo_info is not NullUndo:
-		undo.append(undo_info)
-	    undo.append(self.end_change_children())
-	    if len(undo) <= 2:
-		undo = NullUndo
-		selection = infolist
-	    else:
-		undo = CreateListUndo(undo)
-	    return (selection, undo)
-	except:
-	    Undo(CreateListUndo(undo))
-	    raise
+            undo_info = self.permute_objects(permutation)
+            if undo_info is not NullUndo:
+                undo.append(undo_info)
+            undo.append(self.end_change_children())
+            if len(undo) <= 2:
+                undo = NullUndo
+                selection = infolist
+            else:
+                undo = CreateListUndo(undo)
+            return (selection, undo)
+        except:
+            Undo(CreateListUndo(undo))
+            raise
 
     def MoveObjectsUp(self, infolist):
-	sliced = list_to_tree_sliced(infolist)
-	sliced.reverse()
-	undo = [self.begin_change_children()]
-	selection = []
-	permutation = range(len(self.objects))
-	objects = self.objects
-	max = len(objects)
-	try:
-	    for start, end in sliced:
-		if type(end) == IntType:
-		    if end < max:
-			temp = permutation[start:end]
-			del permutation[start:end]
-			permutation[start + 1:start + 1] = temp
-			selection = selection + select_range(start + 1,
-							   objects[start:end])
-		    else:
-			selection = selection + select_range(start,
-							   objects[start:end])
+        sliced = list_to_tree_sliced(infolist)
+        sliced.reverse()
+        undo = [self.begin_change_children()]
+        selection = []
+        permutation = range(len(self.objects))
+        objects = self.objects
+        max = len(objects)
+        try:
+            for start, end in sliced:
+                if type(end) == IntType:
+                    if end < max:
+                        temp = permutation[start:end]
+                        del permutation[start:end]
+                        permutation[start + 1:start + 1] = temp
+                        selection = selection + select_range(start + 1,
+                                                             objects[start:end])
+                    else:
+                        selection = selection + select_range(start,
+                                                             objects[start:end])
 
-		elif type(end) == ListType:
-		    sel, undo_info = objects[start].MoveObjectsUp(end)
-		    if undo_info is not NullUndo:
-			undo.append(undo_info)
-		    selection = selection + prepend_idx(start, sel)
-		else:
-		    if start < max - 1:
-			del permutation[start]
-			permutation.insert(start + 1, start)
-			selection.append(build_info(start + 1, objects[start]))
-		    else:
-			selection.append(build_info(start, objects[start]))
+                elif type(end) == ListType:
+                    sel, undo_info = objects[start].MoveObjectsUp(end)
+                    if undo_info is not NullUndo:
+                        undo.append(undo_info)
+                    selection = selection + prepend_idx(start, sel)
+                else:
+                    if start < max - 1:
+                        del permutation[start]
+                        permutation.insert(start + 1, start)
+                        selection.append(build_info(start + 1, objects[start]))
+                    else:
+                        selection.append(build_info(start, objects[start]))
 
-	    undo_info = self.permute_objects(permutation)
-	    if undo_info is not NullUndo:
-		undo.append(undo_info)
-	    undo.append(self.end_change_children())
-	    if len(undo) <= 2:
-		undo = NullUndo
-		selection = infolist
-	    else:
-		undo = CreateListUndo(undo)
-	    return (selection, undo)
-	except:
-	    Undo(CreateListUndo(undo))
-	    raise
+            undo_info = self.permute_objects(permutation)
+            if undo_info is not NullUndo:
+                undo.append(undo_info)
+            undo.append(self.end_change_children())
+            if len(undo) <= 2:
+                undo = NullUndo
+                selection = infolist
+            else:
+                undo = CreateListUndo(undo)
+            return (selection, undo)
+        except:
+            Undo(CreateListUndo(undo))
+            raise
 
     def DuplicateObjects(self, infolist, offset):
-	infolist = list_to_tree2(infolist)
+        infolist = list_to_tree2(infolist)
 
-	objects = self.objects
-	undo = [self.begin_change_children()]
-	selection = []
-	added = 0
-	try:
-	    for idx, obj in infolist:
-		idx = idx + added
-		if type(obj) == ListType:
-		    # duplicate in subobj
-		    sel, undoinfo = objects[idx].DuplicateObjects(obj, offset)
-		    undo.append(undoinfo)
-		    selection = selection + prepend_idx(idx, sel)
-		else:
-		    obj = obj.Duplicate()
-		    obj.Translate(offset)
-		    sel, undoinfo = self.Insert(obj, idx + 1)
-		    undo.append(undoinfo)
-		    selection.append(sel)
-		    added = added + 1
-	    undo.append(self.end_change_children())
-	    return (selection, CreateListUndo(undo))
-	except:
-	    Undo(CreateListUndo(undo))
-	    raise
+        objects = self.objects
+        undo = [self.begin_change_children()]
+        selection = []
+        added = 0
+        try:
+            for idx, obj in infolist:
+                idx = idx + added
+                if type(obj) == ListType:
+                    # duplicate in subobj
+                    sel, undoinfo = objects[idx].DuplicateObjects(obj, offset)
+                    undo.append(undoinfo)
+                    selection = selection + prepend_idx(idx, sel)
+                else:
+                    obj = obj.Duplicate()
+                    obj.Translate(offset)
+                    sel, undoinfo = self.Insert(obj, idx + 1)
+                    undo.append(undoinfo)
+                    selection.append(sel)
+                    added = added + 1
+            undo.append(self.end_change_children())
+            return (selection, CreateListUndo(undo))
+        except:
+            Undo(CreateListUndo(undo))
+            raise

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/dashes.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/dashes.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/dashes.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -28,14 +28,14 @@
 def StandardDashes():
     global std_dashes
     if std_dashes is None:
-	filename = os.path.join(config.std_res_dir, config.preferences.dashes)
-	try:
-	    std_dashes = []
-	    read_resource_file(filename, '##Sketch Dashes 0',
-			       _("%s is not dashes file"),
-			       {'dashes': std_dashes.append})
-	except:
-	    warn_tb(USER, _("Error trying to read dashes from %s\n"
+        filename = os.path.join(config.std_res_dir, config.preferences.dashes)
+        try:
+            std_dashes = []
+            read_resource_file(filename, '##Sketch Dashes 0',
+                               _("%s is not dashes file"),
+                               {'dashes': std_dashes.append})
+        except:
+            warn_tb(USER, _("Error trying to read dashes from %s\n"
                             "Using builtin defaults"), filename)
-	    std_dashes = [(), (5, 5)]
+            std_dashes = [(), (5, 5)]
     return std_dashes

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/document.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/document.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/document.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -77,174 +77,174 @@
     script_access = {}
 
     def __init__(self, create_layer = 0):
-	self.snap_grid = GridLayer()
-	self.snap_grid.SetDocument(self)
-	self.guide_layer = GuideLayer(_("Guide Lines"))
-	self.guide_layer.SetDocument(self)
-	if create_layer:
-	    # a new empty document
-	    self.active_layer = Layer(_("Layer 1"))
-	    self.active_layer.SetDocument(self)
-	    self.layers = [self.active_layer, self.guide_layer,
-			   self.snap_grid]
-	else:
-	    # we're being created by the load module
-	    self.active_layer = None
-	    self.layers = []
+        self.snap_grid = GridLayer()
+        self.snap_grid.SetDocument(self)
+        self.guide_layer = GuideLayer(_("Guide Lines"))
+        self.guide_layer.SetDocument(self)
+        if create_layer:
+            # a new empty document
+            self.active_layer = Layer(_("Layer 1"))
+            self.active_layer.SetDocument(self)
+            self.layers = [self.active_layer, self.guide_layer,
+                           self.snap_grid]
+        else:
+            # we're being created by the load module
+            self.active_layer = None
+            self.layers = []
 
     def __del__(self):
-	if __debug__:
-	    pdebug('__del__', '__del__', self.meta.filename)
+        if __debug__:
+            pdebug('__del__', '__del__', self.meta.filename)
 
     def __getitem__(self, idx):
-	if type(idx) == IntType:
-	    return self.layers[idx]
-	elif type(idx) == TupleType:
-	    if len(idx) > 1:
-		return self.layers[idx[0]][idx[1:]]
-	    elif len(idx) == 1:
-		return self.layers[idx[0]]
-	raise ValueError, 'invalid index %s' % `idx`
+        if type(idx) == IntType:
+            return self.layers[idx]
+        elif type(idx) == TupleType:
+            if len(idx) > 1:
+                return self.layers[idx[0]][idx[1:]]
+            elif len(idx) == 1:
+                return self.layers[idx[0]]
+        raise ValueError, 'invalid index %s' % `idx`
 
     def AppendLayer(self, layer_name = None, *args, **kw_args):
-	try:
-	    old_layers = self.layers[:]
-	    if layer_name is None:
-		layer_name = _("Layer %d") % (len(self.layers) + 1)
-	    else:
-		layer_name = str(layer_name)
-	    layer = apply(Layer, (layer_name,) + args, kw_args)
-	    layer.SetDocument(self)
-	    self.layers.append(layer)
-	    if not self.active_layer:
-		self.active_layer = layer
-	    return layer
-	except:
-	    self.layers[:] = old_layers
-	    raise
+        try:
+            old_layers = self.layers[:]
+            if layer_name is None:
+                layer_name = _("Layer %d") % (len(self.layers) + 1)
+            else:
+                layer_name = str(layer_name)
+            layer = apply(Layer, (layer_name,) + args, kw_args)
+            layer.SetDocument(self)
+            self.layers.append(layer)
+            if not self.active_layer:
+                self.active_layer = layer
+            return layer
+        except:
+            self.layers[:] = old_layers
+            raise
     script_access['AppendLayer'] = SCRIPT_OBJECT
 
     def BoundingRect(self, visible = 1, printable = 0):
-	rects = []
-	for layer in self.layers:
-	    if ((visible and layer.Visible())
-		or (printable and layer.Printable())):
-		rect = layer.bounding_rect
-		if rect and rect != InfinityRect:
-		    rects.append(rect)
-	if rects:
-	    return reduce(UnionRects, rects)
-	return None
+        rects = []
+        for layer in self.layers:
+            if ((visible and layer.Visible())
+                or (printable and layer.Printable())):
+                rect = layer.bounding_rect
+                if rect and rect != InfinityRect:
+                    rects.append(rect)
+        if rects:
+            return reduce(UnionRects, rects)
+        return None
     script_access['BoundingRect'] = SCRIPT_GET
 
     def augment_sel_info(self, info, layeridx):
-	if type(layeridx) != IntType:
-	    layeridx = self.layers.index(layeridx)
-	return selinfo.prepend_idx(layeridx, info)
+        if type(layeridx) != IntType:
+            layeridx = self.layers.index(layeridx)
+        return selinfo.prepend_idx(layeridx, info)
 
     def insert(self, object, at = None, layer = None):
-	undo_info = None
-	try:
-	    if layer is None:
-		layer = self.active_layer
-	    elif type(layer) == IntType:
-		layer = self.layers[layer]
-	    if layer is None or layer.Locked():
-		raise SketchInternalError('Layer %s is locked' % layer)
-	    if type(object) == ListType:
-		for obj in object:
-		    obj.SetDocument(self)
-	    else:
-		object.SetDocument(self)
-	    sel_info, undo_info = layer.Insert(object, at)
-	    sel_info = self.augment_sel_info(sel_info, layer)
-	    return (sel_info, undo_info)
-	except:
-	    if undo_info is not None:
-		Undo(undo_info)
-	    raise
+        undo_info = None
+        try:
+            if layer is None:
+                layer = self.active_layer
+            elif type(layer) == IntType:
+                layer = self.layers[layer]
+            if layer is None or layer.Locked():
+                raise SketchInternalError('Layer %s is locked' % layer)
+            if type(object) == ListType:
+                for obj in object:
+                    obj.SetDocument(self)
+            else:
+                object.SetDocument(self)
+            sel_info, undo_info = layer.Insert(object, at)
+            sel_info = self.augment_sel_info(sel_info, layer)
+            return (sel_info, undo_info)
+        except:
+            if undo_info is not None:
+                Undo(undo_info)
+            raise
 
     def selection_from_point(self, p, hitrect, device, path = None):
-	# iterate top down (i.e. backwards) through the list of layers
-	if path:
-	    path_layer = path[0]
-	    path = path[1:]
-	else:
-	    path_layer = -1
-	for idx in range(len(self.layers) - 1, -1, -1):
-	    if idx == path_layer:
-		info = self.layers[idx].SelectSubobject(p, hitrect, device,
-							path)
-	    else:
-		info = self.layers[idx].SelectSubobject(p, hitrect, device)
-	    if info:
-		return self.augment_sel_info(info, idx)
-	else:
-	    return None
+        # iterate top down (i.e. backwards) through the list of layers
+        if path:
+            path_layer = path[0]
+            path = path[1:]
+        else:
+            path_layer = -1
+        for idx in range(len(self.layers) - 1, -1, -1):
+            if idx == path_layer:
+                info = self.layers[idx].SelectSubobject(p, hitrect, device,
+                                                        path)
+            else:
+                info = self.layers[idx].SelectSubobject(p, hitrect, device)
+            if info:
+                return self.augment_sel_info(info, idx)
+        else:
+            return None
 
     def selection_from_rect(self, rect):
-	info = []
-	for layer in self.layers:
-	    info = info + self.augment_sel_info(layer.SelectRect(rect), layer)
-	return info
+        info = []
+        for layer in self.layers:
+            info = info + self.augment_sel_info(layer.SelectRect(rect), layer)
+        return info
 
     def Draw(self, device, rect = None):
-	for layer in self.layers:
-	    layer.Draw(device, rect)
+        for layer in self.layers:
+            layer.Draw(device, rect)
 
     def Grid(self):
-	return self.snap_grid
+        return self.snap_grid
 
     def SnapToGrid(self, p):
-	return self.snap_grid.Snap(p)
+        return self.snap_grid.Snap(p)
 
     def SnapToGuide(self, p, maxdist):
-	return self.guide_layer.Snap(p) #, maxdist)
+        return self.guide_layer.Snap(p) #, maxdist)
 
     def DocumentInfo(self):
-	info = []
-	info.append('%d layers' % len(self.layers))
-	for idx in range(len(self.layers)):
-	    layer = self.layers[idx]
-	    info.append('%d: %s,\t%d objects' % (idx + 1, layer.name,
-						 len(layer.objects)))
-	return join(info, '\n')
+        info = []
+        info.append('%d layers' % len(self.layers))
+        for idx in range(len(self.layers)):
+            layer = self.layers[idx]
+            info.append('%d: %s,\t%d objects' % (idx + 1, layer.name,
+                                                 len(layer.objects)))
+        return join(info, '\n')
 
     def SaveToFile(self, file):
-	file.BeginDocument()
-	self.page_layout.SaveToFile(file)
-	self.write_styles(file)
-	for layer in self.layers:
-	    layer.SaveToFile(file)
-	file.EndDocument()
+        file.BeginDocument()
+        self.page_layout.SaveToFile(file)
+        self.write_styles(file)
+        for layer in self.layers:
+            layer.SaveToFile(file)
+        file.EndDocument()
 
     def load_AppendObject(self, layer):
-	self.layers.append(layer)
+        self.layers.append(layer)
 
     def load_Done(self):
-	pass
+        pass
 
     def load_Completed(self):
-	if not self.layers:
-	    self.layers = [Layer(_("Layer 1"))]
-	if self.active_layer is None:
-	    for layer in self.layers:
-		if layer.CanSelect():
-		    self.active_layer = layer
-		    break
-	add_guide_layer = add_grid_layer = 1
-	for layer in self.layers:
-	    layer.SetDocument(self)
-	    if isinstance(layer, GuideLayer):
-		self.guide_layer = layer
-		add_guide_layer = 0
-	    if isinstance(layer, GridLayer):
-		self.snap_grid = layer
-		add_grid_layer = 0
-	if add_guide_layer:
-	    self.layers.append(self.guide_layer)
-	if add_grid_layer:
-	    self.layers.append(self.snap_grid)
+        if not self.layers:
+            self.layers = [Layer(_("Layer 1"))]
+        if self.active_layer is None:
+            for layer in self.layers:
+                if layer.CanSelect():
+                    self.active_layer = layer
+                    break
+        add_guide_layer = add_grid_layer = 1
+        for layer in self.layers:
+            layer.SetDocument(self)
+            if isinstance(layer, GuideLayer):
+                self.guide_layer = layer
+                add_guide_layer = 0
+            if isinstance(layer, GridLayer):
+                self.snap_grid = layer
+                add_grid_layer = 0
+        if add_guide_layer:
+            self.layers.append(self.guide_layer)
+        if add_grid_layer:
+            self.layers.append(self.snap_grid)
 
 
 #
@@ -267,747 +267,747 @@
 class EditDocument(SketchDocument, QueueingPublisher):
 
     drag_mask = Button1Mask # canvas sometimes has the doc as current
-			    # object
+                            # object
     script_access = SketchDocument.script_access.copy()
 
     def __init__(self, create_layer = 0):
-	SketchDocument.__init__(self, create_layer)
-	QueueingPublisher.__init__(self)
-	self.selection = SizeSelection()
-	self.__init_undo()
-	self.was_dragged = 0
-	self.meta = MetaInfo()
-	self.hit_cache = None
-	self.connector = Connector()
-	self.init_transaction()
-	self.init_clear()
-	self.init_styles()
-	self.init_after_handler()
-	self.init_layout()
+        SketchDocument.__init__(self, create_layer)
+        QueueingPublisher.__init__(self)
+        self.selection = SizeSelection()
+        self.__init_undo()
+        self.was_dragged = 0
+        self.meta = MetaInfo()
+        self.hit_cache = None
+        self.connector = Connector()
+        self.init_transaction()
+        self.init_clear()
+        self.init_styles()
+        self.init_after_handler()
+        self.init_layout()
 
     def Destroy(self):
-	self.undo = None
-	self.destroy_styles()
-	RemovePublisher(self)
-	for layer in self.layers:
-	    layer.Destroy()
-	self.layers = []
-	self.active_layer = None
-	self.guide_layer = None
-	self.snap_grid = None
-	# make self.connector empty connector to remove circular refs
-	# and to allow object to call document.connector.RemovePublisher
-	# in their __del__ methods
-	self.connector = Connector()
-	self.selection = None
-	self.transaction_undo = []
-	self.transaction_sel = []
+        self.undo = None
+        self.destroy_styles()
+        RemovePublisher(self)
+        for layer in self.layers:
+            layer.Destroy()
+        self.layers = []
+        self.active_layer = None
+        self.guide_layer = None
+        self.snap_grid = None
+        # make self.connector empty connector to remove circular refs
+        # and to allow object to call document.connector.RemovePublisher
+        # in their __del__ methods
+        self.connector = Connector()
+        self.selection = None
+        self.transaction_undo = []
+        self.transaction_sel = []
 
     def queue_layer(self, *args):
-	if self.transaction:
-	    apply(self.queue_message, (LAYER,) + args)
-	    return (self.queue_layer, args)
-	else:
-	    apply(self.issue, (LAYER,) + args)
+        if self.transaction:
+            apply(self.queue_message, (LAYER,) + args)
+            return (self.queue_layer, args)
+        else:
+            apply(self.issue, (LAYER,) + args)
 
     def queue_selection(self):
-	self.queue_message(SELECTION)
+        self.queue_message(SELECTION)
 
     def queue_edited(self):
-	# An EDITED message should probably indicate the type of edit,
-	# i.e. whether properties changed, the geometry of objects
-	# changed, etc.; hence the additional string argument which may
-	# hold this information in the future
-	self.queue_message(EDITED, '')
-	return (self.queue_edited,)
+        # An EDITED message should probably indicate the type of edit,
+        # i.e. whether properties changed, the geometry of objects
+        # changed, etc.; hence the additional string argument which may
+        # hold this information in the future
+        self.queue_message(EDITED, '')
+        return (self.queue_edited,)
 
     def Subscribe(self, channel, func, *args):
-	Connect(self, channel, func, args)
+        Connect(self, channel, func, args)
 
     def Unsubscribe(self, channel, func, *args):
-	Disconnect(self, channel, func, args)
+        Disconnect(self, channel, func, args)
 
     def init_after_handler(self):
-	self.after_handlers = []
+        self.after_handlers = []
 
     def AddAfterHandler(self, handler, args = (), depth = 0):
-	handler = (depth, handler, args)
-	try:
-	    self.after_handlers.remove(handler)
-	except ValueError:
-	    pass
-	self.after_handlers.append(handler)
+        handler = (depth, handler, args)
+        try:
+            self.after_handlers.remove(handler)
+        except ValueError:
+            pass
+        self.after_handlers.append(handler)
 
     def call_after_handlers(self):
-	if not self.after_handlers:
-	    return 0
+        if not self.after_handlers:
+            return 0
 
-	while self.after_handlers:
+        while self.after_handlers:
             handlers = self.after_handlers
 
-	    handlers.sort()
-	    handlers.reverse()
-	    depth = handlers[0][0]
+            handlers.sort()
+            handlers.reverse()
+            depth = handlers[0][0]
 
-	    count = 0
-	    for d, handler, args in handlers:
-		if d == depth:
-		    count = count + 1
-		else:
-		    break
-	    self.after_handlers = handlers[count:]
-	    handlers = handlers[:count]
+            count = 0
+            for d, handler, args in handlers:
+                if d == depth:
+                    count = count + 1
+                else:
+                    break
+            self.after_handlers = handlers[count:]
+            handlers = handlers[:count]
 
-	    for d, handler, args in handlers:
-		try:
-		    apply(handler, args)
-		except:
-		    warn_tb(INTERNAL, "In after handler `%s'%s", handler, args)
+            for d, handler, args in handlers:
+                try:
+                    apply(handler, args)
+                except:
+                    warn_tb(INTERNAL, "In after handler `%s'%s", handler, args)
 
-	return 1
+        return 1
 
     def init_clear(self):
-	self.clear_rects = []
-	self.clear_all = 0
+        self.clear_rects = []
+        self.clear_all = 0
 
     reset_clear = init_clear
 
     def AddClearRect(self, rect):
-	self.clear_rects.append(rect)
-	return (self.AddClearRect, rect)
+        self.clear_rects.append(rect)
+        return (self.AddClearRect, rect)
 
     def view_redraw_all(self):
-	self.clear_all = 1
-	return (self.view_redraw_all,)
+        self.clear_all = 1
+        return (self.view_redraw_all,)
 
     def issue_redraw(self):
-	try:
-	    if self.clear_all:
-		Issue(self, REDRAW, 1)
-	    else:
-		Issue(self, REDRAW, 0, self.clear_rects)
-	finally:
-	    self.clear_rects = []
-	    self.clear_all = 0
+        try:
+            if self.clear_all:
+                Issue(self, REDRAW, 1)
+            else:
+                Issue(self, REDRAW, 0, self.clear_rects)
+        finally:
+            self.clear_rects = []
+            self.clear_all = 0
 
     def init_transaction(self):
-	self.reset_transaction()
+        self.reset_transaction()
 
     def reset_transaction(self):
-	self.transaction = 0
-	self.transaction_name = ''
-	self.transaction_sel = []
-	self.transaction_undo = []
-	self.transaction_sel_ignore = 0
-	self.transaction_clear = None
-	self.transaction_aborted = 0
-	self.transaction_cleanup = []
+        self.transaction = 0
+        self.transaction_name = ''
+        self.transaction_sel = []
+        self.transaction_undo = []
+        self.transaction_sel_ignore = 0
+        self.transaction_clear = None
+        self.transaction_aborted = 0
+        self.transaction_cleanup = []
 
     def cleanup_transaction(self):
-	for handler, args in self.transaction_cleanup:
-	    try:
-		apply(handler, args)
-	    except:
-		warn_tb(INTERNAL, "in cleanup handler %s%s", handler, `args`)
-	self.transaction_cleanup = []
+        for handler, args in self.transaction_cleanup:
+            try:
+                apply(handler, args)
+            except:
+                warn_tb(INTERNAL, "in cleanup handler %s%s", handler, `args`)
+        self.transaction_cleanup = []
 
     def add_cleanup_handler(self, handler, *args):
-	handler = (handler, args)
-	try:
-	    self.transaction_cleanup.remove(handler)
-	except ValueError:
-	    pass
-	self.transaction_cleanup.append(handler)
+        handler = (handler, args)
+        try:
+            self.transaction_cleanup.remove(handler)
+        except ValueError:
+            pass
+        self.transaction_cleanup.append(handler)
 
     def begin_transaction(self, name = '', no_selection = 0,
-			  clear_selection_rect = 1):
-	if self.transaction_aborted:
-	    raise AbortTransactionError
-	if self.transaction == 0:
-	    if not no_selection:
-		selinfo = self.selection.GetInfo()[:]
-		if selinfo != self.transaction_sel:
-		    self.transaction_sel = selinfo
-		self.transaction_sel_mode = self.selection.__class__
-	    self.transaction_sel_ignore = no_selection
-	    self.transaction_name = name
-	    self.transaction_undo = []
-	    if clear_selection_rect:
-		if self.selection:
-		    self.transaction_clear = self.selection.bounding_rect
-	    else:
-		self.transaction_clear = None
-	elif not self.transaction_name:
-	    self.transaction_name = name
-	self.transaction = self.transaction + 1
+                          clear_selection_rect = 1):
+        if self.transaction_aborted:
+            raise AbortTransactionError
+        if self.transaction == 0:
+            if not no_selection:
+                selinfo = self.selection.GetInfo()[:]
+                if selinfo != self.transaction_sel:
+                    self.transaction_sel = selinfo
+                self.transaction_sel_mode = self.selection.__class__
+            self.transaction_sel_ignore = no_selection
+            self.transaction_name = name
+            self.transaction_undo = []
+            if clear_selection_rect:
+                if self.selection:
+                    self.transaction_clear = self.selection.bounding_rect
+            else:
+                self.transaction_clear = None
+        elif not self.transaction_name:
+            self.transaction_name = name
+        self.transaction = self.transaction + 1
 
     def end_transaction(self, issue = (), queue_edited = 0):
-	self.transaction = self.transaction - 1
-	if self.transaction_aborted:
-	    # end an aborted transaction
-	    if self.transaction == 0:
-		# undo the changes already done...
-		undo = self.transaction_undo
-		undo.reverse()
-		map(Undo, undo)
-		self.cleanup_transaction()
-		self.reset_transaction()
-		self.reset_clear()
-	else:
-	    # a normal transaction
-	    if type(issue) == StringType:
-		self.queue_message(issue)
-	    else:
-		for channel in issue:
-		    self.queue_message(channel)
-	    if self.transaction == 0:
-		# the outermost end_transaction
-		# increase transaction flag temporarily because some
-		# after handlers might call public methods that are
-		# themselves transactions...
-		self.transaction = 1
-		if self.call_after_handlers():
-		    self.selection.ResetRectangle()
-		self.transaction = 0
-		undo = CreateListUndo(self.transaction_undo)
-		if undo is not NullUndo:
-		    undo = [undo]
-		    if self.transaction_clear is not None:
-			undo.append(self.AddClearRect(self.transaction_clear))
-			if self.selection:
-			    self.selection.ResetRectangle()
-			    rect = self.selection.bounding_rect
-			    undo.append(self.AddClearRect(rect))
-		    if queue_edited:
-			undo.append(self.queue_edited())
-		    undo = CreateListUndo(undo)
-		    if self.transaction_sel_ignore:
-			self.__real_add_undo(self.transaction_name, undo)
-		    else:
-			self.__real_add_undo(self.transaction_name, undo,
-					     self.transaction_sel,
-					     self.transaction_sel_mode)
-		self.flush_message_queue()
-		self.issue_redraw()
-		self.cleanup_transaction()
-		self.reset_transaction()
-		self.reset_clear()
-	    elif self.transaction < 0:
-		raise SketchInternalError('transaction < 0')
+        self.transaction = self.transaction - 1
+        if self.transaction_aborted:
+            # end an aborted transaction
+            if self.transaction == 0:
+                # undo the changes already done...
+                undo = self.transaction_undo
+                undo.reverse()
+                map(Undo, undo)
+                self.cleanup_transaction()
+                self.reset_transaction()
+                self.reset_clear()
+        else:
+            # a normal transaction
+            if type(issue) == StringType:
+                self.queue_message(issue)
+            else:
+                for channel in issue:
+                    self.queue_message(channel)
+            if self.transaction == 0:
+                # the outermost end_transaction
+                # increase transaction flag temporarily because some
+                # after handlers might call public methods that are
+                # themselves transactions...
+                self.transaction = 1
+                if self.call_after_handlers():
+                    self.selection.ResetRectangle()
+                self.transaction = 0
+                undo = CreateListUndo(self.transaction_undo)
+                if undo is not NullUndo:
+                    undo = [undo]
+                    if self.transaction_clear is not None:
+                        undo.append(self.AddClearRect(self.transaction_clear))
+                        if self.selection:
+                            self.selection.ResetRectangle()
+                            rect = self.selection.bounding_rect
+                            undo.append(self.AddClearRect(rect))
+                    if queue_edited:
+                        undo.append(self.queue_edited())
+                    undo = CreateListUndo(undo)
+                    if self.transaction_sel_ignore:
+                        self.__real_add_undo(self.transaction_name, undo)
+                    else:
+                        self.__real_add_undo(self.transaction_name, undo,
+                                             self.transaction_sel,
+                                             self.transaction_sel_mode)
+                self.flush_message_queue()
+                self.issue_redraw()
+                self.cleanup_transaction()
+                self.reset_transaction()
+                self.reset_clear()
+            elif self.transaction < 0:
+                raise SketchInternalError('transaction < 0')
 
     def abort_transaction(self):
-	self.transaction_aborted = 1
-	warn_tb(INTERNAL, "in transaction `%s'" % self.transaction_name)
-	raise AbortTransactionError
+        self.transaction_aborted = 1
+        warn_tb(INTERNAL, "in transaction `%s'" % self.transaction_name)
+        raise AbortTransactionError
 
     # public versions of the transaction methods
     BeginTransaction = begin_transaction
     AbortTransaction = abort_transaction
 
     def EndTransaction(self):
-	self.end_transaction(queue_edited = 1)
+        self.end_transaction(queue_edited = 1)
 
     def Insert(self, object, undo_text = _("Create Object")):
-	if isinstance(object, guide.GuideLine):
-	    self.add_guide_line(object)
-	else:
-	    self.begin_transaction(undo_text, clear_selection_rect = 0)
-	    try:
-		try:
-		    object.SetDocument(self)
-		    selected, undo = self.insert(object)
-		    self.add_undo(undo)
-		    self.add_undo(self.AddClearRect(object.bounding_rect))
-		    self.__set_selection(selected, SelectSet)
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction(queue_edited = 1)
+        if isinstance(object, guide.GuideLine):
+            self.add_guide_line(object)
+        else:
+            self.begin_transaction(undo_text, clear_selection_rect = 0)
+            try:
+                try:
+                    object.SetDocument(self)
+                    selected, undo = self.insert(object)
+                    self.add_undo(undo)
+                    self.add_undo(self.AddClearRect(object.bounding_rect))
+                    self.__set_selection(selected, SelectSet)
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction(queue_edited = 1)
 
     def SelectPoint(self, p, device, type = SelectSet):
-	# find object at point, and modify the current selection
-	# according to type
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		if type == SelectSubobjects:
-		    path = self.selection.GetPath()
-		else:
-		    path = ()
-		rect = device.HitRectAroundPoint(p)
-		if self.hit_cache:
-		    cp, cdevice, hit = self.hit_cache
-		    self.hit_cache = None
-		    if p is cp and device is cdevice:
-			selected = hit
-		    else:
-			selected = self.selection_from_point(p, rect, device,
-							     path)
-		else:
-		    selected = self.selection_from_point(p, rect, device, path)
-		if type == SelectGuide:
+        # find object at point, and modify the current selection
+        # according to type
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                if type == SelectSubobjects:
+                    path = self.selection.GetPath()
+                else:
+                    path = ()
+                rect = device.HitRectAroundPoint(p)
+                if self.hit_cache:
+                    cp, cdevice, hit = self.hit_cache
+                    self.hit_cache = None
+                    if p is cp and device is cdevice:
+                        selected = hit
+                    else:
+                        selected = self.selection_from_point(p, rect, device,
+                                                             path)
+                else:
+                    selected = self.selection_from_point(p, rect, device, path)
+                if type == SelectGuide:
                     if selected and selected[-1].is_GuideLine:
                         return selected[-1]
-		    return None
-		elif selected:
-		    path, object = selected
-		    if self.layers[path[0]] is self.guide_layer:
-			if object.is_GuideLine:
-			    # guide lines cannot be selected in the
-			    # ordinary way, but other objects on the
-			    # guide layer can.
-			    selected = None
-		self.__set_selection(selected, type)
+                    return None
+                elif selected:
+                    path, object = selected
+                    if self.layers[path[0]] is self.guide_layer:
+                        if object.is_GuideLine:
+                            # guide lines cannot be selected in the
+                            # ordinary way, but other objects on the
+                            # guide layer can.
+                            selected = None
+                self.__set_selection(selected, type)
 
                 if self.IsEditMode():
                     object = self.CurrentObject()
                     if object is not None and object.is_Text:
                         self.SelectPointPart(p, device, SelectSet)
 
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
-	return selected
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
+        return selected
 
     def SelectRect(self, rect, mode = SelectSet):
-	# Find all objects contained in rect and modify the current
-	# selection according to mode
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		self.hit_cache = None
-		selected = self.selection_from_rect(rect)
-		self.__set_selection(selected, mode)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
-	return selected
+        # Find all objects contained in rect and modify the current
+        # selection according to mode
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                self.hit_cache = None
+                selected = self.selection_from_rect(rect)
+                self.__set_selection(selected, mode)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
+        return selected
 
     def SelectRectPart(self, rect, mode = SelectSet):
-	# Select the part of the CSO that lies in rect. Currently this
-	# works only in edit mode. For a PolyBezier this means that all
-	# nodes within rect are selected.
-	if not self.IsEditMode():
-	    raise SketchInternalError('SelectRectPart requires edit mode')
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		self.hit_cache = None
-		self.selection.SelectRect(rect, mode)
-		self.queue_selection()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # Select the part of the CSO that lies in rect. Currently this
+        # works only in edit mode. For a PolyBezier this means that all
+        # nodes within rect are selected.
+        if not self.IsEditMode():
+            raise SketchInternalError('SelectRectPart requires edit mode')
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                self.hit_cache = None
+                self.selection.SelectRect(rect, mode)
+                self.queue_selection()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def SelectPointPart(self, p, device, mode = SelectSet):
-	# Select the part of the current object under the point p.
-	# Like SelectRectPart this only works in edit mode.
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
+        # Select the part of the current object under the point p.
+        # Like SelectRectPart this only works in edit mode.
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
                 self.hit_cache = None
                 rect = device.HitRectAroundPoint(p)
                 self.selection.SelectPoint(p, rect, device, mode)
-		if mode != SelectDrag:
-		    self.queue_selection()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+                if mode != SelectDrag:
+                    self.queue_selection()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def SelectHandle(self, handle, mode = SelectSet):
-	# Select the handle indicated by handle. This only works in edit
-	# mode.
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		self.hit_cache = None
-		self.selection.SelectHandle(handle, mode)
-		if mode != SelectDrag:
-		    self.queue_selection()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # Select the handle indicated by handle. This only works in edit
+        # mode.
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                self.hit_cache = None
+                self.selection.SelectHandle(handle, mode)
+                if mode != SelectDrag:
+                    self.queue_selection()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def SelectAll(self):
-	# Select all objects that can currently be selected.
-	# XXX should the objects in the guide layer also be selected by
-	# this method? (currently they are)
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		sel_info = []
-		for layer_idx in range(len(self.layers)):
-		    sel = self.layers[layer_idx].SelectAll()
-		    if sel:
-			sel = self.augment_sel_info(sel, layer_idx)
-			sel_info = sel_info + sel
-		self.__set_selection(sel_info, SelectSet)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # Select all objects that can currently be selected.
+        # XXX should the objects in the guide layer also be selected by
+        # this method? (currently they are)
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                sel_info = []
+                for layer_idx in range(len(self.layers)):
+                    sel = self.layers[layer_idx].SelectAll()
+                    if sel:
+                        sel = self.augment_sel_info(sel, layer_idx)
+                        sel_info = sel_info + sel
+                self.__set_selection(sel_info, SelectSet)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
     script_access['SelectAll'] = SCRIPT_GET
 
     def SelectNone(self):
-	# Deselect all objects.
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		self.__set_selection(None, SelectSet)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # Deselect all objects.
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                self.__set_selection(None, SelectSet)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
     script_access['SelectNone'] = SCRIPT_GET
 
     def SelectObject(self, objects, mode = SelectSet):
-	# Select the objects defined by OBJECTS. OBJECTS may be a single
-	# GraphicsObject or a list of such objects. Modify the current
-	# selection according to MODE.
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		if type(objects) != ListType:
-		    objects = [objects]
-		selinfo = []
-		for object in objects:
-		    selinfo.append(object.SelectionInfo())
+        # Select the objects defined by OBJECTS. OBJECTS may be a single
+        # GraphicsObject or a list of such objects. Modify the current
+        # selection according to MODE.
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                if type(objects) != ListType:
+                    objects = [objects]
+                selinfo = []
+                for object in objects:
+                    selinfo.append(object.SelectionInfo())
                 if selinfo:
                     self.__set_selection(selinfo, mode)
                 else:
                     self.__set_selection(None, SelectSet)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
     #script_access['SelectObject'] = SCRIPT_GET
 
 
     def select_first_in_layer(self, idx = 0):
-	for layer in self.layers[idx:]:
-	    if layer.CanSelect() and not layer.is_SpecialLayer:
-		object = layer.SelectFirstChild()
-		if object is not None:
-		    return object
+        for layer in self.layers[idx:]:
+            if layer.CanSelect() and not layer.is_SpecialLayer:
+                object = layer.SelectFirstChild()
+                if object is not None:
+                    return object
 
     def SelectNextObject(self):
-	# If exactly one object is selected select its next higher
-	# sibling. If there is no next sibling and its parent is a
-	# layer, select the first object in the next higher layer that
-	# allows selections.
-	#
-	# If more than one object is currently selected, deselect all
-	# but the the highest of them.
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		info = self.selection.GetInfo()
-		if len(info) > 1:
-		    self.__set_selection(info[-1], SelectSet)
-		elif info:
-		    path, object = info[0]
-		    parent = object.parent
-		    object = parent.SelectNextChild(object, path[-1])
-		    if object is None and parent.is_Layer:
-			idx = self.layers.index(parent)
-			object = self.select_first_in_layer(idx + 1)
-		    if object is not None:
-			self.SelectObject(object)
-		else:
-		    object = self.select_first_in_layer()
-		    if object is not None:
-			self.SelectObject(object)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # If exactly one object is selected select its next higher
+        # sibling. If there is no next sibling and its parent is a
+        # layer, select the first object in the next higher layer that
+        # allows selections.
+        #
+        # If more than one object is currently selected, deselect all
+        # but the the highest of them.
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                info = self.selection.GetInfo()
+                if len(info) > 1:
+                    self.__set_selection(info[-1], SelectSet)
+                elif info:
+                    path, object = info[0]
+                    parent = object.parent
+                    object = parent.SelectNextChild(object, path[-1])
+                    if object is None and parent.is_Layer:
+                        idx = self.layers.index(parent)
+                        object = self.select_first_in_layer(idx + 1)
+                    if object is not None:
+                        self.SelectObject(object)
+                else:
+                    object = self.select_first_in_layer()
+                    if object is not None:
+                        self.SelectObject(object)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
     script_access['SelectNextObject'] = SCRIPT_GET
 
     def select_last_in_layer(self, idx):
-	if idx < 0:
-	    return
-	layers = self.layers[:idx + 1]
-	layers.reverse()
-	for layer in layers:
-	    if layer.CanSelect() and not layer.is_SpecialLayer:
-		object = layer.SelectLastChild()
-		if object is not None:
-		    return object
+        if idx < 0:
+            return
+        layers = self.layers[:idx + 1]
+        layers.reverse()
+        for layer in layers:
+            if layer.CanSelect() and not layer.is_SpecialLayer:
+                object = layer.SelectLastChild()
+                if object is not None:
+                    return object
 
     def SelectPreviousObject(self):
-	# If exactly one object is selected select its next lower
-	# sibling. If there is no lower sibling and its parent is a
-	# layer, select the last object in the next lower layer that
-	# allows selections.
-	#
-	# If more than one object is currently selected, deselect all
-	# but the the lowest of them.
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		info = self.selection.GetInfo()
-		if len(info) > 1:
-		    self.__set_selection(info[0], SelectSet)
-		elif info:
-		    path, object = info[0]
-		    parent = object.parent
-		    object = parent.SelectPreviousChild(object, path[-1])
-		    if object is None and parent.is_Layer:
-			idx = self.layers.index(parent)
-			object = self.select_last_in_layer(idx - 1)
-		    if object is not None:
-			self.SelectObject(object)
-		else:
-		    object = self.select_last_in_layer(len(self.layers))
-		    if object is not None:
-			self.SelectObject(object)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # If exactly one object is selected select its next lower
+        # sibling. If there is no lower sibling and its parent is a
+        # layer, select the last object in the next lower layer that
+        # allows selections.
+        #
+        # If more than one object is currently selected, deselect all
+        # but the the lowest of them.
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                info = self.selection.GetInfo()
+                if len(info) > 1:
+                    self.__set_selection(info[0], SelectSet)
+                elif info:
+                    path, object = info[0]
+                    parent = object.parent
+                    object = parent.SelectPreviousChild(object, path[-1])
+                    if object is None and parent.is_Layer:
+                        idx = self.layers.index(parent)
+                        object = self.select_last_in_layer(idx - 1)
+                    if object is not None:
+                        self.SelectObject(object)
+                else:
+                    object = self.select_last_in_layer(len(self.layers))
+                    if object is not None:
+                        self.SelectObject(object)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
     script_access['SelectPreviousObject'] = SCRIPT_GET
 
     def SelectFirstChild(self):
-	# If exactly one object is selected and this object is a
-	# compound object, select its first (lowest) child. The first
-	# child is the object returned by the compound object's method
-	# SelectFirstChild. If that method returns none, do nothing.
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		objects = self.selection.GetObjects()
-		if len(objects) == 1:
-		    object = objects[0]
-		    if object.is_Compound:
-			object = object.SelectFirstChild()
-			if object is not None:
-			    self.SelectObject(object)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # If exactly one object is selected and this object is a
+        # compound object, select its first (lowest) child. The first
+        # child is the object returned by the compound object's method
+        # SelectFirstChild. If that method returns none, do nothing.
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                objects = self.selection.GetObjects()
+                if len(objects) == 1:
+                    object = objects[0]
+                    if object.is_Compound:
+                        object = object.SelectFirstChild()
+                        if object is not None:
+                            self.SelectObject(object)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
     script_access['SelectFirstChild'] = SCRIPT_GET
 
     def SelectParent(self):
-	# Select the parent of the currently selected object(s).
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		if len(self.selection) > 1:
-		    path = selinfo.common_prefix(self.selection.GetInfo())
-		    if len(path) > 1:
-			object = self[path]
-			self.SelectObject(object)
-		elif len(self.selection) == 1:
-		    object = self.selection.GetObjects()[0].parent
-		    if not object.is_Layer:
-			self.SelectObject(object)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # Select the parent of the currently selected object(s).
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                if len(self.selection) > 1:
+                    path = selinfo.common_prefix(self.selection.GetInfo())
+                    if len(path) > 1:
+                        object = self[path]
+                        self.SelectObject(object)
+                elif len(self.selection) == 1:
+                    object = self.selection.GetObjects()[0].parent
+                    if not object.is_Layer:
+                        self.SelectObject(object)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
     script_access['SelectParent'] = SCRIPT_GET
 
     def DeselectObject(self, object):
-	# Deselect the object OBJECT.
-	# XXX: for large selections this can be very slow.
-	selected = self.selection.GetObjects()
-	try:
-	    index = selected.index(object)
-	except ValueError:
-	    return
-	info = self.selection.GetInfo()
-	del info[index]
-	self.__set_selection(info, SelectSet)
+        # Deselect the object OBJECT.
+        # XXX: for large selections this can be very slow.
+        selected = self.selection.GetObjects()
+        try:
+            index = selected.index(object)
+        except ValueError:
+            return
+        info = self.selection.GetInfo()
+        del info[index]
+        self.__set_selection(info, SelectSet)
 
     def __set_selection(self, selected, type):
-	# Modify the current selection. SELECTED is a list of selection
-	# info describing the new selection, TYPE indicates how the
-	# current selection is modified:
-	#
-	# type			Meaning
-	# SelectSet		Replace the old selection by the new one
-	# SelectSubtract	Subtract the new selection from the old one
-	# SelectAdd		Add the new selection to the old one.
-	# SelectSubobjects	like SelectSet here
-	changed = 0
-	if type == SelectAdd:
-	    if selected:
-		changed = self.selection.Add(selected)
-	elif type == SelectSubtract:
-	    if selected:
-		changed = self.selection.Subtract(selected)
-	elif type == SelectGuide:
-	    if selected:
-		pass
-	else:
-	    # type is SelectSet or SelectSubobjects
-	    # set the selection. make a size selection if necessary
-	    if self.selection.__class__ == TrafoSelection:
-		self.selection = SizeSelection()
-		changed = 1
-	    changed = self.selection.SetSelection(selected) or changed
-	if changed:
-	    self.queue_selection()
+        # Modify the current selection. SELECTED is a list of selection
+        # info describing the new selection, TYPE indicates how the
+        # current selection is modified:
+        #
+        # type			Meaning
+        # SelectSet		Replace the old selection by the new one
+        # SelectSubtract	Subtract the new selection from the old one
+        # SelectAdd		Add the new selection to the old one.
+        # SelectSubobjects	like SelectSet here
+        changed = 0
+        if type == SelectAdd:
+            if selected:
+                changed = self.selection.Add(selected)
+        elif type == SelectSubtract:
+            if selected:
+                changed = self.selection.Subtract(selected)
+        elif type == SelectGuide:
+            if selected:
+                pass
+        else:
+            # type is SelectSet or SelectSubobjects
+            # set the selection. make a size selection if necessary
+            if self.selection.__class__ == TrafoSelection:
+                self.selection = SizeSelection()
+                changed = 1
+            changed = self.selection.SetSelection(selected) or changed
+        if changed:
+            self.queue_selection()
 
     def SetMode(self, mode):
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		if mode == SelectionMode:
-		    self.selection = SizeSelection(self.selection)
-		else:
-		    self.selection = EditSelection(self.selection)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction(issue = (SELECTION, MODE))
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                if mode == SelectionMode:
+                    self.selection = SizeSelection(self.selection)
+                else:
+                    self.selection = EditSelection(self.selection)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction(issue = (SELECTION, MODE))
 
     def Mode(self):
-	if self.selection.__class__ == EditSelection:
-	    return EditMode
-	return SelectionMode
+        if self.selection.__class__ == EditSelection:
+            return EditMode
+        return SelectionMode
     script_access['Mode'] = SCRIPT_GET
 
     def IsSelectionMode(self):
-	return self.Mode() == SelectionMode
+        return self.Mode() == SelectionMode
     script_access['IsSelectionMode'] = SCRIPT_GET
 
     def IsEditMode(self):
-	return self.Mode() == EditMode
+        return self.Mode() == EditMode
     script_access['IsEditMode'] = SCRIPT_GET
 
 
     def SelectionHit(self, p, device, test_all = 1):
-	# Return true, if the point P hits the currently selected
-	# objects.
-	#
-	# If test_all is true (the default), find the object that would
-	# be selected by SelectPoint and return true if it or one of its
-	# ancestors is contained in the current selection and false
-	# otherwise.
-	#
-	# If test_all is false, just test the currently selected objects.
-	rect = device.HitRectAroundPoint(p)
-	if len(self.selection) < 10 or not test_all:
-	    selection_hit = self.selection.Hit(p, rect, device)
-	    if not test_all or not selection_hit:
-		return selection_hit
-	if test_all:
-	    path = self.selection.GetPath()
-	    if len(path) > 2:
-		path = path[:-1]
-	    else:
-		path = ()
-	    hit = self.selection_from_point(p, rect, device, path)
-	    self.hit_cache = (p, device, hit)
-	    while hit:
-		if hit in self.selection.GetInfo():
-		    return 1
-		hit = selinfo.get_parent(hit)
-	    #self.hit_cache = None
-	    return 0
+        # Return true, if the point P hits the currently selected
+        # objects.
+        #
+        # If test_all is true (the default), find the object that would
+        # be selected by SelectPoint and return true if it or one of its
+        # ancestors is contained in the current selection and false
+        # otherwise.
+        #
+        # If test_all is false, just test the currently selected objects.
+        rect = device.HitRectAroundPoint(p)
+        if len(self.selection) < 10 or not test_all:
+            selection_hit = self.selection.Hit(p, rect, device)
+            if not test_all or not selection_hit:
+                return selection_hit
+        if test_all:
+            path = self.selection.GetPath()
+            if len(path) > 2:
+                path = path[:-1]
+            else:
+                path = ()
+            hit = self.selection_from_point(p, rect, device, path)
+            self.hit_cache = (p, device, hit)
+            while hit:
+                if hit in self.selection.GetInfo():
+                    return 1
+                hit = selinfo.get_parent(hit)
+            #self.hit_cache = None
+            return 0
 
     def GetSelectionHandles(self):
-	if self.selection:
-	    return self.selection.GetHandles()
-	else:
-	    return []
+        if self.selection:
+            return self.selection.GetHandles()
+        else:
+            return []
 
     #
     #	Get information about the selected objects
     #
 
     def HasSelection(self):
-	# Return true, if one or more objects are selected
-	return len(self.selection)
+        # Return true, if one or more objects are selected
+        return len(self.selection)
     script_access['HasSelection'] = SCRIPT_GET
 
     def CountSelected(self):
-	# Return the number of currently selected objects
-	return len(self.selection)
+        # Return the number of currently selected objects
+        return len(self.selection)
     script_access['CountSelected'] = SCRIPT_GET
 
     def SelectionInfoText(self):
-	# Return a string describing the selected object(s)
-	return self.selection.InfoText()
+        # Return a string describing the selected object(s)
+        return self.selection.InfoText()
     script_access['SelectionInfoText'] = SCRIPT_GET
 
     def CurrentInfoText(self):
         return self.selection.CurrentInfoText()
 
     def SelectionBoundingRect(self):
-	# Return the bounding rect of the current selection
-	return self.selection.bounding_rect
+        # Return the bounding rect of the current selection
+        return self.selection.bounding_rect
     script_access['SelectionBoundingRect'] = SCRIPT_GET
 
     def CurrentObject(self):
-	# If exactly one object is selected return that, None instead.
-	if len(self.selection) == 1:
-	    return self.selection.GetObjects()[0]
-	return None
+        # If exactly one object is selected return that, None instead.
+        if len(self.selection) == 1:
+            return self.selection.GetObjects()[0]
+        return None
     script_access['CurrentObject'] = SCRIPT_OBJECT
 
     def SelectedObjects(self):
-	# Return the selected objects as a list. They are listed in the
-	# order in which they are drawn.
-	return self.selection.GetObjects()
+        # Return the selected objects as a list. They are listed in the
+        # order in which they are drawn.
+        return self.selection.GetObjects()
     script_access['SelectedObjects'] = SCRIPT_OBJECTLIST
 
     def CurrentProperties(self):
-	# Return the properties of the current object if exactly one
-	# object is selected. Return EmptyProperties otherwise.
-	if self.selection:
-	    if len(self.selection) > 1:
-		return EmptyProperties
-	    return self.selection.GetInfo()[0][-1].Properties()
-	return EmptyProperties
+        # Return the properties of the current object if exactly one
+        # object is selected. Return EmptyProperties otherwise.
+        if self.selection:
+            if len(self.selection) > 1:
+                return EmptyProperties
+            return self.selection.GetInfo()[0][-1].Properties()
+        return EmptyProperties
     script_access['CurrentProperties'] = SCRIPT_OBJECT
 
 
     def CurrentFillColor(self):
-	# Return the fill color of the current object if exactly one
-	# object is selected and that object has a solid fill. Return
-	# None otherwise.
-	if len(self.selection) == 1:
-	    properties = self.selection.GetInfo()[0][-1].Properties()
-	    try:
-		return	properties.fill_pattern.Color()
-	    except AttributeError:
-		pass
-	return None
+        # Return the fill color of the current object if exactly one
+        # object is selected and that object has a solid fill. Return
+        # None otherwise.
+        if len(self.selection) == 1:
+            properties = self.selection.GetInfo()[0][-1].Properties()
+            try:
+                return	properties.fill_pattern.Color()
+            except AttributeError:
+                pass
+        return None
     script_access['CurrentFillColor'] = SCRIPT_GET
 
 
     def PickObject(self, device, point, selectable = 0):
-	# Return the object that is hit by a click at POINT. The object
-	# is not selected and should not be modified by the caller.
+        # Return the object that is hit by a click at POINT. The object
+        # is not selected and should not be modified by the caller.
         #
-	# If selectable is false, this function descends into compound
-	# objects that are normally selected as a whole when one of
-	# their children is hit. If selectable is true, the search is
-	# done as for a normal selection.
+        # If selectable is false, this function descends into compound
+        # objects that are normally selected as a whole when one of
+        # their children is hit. If selectable is true, the search is
+        # done as for a normal selection.
         #
         # This method is intended to be used to
-	# let the user click on the drawing and extract properties from
-	# the indicated object. The fill and line dialogs use this
-	# indirectly (through the canvas object's PickObject) for their
-	# 'Update From...' button.
-	#
-	# XXX should this be implemented by calling WalkHierarchy
-	# instead of requiring a special PickObject method in each
-	# compound? Unlike the normal hit-test, this method is not that
-	# time critical and WalkHierarchy is sufficiently fast for most
-	# purposes (see extract_snap_points in the canvas).
-	# WalkHierarchy would have to be able to traverse the hierarchy
-	# top down and not just bottom up.
+        # let the user click on the drawing and extract properties from
+        # the indicated object. The fill and line dialogs use this
+        # indirectly (through the canvas object's PickObject) for their
+        # 'Update From...' button.
+        #
+        # XXX should this be implemented by calling WalkHierarchy
+        # instead of requiring a special PickObject method in each
+        # compound? Unlike the normal hit-test, this method is not that
+        # time critical and WalkHierarchy is sufficiently fast for most
+        # purposes (see extract_snap_points in the canvas).
+        # WalkHierarchy would have to be able to traverse the hierarchy
+        # top down and not just bottom up.
         object = None
-	rect = device.HitRectAroundPoint(point)
+        rect = device.HitRectAroundPoint(point)
         if not selectable:
             layers = self.layers[:]
             layers.reverse()
@@ -1019,12 +1019,12 @@
             selected = self.selection_from_point(point, rect, device)
             if selected:
                 object = selected[-1]
-	return object
+        return object
 
     def PickActiveObject(self, device, p):
         # return the object under point if it's selected or a guide
         # line. None otherwise.
-	rect = device.HitRectAroundPoint(p)
+        rect = device.HitRectAroundPoint(p)
         path = self.selection.GetPath()
         if len(path) > 2:
             path = path[:-1]
@@ -1042,354 +1042,354 @@
             else:
                 hit = hit[-1]
         return hit
-    
+
     #
     #
     #
 
     def WalkHierarchy(self, func, printable = 1, visible = 1, all = 0):
-	# XXX make the selection of layers more versatile
-	for layer in self.layers:
-	    if (all
+        # XXX make the selection of layers more versatile
+        for layer in self.layers:
+            if (all
                 or printable and layer.Printable()
                 or visible and layer.Visible()):
-		layer.WalkHierarchy(func)
+                layer.WalkHierarchy(func)
 
     #
     #
     #
     def ButtonDown(self, p, button, state):
-	self.was_dragged = 0
-	self.old_change_rect = self.selection.ChangeRect()
-	result = self.selection.ButtonDown(p, button, state)
-	return result
+        self.was_dragged = 0
+        self.old_change_rect = self.selection.ChangeRect()
+        result = self.selection.ButtonDown(p, button, state)
+        return result
 
     def MouseMove(self, p, state):
-	self.was_dragged = 1
-	self.selection.MouseMove(p, state)
+        self.was_dragged = 1
+        self.selection.MouseMove(p, state)
 
     def ButtonUp(self, p, button, state):
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		if self.was_dragged:
-		    undo_text, undo_edit \
-			       = self.selection.ButtonUp(p, button, state)
-		    if undo_edit is not None and undo_edit != NullUndo:
-			self.add_undo(undo_text, undo_edit)
-			uc1 = self.AddClearRect(self.old_change_rect)
-			uc2 = self.AddClearRect(self.selection.ChangeRect())
-			self.add_undo(uc1, uc2)
-			self.add_undo(self.queue_edited())
-		    else:
-			# the user probably just moved the rotation
-			# center point. The canvas has to update the
-			# handles
-			self.queue_selection()
-		else:
-		    self.selection.ButtonUp(p, button, state, forget_trafo = 1)
-		    self.ToggleSelectionBehaviour()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                if self.was_dragged:
+                    undo_text, undo_edit \
+                             = self.selection.ButtonUp(p, button, state)
+                    if undo_edit is not None and undo_edit != NullUndo:
+                        self.add_undo(undo_text, undo_edit)
+                        uc1 = self.AddClearRect(self.old_change_rect)
+                        uc2 = self.AddClearRect(self.selection.ChangeRect())
+                        self.add_undo(uc1, uc2)
+                        self.add_undo(self.queue_edited())
+                    else:
+                        # the user probably just moved the rotation
+                        # center point. The canvas has to update the
+                        # handles
+                        self.queue_selection()
+                else:
+                    self.selection.ButtonUp(p, button, state, forget_trafo = 1)
+                    self.ToggleSelectionBehaviour()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def ToggleSelectionBehaviour(self):
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		if self.selection.__class__ == SizeSelection:
-		    self.selection = TrafoSelection(self.selection)
-		elif self.selection.__class__ == TrafoSelection:
-		    self.selection = SizeSelection(self.selection)
-		self.queue_selection()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                if self.selection.__class__ == SizeSelection:
+                    self.selection = TrafoSelection(self.selection)
+                elif self.selection.__class__ == TrafoSelection:
+                    self.selection = SizeSelection(self.selection)
+                self.queue_selection()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def DrawDragged(self, device, partially = 0):
-	self.selection.DrawDragged(device, partially)
+        self.selection.DrawDragged(device, partially)
 
     def Hide(self, device, partially = 0):
-	self.selection.Hide(device, partially)
+        self.selection.Hide(device, partially)
 
     def Show(self, device, partially = 0):
-	self.selection.Show(device, partially)
+        self.selection.Show(device, partially)
 
     def ChangeRect(self):
-	return self.selection.ChangeRect()
+        return self.selection.ChangeRect()
 
     #
     #	The undo mechanism
     #
 
     def __init_undo(self):
-	self.undo = UndoRedo()
+        self.undo = UndoRedo()
 
     def CanUndo(self):
-	return self.undo.CanUndo()
+        return self.undo.CanUndo()
     script_access['CanUndo'] = SCRIPT_GET
 
     def CanRedo(self):
-	return self.undo.CanRedo()
+        return self.undo.CanRedo()
     script_access['CanRedo'] = SCRIPT_GET
 
     def Undo(self):
-	if self.undo.CanUndo():
-	    self.begin_transaction(clear_selection_rect = 0)
-	    try:
-		try:
-		    self.undo.Undo()
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction(issue = UNDO)
+        if self.undo.CanUndo():
+            self.begin_transaction(clear_selection_rect = 0)
+            try:
+                try:
+                    self.undo.Undo()
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction(issue = UNDO)
     script_access['Undo'] = SCRIPT_GET
 
     def add_undo(self, *infos):
-	# Add undoinfo for the current transaction. should not be called
-	# when not in a transaction.
-	if infos:
-	    if type(infos[0]) == StringType:
-		if not self.transaction_name:
-		    self.transaction_name = infos[0]
-		infos = infos[1:]
-		if not infos:
-		    return
-	    for info in infos:
-		if type(info) == ListType:
-		    info = CreateListUndo(info)
-		else:
-		    if type(info[0]) == StringType:
-			if __debug__:
-			    pdebug(None, 'add_undo: info contains text')
-			info = info[1:]
-		self.transaction_undo.append(info)
+        # Add undoinfo for the current transaction. should not be called
+        # when not in a transaction.
+        if infos:
+            if type(infos[0]) == StringType:
+                if not self.transaction_name:
+                    self.transaction_name = infos[0]
+                infos = infos[1:]
+                if not infos:
+                    return
+            for info in infos:
+                if type(info) == ListType:
+                    info = CreateListUndo(info)
+                else:
+                    if type(info[0]) == StringType:
+                        if __debug__:
+                            pdebug(None, 'add_undo: info contains text')
+                        info = info[1:]
+                self.transaction_undo.append(info)
 
     # public version of add_undo. to be called between calls to
     # BeginTransaction and EndTransaction/AbortTransaction
     AddUndo = add_undo
 
     def __undo_set_sel(self, selclass, selinfo, redo_class, redo_info):
-	old_class = self.selection.__class__
-	if old_class != selclass:
-	    self.selection = selclass(selinfo)
-	    self.queue_message(MODE)
-	else:
-	    # keep the same selection object to avoid creating a new
-	    # editor object in EditMode
-	    self.selection.SetSelection(selinfo)
-	self.queue_selection()
-	return (self.__undo_set_sel, redo_class, redo_info, selclass, selinfo)
+        old_class = self.selection.__class__
+        if old_class != selclass:
+            self.selection = selclass(selinfo)
+            self.queue_message(MODE)
+        else:
+            # keep the same selection object to avoid creating a new
+            # editor object in EditMode
+            self.selection.SetSelection(selinfo)
+        self.queue_selection()
+        return (self.__undo_set_sel, redo_class, redo_info, selclass, selinfo)
 
     def __real_add_undo(self, text, undo, selinfo = None, selclass = None):
-	if undo is not NullUndo:
-	    if selinfo is not None:
-		new_class = self.selection.__class__
-		new_info = self.selection.GetInfo()[:]
-		if new_info == selinfo:
-		    # make both lists identical
-		    new_info = selinfo
-		undo_sel = (self.__undo_set_sel, selclass, selinfo,
-			    new_class, new_info)
-		info = (text, UndoAfter, undo_sel, undo)
-	    else:
-		info = (text, undo)
-	    self.undo.AddUndo(info)
-	    self.queue_message(UNDO)
+        if undo is not NullUndo:
+            if selinfo is not None:
+                new_class = self.selection.__class__
+                new_info = self.selection.GetInfo()[:]
+                if new_info == selinfo:
+                    # make both lists identical
+                    new_info = selinfo
+                undo_sel = (self.__undo_set_sel, selclass, selinfo,
+                            new_class, new_info)
+                info = (text, UndoAfter, undo_sel, undo)
+            else:
+                info = (text, undo)
+            self.undo.AddUndo(info)
+            self.queue_message(UNDO)
 
 
     def Redo(self):
-	if self.undo.CanRedo():
-	    self.begin_transaction(clear_selection_rect = 0)
-	    try:
-		try:
-		    self.undo.Redo()
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction(issue = UNDO)
+        if self.undo.CanRedo():
+            self.begin_transaction(clear_selection_rect = 0)
+            try:
+                try:
+                    self.undo.Redo()
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction(issue = UNDO)
     script_access['Redo'] = SCRIPT_GET
 
     def ResetUndo(self):
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		self.undo.Reset()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction(issue = UNDO)
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                self.undo.Reset()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction(issue = UNDO)
     script_access['ResetUndo'] = SCRIPT_GET
 
     def UndoMenuText(self):
-	return self.undo.UndoText()
+        return self.undo.UndoText()
     script_access['UndoMenuText'] = SCRIPT_GET
 
     def RedoMenuText(self):
-	return self.undo.RedoText()
+        return self.undo.RedoText()
     script_access['RedoMenuText'] = SCRIPT_GET
 
     def SetUndoLimit(self, limit):
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		self.undo.SetUndoLimit(limit)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction(issue = UNDO)
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                self.undo.SetUndoLimit(limit)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction(issue = UNDO)
     script_access['SetUndoLimit'] = SCRIPT_GET
 
     def WasEdited(self):
-	# return true if document has changed since last save
-	return self.undo.UndoCount()
+        # return true if document has changed since last save
+        return self.undo.UndoCount()
     script_access['WasEdited'] = SCRIPT_GET
 
     def ClearEdited(self):
-	self.undo.ResetUndoCount()
-	self.issue(UNDO)
+        self.undo.ResetUndoCount()
+        self.issue(UNDO)
 
     #
     #
 
     def apply_to_selected(self, undo_text, func):
-	if self.selection:
-	    self.begin_transaction(undo_text)
-	    try:
-		try:
-		    self.add_undo(self.selection.ForAllUndo(func))
-		    self.queue_selection()
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.selection:
+            self.begin_transaction(undo_text)
+            try:
+                try:
+                    self.add_undo(self.selection.ForAllUndo(func))
+                    self.queue_selection()
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def AddStyle(self, style):
-	if type(style) == StringType:
-	    style = self.GetDynamicStyle(style)
-	self.apply_to_selected(_("Add Style"),
-			       lambda o, style = style: o.AddStyle(style))
+        if type(style) == StringType:
+            style = self.GetDynamicStyle(style)
+        self.apply_to_selected(_("Add Style"),
+                               lambda o, style = style: o.AddStyle(style))
 
     def SetLineColor(self, color):
-	# Set the line color of the currently selected objects.
-	# XXX this method shpuld be removed in favour of the more
-	# generic SetProperties.
-	self.SetProperties(line_pattern = SolidPattern(color),
-			   if_type_present = 1)
+        # Set the line color of the currently selected objects.
+        # XXX this method shpuld be removed in favour of the more
+        # generic SetProperties.
+        self.SetProperties(line_pattern = SolidPattern(color),
+                           if_type_present = 1)
 
     def SetProperties(self, **kw):
-	self.apply_to_selected(_("Set Properties"),
-			       lambda o, kw=kw: apply(o.SetProperties, (), kw))
+        self.apply_to_selected(_("Set Properties"),
+                               lambda o, kw=kw: apply(o.SetProperties, (), kw))
 
     def SetStyle(self, style):
-	if type(style) == StringType:
-	    style = self.get_dynamic_style(style)
-	    self.AddStyle(style)
+        if type(style) == StringType:
+            style = self.get_dynamic_style(style)
+            self.AddStyle(style)
 
     #
     #	Deleting and rearranging objects...
     #
 
     def remove_objects(self, infolist):
-	split = selinfo.list_to_tree(infolist)
-	undo = []
-	try:
-	    for layer, infolist in split:
-		undo.append(self.layers[layer].RemoveObjects(infolist))
-	    return CreateListUndo(undo)
-	except:
-	    Undo(CreateListUndo(undo))
-	    raise
+        split = selinfo.list_to_tree(infolist)
+        undo = []
+        try:
+            for layer, infolist in split:
+                undo.append(self.layers[layer].RemoveObjects(infolist))
+            return CreateListUndo(undo)
+        except:
+            Undo(CreateListUndo(undo))
+            raise
 
     def remove_selected(self):
-	return self.remove_objects(self.selection.GetInfo())
+        return self.remove_objects(self.selection.GetInfo())
 
     def RemoveSelected(self):
-	# Remove all selected objects. After successful completion, the
-	# selection will be empty.
-	if self.selection:
-	    self.begin_transaction(_("Delete"))
-	    try:
-		try:
-		    self.add_undo(self.remove_selected())
-		    self.__set_selection(None, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        # Remove all selected objects. After successful completion, the
+        # selection will be empty.
+        if self.selection:
+            self.begin_transaction(_("Delete"))
+            try:
+                try:
+                    self.add_undo(self.remove_selected())
+                    self.__set_selection(None, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def __call_layer_method_sel(self, undotext, methodname, *args):
-	if not self.selection:
-	    return
-	self.begin_transaction(undotext)
-	try:
-	    try:
-		split = selinfo.list_to_tree(self.selection.GetInfo())
-		edited = 0
-		selection = []
-		for layer, infolist in split:
-		    method = getattr(self.layers[layer], methodname)
-		    sel, undo = apply(method, (infolist,) + args)
-		    if undo is not NullUndo:
-			self.add_undo(undo)
-			edited = 1
-		    selection = selection + self.augment_sel_info(sel, layer)
-		self.__set_selection(selection, SelectSet)
-		if edited:
-		    self.add_undo(self.queue_edited())
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        if not self.selection:
+            return
+        self.begin_transaction(undotext)
+        try:
+            try:
+                split = selinfo.list_to_tree(self.selection.GetInfo())
+                edited = 0
+                selection = []
+                for layer, infolist in split:
+                    method = getattr(self.layers[layer], methodname)
+                    sel, undo = apply(method, (infolist,) + args)
+                    if undo is not NullUndo:
+                        self.add_undo(undo)
+                        edited = 1
+                    selection = selection + self.augment_sel_info(sel, layer)
+                self.__set_selection(selection, SelectSet)
+                if edited:
+                    self.add_undo(self.queue_edited())
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def MoveSelectedToTop(self):
-	self.__call_layer_method_sel(_("Move To Top"), 'MoveObjectsToTop')
+        self.__call_layer_method_sel(_("Move To Top"), 'MoveObjectsToTop')
 
     def MoveSelectedToBottom(self):
-	self.__call_layer_method_sel(_("Move To Bottom"),'MoveObjectsToBottom')
+        self.__call_layer_method_sel(_("Move To Bottom"),'MoveObjectsToBottom')
 
     def MoveSelectionDown(self):
-	self.__call_layer_method_sel(_("Lower"), 'MoveObjectsDown')
+        self.__call_layer_method_sel(_("Lower"), 'MoveObjectsDown')
 
     def MoveSelectionUp(self):
-	self.__call_layer_method_sel(_("Raise"), 'MoveObjectsUp')
+        self.__call_layer_method_sel(_("Raise"), 'MoveObjectsUp')
 
     def MoveSelectionToLayer(self, layer):
-	if self.selection:
-	    self.begin_transaction(_("Move Selection to `%s'")
-				   % self.layers[layer].Name())
-	    try:
-		try:
-		    # remove the objects from the document...
-		    self.add_undo(self.remove_selected())
-		    # ... and insert them a the end of the layer
-		    objects = self.selection.GetObjects()
-		    select, undo_insert = self.insert(objects, layer = layer)
+        if self.selection:
+            self.begin_transaction(_("Move Selection to `%s'")
+                                   % self.layers[layer].Name())
+            try:
+                try:
+                    # remove the objects from the document...
+                    self.add_undo(self.remove_selected())
+                    # ... and insert them a the end of the layer
+                    objects = self.selection.GetObjects()
+                    select, undo_insert = self.insert(objects, layer = layer)
 
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     #
     #	Cut/Copy
     #
 
     def copy_objects(self, objects):
-	copies = []
-	for obj in objects:
-	    copies.append(obj.Duplicate())
+        copies = []
+        for obj in objects:
+            copies.append(obj.Duplicate())
 
-	if len(copies) > 1:
-	    copies = Group(copies)
-	else:
-	    copies = copies[0]
+        if len(copies) > 1:
+            copies = Group(copies)
+        else:
+            copies = copies[0]
             # This is ugly: Special case for internal path text objects.
             # If the internal path text object is the only selected
             # object, turn the copy into a normal simple text object.
@@ -1401,41 +1401,41 @@
                 copies = text.SimpleText(text = copies.Text(),
                                          properties = properties)
 
-	copies.UntieFromDocument()
-	copies.SetDocument(None)
-	return copies
+        copies.UntieFromDocument()
+        copies.SetDocument(None)
+        return copies
 
     def CopyForClipboard(self):
-	if self.selection:
-	    return self.copy_objects(self.selection.GetObjects())
+        if self.selection:
+            return self.copy_objects(self.selection.GetObjects())
 
     def CutForClipboard(self):
-	result = None
-	if self.selection:
-	    self.begin_transaction(_("Cut"))
-	    try:
-		try:
-		    objects = self.selection.GetObjects()
-		    result = self.copy_objects(objects)
-		    self.add_undo(self.remove_selected())
-		    self.__set_selection(None, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    result = None
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
-	return result
+        result = None
+        if self.selection:
+            self.begin_transaction(_("Cut"))
+            try:
+                try:
+                    objects = self.selection.GetObjects()
+                    result = self.copy_objects(objects)
+                    self.add_undo(self.remove_selected())
+                    self.__set_selection(None, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    result = None
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
+        return result
 
     #
     #	Duplicate
     #
 
     def DuplicateSelected(self, offset = None):
-	if offset is None:
-	    offset = Point(config.preferences.duplicate_offset)
-	self.__call_layer_method_sel(_("Duplicate"), 'DuplicateObjects',
-				     offset)
+        if offset is None:
+            offset = Point(config.preferences.duplicate_offset)
+        self.__call_layer_method_sel(_("Duplicate"), 'DuplicateObjects',
+                                     offset)
 
     #
     #	Group
@@ -1464,65 +1464,65 @@
             self.end_transaction()
 
     def CanGroup(self):
-	return len(self.selection) > 1
+        return len(self.selection) > 1
 
     def GroupSelected(self):
-	if self.CanGroup():
+        if self.CanGroup():
             self.group_selected(_("Create Group"), Group)
 
     def CanUngroup(self):
-	infos = self.selection.GetInfo()
-	return len(infos) == 1 and infos[0][-1].is_Group
+        infos = self.selection.GetInfo()
+        return len(infos) == 1 and infos[0][-1].is_Group
 
     def UngroupSelected(self):
-	if self.CanUngroup():
-	    self.begin_transaction(_("Ungroup"))
-	    try:
-		try:
-		    self.add_undo(self.remove_selected())
-		    info, group = self.selection.GetInfo()[0]
-		    objects = group.Ungroup()
-		    select, undo_insert = self.insert(objects, at = info[1:],
-						      layer = info[0])
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanUngroup():
+            self.begin_transaction(_("Ungroup"))
+            try:
+                try:
+                    self.add_undo(self.remove_selected())
+                    info, group = self.selection.GetInfo()[0]
+                    objects = group.Ungroup()
+                    select, undo_insert = self.insert(objects, at = info[1:],
+                                                      layer = info[0])
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def CanCreateMaskGroup(self):
-	infos = self.selection.GetInfo()
-	return len(infos) > 1 and infos[-1][-1].is_clip
+        infos = self.selection.GetInfo()
+        return len(infos) > 1 and infos[-1][-1].is_clip
 
     def CreateMaskGroup(self):
-	if self.CanCreateMaskGroup():
-	    self.begin_transaction(_("Create Mask Group"))
-	    try:
-		try:
-		    import maskgroup
-		    self.add_undo(self.remove_selected())
-		    objects = self.selection.GetObjects()
-		    if config.preferences.topmost_is_mask:
-			mask = objects[-1]
-			del objects[-1]
-			objects.insert(0, mask)
-		    group = maskgroup.MaskGroup(objects)
-		    parent = selinfo.common_prefix(self.selection.GetInfo())
-		    if parent:
-			layer = parent[0]
-			at = parent[1:]
-		    else:
-			layer = None
-			at = None
-		    select, undo_insert = self.insert(group, at = at,
-						      layer = layer)
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanCreateMaskGroup():
+            self.begin_transaction(_("Create Mask Group"))
+            try:
+                try:
+                    import maskgroup
+                    self.add_undo(self.remove_selected())
+                    objects = self.selection.GetObjects()
+                    if config.preferences.topmost_is_mask:
+                        mask = objects[-1]
+                        del objects[-1]
+                        objects.insert(0, mask)
+                    group = maskgroup.MaskGroup(objects)
+                    parent = selinfo.common_prefix(self.selection.GetInfo())
+                    if parent:
+                        layer = parent[0]
+                        at = parent[1:]
+                    else:
+                        layer = None
+                        at = None
+                    select, undo_insert = self.insert(group, at = at,
+                                                      layer = layer)
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
 
     #
@@ -1530,14 +1530,14 @@
     #
 
     def TransformSelected(self, trafo, undo_text = _("Transform")):
-	self.apply_to_selected(undo_text, lambda o, t = trafo: o.Transform(t))
+        self.apply_to_selected(undo_text, lambda o, t = trafo: o.Transform(t))
 
     def TranslateSelected(self, offset, undo_text = _("Translate")):
-	self.apply_to_selected(undo_text, lambda o, v = offset: o.Translate(v))
+        self.apply_to_selected(undo_text, lambda o, v = offset: o.Translate(v))
 
     def RemoveTransformation(self):
-	self.apply_to_selected(_("Remove Transformation"),
-			       lambda o: o.RemoveTransformation())
+        self.apply_to_selected(_("Remove Transformation"),
+                               lambda o: o.RemoveTransformation())
 
     #
     #	Align, Flip, ...
@@ -1548,294 +1548,294 @@
 
     def AlignSelection(self, x, y, reference = 'selection'):
         if self.selection and (x or y):
-	    self.begin_transaction(_("Align Objects"))
-	    try:
-		try:
+            self.begin_transaction(_("Align Objects"))
+            try:
+                try:
                     add_undo = self.add_undo
                     objects = self.selection.GetObjects()
-		    if reference == 'page':
-			br = self.PageRect()
+                    if reference == 'page':
+                        br = self.PageRect()
                     elif reference == 'lowermost':
                         br = objects[0].coord_rect
-		    else:
-			br = self.selection.coord_rect
-		    for obj in objects:
-			r = obj.coord_rect
-			xoff = yoff = 0
-			if x == 1:
-			    xoff = br.left - r.left
-			elif x == 3:
-			    xoff = br.right - r.right
-			elif x == 2:
-			    xoff = (br.left + br.right - r.left - r.right) / 2
+                    else:
+                        br = self.selection.coord_rect
+                    for obj in objects:
+                        r = obj.coord_rect
+                        xoff = yoff = 0
+                        if x == 1:
+                            xoff = br.left - r.left
+                        elif x == 3:
+                            xoff = br.right - r.right
+                        elif x == 2:
+                            xoff = (br.left + br.right - r.left - r.right) / 2
 
-			if y == 1:
-			    yoff = br.top - r.top
-			elif y == 3:
-			    yoff = br.bottom - r.bottom
-			elif y == 2:
-			    yoff = (br.top + br.bottom - r.top - r.bottom) / 2
+                        if y == 1:
+                            yoff = br.top - r.top
+                        elif y == 3:
+                            yoff = br.bottom - r.bottom
+                        elif y == 2:
+                            yoff = (br.top + br.bottom - r.top - r.bottom) / 2
 
-			add_undo(obj.Translate(Point(xoff, yoff)))
+                        add_undo(obj.Translate(Point(xoff, yoff)))
 
-		    add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+                    add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def AbutHorizontal(self):
-	if len(self.selection) > 1:
-	    self.begin_transaction(_("Abut Horizontal"))
-	    try:
-		try:
-		    pos = []
-		    for obj in self.selection.GetObjects():
-			rect = obj.coord_rect
-			pos.append((rect.left, rect.top,
-				    rect.right - rect.left, obj))
-		    pos.sort()
-		    undo = []
-		    start, top, width, ob = pos[0]
-		    next = start + width
-		    for left, top, width, obj in pos[1:]:
-			off = Point(next - left, 0)
-			self.add_undo(obj.Translate(off))
-			next = next + width
+        if len(self.selection) > 1:
+            self.begin_transaction(_("Abut Horizontal"))
+            try:
+                try:
+                    pos = []
+                    for obj in self.selection.GetObjects():
+                        rect = obj.coord_rect
+                        pos.append((rect.left, rect.top,
+                                    rect.right - rect.left, obj))
+                    pos.sort()
+                    undo = []
+                    start, top, width, ob = pos[0]
+                    next = start + width
+                    for left, top, width, obj in pos[1:]:
+                        off = Point(next - left, 0)
+                        self.add_undo(obj.Translate(off))
+                        next = next + width
 
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def AbutVertical(self):
-	if len(self.selection) > 1:
-	    self.begin_transaction(_("Abut Vertical"))
-	    try:
-		try:
-		    pos = []
-		    for obj in self.selection.GetObjects():
-			rect = obj.coord_rect
-			pos.append((rect.top, -rect.left,
-				    rect.top - rect.bottom, obj))
-		    pos.sort()
-		    pos.reverse()
-		    undo = []
-		    start, left, height, ob = pos[0]
-		    next = start - height
-		    for top, left, height, obj in pos[1:]:
-			off = Point(0, next - top)
-			self.add_undo(obj.Translate(off))
-			next = next - height
+        if len(self.selection) > 1:
+            self.begin_transaction(_("Abut Vertical"))
+            try:
+                try:
+                    pos = []
+                    for obj in self.selection.GetObjects():
+                        rect = obj.coord_rect
+                        pos.append((rect.top, -rect.left,
+                                    rect.top - rect.bottom, obj))
+                    pos.sort()
+                    pos.reverse()
+                    undo = []
+                    start, left, height, ob = pos[0]
+                    next = start - height
+                    for top, left, height, obj in pos[1:]:
+                        off = Point(0, next - top)
+                        self.add_undo(obj.Translate(off))
+                        next = next - height
 
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def FlipSelected(self, horizontal = 0, vertical = 0):
-	if self.selection and (horizontal or vertical):
-	    self.begin_transaction()
-	    try:
-		try:
-		    rect = self.selection.coord_rect
-		    if horizontal:
-			xoff = rect.left + rect.right
-			factx = -1
-			text = _("Flip Horizontal")
-		    else:
-			xoff = 0
-			factx = 1
-		    if vertical:
-			yoff = rect.top + rect.bottom
-			facty = -1
-			text = _("Flip Vertical")
-		    else:
-			yoff = 0
-			facty = 1
-		    if horizontal and vertical:
-			text = _("Flip Both")
-		    trafo = Trafo(factx, 0, 0, facty, xoff, yoff)
-		    self.TransformSelected(trafo, text)
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.selection and (horizontal or vertical):
+            self.begin_transaction()
+            try:
+                try:
+                    rect = self.selection.coord_rect
+                    if horizontal:
+                        xoff = rect.left + rect.right
+                        factx = -1
+                        text = _("Flip Horizontal")
+                    else:
+                        xoff = 0
+                        factx = 1
+                    if vertical:
+                        yoff = rect.top + rect.bottom
+                        facty = -1
+                        text = _("Flip Vertical")
+                    else:
+                        yoff = 0
+                        facty = 1
+                    if horizontal and vertical:
+                        text = _("Flip Both")
+                    trafo = Trafo(factx, 0, 0, facty, xoff, yoff)
+                    self.TransformSelected(trafo, text)
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     #
     #
     #
 
     def CallObjectMethod(self, aclass, description, methodname, *args):
-	self.begin_transaction(description)
-	try:
-	    try:
-		undo = self.selection.CallObjectMethod(aclass, methodname,
-						       args)
-		if undo != NullUndo:
-		    self.add_undo(undo)
-		    self.add_undo(self.queue_edited())
-		    # force recomputation of selections rects:
-		    self.selection.ResetRectangle()
-		else:
-		    # in case the handles have to be updated
-		    self.queue_selection()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(description)
+        try:
+            try:
+                undo = self.selection.CallObjectMethod(aclass, methodname,
+                                                       args)
+                if undo != NullUndo:
+                    self.add_undo(undo)
+                    self.add_undo(self.queue_edited())
+                    # force recomputation of selections rects:
+                    self.selection.ResetRectangle()
+                else:
+                    # in case the handles have to be updated
+                    self.queue_selection()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def GetObjectMethod(self, aclass, method):
-	return self.selection.GetObjectMethod(aclass, method)
+        return self.selection.GetObjectMethod(aclass, method)
 
     def CurrentObjectCompatible(self, aclass):
-	obj = self.CurrentObject()
-	if obj is not None:
-	    if aclass.is_Editor:
-		return isinstance(obj, aclass.EditedClass)
-	    else:
-		return isinstance(obj, aclass)
-	return 0
+        obj = self.CurrentObject()
+        if obj is not None:
+            if aclass.is_Editor:
+                return isinstance(obj, aclass.EditedClass)
+            else:
+                return isinstance(obj, aclass)
+        return 0
 
     # XXX the following methods for blend groups, path text, clones and
     # bezier objects should perhaps be implemented in their respective
     # modules (and then somehow grafted onto the document class?)
 
     def CanBlend(self):
-	info = self.selection.GetInfo()
-	if len(info) == 2:
-	    path1, obj1 = info[0]
-	    path2, obj2 = info[1]
-	    if len(path1) == len(path2) + 1:
-		return obj1.parent.is_Blend and 2
-	    if len(path1) + 1 == len(path2):
-		return obj2.parent.is_Blend and 2
-	    return len(path1) == len(path2)
-	return 0
+        info = self.selection.GetInfo()
+        if len(info) == 2:
+            path1, obj1 = info[0]
+            path2, obj2 = info[1]
+            if len(path1) == len(path2) + 1:
+                return obj1.parent.is_Blend and 2
+            if len(path1) + 1 == len(path2):
+                return obj2.parent.is_Blend and 2
+            return len(path1) == len(path2)
+        return 0
 
     def Blend(self, steps):
-	info = self.selection.GetInfo()
-	path1, obj1 = info[0]
-	path2, obj2 = info[1]
-	if len(path1) == len(path2) + 1:
-	    if obj1.parent.is_Blend:
-		del info[0]
-	    else:
-		return
-	elif len(path1) + 1 == len(path2):
-	    if obj2.parent.is_Blend:
-		del info[1]
-	    else:
-		return
-	elif len(path1) != len(path2):
-	    return
-	if steps >= 2:
-	    import blendgroup, blend
-	    self.begin_transaction(_("Blend"))
-	    try:
-		try:
-		    self.add_undo(self.remove_objects(info))
-		    try:
-			blendgrp, undo = blendgroup.CreateBlendGroup(obj1,obj2,
-								     steps)
-			self.add_undo(undo)
-		    except blend.MismatchError:
-			warn(USER, _("I can't blend the selected objects"))
-			# XXX: is there some other solution?:
-			raise
+        info = self.selection.GetInfo()
+        path1, obj1 = info[0]
+        path2, obj2 = info[1]
+        if len(path1) == len(path2) + 1:
+            if obj1.parent.is_Blend:
+                del info[0]
+            else:
+                return
+        elif len(path1) + 1 == len(path2):
+            if obj2.parent.is_Blend:
+                del info[1]
+            else:
+                return
+        elif len(path1) != len(path2):
+            return
+        if steps >= 2:
+            import blendgroup, blend
+            self.begin_transaction(_("Blend"))
+            try:
+                try:
+                    self.add_undo(self.remove_objects(info))
+                    try:
+                        blendgrp, undo = blendgroup.CreateBlendGroup(obj1,obj2,
+                                                                     steps)
+                        self.add_undo(undo)
+                    except blend.MismatchError:
+                        warn(USER, _("I can't blend the selected objects"))
+                        # XXX: is there some other solution?:
+                        raise
 
-		    if len(info) == 2:
-			select, undo_insert = self.insert(blendgrp,
-							  at = path1[1:],
-							  layer = path1[0])
-			self.add_undo(undo_insert)
-			self.__set_selection(select, SelectSet)
-		    else:
-			self.SelectObject(blendgrp)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+                    if len(info) == 2:
+                        select, undo_insert = self.insert(blendgrp,
+                                                          at = path1[1:],
+                                                          layer = path1[0])
+                        self.add_undo(undo_insert)
+                        self.__set_selection(select, SelectSet)
+                    else:
+                        self.SelectObject(blendgrp)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def CanCancelBlend(self):
-	info = self.selection.GetInfo()
-	return len(info) == 1 and info[0][-1].is_Blend
+        info = self.selection.GetInfo()
+        return len(info) == 1 and info[0][-1].is_Blend
 
     def CancelBlend(self):
-	if self.CanCancelBlend():
-	    self.begin_transaction(_("Cancel Blend"))
-	    try:
-		try:
-		    info = self.selection.GetInfo()[0]
-		    self.add_undo(self.remove_selected())
-		    group = info[-1]
-		    objs = group.CancelEffect()
-		    info = info[0]
-		    layer = info[0]
-		    at = info[1:]
-		    select, undo_insert = self.insert(objs, at = at,
-						      layer = layer)
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanCancelBlend():
+            self.begin_transaction(_("Cancel Blend"))
+            try:
+                try:
+                    info = self.selection.GetInfo()[0]
+                    self.add_undo(self.remove_selected())
+                    group = info[-1]
+                    objs = group.CancelEffect()
+                    info = info[0]
+                    layer = info[0]
+                    at = info[1:]
+                    select, undo_insert = self.insert(objs, at = at,
+                                                      layer = layer)
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     #
     #
 
     def CanCreatePathText(self):
-	return CanCreatePathText(self.selection.GetObjects())
+        return CanCreatePathText(self.selection.GetObjects())
 
     def CreatePathText(self):
-	if self.CanCreatePathText():
-	    self.begin_transaction(_("Create Path Text"))
-	    try:
-		try:
-		    self.add_undo(self.remove_selected())
-		    object = CreatePathText(self.selection.GetObjects())
+        if self.CanCreatePathText():
+            self.begin_transaction(_("Create Path Text"))
+            try:
+                try:
+                    self.add_undo(self.remove_selected())
+                    object = CreatePathText(self.selection.GetObjects())
 
-		    select, undo_insert = self.insert(object)
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+                    select, undo_insert = self.insert(object)
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     #
     #	Clone (under construction...)
     #
 
     def CanCreateClone(self):
-	if len(self.selection) == 1:
-	    obj = self.selection.GetObjects()[0]
-	    return not obj.is_Compound
-	return 0
+        if len(self.selection) == 1:
+            obj = self.selection.GetObjects()[0]
+            return not obj.is_Compound
+        return 0
 
     def CreateClone(self):
-	if self.CanCreateClone():
-	    self.begin_transaction(_("Create Clone"))
-	    try:
-		try:
-		    from clone import CreateClone
-		    object = self.selection.GetObjects()[0]
-		    clone, undo_clone = CreateClone(object)
-		    self.add_undo(undo_clone)
-		    select, undo_insert = self.insert(clone)
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanCreateClone():
+            self.begin_transaction(_("Create Clone"))
+            try:
+                try:
+                    from clone import CreateClone
+                    object = self.selection.GetObjects()[0]
+                    clone, undo_clone = CreateClone(object)
+                    self.add_undo(undo_clone)
+                    select, undo_insert = self.insert(clone)
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
 
     #
@@ -1843,51 +1843,51 @@
     #
 
     def CanCombineBeziers(self):
-	if len(self.selection) > 1:
-	    can = 1
-	    for obj in self.selection.GetObjects():
-		can = can and obj.is_Bezier
-	    return can
-	return 0
+        if len(self.selection) > 1:
+            can = 1
+            for obj in self.selection.GetObjects():
+                can = can and obj.is_Bezier
+            return can
+        return 0
 
     def CombineBeziers(self):
-	if self.CanCombineBeziers():
-	    self.begin_transaction(_("Combine Beziers"))
-	    try:
-		try:
-		    self.add_undo(self.remove_selected())
-		    objects = self.selection.GetObjects()
-		    combined = CombineBeziers(objects)
-		    select, undo_insert = self.insert(combined)
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanCombineBeziers():
+            self.begin_transaction(_("Combine Beziers"))
+            try:
+                try:
+                    self.add_undo(self.remove_selected())
+                    objects = self.selection.GetObjects()
+                    combined = CombineBeziers(objects)
+                    select, undo_insert = self.insert(combined)
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def CanSplitBeziers(self):
-	return len(self.selection) == 1 \
-	       and self.selection.GetObjects()[0].is_Bezier
+        return len(self.selection) == 1 \
+               and self.selection.GetObjects()[0].is_Bezier
 
     def SplitBeziers(self):
-	if self.CanSplitBeziers():
-	    self.begin_transaction(_("Split Beziers"))
-	    try:
-		try:
-		    self.add_undo(self.remove_selected())
-		    info, bezier = self.selection.GetInfo()[0]
-		    objects = bezier.PathsAsObjects()
-		    select, undo_insert = self.insert(objects, at = info[1:],
-						      layer =info[0])
-		    self.add_undo(undo_insert)
-		    self.__set_selection(select, SelectSet)
-		    self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanSplitBeziers():
+            self.begin_transaction(_("Split Beziers"))
+            try:
+                try:
+                    self.add_undo(self.remove_selected())
+                    info, bezier = self.selection.GetInfo()[0]
+                    objects = bezier.PathsAsObjects()
+                    select, undo_insert = self.insert(objects, at = info[1:],
+                                                      layer =info[0])
+                    self.add_undo(undo_insert)
+                    self.__set_selection(select, SelectSet)
+                    self.add_undo(self.queue_edited())
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def CanConvertToCurve(self):
         for obj in self.selection.GetObjects():
@@ -1896,10 +1896,10 @@
         return 0
 
     def ConvertToCurve(self):
-	if self.CanConvertToCurve():
-	    self.begin_transaction(_("Convert To Curve"))
-	    try:
-		try:
+        if self.CanConvertToCurve():
+            self.begin_transaction(_("Convert To Curve"))
+            try:
+                try:
                     selection = []
                     edited = 0
                     for info, object in self.selection.GetInfo():
@@ -1914,254 +1914,254 @@
                     self.__set_selection(selection, SelectSet)
                     if edited:
                         self.add_undo(self.queue_edited())
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     #
     #
     #
 
     def Layers(self):
-	return self.layers[:]
+        return self.layers[:]
 
     def NumLayers(self):
-	return len(self.layers)
+        return len(self.layers)
 
     def ActiveLayer(self):
-	return self.active_layer
+        return self.active_layer
 
     def ActiveLayerIdx(self):
-	if self.active_layer is None:
-	    return None
-	return self.layers.index(self.active_layer)
+        if self.active_layer is None:
+            return None
+        return self.layers.index(self.active_layer)
 
     def SetActiveLayer(self, idx):
-	if type(idx) == IntType:
-	    layer = self.layers[idx]
-	else:
-	    layer = idx
-	if not layer.Locked():
-	    self.active_layer = layer
-	self.queue_layer(LAYER_ACTIVE)
+        if type(idx) == IntType:
+            layer = self.layers[idx]
+        else:
+            layer = idx
+        if not layer.Locked():
+            self.active_layer = layer
+        self.queue_layer(LAYER_ACTIVE)
 
     def LayerIndex(self, layer):
-	return self.layers.index(layer)
+        return self.layers.index(layer)
 
     def update_active_layer(self):
-	if self.active_layer is not None and self.active_layer.CanSelect():
-	    return
-	self.find_active_layer()
+        if self.active_layer is not None and self.active_layer.CanSelect():
+            return
+        self.find_active_layer()
 
     def find_active_layer(self, idx = None):
-	if idx is not None:
-	    layer = self.layers[idx]
-	    if layer.CanSelect():
-		self.SetActiveLayer(idx)
-		return
-	for layer in self.layers:
-	    if layer.CanSelect():
-		self.SetActiveLayer(layer)
-		return
-	self.active_layer = None
-	self.queue_layer(LAYER_ACTIVE)
+        if idx is not None:
+            layer = self.layers[idx]
+            if layer.CanSelect():
+                self.SetActiveLayer(idx)
+                return
+        for layer in self.layers:
+            if layer.CanSelect():
+                self.SetActiveLayer(layer)
+                return
+        self.active_layer = None
+        self.queue_layer(LAYER_ACTIVE)
 
     def deselect_layer(self, layer_idx):
-	# Deselect all objects in layer given by layer_idx
-	# Called when a layer is deleted or becomes locked
-	sel = selinfo.list_to_tree(self.selection.GetInfo())
-	for idx, info in sel:
-	    if idx == layer_idx:
-		self.__set_selection(selinfo.tree_to_list([(idx, info)]),
-				     SelectSubtract)
+        # Deselect all objects in layer given by layer_idx
+        # Called when a layer is deleted or becomes locked
+        sel = selinfo.list_to_tree(self.selection.GetInfo())
+        for idx, info in sel:
+            if idx == layer_idx:
+                self.__set_selection(selinfo.tree_to_list([(idx, info)]),
+                                     SelectSubtract)
 
     def SelectLayer(self, layer_idx, mode = SelectSet):
-	# Select all children of the layer given by layer_idx
-	self.begin_transaction(_("Select Layer"), clear_selection_rect = 0)
-	try:
-	    try:
-		layer = self.layers[layer_idx]
-		info = self.augment_sel_info(layer.SelectAll(), layer_idx)
-		self.__set_selection(info, mode)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        # Select all children of the layer given by layer_idx
+        self.begin_transaction(_("Select Layer"), clear_selection_rect = 0)
+        try:
+            try:
+                layer = self.layers[layer_idx]
+                info = self.augment_sel_info(layer.SelectAll(), layer_idx)
+                self.__set_selection(info, mode)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def SetLayerState(self, layer_idx, visible, printable, locked, outlined):
-	self.begin_transaction(_("Change Layer State"),
-			       clear_selection_rect = 0)
-	try:
-	    try:
-		layer = self.layers[layer_idx]
-		self.add_undo(layer.SetState(visible, printable, locked,
-					     outlined))
-		if not layer.CanSelect():
-		    # XXX: this depends on whether we're drawing visible or
-		    # printable layers
-		    self.deselect_layer(layer_idx)
-		    self.update_active_layer()
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(_("Change Layer State"),
+                               clear_selection_rect = 0)
+        try:
+            try:
+                layer = self.layers[layer_idx]
+                self.add_undo(layer.SetState(visible, printable, locked,
+                                             outlined))
+                if not layer.CanSelect():
+                    # XXX: this depends on whether we're drawing visible or
+                    # printable layers
+                    self.deselect_layer(layer_idx)
+                    self.update_active_layer()
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def SetLayerColor(self, layer_idx, color):
-	self.begin_transaction(_("Set Layer Outline Color"),
-			       clear_selection_rect = 0)
-	try:
-	    try:
-		layer = self.layers[layer_idx]
-		self.add_undo(layer.SetOutlineColor(color))
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(_("Set Layer Outline Color"),
+                               clear_selection_rect = 0)
+        try:
+            try:
+                layer = self.layers[layer_idx]
+                self.add_undo(layer.SetOutlineColor(color))
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def SetLayerName(self, idx, name):
-	self.begin_transaction(_("Rename Layer"), clear_selection_rect = 0)
-	try:
-	    try:
-		layer = self.layers[idx]
-		self.add_undo(layer.SetName(name))
-		self.add_undo(self.queue_layer())
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(_("Rename Layer"), clear_selection_rect = 0)
+        try:
+            try:
+                layer = self.layers[idx]
+                self.add_undo(layer.SetName(name))
+                self.add_undo(self.queue_layer())
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def AppendLayer(self, *args, **kw_args):
-	self.begin_transaction(_("Append Layer"),clear_selection_rect = 0)
-	try:
-	    try:
-		layer = apply(SketchDocument.AppendLayer, (self,) + args,
-			      kw_args)
-		self.add_undo((self._remove_layer, len(self.layers) - 1))
-		self.queue_layer(LAYER_ORDER, layer)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
-	return layer
+        self.begin_transaction(_("Append Layer"),clear_selection_rect = 0)
+        try:
+            try:
+                layer = apply(SketchDocument.AppendLayer, (self,) + args,
+                              kw_args)
+                self.add_undo((self._remove_layer, len(self.layers) - 1))
+                self.queue_layer(LAYER_ORDER, layer)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
+        return layer
 
     def NewLayer(self):
-	self.begin_transaction(_("New Layer"), clear_selection_rect = 0)
-	try:
-	    try:
-		self.AppendLayer()
-		self.active_layer = self.layers[-1]
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(_("New Layer"), clear_selection_rect = 0)
+        try:
+            try:
+                self.AppendLayer()
+                self.active_layer = self.layers[-1]
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def _move_layer_up(self, idx):
-	# XXX: exception handling
-	if idx < len(self.layers) - 1:
-	    # move the layer...
-	    layer = self.layers[idx]
-	    del self.layers[idx]
-	    self.layers.insert(idx + 1, layer)
-	    other = self.layers[idx]
-	    # ... and adjust the selection
-	    sel = self.selection.GetInfoTree()
-	    newsel = []
-	    for i, info in sel:
-		if i == idx:
-		    i = idx + 1
-		elif i == idx + 1:
-		    i = idx
-		newsel.append((i, info))
-	    self.__set_selection(selinfo.tree_to_list(newsel), SelectSet)
-	    self.queue_layer(LAYER_ORDER, layer, other)
-	    return (self._move_layer_down, idx + 1)
-	return None
+        # XXX: exception handling
+        if idx < len(self.layers) - 1:
+            # move the layer...
+            layer = self.layers[idx]
+            del self.layers[idx]
+            self.layers.insert(idx + 1, layer)
+            other = self.layers[idx]
+            # ... and adjust the selection
+            sel = self.selection.GetInfoTree()
+            newsel = []
+            for i, info in sel:
+                if i == idx:
+                    i = idx + 1
+                elif i == idx + 1:
+                    i = idx
+                newsel.append((i, info))
+            self.__set_selection(selinfo.tree_to_list(newsel), SelectSet)
+            self.queue_layer(LAYER_ORDER, layer, other)
+            return (self._move_layer_down, idx + 1)
+        return None
 
     def _move_layer_down(self, idx):
-	# XXX: exception handling
-	if idx > 0:
-	    # move the layer...
-	    layer = self.layers[idx]
-	    del self.layers[idx]
-	    self.layers.insert(idx - 1, layer)
-	    other = self.layers[idx]
-	    # ...and adjust the selection
-	    sel = self.selection.GetInfoTree()
-	    newsel = []
-	    for i, info in sel:
-		if i == idx:
-		    i = idx - 1
-		elif i == idx - 1:
-		    i = idx
-		newsel.append((i, info))
-	    self.__set_selection(selinfo.tree_to_list(newsel), SelectSet)
-	    self.queue_layer(LAYER_ORDER, layer, other)
-	    return (self._move_layer_up, idx - 1)
-	return NullUndo
+        # XXX: exception handling
+        if idx > 0:
+            # move the layer...
+            layer = self.layers[idx]
+            del self.layers[idx]
+            self.layers.insert(idx - 1, layer)
+            other = self.layers[idx]
+            # ...and adjust the selection
+            sel = self.selection.GetInfoTree()
+            newsel = []
+            for i, info in sel:
+                if i == idx:
+                    i = idx - 1
+                elif i == idx - 1:
+                    i = idx
+                newsel.append((i, info))
+            self.__set_selection(selinfo.tree_to_list(newsel), SelectSet)
+            self.queue_layer(LAYER_ORDER, layer, other)
+            return (self._move_layer_up, idx - 1)
+        return NullUndo
 
     def MoveLayerUp(self, idx):
-	if idx < len(self.layers) - 1:
-	    self.begin_transaction(_("Move Layer Up"), clear_selection_rect=0)
-	    try:
-		try:
-		    self.add_undo(self._move_layer_up(idx))
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if idx < len(self.layers) - 1:
+            self.begin_transaction(_("Move Layer Up"), clear_selection_rect=0)
+            try:
+                try:
+                    self.add_undo(self._move_layer_up(idx))
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def MoveLayerDown(self, idx):
-	if idx > 0:
-	    self.begin_transaction(_("Move Layer Down"),clear_selection_rect=0)
-	    try:
-		try:
-		    self.add_undo(self._move_layer_down(idx))
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if idx > 0:
+            self.begin_transaction(_("Move Layer Down"),clear_selection_rect=0)
+            try:
+                try:
+                    self.add_undo(self._move_layer_down(idx))
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def _remove_layer(self, idx):
-	layer = self.layers[idx]
-	del self.layers[idx]
-	if layer is self.active_layer:
-	    if idx < len(self.layers):
-		self.find_active_layer(idx)
-	    else:
-		self.find_active_layer()
-	sel = self.selection.GetInfoTree()
-	newsel = []
-	for i, info in sel:
-	    if i == idx:
-		continue
-	    elif i > idx:
-		i = i - 1
-	    newsel.append((i, info))
-	self.__set_selection(selinfo.tree_to_list(newsel), SelectSet)
+        layer = self.layers[idx]
+        del self.layers[idx]
+        if layer is self.active_layer:
+            if idx < len(self.layers):
+                self.find_active_layer(idx)
+            else:
+                self.find_active_layer()
+        sel = self.selection.GetInfoTree()
+        newsel = []
+        for i, info in sel:
+            if i == idx:
+                continue
+            elif i > idx:
+                i = i - 1
+            newsel.append((i, info))
+        self.__set_selection(selinfo.tree_to_list(newsel), SelectSet)
 
-	self.queue_layer(LAYER_ORDER, layer)
-	return (self._insert_layer, idx, layer)
+        self.queue_layer(LAYER_ORDER, layer)
+        return (self._insert_layer, idx, layer)
 
     def _insert_layer(self, idx, layer):
-	self.layers.insert(idx, layer)
-	layer.SetDocument(self)
-	self.queue_layer(LAYER_ORDER, layer)
-	return (self._remove_layer, idx)
+        self.layers.insert(idx, layer)
+        layer.SetDocument(self)
+        self.queue_layer(LAYER_ORDER, layer)
+        return (self._remove_layer, idx)
 
     def CanDeleteLayer(self, idx):
-	return (len(self.layers) > 3 and not self.layers[idx].is_SpecialLayer)
+        return (len(self.layers) > 3 and not self.layers[idx].is_SpecialLayer)
 
     def DeleteLayer(self, idx):
-	if self.CanDeleteLayer(idx):
-	    self.begin_transaction(_("Delete Layer"), clear_selection_rect = 0)
-	    try:
-		try:
-		    self.add_undo(self._remove_layer(idx))
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanDeleteLayer(idx):
+            self.begin_transaction(_("Delete Layer"), clear_selection_rect = 0)
+            try:
+                try:
+                    self.add_undo(self._remove_layer(idx))
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
 
 
@@ -2170,50 +2170,50 @@
     #
 
     def queue_style(self):
-	self.queue_message(STYLE)
-	return (self.queue_style,)
+        self.queue_message(STYLE)
+        return (self.queue_style,)
 
     def init_styles(self):
-	self.styles = UndoDict()
-	self.auto_assign_styles = 1
-	self.asked_about = {}
+        self.styles = UndoDict()
+        self.auto_assign_styles = 1
+        self.asked_about = {}
 
     def destroy_styles(self):
-	for style in self.styles.values():
-	    style.Destroy()
-	self.styles = None
+        for style in self.styles.values():
+            style.Destroy()
+        self.styles = None
 
     def get_dynamic_style(self, name):
-	return self.styles[name]
+        return self.styles[name]
 
     def GetDynamicStyle(self, name):
-	try:
-	    return self.styles[name]
-	except KeyError:
-	    return None
+        try:
+            return self.styles[name]
+        except KeyError:
+            return None
 
     def Styles(self):
-	return self.styles.values()
+        return self.styles.values()
 
     def write_styles(self, file):
-	for style in self.styles.values():
-	    style.SaveToFile(file)
+        for style in self.styles.values():
+            style.SaveToFile(file)
 
     def load_AddStyle(self, style):
-	self.styles.SetItem(style.Name(), style)
+        self.styles.SetItem(style.Name(), style)
 
     def add_dynamic_style(self, name, style):
-	if style:
-	    style = style.AsDynamicStyle()
-	    self.add_undo(self.styles.SetItem(name, style))
-	    self.add_undo(self.queue_style())
-	    return style
+        if style:
+            style = style.AsDynamicStyle()
+            self.add_undo(self.styles.SetItem(name, style))
+            self.add_undo(self.queue_style())
+            return style
 
     def update_style_dependencies(self, style):
-	def update(obj, style = style):
-	    obj.ObjectChanged(style)
-	self.WalkHierarchy(update)
-	return (self.update_style_dependencies, style)
+        def update(obj, style = style):
+            obj.ObjectChanged(style)
+        self.WalkHierarchy(update)
+        return (self.update_style_dependencies, style)
 
     def UpdateDynamicStyleSel(self):
         if len(self.selection) == 1:
@@ -2247,115 +2247,115 @@
                 self.end_transaction()
 
     def CanCreateStyle(self):
-	if len(self.selection) == 1:
-	    obj = self.selection.GetObjects()[0]
-	    return obj.has_fill or obj.has_line
-	return 0
+        if len(self.selection) == 1:
+            obj = self.selection.GetObjects()[0]
+            return obj.has_fill or obj.has_line
+        return 0
 
     def CreateStyleFromSelection(self, name, which_properties):
-	if self.CanCreateStyle():
-	    properties = self.CurrentProperties()
-	    style = properties.CreateStyle(which_properties)
-	    self.begin_transaction(_("Create Style %s") % name,
-				   clear_selection_rect = 0)
-	    try:
-		try:
-		    style = self.add_dynamic_style(name, style)
-		    self.AddStyle(style)
-		except:
-		    self.abort_transaction()
-	    finally:
-		self.end_transaction()
+        if self.CanCreateStyle():
+            properties = self.CurrentProperties()
+            style = properties.CreateStyle(which_properties)
+            self.begin_transaction(_("Create Style %s") % name,
+                                   clear_selection_rect = 0)
+            try:
+                try:
+                    style = self.add_dynamic_style(name, style)
+                    self.AddStyle(style)
+                except:
+                    self.abort_transaction()
+            finally:
+                self.end_transaction()
 
     def RemoveDynamicStyle(self, name):
-	style = self.GetDynamicStyle(name)
-	if not style:
-	    # style does not exist. XXX: raise an exception ?
-	    return
-	self.begin_transaction(_("Remove Style %s") % name,
-			       clear_selection_rect = 0)
-	try:
-	    try:
-		def remove(obj, style = style, add_undo = self.add_undo):
-		    add_undo(obj.ObjectRemoved(style))
-		self.WalkHierarchy(remove)
-		self.add_undo(self.styles.DelItem(name))
-		self.add_undo(self.queue_style())
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        style = self.GetDynamicStyle(name)
+        if not style:
+            # style does not exist. XXX: raise an exception ?
+            return
+        self.begin_transaction(_("Remove Style %s") % name,
+                               clear_selection_rect = 0)
+        try:
+            try:
+                def remove(obj, style = style, add_undo = self.add_undo):
+                    add_undo(obj.ObjectRemoved(style))
+                self.WalkHierarchy(remove)
+                self.add_undo(self.styles.DelItem(name))
+                self.add_undo(self.queue_style())
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def GetStyleNames(self):
-	names = self.styles.keys()
-	names.sort()
-	return names
+        names = self.styles.keys()
+        names.sort()
+        return names
 
     #
     #	Layout
     #
 
     def queue_layout(self):
-	self.queue_message(LAYOUT)
-	return (self.queue_layout,)
+        self.queue_message(LAYOUT)
+        return (self.queue_layout,)
 
     def init_layout(self):
-	self.page_layout = pagelayout.PageLayout()
+        self.page_layout = pagelayout.PageLayout()
 
     def Layout(self):
-	return self.page_layout
+        return self.page_layout
 
     def PageSize(self):
-	return (self.page_layout.Width(), self.page_layout.Height())
+        return (self.page_layout.Width(), self.page_layout.Height())
 
     def PageRect(self):
-	w, h = self.page_layout.Size()
-	return Rect(0, 0, w, h)
+        w, h = self.page_layout.Size()
+        return Rect(0, 0, w, h)
 
     def load_SetLayout(self, layout):
-	self.page_layout = layout
+        self.page_layout = layout
 
     def __set_page_layout(self, layout):
-	undo = (self.__set_page_layout, self.page_layout)
-	self.page_layout = layout
-	self.queue_layout()
-	return undo
+        undo = (self.__set_page_layout, self.page_layout)
+        self.page_layout = layout
+        self.queue_layout()
+        return undo
 
     def SetLayout(self, layout):
-	self.begin_transaction(clear_selection_rect = 0)
-	try:
-	    try:
-		undo = self.__set_page_layout(layout)
-		self.add_undo(_("Change Page Layout"), undo)
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(clear_selection_rect = 0)
+        try:
+            try:
+                undo = self.__set_page_layout(layout)
+                self.add_undo(_("Change Page Layout"), undo)
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     #
     #	Grid Settings
     #
 
     def queue_grid(self):
-	self.queue_message(GRID)
-	return (self.queue_grid,)
+        self.queue_message(GRID)
+        return (self.queue_grid,)
 
     def SetGridGeometry(self, geometry):
-	self.begin_transaction(_("Set Grid Geometry"))
-	try:
-	    try:
-		self.add_undo(self.snap_grid.SetGeometry(geometry))
-		self.add_undo(self.queue_grid())
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(_("Set Grid Geometry"))
+        try:
+            try:
+                self.add_undo(self.snap_grid.SetGeometry(geometry))
+                self.add_undo(self.queue_grid())
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def GridGeometry(self):
         return self.snap_grid.Geometry()
 
     def GridLayerChanged(self):
-	return self.queue_grid()
+        return self.queue_grid()
 
 
     #
@@ -2363,76 +2363,76 @@
     #
 
     def add_guide_line(self, line):
-	self.begin_transaction(_("Add Guide Line"), clear_selection_rect = 0)
-	try:
-	    try:
-		sel, undo = self.guide_layer.Insert(line, 0)
-		self.add_undo(undo)
-		self.add_undo(self.AddClearRect(line.get_clear_rect()))
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        self.begin_transaction(_("Add Guide Line"), clear_selection_rect = 0)
+        try:
+            try:
+                sel, undo = self.guide_layer.Insert(line, 0)
+                self.add_undo(undo)
+                self.add_undo(self.AddClearRect(line.get_clear_rect()))
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def AddGuideLine(self, point, horizontal):
-	self.add_guide_line(guide.GuideLine(point, horizontal))
+        self.add_guide_line(guide.GuideLine(point, horizontal))
 
     def RemoveGuideLine(self, line):
-	if not line.parent is self.guide_layer or not line.is_GuideLine:
-	    return
-	self.begin_transaction(_("Delete Guide Line"),
-			       clear_selection_rect = 0)
-	try:
-	    try:
-		self.add_undo(self.remove_objects([line.SelectionInfo()]))
-		self.add_undo(self.AddClearRect(line.get_clear_rect()))
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        if not line.parent is self.guide_layer or not line.is_GuideLine:
+            return
+        self.begin_transaction(_("Delete Guide Line"),
+                               clear_selection_rect = 0)
+        try:
+            try:
+                self.add_undo(self.remove_objects([line.SelectionInfo()]))
+                self.add_undo(self.AddClearRect(line.get_clear_rect()))
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def MoveGuideLine(self, line, point):
-	if not line.parent is self.guide_layer or not line.is_GuideLine:
-	    return
-	self.begin_transaction(_("Move Guide Line"), clear_selection_rect = 0)
-	try:
-	    try:
-		self.add_undo(self.AddClearRect(line.get_clear_rect()))
-		self.add_undo(line.SetPoint(point))
-		self.add_undo(self.AddClearRect(line.get_clear_rect()))
-		self.add_undo(self.GuideLayerChanged(line.parent))
-	    except:
-		self.abort_transaction()
-	finally:
-	    self.end_transaction()
+        if not line.parent is self.guide_layer or not line.is_GuideLine:
+            return
+        self.begin_transaction(_("Move Guide Line"), clear_selection_rect = 0)
+        try:
+            try:
+                self.add_undo(self.AddClearRect(line.get_clear_rect()))
+                self.add_undo(line.SetPoint(point))
+                self.add_undo(self.AddClearRect(line.get_clear_rect()))
+                self.add_undo(self.GuideLayerChanged(line.parent))
+            except:
+                self.abort_transaction()
+        finally:
+            self.end_transaction()
 
     def GuideLayerChanged(self, layer):
-	self.queue_message(GUIDE_LINES, layer)
-	return (self.GuideLayerChanged, layer)
+        self.queue_message(GUIDE_LINES, layer)
+        return (self.GuideLayerChanged, layer)
 
     def GuideLines(self):
-	return self.guide_layer.GuideLines()
+        return self.guide_layer.GuideLines()
 
 
     #
     #
     def as_group(self):
-	for name in self.GetStyleNames():
-	    self.RemoveDynamicStyle(name)
-	layers = self.layers
-	self.layers = []
-	groups = []
-	for layer in layers:
-	    if not layer.is_SpecialLayer:
-		layer.UntieFromDocument()
-		objects = layer.GetObjects()
-		layer.objects = []
-		if objects:
-		    groups.append(Group(objects))
-	    else:
-		layer.Destroy()
-	if groups:
-	    return Group(groups)
-	else:
-	    return None
+        for name in self.GetStyleNames():
+            self.RemoveDynamicStyle(name)
+        layers = self.layers
+        self.layers = []
+        groups = []
+        for layer in layers:
+            if not layer.is_SpecialLayer:
+                layer.UntieFromDocument()
+                objects = layer.GetObjects()
+                layer.objects = []
+                if objects:
+                    groups.append(Group(objects))
+            else:
+                layer.Destroy()
+        if groups:
+            return Group(groups)
+        else:
+            return None
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/ellipse.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/ellipse.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/ellipse.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -47,16 +47,16 @@
 # helper function for snapping (might be useful elsewhere too):
 def snap_to_line(start, end, p):
     if start != end:
-	result = [(abs(start - p), start), (abs(end - p), end)]
-	v = end - start
-	length = abs(v)
-	r = (v * (p - start)) / (length ** 2)
-	if 0 <= r <= 1.0:
-	    p2 = start + r * v
-	    result.append((abs(p2 - p), p2))
-	return min(result)
+        result = [(abs(start - p), start), (abs(end - p), end)]
+        v = end - start
+        length = abs(v)
+        r = (v * (p - start)) / (length ** 2)
+        if 0 <= r <= 1.0:
+            p2 = start + r * v
+            result.append((abs(p2 - p), p2))
+        return min(result)
     else:
-	return (abs(start - p), start)
+        return (abs(start - p), start)
 
 
 
@@ -70,42 +70,42 @@
     commands = RectangularPrimitive.commands[:]
 
     def __init__(self, trafo = None, start_angle = 0.0, end_angle = 0.0,
-		 arc_type = ArcPieSlice, properties = None, duplicate = None):
-	if duplicate is not None:
-	    self.start_angle = duplicate.start_angle
-	    self.end_angle = duplicate.end_angle
-	    self.arc_type = duplicate.arc_type
-	else:
-	    self.start_angle = start_angle
-	    self.end_angle = end_angle
-	    self.arc_type = arc_type
-	RectangularPrimitive.__init__(self, trafo, properties = properties,
-				      duplicate = duplicate)
-	self.normalize()
+                 arc_type = ArcPieSlice, properties = None, duplicate = None):
+        if duplicate is not None:
+            self.start_angle = duplicate.start_angle
+            self.end_angle = duplicate.end_angle
+            self.arc_type = duplicate.arc_type
+        else:
+            self.start_angle = start_angle
+            self.end_angle = end_angle
+            self.arc_type = arc_type
+        RectangularPrimitive.__init__(self, trafo, properties = properties,
+                                      duplicate = duplicate)
+        self.normalize()
 
     def DrawShape(self, device, rect = None, clip = 0):
-	Primitive.DrawShape(self, device)
-	device.SimpleEllipse(self.trafo, self.start_angle, self.end_angle,
-			     self.arc_type, rect, clip)
+        Primitive.DrawShape(self, device)
+        device.SimpleEllipse(self.trafo, self.start_angle, self.end_angle,
+                             self.arc_type, rect, clip)
 
     def SetAngles(self, start_angle, end_angle):
-	undo = (self.SetAngles, self.start_angle, self.end_angle)
-	self.start_angle = start_angle
-	self.end_angle = end_angle
-	self.normalize()
-	self._changed()
-	return undo
+        undo = (self.SetAngles, self.start_angle, self.end_angle)
+        self.start_angle = start_angle
+        self.end_angle = end_angle
+        self.normalize()
+        self._changed()
+        return undo
 
     def Angles(self):
         return self.start_angle, self.end_angle
 
     def SetArcType(self, arc_type):
-	if arc_type == self.arc_type:
-	    return NullUndo
-	undo = (self.SetArcType, self.arc_type)
-	self.arc_type = arc_type
-	self._changed()
-	return undo
+        if arc_type == self.arc_type:
+            return NullUndo
+        undo = (self.SetArcType, self.arc_type)
+        self.arc_type = arc_type
+        self._changed()
+        return undo
 
     def ArcType(self):
         return self.arc_type
@@ -113,21 +113,21 @@
     AddCmd(commands, 'EllipseArc', _("Arc"), SetArcType, args = ArcArc)
     AddCmd(commands, 'EllipseChord', _("Chord"), SetArcType, args = ArcChord)
     AddCmd(commands, 'EllipsePieSlice', _("Pie Slice"), SetArcType,
-	   args = ArcPieSlice)
+           args = ArcPieSlice)
 
     def normalize(self):
-	pi2 = 2 * pi
-	self.start_angle = fmod(self.start_angle, pi2)
-	if self.start_angle < 0:
-	    self.start_angle = self.start_angle + pi2
-	self.end_angle = fmod(self.end_angle, pi2)
-	if self.end_angle < 0:
-	    self.end_angle = self.end_angle + pi2
+        pi2 = 2 * pi
+        self.start_angle = fmod(self.start_angle, pi2)
+        if self.start_angle < 0:
+            self.start_angle = self.start_angle + pi2
+        self.end_angle = fmod(self.end_angle, pi2)
+        if self.end_angle < 0:
+            self.end_angle = self.end_angle + pi2
 
     def Paths(self):
         path = _sketch.approx_arc(self.start_angle, self.end_angle,
                                   self.arc_type)
-	path.Transform(self.trafo)
+        path.Transform(self.trafo)
         return (path,)
 
     def AsBezier(self):
@@ -135,92 +135,92 @@
                           properties = self.properties.Duplicate())
 
     def Hit(self, p, rect, device, clip = 0):
-	return device.SimpleEllipseHit(p, self.trafo, self.start_angle,
-				       self.end_angle, self.arc_type,
-				       self.properties, self.Filled() or clip,
-				       ignore_outline_mode = clip)
+        return device.SimpleEllipseHit(p, self.trafo, self.start_angle,
+                                       self.end_angle, self.arc_type,
+                                       self.properties, self.Filled() or clip,
+                                       ignore_outline_mode = clip)
 
     def Blend(self, other, p, q):
-	blended = RectangularPrimitive.Blend(self, other, p, q)
-	if self.start_angle != self.end_angle \
-	   or other.start_angle != other.end_angle:
-	    blended.start_angle = p * self.start_angle + q * other.start_angle
-	    blended.end_angle = p * self.end_angle + q * other.end_angle
-	    if self.start_angle == self.end_angle:
-		blended.arc_type = other.arc_type
-	    elif other.start_angle == other.end_angle:
-		blended.arc_type = self.arc_type
-	    else:
-		if self.arc_type == other.arc_type:
-		    blended.arc_type = self.arc_type
-		# The rest of the arc type blends is quite arbitrary
-		# XXX: are these rules acceptable? Maybe we should blend
-		# the ellipses as bezier curves if the arc types differ
-		elif self.arc_type == ArcArc or other.arc_type == ArcArc:
-		    blended.arc_type = ArcArc
-		elif self.arc_type == ArcChord or other.arc_type == ArcChord:
-		    blended.arc_type = ArcChord
-		else:
-		    blended.arc_type = ArcPieSlice
-	return blended
+        blended = RectangularPrimitive.Blend(self, other, p, q)
+        if self.start_angle != self.end_angle \
+           or other.start_angle != other.end_angle:
+            blended.start_angle = p * self.start_angle + q * other.start_angle
+            blended.end_angle = p * self.end_angle + q * other.end_angle
+            if self.start_angle == self.end_angle:
+                blended.arc_type = other.arc_type
+            elif other.start_angle == other.end_angle:
+                blended.arc_type = self.arc_type
+            else:
+                if self.arc_type == other.arc_type:
+                    blended.arc_type = self.arc_type
+                # The rest of the arc type blends is quite arbitrary
+                # XXX: are these rules acceptable? Maybe we should blend
+                # the ellipses as bezier curves if the arc types differ
+                elif self.arc_type == ArcArc or other.arc_type == ArcArc:
+                    blended.arc_type = ArcArc
+                elif self.arc_type == ArcChord or other.arc_type == ArcChord:
+                    blended.arc_type = ArcChord
+                else:
+                    blended.arc_type = ArcPieSlice
+        return blended
 
     def GetSnapPoints(self):
-	t = self.trafo
-	start_angle = self.start_angle; end_angle = self.end_angle
-	if self.start_angle == self.end_angle:
-	    a = Point(t.m11, t.m21)
-	    b = Point(t.m12, t.m22)
-	    c = t.offset()
-	    return [c, c + a, c - a, c + b, c - b]
-	else:
-	    points = [t(Polar(start_angle)), t(Polar(end_angle)), t.offset()]
-	    if end_angle < start_angle:
-		end_angle = end_angle + 2 * pi
-	    pi2 = pi / 2
-	    angle = pi2 * (floor(start_angle / pi2) + 1)
-	    while angle < end_angle:
-		points.append(t(Polar(1, angle)))
-		angle = angle + pi2
-	    return points
+        t = self.trafo
+        start_angle = self.start_angle; end_angle = self.end_angle
+        if self.start_angle == self.end_angle:
+            a = Point(t.m11, t.m21)
+            b = Point(t.m12, t.m22)
+            c = t.offset()
+            return [c, c + a, c - a, c + b, c - b]
+        else:
+            points = [t(Polar(start_angle)), t(Polar(end_angle)), t.offset()]
+            if end_angle < start_angle:
+                end_angle = end_angle + 2 * pi
+            pi2 = pi / 2
+            angle = pi2 * (floor(start_angle / pi2) + 1)
+            while angle < end_angle:
+                points.append(t(Polar(1, angle)))
+                angle = angle + pi2
+            return points
 
     def Snap(self, p):
-	try:
-	    r, phi = self.trafo.inverse()(p).polar()
-	    start_angle = self.start_angle; end_angle = self.end_angle
-	    p2 = self.trafo(Polar(1, phi))
-	    if start_angle == end_angle:
-		result = (abs(p - p2), p2)
-	    else:
-		result = []
-		if phi < 0:
-		    phi = phi + 2 * pi
-		if start_angle < end_angle:
-		    between = start_angle <= phi <= end_angle
-		else:
-		    between = start_angle <= phi or phi <= end_angle
-		if between:
-		    result.append((abs(p - p2), p2))
-		start = self.trafo(Polar(self.start_angle))
-		end = self.trafo(Polar(self.end_angle))
-		if self.arc_type == ArcArc:
-		    result.append((abs(start - p), start))
-		    result.append((abs(end - p), end))
-		elif self.arc_type == ArcChord:
-		    result.append((snap_to_line(start, end, p)))
-		elif self.arc_type == ArcPieSlice:
-		    center = self.trafo.offset()
-		    result.append(snap_to_line(start, center, p))
-		    result.append(snap_to_line(end, center, p))
-		result = min(result)
-	    return result
-	except SingularMatrix:
-	    # XXX this case could be handled better.
-	    return (1e200, p)
+        try:
+            r, phi = self.trafo.inverse()(p).polar()
+            start_angle = self.start_angle; end_angle = self.end_angle
+            p2 = self.trafo(Polar(1, phi))
+            if start_angle == end_angle:
+                result = (abs(p - p2), p2)
+            else:
+                result = []
+                if phi < 0:
+                    phi = phi + 2 * pi
+                if start_angle < end_angle:
+                    between = start_angle <= phi <= end_angle
+                else:
+                    between = start_angle <= phi or phi <= end_angle
+                if between:
+                    result.append((abs(p - p2), p2))
+                start = self.trafo(Polar(self.start_angle))
+                end = self.trafo(Polar(self.end_angle))
+                if self.arc_type == ArcArc:
+                    result.append((abs(start - p), start))
+                    result.append((abs(end - p), end))
+                elif self.arc_type == ArcChord:
+                    result.append((snap_to_line(start, end, p)))
+                elif self.arc_type == ArcPieSlice:
+                    center = self.trafo.offset()
+                    result.append(snap_to_line(start, center, p))
+                    result.append(snap_to_line(end, center, p))
+                result = min(result)
+            return result
+        except SingularMatrix:
+            # XXX this case could be handled better.
+            return (1e200, p)
 
 
     def update_rects(self):
-	trafo = self.trafo
-	start = trafo.offset()
+        trafo = self.trafo
+        start = trafo.offset()
         # On some systems, atan2 can raise a ValueError if both
         # parameters are 0. In that case, the actual value the of angle
         # is not important since in the computation of p below, the
@@ -235,46 +235,46 @@
             phi2 = atan2(trafo.m22, trafo.m21)
         except ValueError:
             phi2 = 0
-	p = Point(trafo.m11 * cos(phi1) + trafo.m12 * sin(phi1),
-		  trafo.m21 * cos(phi2) + trafo.m22 * sin(phi2))
-	self.coord_rect = r = Rect(start + p, start - p)
-	if self.properties.HasLine():
-	    width = self.properties.line_width
-	    r = r.grown(width / 2 + 1)
-	    # add the bounding boxes of arrows
-	    if self.arc_type == ArcArc:
-		pi2 = pi / 2
-		arrow1 = self.properties.line_arrow1
-		if arrow1 is not None:
-		    pos = trafo(Polar(1, self.start_angle))
-		    dir = trafo.DTransform(Polar(1, self.start_angle - pi2))
-		    r = UnionRects(r, arrow1.BoundingRect(pos, dir, width))
-		arrow2 = self.properties.line_arrow2
-		if arrow2 is not None:
-		    pos = trafo(Polar(1, self.end_angle))
-		    dir = trafo.DTransform(Polar(1, self.end_angle + pi2))
-		    r = UnionRects(r, arrow2.BoundingRect(pos, dir, width))
-	self.bounding_rect = r
+        p = Point(trafo.m11 * cos(phi1) + trafo.m12 * sin(phi1),
+                  trafo.m21 * cos(phi2) + trafo.m22 * sin(phi2))
+        self.coord_rect = r = Rect(start + p, start - p)
+        if self.properties.HasLine():
+            width = self.properties.line_width
+            r = r.grown(width / 2 + 1)
+            # add the bounding boxes of arrows
+            if self.arc_type == ArcArc:
+                pi2 = pi / 2
+                arrow1 = self.properties.line_arrow1
+                if arrow1 is not None:
+                    pos = trafo(Polar(1, self.start_angle))
+                    dir = trafo.DTransform(Polar(1, self.start_angle - pi2))
+                    r = UnionRects(r, arrow1.BoundingRect(pos, dir, width))
+                arrow2 = self.properties.line_arrow2
+                if arrow2 is not None:
+                    pos = trafo(Polar(1, self.end_angle))
+                    dir = trafo.DTransform(Polar(1, self.end_angle + pi2))
+                    r = UnionRects(r, arrow2.BoundingRect(pos, dir, width))
+        self.bounding_rect = r
 
     def Info(self):
-	trafo = self.trafo
-	w = hypot(trafo.m11, trafo.m21)
-	h = hypot(trafo.m12, trafo.m22)
-	dict = {'center': trafo.offset(), 'radius': w, 'axes': (w, h)}
-	if w == h:
-	    text = _("Circle radius %(radius)[length], "
+        trafo = self.trafo
+        w = hypot(trafo.m11, trafo.m21)
+        h = hypot(trafo.m12, trafo.m22)
+        dict = {'center': trafo.offset(), 'radius': w, 'axes': (w, h)}
+        if w == h:
+            text = _("Circle radius %(radius)[length], "
                      "center %(center)[position]")
         else:
             text = _("Ellipse axes %(axes)[size], center %(center)[position]")
         return text, dict
 
     def SaveToFile(self, file):
-	Primitive.SaveToFile(self, file)
-	file.Ellipse(self.trafo, self.start_angle, self.end_angle,
-		     self.arc_type)
+        Primitive.SaveToFile(self, file)
+        file.Ellipse(self.trafo, self.start_angle, self.end_angle,
+                     self.arc_type)
 
     def Editor(self):
-	return EllipseEditor(self)
+        return EllipseEditor(self)
 
     context_commands = ('EllipseArc', 'EllipseChord', 'EllipsePieSlice')
 
@@ -305,7 +305,7 @@
             end = self.apply_constraint(self.drag_cur, state)
             d = (end - start) / 2
             self.trafo = Trafo(d.x, 0, 0, d.y, start.x + d.x, start.y + d.y)
-            
+
     def MouseMove(self, p, state):
         # Bypass RectangularCreator
         Creator.MouseMove(self, p, state)
@@ -316,7 +316,7 @@
         self.compute_trafo(state)
 
     def DrawDragged(self, device, partially):
-	device.DrawEllipse(self.trafo(-1, -1), self.trafo(1, 1))
+        device.DrawEllipse(self.trafo(-1, -1), self.trafo(1, 1))
 
     def CurrentInfoText(self):
         t = self.trafo
@@ -331,7 +331,7 @@
         return text, data
 
     def CreatedObject(self):
-	return Ellipse(self.trafo,
+        return Ellipse(self.trafo,
                        properties = DefaultGraphicsProperties())
 
 
@@ -342,88 +342,88 @@
     selection = 0
 
     def ButtonDown(self, p, button, state):
-	if self.selection == 1:
-	    start = self.trafo(cos(self.start_angle), sin(self.start_angle))
-	else:
-	    start = self.trafo(cos(self.end_angle), sin(self.end_angle))
-	Editor.DragStart(self, start)
-	return p - start
+        if self.selection == 1:
+            start = self.trafo(cos(self.start_angle), sin(self.start_angle))
+        else:
+            start = self.trafo(cos(self.end_angle), sin(self.end_angle))
+        Editor.DragStart(self, start)
+        return p - start
 
     def apply_constraint(self, p, state):
-	if state & ConstraintMask:
-	    try:
-		inverse = self.trafo.inverse()
-		p2 = inverse(p)
-		r, phi = p2.polar()
-		pi12 = pi / 12
-		angle = pi12 * floor(phi / pi12 + 0.5)
-		pi2 = 2 * pi
-		d1 = fmod(abs(phi - angle), pi2)
-		if self.selection == 1:
-		    selected_angle = self.end_angle
-		else:
-		    selected_angle = self.start_angle
-		d2 = fmod(abs(phi - selected_angle), pi2)
-		if d2 < d1:
-		    phi = selected_angle
-		else:
-		    phi = angle
-		p = self.trafo(Polar(r, phi))
-	    except SingularMatrix:
-		pass
-	return p
+        if state & ConstraintMask:
+            try:
+                inverse = self.trafo.inverse()
+                p2 = inverse(p)
+                r, phi = p2.polar()
+                pi12 = pi / 12
+                angle = pi12 * floor(phi / pi12 + 0.5)
+                pi2 = 2 * pi
+                d1 = fmod(abs(phi - angle), pi2)
+                if self.selection == 1:
+                    selected_angle = self.end_angle
+                else:
+                    selected_angle = self.start_angle
+                d2 = fmod(abs(phi - selected_angle), pi2)
+                if d2 < d1:
+                    phi = selected_angle
+                else:
+                    phi = angle
+                p = self.trafo(Polar(r, phi))
+            except SingularMatrix:
+                pass
+        return p
 
     def MouseMove(self, p, state):
-	p = self.apply_constraint(p, state)
-	Editor.MouseMove(self, p, state)
+        p = self.apply_constraint(p, state)
+        Editor.MouseMove(self, p, state)
 
     def ButtonUp(self, p, button, state):
-	p = self.apply_constraint(p, state)
-	Editor.DragStop(self, p)
-	start_angle, end_angle, arc_type = self.angles()
-	return CreateMultiUndo(self.object.SetAngles(start_angle, end_angle),
-			       self.object.SetArcType(arc_type))
+        p = self.apply_constraint(p, state)
+        Editor.DragStop(self, p)
+        start_angle, end_angle, arc_type = self.angles()
+        return CreateMultiUndo(self.object.SetAngles(start_angle, end_angle),
+                               self.object.SetArcType(arc_type))
 
     def angles(self):
-	start_angle = self.start_angle; end_angle = self.end_angle
-	if self.arc_type == ArcChord:
-	    arc_type = ArcChord
-	else:
-	    arc_type = ArcPieSlice
+        start_angle = self.start_angle; end_angle = self.end_angle
+        if self.arc_type == ArcChord:
+            arc_type = ArcChord
+        else:
+            arc_type = ArcPieSlice
 
-	try:
-	    inverse = self.trafo.inverse()
-	    p = inverse(self.drag_cur)
-	    if self.selection == 1:
-		start_angle = atan2(p.y, p.x)
-	    elif self.selection == 2:
-		end_angle = atan2(p.y, p.x)
-	    if abs(p) > 1:
-		arc_type = ArcArc
-	except SingularMatrix:
-	    pass
-	if fmod(abs(start_angle - end_angle), 2 * pi) < 0.0001:
-	    if self.selection == 1:
-		start_angle = end_angle
-	    else:
-		end_angle = start_angle
-	return (start_angle, end_angle, arc_type)
+        try:
+            inverse = self.trafo.inverse()
+            p = inverse(self.drag_cur)
+            if self.selection == 1:
+                start_angle = atan2(p.y, p.x)
+            elif self.selection == 2:
+                end_angle = atan2(p.y, p.x)
+            if abs(p) > 1:
+                arc_type = ArcArc
+        except SingularMatrix:
+            pass
+        if fmod(abs(start_angle - end_angle), 2 * pi) < 0.0001:
+            if self.selection == 1:
+                start_angle = end_angle
+            else:
+                end_angle = start_angle
+        return (start_angle, end_angle, arc_type)
 
     def DrawDragged(self, device, partially):
-	start_angle, end_angle, arc_type = self.angles()
-	device.SimpleEllipse(self.trafo, start_angle, end_angle, arc_type)
+        start_angle, end_angle, arc_type = self.angles()
+        device.SimpleEllipse(self.trafo, start_angle, end_angle, arc_type)
 
     def GetHandles(self):
-	trafo = self.trafo
-	start_angle = self.start_angle; end_angle = self.end_angle
-	p1 = trafo(cos(self.start_angle), sin(self.start_angle))
-	if start_angle == end_angle:
-	    return [handle.MakeNodeHandle(p1)]
-	p2 = trafo(cos(self.end_angle), sin(self.end_angle))
-	return [handle.MakeNodeHandle(p1), handle.MakeNodeHandle(p2)]
+        trafo = self.trafo
+        start_angle = self.start_angle; end_angle = self.end_angle
+        p1 = trafo(cos(self.start_angle), sin(self.start_angle))
+        if start_angle == end_angle:
+            return [handle.MakeNodeHandle(p1)]
+        p2 = trafo(cos(self.end_angle), sin(self.end_angle))
+        return [handle.MakeNodeHandle(p1), handle.MakeNodeHandle(p2)]
 
     def SelectHandle(self, handle, mode):
-	self.selection = handle.index + 1
+        self.selection = handle.index + 1
 
     def SelectPoint(self, p, rect, device, mode):
-	return 0
+        return 0

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/eps.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/eps.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/eps.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -32,10 +32,10 @@
 
 
 gs_command = ('gs -sDEVICE=ppmraw -r%(resolution)d -dNOPAUSE -dSAFER -q'
-	      ' -sOutputFile=%(temp)s -g%(width)dx%(height)d'
-	      ' -c %(offx)f %(offy)f translate'
-	      ' /oldshowpage /showpage load def /showpage \'{}\' def '
-	      ' -f %(filename)s -c oldshowpage quit')
+              ' -sOutputFile=%(temp)s -g%(width)dx%(height)d'
+              ' -c %(offx)f %(offy)f translate'
+              ' /oldshowpage /showpage load def /showpage \'{}\' def '
+              ' -f %(filename)s -c oldshowpage quit')
 
 def render_preview(filename, startx, starty, width, height, resolution = None):
     import tempfile
@@ -50,75 +50,75 @@
         factor = resolution / 72.0
         width = int(math.ceil(width * factor))
         height = int(math.ceil(height * factor))
-	offx = -startx
-	offy = -starty
-	os.system(gs_command % locals())
+        offx = -startx
+        offy = -starty
+        os.system(gs_command % locals())
 
-	image = PIL.Image.open(temp)
-	image.load()
-	return image
+        image = PIL.Image.open(temp)
+        image.load()
+        return image
     finally:
-	try:
-	    os.unlink(temp)
-	except:
-	    pass
+        try:
+            os.unlink(temp)
+        except:
+            pass
 
 
 
 class EpsData(ExternalData):
 
     def __init__(self, filename):
-	self.info = info = dscparser.parse_eps_file(filename)
-	self.filename = filename
-	if info.BoundingBox:
-	    llx, lly, urx, ury = info.BoundingBox
-	    self.width = Point(urx - llx, 0)
-	    self.height = Point(0, ury - lly)
-	    self.start = (llx, lly)
-	    self.size = (urx - llx, ury - lly)
-	    self.image = None
-	    try:
-		self.image = render_preview(filename, llx, lly,
-					    urx - llx, ury - lly)
-	    except IOError:
-		pass
-	else:
-	    raise TypeError, '%s has no BoundingBox' % filename
+        self.info = info = dscparser.parse_eps_file(filename)
+        self.filename = filename
+        if info.BoundingBox:
+            llx, lly, urx, ury = info.BoundingBox
+            self.width = Point(urx - llx, 0)
+            self.height = Point(0, ury - lly)
+            self.start = (llx, lly)
+            self.size = (urx - llx, ury - lly)
+            self.image = None
+            try:
+                self.image = render_preview(filename, llx, lly,
+                                            urx - llx, ury - lly)
+            except IOError:
+                pass
+        else:
+            raise TypeError, '%s has no BoundingBox' % filename
 
-	ExternalData.__init__(self, filename)
+        ExternalData.__init__(self, filename)
 
     def Start(self):
-	return self.start
+        return self.start
 
     def Size(self):
-	return self.size
+        return self.size
 
     def WriteLines(self, file):
-	write = file.write
+        write = file.write
 
-	try:
-	    infile = open(self.filename, 'r')
-	except IOError, val:
-	    raise IOError, (filename, val)
-	try:
-	    readline = infile.readline
+        try:
+            infile = open(self.filename, 'r')
+        except IOError, val:
+            raise IOError, (filename, val)
+        try:
+            readline = infile.readline
 
-	    line = readline()
-	    while line:
-		if line[:15] == '%%BeginPreview:':
-		    while line[:12] != '%%EndPreview':
-			line = readline()
-		    continue
-		write(line)
-		line = readline()
-	finally:
-	    infile.close()
+            line = readline()
+            while line:
+                if line[:15] == '%%BeginPreview:':
+                    while line[:12] != '%%EndPreview':
+                        line = readline()
+                    continue
+                write(line)
+                line = readline()
+        finally:
+            infile.close()
 
 
 def load_eps(filename):
     eps = get_cached(filename)
     if eps:
-	return eps
+        return eps
     return EpsData(filename)
 
 
@@ -128,30 +128,30 @@
     is_Eps = 1
 
     def __init__(self, filename = '', trafo = None, duplicate = None):
-	if duplicate is None:
-	    if not filename:
-		raise ValueError, 'filename must be provided'
-	    data = load_eps(filename)
-	else:
-	    data = None
-	ExternalGraphics.__init__(self, data, trafo,
-				  duplicate = duplicate)
+        if duplicate is None:
+            if not filename:
+                raise ValueError, 'filename must be provided'
+            data = load_eps(filename)
+        else:
+            data = None
+        ExternalGraphics.__init__(self, data, trafo,
+                                  duplicate = duplicate)
 
     def DrawShape(self, device, rect = None):
-	device.DrawEps(self.data, self.trafo)
+        device.DrawEps(self.data, self.trafo)
 
     def Info(self):
         filename = os.path.basename(self.data.Filename())
         width, height = self.data.Size()
         x, y = self.trafo.offset()
-	return _("EpsFile `%(filename)s' %(width)d x %(height)d "
+        return _("EpsFile `%(filename)s' %(width)d x %(height)d "
                  "at (%(x)d, %(y)d)") % locals()
 
     def SaveToFile(self, file):
-	file.EpsFile(self.data, self.trafo)
+        file.EpsFile(self.data, self.trafo)
 
     def PSNeededResources(self):
-	return self.data.info.DocumentNeededResources
+        return self.data.info.DocumentNeededResources
 
 
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/external.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/external.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/external.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -38,18 +38,18 @@
     filename = ''
 
     def __init__(self, filename = '', do_cache = 1):
-	if filename and do_cache:
-	    self.stored_in_cache = 1
-	    instance_cache[filename] = self
+        if filename and do_cache:
+            self.stored_in_cache = 1
+            instance_cache[filename] = self
         if filename:
             self.filename = filename
 
     def __del__(self):
-	if self.stored_in_cache and instance_cache.has_key(self.filename):
-	    del instance_cache[self.filename]
+        if self.stored_in_cache and instance_cache.has_key(self.filename):
+            del instance_cache[self.filename]
 
     def Filename(self):
-	return self.filename
+        return self.filename
 
 
     # to be supplied by derived classes
@@ -59,7 +59,7 @@
 
 def get_cached(filename):
     if instance_cache.has_key(filename):
-	return instance_cache[filename]
+        return instance_cache[filename]
     return None
 
 
@@ -72,11 +72,11 @@
     data = None
 
     def __init__(self, data = None, trafo = None, duplicate = None):
-	RectangularObject.__init__(self, trafo, duplicate = duplicate)
-	GraphicsObject.__init__(self, duplicate = duplicate)
-	if duplicate is not None:
-	    data = duplicate.data
-	self.data = data
+        RectangularObject.__init__(self, trafo, duplicate = duplicate)
+        GraphicsObject.__init__(self, duplicate = duplicate)
+        if duplicate is not None:
+            data = duplicate.data
+        self.data = data
 
     def Data(self):
         return self.data
@@ -88,66 +88,66 @@
         return undo
 
     def Hit(self, p, rect, device, clip = 0):
-	width, height = self.data.Size()
-	return device.ParallelogramHit(p, self.trafo, width, height, 1,
-				       ignore_outline_mode = clip)
+        width, height = self.data.Size()
+        return device.ParallelogramHit(p, self.trafo, width, height, 1,
+                                       ignore_outline_mode = clip)
 
     def SetLowerLeftCorner(self, corner):
-	# Used by the place mode in SketchCanvas. Currently no undo
-	# needed since this is called *before* self is a part of a
-	# document.
-	self.trafo = apply(Trafo, self.trafo.coeff()[:4] + tuple(corner))
-	self.del_lazy_attrs()
+        # Used by the place mode in SketchCanvas. Currently no undo
+        # needed since this is called *before* self is a part of a
+        # document.
+        self.trafo = apply(Trafo, self.trafo.coeff()[:4] + tuple(corner))
+        self.del_lazy_attrs()
 
     def RemoveTransformation(self):
-	if self.trafo.matrix() != IdentityMatrix:
-	    center = self.coord_rect.center()
-	    width, height = self.data.Size()
-	    trafo = Trafo(1, 0, 0, 1,
-			  center.x - width / 2, center.y - height / 2)
-	    return self.set_transformation(trafo)
-	return NullUndo
+        if self.trafo.matrix() != IdentityMatrix:
+            center = self.coord_rect.center()
+            width, height = self.data.Size()
+            trafo = Trafo(1, 0, 0, 1,
+                          center.x - width / 2, center.y - height / 2)
+            return self.set_transformation(trafo)
+        return NullUndo
 
     def update_rects(self):
-	width, height = self.data.Size()
-	rect = self.trafo(Rect(0, 0, width, height))
-	self.coord_rect = rect
-	self.bounding_rect = rect.grown(2)
+        width, height = self.data.Size()
+        rect = self.trafo(Rect(0, 0, width, height))
+        self.coord_rect = rect
+        self.bounding_rect = rect.grown(2)
 
     def Info(self):
-	# Should be overwritten by derived classes
-	return 'ExternalGraphics'
+        # Should be overwritten by derived classes
+        return 'ExternalGraphics'
 
     def SetProperties(self, **kw):
-	return NullUndo
+        return NullUndo
 
     def AddStyle(self, style):
-	return NullUndo
+        return NullUndo
 
     def Properties(self):
-	return EmptyProperties
+        return EmptyProperties
 
     def GetSnapPoints(self):
         width, height = self.data.Size()
         corners = ((0, 0), (width, 0), (width, height), (0, height))
-	return map(self.trafo, corners)
+        return map(self.trafo, corners)
 
     def Snap(self, p):
         width, height = self.data.Size()
-	try:
-	    x, y = self.trafo.inverse()(p)
-	    if 0 <= x <= width:
-		if 0 <= y <= height:
-		    x = round(x / width) * width
-		    y = round(y / height) * height
-		else:
-		    y = min(max(y, 0), height)
-	    else:
+        try:
+            x, y = self.trafo.inverse()(p)
+            if 0 <= x <= width:
+                if 0 <= y <= height:
+                    x = round(x / width) * width
+                    y = round(y / height) * height
+                else:
+                    y = min(max(y, 0), height)
+            else:
                 x = min(max(x, 0), width)
-		if 0 > y or y > height:
+                if 0 > y or y > height:
                     y = min(max(y, 0), height)
 
-	    p2 = self.trafo(x, y)
-	    return (abs(p - p2), p2)
-	except SingularMatrix:
-	    return (1e200, p)
+            p2 = self.trafo(x, y)
+            return (abs(p - p2), p2)
+        except SingularMatrix:
+            return (1e200, p)

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/font.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/font.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/font.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -67,25 +67,25 @@
     charmetrics = {encoding.notdef: (0, 0,0,0,0)}
     font_encoding = [encoding.notdef] * 256
     while 1:
-	line = afm.readline()
-	if line == 'EndCharMetrics\n':
-	    break
-	items = filter(None, map(strip, split(line, ';')))
+        line = afm.readline()
+        if line == 'EndCharMetrics\n':
+            break
+        items = filter(None, map(strip, split(line, ';')))
         if not items:
             continue
-	code = name = width = bbox = None
-	for item in items:
-	    [key, value] = split(item, None, 1)
-	    if key == 'C':
-		code = atoi(value)
-	    elif key == 'WX':
-		width = int(round(atof(value)))
-	    elif key == 'N':
-		name = value
-	    elif key == 'B':
-		bbox = tuple(map(int,map(round,map(atof,split(value)))))
-	charmetrics[name] = (width,) + bbox
-	font_encoding[code] = name
+        code = name = width = bbox = None
+        for item in items:
+            [key, value] = split(item, None, 1)
+            if key == 'C':
+                code = atoi(value)
+            elif key == 'WX':
+                width = int(round(atof(value)))
+            elif key == 'N':
+                name = value
+            elif key == 'B':
+                bbox = tuple(map(int,map(round,map(atof,split(value)))))
+        charmetrics[name] = (width,) + bbox
+        font_encoding[code] = name
     return charmetrics, font_encoding
 
 def read_afm_file(filename):
@@ -96,51 +96,51 @@
     font_encoding = [encoding.notdef] * 256
 
     while 1:
-	line = afm.readline()
-	if not line:
-	    break
+        line = afm.readline()
+        if not line:
+            break
         try:
             [key, value] = split(line, None, 1)
         except ValueError:
             # this normally means that a line contained only a keyword
             # but no value or that the line was empty
             continue
-	try:
-	    action = converters[key]
-	except KeyError:
-	    continue
-	if action:
-	    attribs[key] = action(value)
-	elif key == 'StartCharMetrics':
-	    charmetrics, font_encoding = read_char_metrics(afm)
-	    break
-	else:
-	    # EndFontMetrics
-	    break
+        try:
+            action = converters[key]
+        except KeyError:
+            continue
+        if action:
+            attribs[key] = action(value)
+        elif key == 'StartCharMetrics':
+            charmetrics, font_encoding = read_char_metrics(afm)
+            break
+        else:
+            # EndFontMetrics
+            break
 
     if not charmetrics:
-	raise ValueError, \
-	      'AFM files without individual char metrics not yet supported.'
+        raise ValueError, \
+              'AFM files without individual char metrics not yet supported.'
 
     if attribs.get('EncodingScheme', StandardEncoding) == StandardEncoding:
-	enc = encoding.iso_latin_1
+        enc = encoding.iso_latin_1
     else:
-	enc = font_encoding
+        enc = font_encoding
 
     try:
-	rescharmetrics = map(operator.getitem, [charmetrics] * len(enc), enc)
+        rescharmetrics = map(operator.getitem, [charmetrics] * len(enc), enc)
     except KeyError:
-	# Some iso-latin-1 glyphs are not defined in the font. Try the
-	# slower way and report missing glyphs.
-	length = len(enc)
-	rescharmetrics = [(0, 0,0,0,0)] * length
-	for idx in range(length):
-	    name = enc[idx]
-	    try:
-		rescharmetrics[idx] = charmetrics[name]
-	    except KeyError:
-		# missing character...
-		warn(INTERNAL, '%s: missing character %s', filename, name)
+        # Some iso-latin-1 glyphs are not defined in the font. Try the
+        # slower way and report missing glyphs.
+        length = len(enc)
+        rescharmetrics = [(0, 0,0,0,0)] * length
+        for idx in range(length):
+            name = enc[idx]
+            try:
+                rescharmetrics[idx] = charmetrics[name]
+            except KeyError:
+                # missing character...
+                warn(INTERNAL, '%s: missing character %s', filename, name)
 
     # some fonts don't define ascender and descender (psyr.afm for
     # instance). use the values from the font bounding box instead. This
@@ -154,39 +154,39 @@
     # reads from afm files are only optional (including ascender and
     # descender).
     if not attribs.has_key('Ascender'):
-	attribs['Ascender'] = attribs['FontBBox'][3]
+        attribs['Ascender'] = attribs['FontBBox'][3]
     if not attribs.has_key('Descender'):
-	attribs['Descender'] = attribs['FontBBox'][1]
+        attribs['Descender'] = attribs['FontBBox'][1]
 
     return (CreateFontMetric(attribs['Ascender'], attribs['Descender'],
                              attribs['FontBBox'], attribs['ItalicAngle'],
                              rescharmetrics),
-	    enc)
+            enc)
 
 
 _warned_about_afm = {}
 def read_metric(ps_name):
     for afm in ps_to_filename[ps_name]:
-	afm = afm + '.afm'
-	filename = find_in_path(config.font_path, afm)
-	if filename:
-	    if __debug__:
-		import time
-		start = time.clock()
-	    metric = read_afm_file(filename)
-	    if __debug__:
-		pdebug('timing', 'time to read afm %s: %g', afm,
-		       time.clock() - start)
-	    return metric
+        afm = afm + '.afm'
+        filename = find_in_path(config.font_path, afm)
+        if filename:
+            if __debug__:
+                import time
+                start = time.clock()
+            metric = read_afm_file(filename)
+            if __debug__:
+                pdebug('timing', 'time to read afm %s: %g', afm,
+                       time.clock() - start)
+            return metric
     else:
-	if not _warned_about_afm.get(afm):
-	    warn(USER,
+        if not _warned_about_afm.get(afm):
+            warn(USER,
                  _("I cannot find the metrics for the font %(ps_name)s.\n"
                    "The file %(afm)s is not in the font_path.\n"
                    "I'll use the metrics for %(fallback)s instead."),
-		 ps_name = ps_name, afm = afm,
+                 ps_name = ps_name, afm = afm,
                  fallback = config.preferences.fallback_font)
-	    _warned_about_afm[afm] = 1
+            _warned_about_afm[afm] = 1
         if ps_name != config.preferences.fallback_font:
             return read_metric(config.preferences.fallback_font)
         else:
@@ -197,40 +197,40 @@
 def font_file_name(ps_name):
     names = []
     for basename in ps_to_filename[ps_name]:
-	names.append(basename + '.pfb')
-	names.append(basename + '.pfa')
+        names.append(basename + '.pfb')
+        names.append(basename + '.pfa')
     filename = find_files_in_path(config.font_path, names)
     return filename
 
-    
+
 def read_outlines(ps_name):
     filename = font_file_name(ps_name)
     if filename:
-	if __debug__:
-	    pdebug('font', 'read_outlines: %s', filename)
+        if __debug__:
+            pdebug('font', 'read_outlines: %s', filename)
 
-	import Sketch.Lib.type1
-	return Sketch.Lib.type1.read_outlines(filename)
+        import Sketch.Lib.type1
+        return Sketch.Lib.type1.read_outlines(filename)
     else:
-	raise SketchInternalError('Cannot find file for font %s' % ps_name)
+        raise SketchInternalError('Cannot find file for font %s' % ps_name)
 
 def convert_outline(outline):
     paths = []
     trafo = Scale(0.001)
     for closed, sub in outline:
-	if closed:
-	    sub.append(sub[0])
-	path = CreatePath()
-	paths.append(path)
-	for item in sub:
-	    if len(item) == 2:
-		apply(path.AppendLine, item)
-	    else:
-		apply(path.AppendBezier, item)
-	if closed:
-	    path.load_close()
+        if closed:
+            sub.append(sub[0])
+        path = CreatePath()
+        paths.append(path)
+        for item in sub:
+            if len(item) == 2:
+                apply(path.AppendLine, item)
+            else:
+                apply(path.AppendBezier, item)
+        if closed:
+            path.load_close()
     for path in paths:
-	path.Transform(trafo)
+        path.Transform(trafo)
     return tuple(paths)
 
 
@@ -243,66 +243,66 @@
 def _add_ps_filename(ps_name, filename):
     filename = (filename,)
     if ps_to_filename.has_key(ps_name):
-	filename = ps_to_filename[ps_name] + filename
+        filename = ps_to_filename[ps_name] + filename
     ps_to_filename[ps_name] = filename
 
 def read_font_dirs():
     #print 'read_font_dirs'
     if __debug__:
-	import time
-	start = time.clock()
+        import time
+        start = time.clock()
 
     rx_sfd = re.compile(r'^.*\.sfd$')
     for directory in config.font_path:
         #print directory
-	try:
-	    filenames = os.listdir(directory)
-	except os.error, exc:
-	    warn(USER, _("Cannot list directory %s:%s\n"
+        try:
+            filenames = os.listdir(directory)
+        except os.error, exc:
+            warn(USER, _("Cannot list directory %s:%s\n"
                          "ignoring it in font_path"),
-		 directory, str(exc))
-	    continue
-	dirfiles = filter(rx_sfd.match, filenames)
-	for filename in dirfiles:
-	    filename = os.path.join(directory, filename)
+                 directory, str(exc))
+            continue
+        dirfiles = filter(rx_sfd.match, filenames)
+        for filename in dirfiles:
+            filename = os.path.join(directory, filename)
             #print filename
-	    try:
-		file = open(filename, 'r')
-		line_nr = 0
-		for line in file.readlines():
-		    line_nr = line_nr + 1
-		    line = strip(line)
-		    if not line or line[0] == '#':
-			continue
-		    info = map(intern, split(line, ','))
-		    if len(info) == 6:
-			psname = info[0]
-			fontlist.append(tuple(info[:-1]))
-			_add_ps_filename(psname, info[-1])
-			fontmap[psname] = tuple(info[1:-1])
-		    elif len(info) == 2:
-			psname, basename = info
-			_add_ps_filename(psname, basename)
-		    else:
-			warn(INTERNAL,'%s:%d: line must have exactly 6 fields',
-			     filename, line_nr)
-		file.close()
-	    except IOError, value:
-		warn(USER, _("Cannot load sfd file %(filename)s:%(message)s;"
+            try:
+                file = open(filename, 'r')
+                line_nr = 0
+                for line in file.readlines():
+                    line_nr = line_nr + 1
+                    line = strip(line)
+                    if not line or line[0] == '#':
+                        continue
+                    info = map(intern, split(line, ','))
+                    if len(info) == 6:
+                        psname = info[0]
+                        fontlist.append(tuple(info[:-1]))
+                        _add_ps_filename(psname, info[-1])
+                        fontmap[psname] = tuple(info[1:-1])
+                    elif len(info) == 2:
+                        psname, basename = info
+                        _add_ps_filename(psname, basename)
+                    else:
+                        warn(INTERNAL,'%s:%d: line must have exactly 6 fields',
+                             filename, line_nr)
+                file.close()
+            except IOError, value:
+                warn(USER, _("Cannot load sfd file %(filename)s:%(message)s;"
                              "ignoring it"),
-		     filename = filename, message = value.strerror)
+                     filename = filename, message = value.strerror)
     if __debug__:
-	pdebug('timing', 'time to read font dirs: %g', time.clock() - start)
+        pdebug('timing', 'time to read font dirs: %g', time.clock() - start)
 
 def make_family_to_fonts():
     families = {}
     for item in fontlist:
-	family = item[1]
-	fontname = item[0]
-	if families.has_key(family):
-	    families[family] = families[family] + (fontname,)
-	else:
-	    families[family] = (fontname,)
+        family = item[1]
+        fontname = item[0]
+        if families.has_key(family):
+            families[family] = families[family] + (fontname,)
+        else:
+            families[family] = (fontname,)
     return families
 
 
@@ -314,28 +314,28 @@
 class Font:
 
     def __init__(self, name):
-	self.name = name
-	info = fontmap[name]
-	family, font_attrs, xlfd_start, encoding_name = info
-	self.family = family
-	self.font_attrs = font_attrs
-	self.xlfd_start = lower(xlfd_start)
-	self.encoding_name = encoding_name
-	self.metric, self.encoding = read_metric(self.PostScriptName())
-	self.outlines = None
+        self.name = name
+        info = fontmap[name]
+        family, font_attrs, xlfd_start, encoding_name = info
+        self.family = family
+        self.font_attrs = font_attrs
+        self.xlfd_start = lower(xlfd_start)
+        self.encoding_name = encoding_name
+        self.metric, self.encoding = read_metric(self.PostScriptName())
+        self.outlines = None
 
-	self.ref_count = 0
-	font_cache[self.name] = self
+        self.ref_count = 0
+        font_cache[self.name] = self
 
     def __del__(self):
-	if font_cache is not None and font_cache.has_key(self.name):
-	    del font_cache[self.name]
+        if font_cache is not None and font_cache.has_key(self.name):
+            del font_cache[self.name]
 
     def __repr__(self):
         return "<Font %s>" % self.name
 
     def GetXLFD(self, size_trafo):
-	if type(size_trafo) == TrafoType:
+        if type(size_trafo) == TrafoType:
             if size_trafo.m11 == size_trafo.m22 > 0\
                and size_trafo.m12 == size_trafo.m21 == 0:
                 # a uniform scaling. Special case for better X11R5
@@ -343,65 +343,65 @@
                 return xlfd_template % (self.xlfd_start,
                                         int(round(size_trafo.m11)),
                                         self.encoding_name)
-	    return xlfd_template % (self.xlfd_start, xlfd_matrix(size_trafo),
-				    self.encoding_name)
-	return xlfd_template % (self.xlfd_start, int(round(size_trafo)),
-				self.encoding_name)
+            return xlfd_template % (self.xlfd_start, xlfd_matrix(size_trafo),
+                                    self.encoding_name)
+        return xlfd_template % (self.xlfd_start, int(round(size_trafo)),
+                                self.encoding_name)
 
     def PostScriptName(self):
-	return self.name
+        return self.name
 
     def TextBoundingBox(self, text, size):
-	# Return the bounding rectangle of TEXT when set in this font
-	# with a size of SIZE. The coordinates of the rectangle are
-	# relative to the origin of the first character.
-	llx, lly, urx, ury = self.metric.string_bbox(text)
-	size = size / 1000.0
-	return (llx * size, lly * size, urx * size, ury * size)
+        # Return the bounding rectangle of TEXT when set in this font
+        # with a size of SIZE. The coordinates of the rectangle are
+        # relative to the origin of the first character.
+        llx, lly, urx, ury = self.metric.string_bbox(text)
+        size = size / 1000.0
+        return (llx * size, lly * size, urx * size, ury * size)
 
     def TextCoordBox(self, text, size):
-	# Return the coord rectangle of TEXT when set in this font with
-	# a size of SIZE. The coordinates of the rectangle are relative
-	# to the origin of the first character.
-	metric = self.metric
-	width = metric.string_width(text)
-	size = size / 1000.0
-	return (0,		metric.descender * size,
-		width * size,	metric.ascender * size)
+        # Return the coord rectangle of TEXT when set in this font with
+        # a size of SIZE. The coordinates of the rectangle are relative
+        # to the origin of the first character.
+        metric = self.metric
+        width = metric.string_width(text)
+        size = size / 1000.0
+        return (0,		metric.descender * size,
+                width * size,	metric.ascender * size)
 
     def TextCaretData(self, text, pos, size):
-	from math import tan, pi
-	size = size / 1000.0
-	x = self.metric.string_width(text, pos) * size
-	lly = self.metric.lly * size
-	ury = self.metric.ury * size
-	t = tan(self.metric.italic_angle * pi / 180.0);
-	up = ury - lly
-	return Point(x - t * lly, lly), Point(-t * up, up)
+        from math import tan, pi
+        size = size / 1000.0
+        x = self.metric.string_width(text, pos) * size
+        lly = self.metric.lly * size
+        ury = self.metric.ury * size
+        t = tan(self.metric.italic_angle * pi / 180.0);
+        up = ury - lly
+        return Point(x - t * lly, lly), Point(-t * up, up)
 
     def TypesetText(self, text):
-	return self.metric.typeset_string(text)
+        return self.metric.typeset_string(text)
 
     def IsPrintable(self, char):
-	return self.encoding[ord(char)] != encoding.notdef
+        return self.encoding[ord(char)] != encoding.notdef
 
     def GetOutline(self, char):
-	if self.outlines is None:
-	    self.char_strings, self.cs_interp \
-			       = read_outlines(self.PostScriptName())
-	    self.outlines = {}
-	char_name = self.encoding[ord(char)]
-	outline = self.outlines.get(char_name)
-	if outline is None:
-	    self.cs_interp.execute(self.char_strings[char_name])
-	    outline = convert_outline(self.cs_interp.paths)
-	    self.outlines[char_name] = outline
-	    self.cs_interp.reset()
-	copy = []
-	for path in outline:
-	    path = path.Duplicate()
-	    copy.append(path)
-	return tuple(copy)
+        if self.outlines is None:
+            self.char_strings, self.cs_interp \
+                = read_outlines(self.PostScriptName())
+            self.outlines = {}
+        char_name = self.encoding[ord(char)]
+        outline = self.outlines.get(char_name)
+        if outline is None:
+            self.cs_interp.execute(self.char_strings[char_name])
+            outline = convert_outline(self.cs_interp.paths)
+            self.outlines[char_name] = outline
+            self.cs_interp.reset()
+        copy = []
+        for path in outline:
+            path = path.Duplicate()
+            copy.append(path)
+        return tuple(copy)
 
     def FontFileName(self):
         return font_file_name(self.PostScriptName())
@@ -411,17 +411,17 @@
 _warned_about_font = {}
 def GetFont(fontname):
     if font_cache.has_key(fontname):
-	return font_cache[fontname]
+        return font_cache[fontname]
     if not fontmap.has_key(fontname):
-	if not _warned_about_font.get(fontname):
-	    warn(USER, _("I can't find font %(fontname)s. "
+        if not _warned_about_font.get(fontname):
+            warn(USER, _("I can't find font %(fontname)s. "
                          "I'll use %(fallback)s instead"),
                  fontname = fontname,
                  fallback = config.preferences.fallback_font)
-	    _warned_about_font[fontname] = 1
-	if fontname != config.preferences.fallback_font:
-	    return GetFont(config.preferences.fallback_font)
-	raise ValueError, 'Cannot find font %s.' % fontname
+            _warned_about_font[fontname] = 1
+        if fontname != config.preferences.fallback_font:
+            return GetFont(config.preferences.fallback_font)
+        raise ValueError, 'Cannot find font %s.' % fontname
     return Font(fontname)
 
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/gradient.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/gradient.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/gradient.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -24,114 +24,114 @@
 class Gradient:
 
     def __init__(self, duplicate = None):
-	pass
+        pass
 
     def ColorAt(self, pos):
-	pass
+        pass
 
     def Duplicate(self):
-	return self.__class__(duplicate = self)
+        return self.__class__(duplicate = self)
 
 
 class MultiGradient(Gradient):
 
     def __init__(self, colors = (), duplicate = None):
-	if duplicate is not None:
-	    self.colors = duplicate.colors[:]
-	else:
-	    if len(colors) < 2:
-		raise ValueError, 'at least 2 colors required'
-	    self.colors = colors
+        if duplicate is not None:
+            self.colors = duplicate.colors[:]
+        else:
+            if len(colors) < 2:
+                raise ValueError, 'at least 2 colors required'
+            self.colors = colors
 
     def StartColor(self):
-	return self.colors[0][-1]
+        return self.colors[0][-1]
 
     def SetStartColor(self, color):
-	undo = (self.SetStartColor, self.colors[0][-1])
-	self.colors[0] = (0, color)
-	return undo
+        undo = (self.SetStartColor, self.colors[0][-1])
+        self.colors[0] = (0, color)
+        return undo
 
     def EndColor(self):
-	return self.colors[-1][-1]
+        return self.colors[-1][-1]
 
     def SetEndColor(self, color):
-	undo = (self.SetEndColor, self.colors[-1][-1])
-	self.colors[-1] = (1, color)
-	return undo
+        undo = (self.SetEndColor, self.colors[-1][-1])
+        self.colors[-1] = (1, color)
+        return undo
 
     def ColorAt(self, pos):
-	colors = self.colors
-	for i in range(len(colors) - 1):
-	    if colors[i][0] <= pos and colors[i + 1][0] >= pos:
-		break
-	else:
-	    return self.EndColor()
-	start_pos, start_color = colors[i]
-	if i < len(colors) - 1:
-	    end_pos, end_color = colors[i + 1]
-	else:
-	    return start_color
-	return Blend(end_color, start_color,
-		     (pos - start_pos) / float(end_pos - start_pos))
+        colors = self.colors
+        for i in range(len(colors) - 1):
+            if colors[i][0] <= pos and colors[i + 1][0] >= pos:
+                break
+        else:
+            return self.EndColor()
+        start_pos, start_color = colors[i]
+        if i < len(colors) - 1:
+            end_pos, end_color = colors[i + 1]
+        else:
+            return start_color
+        return Blend(end_color, start_color,
+                     (pos - start_pos) / float(end_pos - start_pos))
 
     def Sample(self, num):
-	colors = self.colors
-	max = num - 1.0
-	pos1, color1 = colors[0]
-	pos2, color2 = colors[1]
-	diff = float(pos2 - pos1)
-	cur = 1
-	result = []
-	blend = color1.Blend
-	for i in range(num):
-	    frac = i / max
-	    while frac > pos2:
-		pos1 = pos2; color1 = color2
-		cur = cur + 1
-		pos2, color2 = colors[cur]
-		diff = float(pos2 - pos1)
-		blend = color1.Blend
-	    frac = (frac - pos1) / diff
-	    result.append(blend(color2, 1 - frac, frac))
-	return result
+        colors = self.colors
+        max = num - 1.0
+        pos1, color1 = colors[0]
+        pos2, color2 = colors[1]
+        diff = float(pos2 - pos1)
+        cur = 1
+        result = []
+        blend = color1.Blend
+        for i in range(num):
+            frac = i / max
+            while frac > pos2:
+                pos1 = pos2; color1 = color2
+                cur = cur + 1
+                pos2, color2 = colors[cur]
+                diff = float(pos2 - pos1)
+                blend = color1.Blend
+            frac = (frac - pos1) / diff
+            result.append(blend(color2, 1 - frac, frac))
+        return result
 
     def Colors(self):
-	return self.colors
+        return self.colors
 
     def SetColors(self):
-	undo = (self.SetColors, self.colors)
-	self.colors = colors
-	return undo
+        undo = (self.SetColors, self.colors)
+        self.colors = colors
+        return undo
 
     def Blend(self, other, frac1, frac2):
-	if type(other) == type(self.colors[0][-1]):
-	    # blend a gradient with a single color
-	    sc = self.colors
-	    c = []
-	    for i in range(len(sc)):
-		p1, c1 = sc[i]
-		c.append((p1, c1.Blend(other, frac1, frac2)))
-	    return self.__class__(c)
-	elif other.__class__ == self.__class__:
-	    # blend two MultiGradient instances
-	    # XXX: improve this...
-	    length = min(len(self.colors), len(other.colors))
-	    sc = self.colors[:length - 1]
-	    sc.append(self.colors[-1])
-	    oc = other.colors[:length - 1]
-	    oc.append(other.colors[-1])
-	    c = []
-	    for i in range(length):
-		p1, c1 = sc[i]
-		p2, c2 = oc[i]
-		c.append((frac1 * p1 + frac2 * p2,
-			  Blend(c1, c2, frac1, frac2)))
-	    return self.__class__(c)
-	else:
-	    raise MismatchError
+        if type(other) == type(self.colors[0][-1]):
+            # blend a gradient with a single color
+            sc = self.colors
+            c = []
+            for i in range(len(sc)):
+                p1, c1 = sc[i]
+                c.append((p1, c1.Blend(other, frac1, frac2)))
+            return self.__class__(c)
+        elif other.__class__ == self.__class__:
+            # blend two MultiGradient instances
+            # XXX: improve this...
+            length = min(len(self.colors), len(other.colors))
+            sc = self.colors[:length - 1]
+            sc.append(self.colors[-1])
+            oc = other.colors[:length - 1]
+            oc.append(other.colors[-1])
+            c = []
+            for i in range(length):
+                p1, c1 = sc[i]
+                p2, c2 = oc[i]
+                c.append((frac1 * p1 + frac2 * p2,
+                          Blend(c1, c2, frac1, frac2)))
+            return self.__class__(c)
+        else:
+            raise MismatchError
 
     def SaveToFile(self, file):
-	file.Gradient(self.colors)
+        file.Gradient(self.colors)
 
 
 # convenience function for the most common gradient type

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/graphics.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/graphics.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/graphics.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -91,22 +91,22 @@
     line = defaultLineStyle
 
     def __init__(self):
-	self.orig_x = self.orig_y = 0.0
-	self.scale = 1.0
-	self.win_to_doc = self.doc_to_win = Identity
-	self.init_trafo_stack()
-	self.gc = None
-	self.outline_mode = 0
-	self.font = None
-	self.clip_region = None
-	self.clip_stack = None
-	self.proc_fill = 0
+        self.orig_x = self.orig_y = 0.0
+        self.scale = 1.0
+        self.win_to_doc = self.doc_to_win = Identity
+        self.init_trafo_stack()
+        self.gc = None
+        self.outline_mode = 0
+        self.font = None
+        self.clip_region = None
+        self.clip_stack = None
+        self.proc_fill = 0
 
     def init_gc(self, widget, **gcargs):
-	self.gc = widget.CreateGC(gcargs)
-	self.widget = widget
-	self.visual = color.skvisual
-	self.InitClip()
+        self.gc = widget.CreateGC(gcargs)
+        self.widget = widget
+        self.visual = color.skvisual
+        self.InitClip()
 
     #
     #	Clipping
@@ -138,111 +138,111 @@
 
 
     def InitClip(self):
-	# reset all clipping...
-	self.gc.SetClipMask(None)
-	self.clip_region = None
-	self.clip_stack = ()
+        # reset all clipping...
+        self.gc.SetClipMask(None)
+        self.clip_region = None
+        self.clip_stack = ()
 
     def IsClipping(self):
-	return self.clip_stack != ()
+        return self.clip_stack != ()
 
     def PushClip(self):
-	self.clip_stack = (self.clip_region, self.clip_stack)
+        self.clip_stack = (self.clip_region, self.clip_stack)
 
     def PopClip(self):
-	# Pop the old clip region from the clip stack and make it the
-	# active clip region.
-	self.clip_region, self.clip_stack = self.clip_stack
-	self.gc.SetClipMask(self.clip_region)
+        # Pop the old clip region from the clip stack and make it the
+        # active clip region.
+        self.clip_region, self.clip_stack = self.clip_stack
+        self.gc.SetClipMask(self.clip_region)
 
     def ClipRegion(self, region):
-	# Itersect the current clip region and REGION and make the
-	# result the new clip region. REGION may be a region object or a
-	# pixmap object of depth 1
-	self.clip_region = IntersectMasks(self.clip_region, region)
-	self.gc.SetClipMask(self.clip_region)
+        # Itersect the current clip region and REGION and make the
+        # result the new clip region. REGION may be a region object or a
+        # pixmap object of depth 1
+        self.clip_region = IntersectMasks(self.clip_region, region)
+        self.gc.SetClipMask(self.clip_region)
 
     def ClipRect(self, recttuple):
-	region = self.widget.CreateRegion()
-	apply(region.UnionRectWithRegion, recttuple)
-	self.ClipRegion(region)
+        region = self.widget.CreateRegion()
+        apply(region.UnionRectWithRegion, recttuple)
+        self.ClipRegion(region)
 
     def ClipPolygon(self, pts):
-	self.ClipRegion(self.widget.PolygonRegion(pts))
+        self.ClipRegion(self.widget.PolygonRegion(pts))
 
     ClipBitmap = ClipRegion
 
     def create_clip_bitmap(self):
-	width = self.widget.width
-	height = self.widget.height
-	bitmap = self.widget.CreatePixmap(width, height, 1)
-	bitmap_gc = bitmap.CreateGC(foreground = 0)
-	bitmap_gc.FillRectangle(0, 0, width, height)
-	bitmap_gc.foreground = 1
-	return (bitmap, bitmap_gc)
+        width = self.widget.width
+        height = self.widget.height
+        bitmap = self.widget.CreatePixmap(width, height, 1)
+        bitmap_gc = bitmap.CreateGC(foreground = 0)
+        bitmap_gc.FillRectangle(0, 0, width, height)
+        bitmap_gc.foreground = 1
+        return (bitmap, bitmap_gc)
 
     #
     # Convert document coordinates to window coordinates and vice versa.
     #
 
     def DocToWin(self, *args):
-	# Return the point in window coords as a tuple of ints
-	return apply(self.doc_to_win.DocToWin, args)
+        # Return the point in window coords as a tuple of ints
+        return apply(self.doc_to_win.DocToWin, args)
 
     def DocToWinPoint(self, p):
-	# Return the point in window coords as a point object
-	return self.doc_to_win(p)
+        # Return the point in window coords as a point object
+        return self.doc_to_win(p)
 
     def LengthToWin(self, len):
-	return int(len * self.scale + 0.5)
+        return int(len * self.scale + 0.5)
 
     def LengthToWinFloat(self, len):
-	return len * self.scale
+        return len * self.scale
 
     def LengthToDoc(self, len):
-	return len / self.scale
+        return len / self.scale
 
     def WinToDoc(self, *args):
-	return apply(self.win_to_doc, args)
+        return apply(self.win_to_doc, args)
 
     def init_trafo_stack(self):
-	self.trafo_stack = ()
-	self.default_trafo = (self.win_to_doc, self.doc_to_win)
+        self.trafo_stack = ()
+        self.default_trafo = (self.win_to_doc, self.doc_to_win)
 
     def SetViewportTransform(self, scale, doc_to_win, win_to_doc):
-	self.scale = scale
-	self.doc_to_win = doc_to_win
-	self.win_to_doc = win_to_doc
-	self.init_trafo_stack()
+        self.scale = scale
+        self.doc_to_win = doc_to_win
+        self.win_to_doc = win_to_doc
+        self.init_trafo_stack()
 
     def InitTrafo():
-	self.win_to_doc, self.doc_to_win = self.default_trafo
-	self.trafo_stack = ()
+        self.win_to_doc, self.doc_to_win = self.default_trafo
+        self.trafo_stack = ()
 
     def PushTrafo(self):
-	self.trafo_stack = (self.win_to_doc, self.doc_to_win, self.trafo_stack)
+        self.trafo_stack = (self.win_to_doc, self.doc_to_win, self.trafo_stack)
 
     def Concat(self, trafo):
-	self.doc_to_win = self.doc_to_win(trafo)
-	try:
-	    self.win_to_doc = trafo.inverse()(self.win_to_doc)
-	except SingularMatrix:
-	    pass
+        self.doc_to_win = self.doc_to_win(trafo)
+        try:
+            self.win_to_doc = trafo.inverse()(self.win_to_doc)
+        except SingularMatrix:
+            pass
 
     def Translate(self, *args):
-	self.Concat(apply(Translation, args))
+        self.Concat(apply(Translation, args))
 
     def Scale(self, factor):
-	self.Concat(Scale(factor))
+        self.Concat(Scale(factor))
 
     def Rotate(self, angle):
-	self.Concat(Rotation(angle))
+        self.Concat(Rotation(angle))
 
     def PopTrafo(self):
-	self.win_to_doc, self.doc_to_win, self.trafo_stack = self.trafo_stack
+        self.win_to_doc, self.doc_to_win, self.trafo_stack = self.trafo_stack
 
     def WindowResized(self, width, height):
-	pass
+        pass
 
 
     #
@@ -250,15 +250,15 @@
     #
 
     def StartDblBuffer(self):
-	self.buffer_pixmap = self.widget.CreatePixmap()
-	self.gc.SetDrawable(self.buffer_pixmap)
+        self.buffer_pixmap = self.widget.CreatePixmap()
+        self.gc.SetDrawable(self.buffer_pixmap)
 
     def EndDblBuffer(self):
-	self.gc.SetDrawable(self.widget)
-	self.buffer_pixmap.CopyArea(self.widget, self.gc, 0, 0,
-				    self.widget.width, self.widget.height,
-				    0, 0)
-	self.buffer_pixmap = None
+        self.gc.SetDrawable(self.widget)
+        self.buffer_pixmap.CopyArea(self.widget, self.gc, 0, 0,
+                                    self.widget.width, self.widget.height,
+                                    0, 0)
+        self.buffer_pixmap = None
 
 
 class SimpleGC(GCDevice):
@@ -271,121 +271,121 @@
     #
 
     def __init__(self):
-	GCDevice.__init__(self)
-	self.current_color = StandardColors.black
+        GCDevice.__init__(self)
+        self.current_color = StandardColors.black
 
     def SetFillColor(self, color):
-	self.current_color = color
-	self.gc.SetForegroundAndFill(self.visual.get_pixel(color))
+        self.current_color = color
+        self.gc.SetForegroundAndFill(self.visual.get_pixel(color))
 
     def SetLineColor(self, color):
-	self.current_color = color
-	self.gc.SetForegroundAndFill(self.visual.get_pixel(color))
+        self.current_color = color
+        self.gc.SetForegroundAndFill(self.visual.get_pixel(color))
 
 
     def SetLineAttributes(self, width, cap = X.CapButt, join = X.JoinMiter,
-			  dashes = None):
-	if dashes:
-	    line = X.LineOnOffDash
-	else:
-	    line = X.LineSolid
-	self.gc.SetLineAttributes(int(round(width * self.scale)), line, cap,
+                          dashes = None):
+        if dashes:
+            line = X.LineOnOffDash
+        else:
+            line = X.LineSolid
+        self.gc.SetLineAttributes(int(round(width * self.scale)), line, cap,
                                   join)
-	if dashes:
-	    if width < 1.0:
-		scale = self.scale
-	    else:
-		scale = width * self.scale
-	    dashes = map(operator.mul, dashes, [scale] * len(dashes))
-	    dashes = map(int, map(round, dashes))
-	    for idx in range(len(dashes)):
-		length = dashes[idx]
-		if length <= 0:
-		    dashes[idx] = 1
-		elif length > 255:
-		    dashes[idx] = 255
-	    self.gc.SetDashes(dashes)
+        if dashes:
+            if width < 1.0:
+                scale = self.scale
+            else:
+                scale = width * self.scale
+            dashes = map(operator.mul, dashes, [scale] * len(dashes))
+            dashes = map(int, map(round, dashes))
+            for idx in range(len(dashes)):
+                length = dashes[idx]
+                if length <= 0:
+                    dashes[idx] = 1
+                elif length > 255:
+                    dashes[idx] = 255
+            self.gc.SetDashes(dashes)
 
     def SetLineSolid(self):
-	self.gc.line_style = X.LineSolid
+        self.gc.line_style = X.LineSolid
 
     def DrawLine(self, start, end):
-	startx, starty	= self.DocToWin(start)
-	endx,	endy	= self.DocToWin(end)
-	self.gc.DrawLine(startx, starty, endx, endy)
+        startx, starty	= self.DocToWin(start)
+        endx,	endy	= self.DocToWin(end)
+        self.gc.DrawLine(startx, starty, endx, endy)
 
     def DrawLineXY(self, x1, y1, x2, y2):
-	startx, starty	= self.DocToWin(x1, y1)
-	endx,	endy	= self.DocToWin(x2, y2)
-	self.gc.DrawLine(startx, starty, endx, endy)
+        startx, starty	= self.DocToWin(x1, y1)
+        endx,	endy	= self.DocToWin(x2, y2)
+        self.gc.DrawLine(startx, starty, endx, endy)
 
     def DrawLines(self, pts):
-	pts = map(self.DocToWin, pts)
-	self.gc.DrawLines(pts, X.CoordModeOrigin)
+        pts = map(self.DocToWin, pts)
+        self.gc.DrawLines(pts, X.CoordModeOrigin)
 
     def FillPolygon(self, pts):
-	pts = map(self.DocToWin, pts)
-	self.gc.FillPolygon(pts, X.Complex, X.CoordModeOrigin)
+        pts = map(self.DocToWin, pts)
+        self.gc.FillPolygon(pts, X.Complex, X.CoordModeOrigin)
 
     def DrawRectangle(self, start, end):
-	# draw the outline of the rectangle whose opposite corners are
-	# start and end.
-	pts = TransformRectangle(self.doc_to_win, Rect(start, end))
-	if type(pts) == TupleType:
-	    apply(self.gc.DrawRectangle, pts)
-	else:
-	    self.gc.DrawLines(pts, X.CoordModeOrigin)
+        # draw the outline of the rectangle whose opposite corners are
+        # start and end.
+        pts = TransformRectangle(self.doc_to_win, Rect(start, end))
+        if type(pts) == TupleType:
+            apply(self.gc.DrawRectangle, pts)
+        else:
+            self.gc.DrawLines(pts, X.CoordModeOrigin)
 
     def FillRectangle(self, left, top, right, bottom):
-	pts = TransformRectangle(self.doc_to_win,
-				 Rect(left, top, right, bottom))
-	if type(pts) == TupleType:
-	    apply(self.gc.FillRectangle, pts)
-	else:
-	    self.gc.FillPolygon(pts, X.Convex, X.CoordModeOrigin)
+        pts = TransformRectangle(self.doc_to_win,
+                                 Rect(left, top, right, bottom))
+        if type(pts) == TupleType:
+            apply(self.gc.FillRectangle, pts)
+        else:
+            self.gc.FillPolygon(pts, X.Convex, X.CoordModeOrigin)
 
     def DrawEllipse(self, start, end):
-	pts = TransformRectangle(self.doc_to_win, Rect(start, end))
+        pts = TransformRectangle(self.doc_to_win, Rect(start, end))
 
-	if type(pts) == TupleType:
-	    apply(self.gc.DrawArc, pts + (0, 360 * 64))
-	else:
-	    d = end - start
-	    self.PushTrafo()
-	    self.Concat(Trafo(d.x, 0, 0, d.y, start.x, start.y))
-	    self.DrawBezierPath(circle_path)
-	    self.PopTrafo()
+        if type(pts) == TupleType:
+            apply(self.gc.DrawArc, pts + (0, 360 * 64))
+        else:
+            d = end - start
+            self.PushTrafo()
+            self.Concat(Trafo(d.x, 0, 0, d.y, start.x, start.y))
+            self.DrawBezierPath(circle_path)
+            self.PopTrafo()
 
     def DrawCircle(self, center, radius):
-	rect = Rect(center.x - radius, center.y - radius,
-		    center.x + radius, center.y + radius)
-	pts = TransformRectangle(self.doc_to_win, rect)
-	if type(pts) == TupleType:
-	    apply(self.gc.DrawArc, pts + (0, 360 * 64))
-	else:
-	    self.PushTrafo()
-	    self.Concat(Trafo(radius, 0, 0, radius, center.x, center.y))
-	    self.DrawBezierPath(circle_path)
-	    self.PopTrafo()
+        rect = Rect(center.x - radius, center.y - radius,
+                    center.x + radius, center.y + radius)
+        pts = TransformRectangle(self.doc_to_win, rect)
+        if type(pts) == TupleType:
+            apply(self.gc.DrawArc, pts + (0, 360 * 64))
+        else:
+            self.PushTrafo()
+            self.Concat(Trafo(radius, 0, 0, radius, center.x, center.y))
+            self.DrawBezierPath(circle_path)
+            self.PopTrafo()
 
     def FillCircle(self, center, radius):
-	rect = Rect(center.x - radius, center.y - radius,
-		    center.x + radius, center.y + radius)
-	pts = TransformRectangle(self.doc_to_win, rect)
-	if type(pts) == TupleType:
-	    apply(self.gc.FillArc, pts + (0, 360 * 64))
-	else:
-	    self.PushTrafo()
-	    self.Concat(Trafo(radius, 0, 0, radius, center.x, center.y))
-	    self.FillBezierPath(circle_path)
-	    self.PopTrafo()
+        rect = Rect(center.x - radius, center.y - radius,
+                    center.x + radius, center.y + radius)
+        pts = TransformRectangle(self.doc_to_win, rect)
+        if type(pts) == TupleType:
+            apply(self.gc.FillArc, pts + (0, 360 * 64))
+        else:
+            self.PushTrafo()
+            self.Concat(Trafo(radius, 0, 0, radius, center.x, center.y))
+            self.FillBezierPath(circle_path)
+            self.PopTrafo()
 
 
     def DrawBezierPath(self, path, rect = None):
-	path.draw_transformed(self.gc, self.doc_to_win, 1, 0, rect)
+        path.draw_transformed(self.gc, self.doc_to_win, 1, 0, rect)
 
     def FillBezierPath(self, path, rect = None):
-	path.draw_transformed(self.gc, self.doc_to_win, 0, 1, rect)
+        path.draw_transformed(self.gc, self.doc_to_win, 0, 1, rect)
 
 
 
@@ -394,61 +394,61 @@
     # some methods common to GraphicsDevice and PostScriptDevice
 
     def draw_arrow(self, arrow, width, pos, dir, rect = None):
-	self.PushTrafo()
-	self.Translate(pos.x, pos.y)
-	self.Rotate(dir.polar()[1])
-	if width >= 1.0:
-	    self.Scale(width)
-	self.SetLineSolid()
-	arrow.Draw(self) #, rect)
-	self.PopTrafo()
+        self.PushTrafo()
+        self.Translate(pos.x, pos.y)
+        self.Rotate(dir.polar()[1])
+        if width >= 1.0:
+            self.Scale(width)
+        self.SetLineSolid()
+        arrow.Draw(self) #, rect)
+        self.PopTrafo()
 
     def draw_arrows(self, paths, rect = None):
-	if self.line:
-	    arrow1 = self.properties.line_arrow1
-	    arrow2 = self.properties.line_arrow2
-	    if arrow1 or arrow2:
-		width = self.properties.line_width
-		for path in paths:
-		    if not path.closed and path.len > 1:
-			if arrow1:
-			    type, controls, p3, cont = path.Segment(1)
-			    p = path.Node(0)
-			    if type == _sketch.Bezier:
-				p1, p2 = controls
-				dir = p - p1
-				if not abs(dir):
-				    dir = p - p2
-			    else:
-				dir = p - p3
-			    self.draw_arrow(arrow1, width, p, dir, rect)
-			if arrow2:
-			    type, controls, p, cont = path.Segment(-1)
-			    p3 = path.Node(-2)
-			    if type == _sketch.Bezier:
-				p1, p2 = controls
-				dir = p - p2
-				if not abs(dir):
-				    dir = p - p1
-			    else:
-				dir = p - p3
-			    self.draw_arrow(arrow2, width, p, dir, rect)
+        if self.line:
+            arrow1 = self.properties.line_arrow1
+            arrow2 = self.properties.line_arrow2
+            if arrow1 or arrow2:
+                width = self.properties.line_width
+                for path in paths:
+                    if not path.closed and path.len > 1:
+                        if arrow1:
+                            type, controls, p3, cont = path.Segment(1)
+                            p = path.Node(0)
+                            if type == _sketch.Bezier:
+                                p1, p2 = controls
+                                dir = p - p1
+                                if not abs(dir):
+                                    dir = p - p2
+                            else:
+                                dir = p - p3
+                            self.draw_arrow(arrow1, width, p, dir, rect)
+                        if arrow2:
+                            type, controls, p, cont = path.Segment(-1)
+                            p3 = path.Node(-2)
+                            if type == _sketch.Bezier:
+                                p1, p2 = controls
+                                dir = p - p2
+                                if not abs(dir):
+                                    dir = p - p1
+                            else:
+                                dir = p - p3
+                            self.draw_arrow(arrow2, width, p, dir, rect)
 
     def draw_ellipse_arrows(self, trafo, start_angle, end_angle, arc_type,
-			    rect = None):
-	if arc_type == const.ArcArc and self.line and start_angle != end_angle:
-	    pi2 = pi / 2
-	    width = self.properties.line_width
-	    arrow1 = self.properties.line_arrow1
-	    if arrow1 is not None:
-		pos = trafo(Polar(1, start_angle))
-		dir = trafo.DTransform(Polar(1, start_angle - pi2))
-		self.draw_arrow(arrow1, width, pos, dir, rect)
-	    arrow2 = self.properties.line_arrow2
-	    if arrow2 is not None:
-		pos = trafo(Polar(1, end_angle))
-		dir = trafo.DTransform(Polar(1, end_angle + pi2))
-		self.draw_arrow(arrow2, width, pos, dir, rect)
+                            rect = None):
+        if arc_type == const.ArcArc and self.line and start_angle != end_angle:
+            pi2 = pi / 2
+            width = self.properties.line_width
+            arrow1 = self.properties.line_arrow1
+            if arrow1 is not None:
+                pos = trafo(Polar(1, start_angle))
+                dir = trafo.DTransform(Polar(1, start_angle - pi2))
+                self.draw_arrow(arrow1, width, pos, dir, rect)
+            arrow2 = self.properties.line_arrow2
+            if arrow2 is not None:
+                pos = trafo(Polar(1, end_angle))
+                dir = trafo.DTransform(Polar(1, end_angle + pi2))
+                self.draw_arrow(arrow2, width, pos, dir, rect)
 
 use_shm_images = 0
 shm_images_supported = 0
@@ -474,180 +474,180 @@
     draw_printable = 0
 
     def __init__(self):
-	SimpleGC.__init__(self)
-	self.line = 0
-	self.fill = 0
-	self.properties = PropertyStack()
-	self.gradient_steps = config.preferences.gradient_steps_editor
-	self.images_drawn = 0
-	self.unknown_fonts = {}
+        SimpleGC.__init__(self)
+        self.line = 0
+        self.fill = 0
+        self.properties = PropertyStack()
+        self.gradient_steps = config.preferences.gradient_steps_editor
+        self.images_drawn = 0
+        self.unknown_fonts = {}
         self.failed_fonts = {}
 
     def InitClip(self):
-	SimpleGC.InitClip(self)
-	self.images_drawn = 0
+        SimpleGC.InitClip(self)
+        self.images_drawn = 0
 
 
     proc_fill = proc_line = 0
     fill_rect = None
 
     def set_properties(self, properties):
-	self.properties = properties
-	if properties.HasFill():
-	    self.fill = 1
-	    self.proc_fill = properties.IsAlgorithmicFill()
-	else:
-	    self.fill = 0
-	    self.proc_fill = 0
-	if properties.HasLine():
-	    self.line = 1
-	    self.proc_line = properties.IsAlgorithmicLine()
-	else:
-	    self.line = 0
-	    self.proc_line = 0
+        self.properties = properties
+        if properties.HasFill():
+            self.fill = 1
+            self.proc_fill = properties.IsAlgorithmicFill()
+        else:
+            self.fill = 0
+            self.proc_fill = 0
+        if properties.HasLine():
+            self.line = 1
+            self.proc_line = properties.IsAlgorithmicLine()
+        else:
+            self.line = 0
+            self.proc_line = 0
 
 
     def SetProperties(self, properties, rect = None):
-	if not self.outline_mode:
-	    self.fill_rect = rect
-	    self.set_properties(properties)
-	else:
-	    # if outline, set only font properties
-	    self.properties.SetProperty(font = properties.font,
-					 font_size = properties.font_size)
+        if not self.outline_mode:
+            self.fill_rect = rect
+            self.set_properties(properties)
+        else:
+            # if outline, set only font properties
+            self.properties.SetProperty(font = properties.font,
+                                        font_size = properties.font_size)
 
     #
     def activate_line(self):
-	self.properties.ExecuteLine(self)
+        self.properties.ExecuteLine(self)
 
     def activate_fill(self):
-	self.properties.ExecuteFill(self, self.fill_rect)
+        self.properties.ExecuteFill(self, self.fill_rect)
 
     #
     #	Patterns
     #
 
     def get_pattern_image(self):
-	width = self.widget.width
-	height = self.widget.height
-	winrect = self.doc_to_win(self.fill_rect)
-	left, top, right, bottom = map(int, map(round, winrect))
-	l = max(left, 0);	r = min(right, width);
-	t = max(top, 0);	b = min(bottom, height);
-	if type(self.clip_region) == PaxRegionType:
-	    cx, cy, cw, ch = self.clip_region.ClipBox()
-	    l = max(l, cx);	r = min(r, cx + cw)
-	    t = max(t, cy);	b = min(b, cy + ch)
-	if l >= r or t >= b:
-	    return None, None, None
-	image = PIL.Image.new('RGB', (r - l, b - t), (255, 255, 255))
-	trafo = Translation(-l, -t)(self.doc_to_win)
-	return image, trafo, (l, t)
+        width = self.widget.width
+        height = self.widget.height
+        winrect = self.doc_to_win(self.fill_rect)
+        left, top, right, bottom = map(int, map(round, winrect))
+        l = max(left, 0);	r = min(right, width);
+        t = max(top, 0);	b = min(bottom, height);
+        if type(self.clip_region) == PaxRegionType:
+            cx, cy, cw, ch = self.clip_region.ClipBox()
+            l = max(l, cx);	r = min(r, cx + cw)
+            t = max(t, cy);	b = min(b, cy + ch)
+        if l >= r or t >= b:
+            return None, None, None
+        image = PIL.Image.new('RGB', (r - l, b - t), (255, 255, 255))
+        trafo = Translation(-l, -t)(self.doc_to_win)
+        return image, trafo, (l, t)
 
     def draw_pattern_image(self, image, pos):
-	if use_shm_images and self.images_drawn:
-	    # force a shmimage to be drawn if ShmPutImage requests might
-	    # be in the queue
-	    self.widget.Sync()
-	self.create_ximage()
-	ximage = self.ximage
-	x, y = pos
-	w, h = image.size
-	_sketch.copy_image_to_ximage(self.visual, image.im, ximage, x, y, w, h)
-	if use_shm_images:
-	    self.gc.ShmPutImage(ximage, x, y, x, y, w, h, 0)
-	    self.images_drawn = 1
-	else:
-	    self.gc.PutImage(ximage, x, y, x, y, w, h)
+        if use_shm_images and self.images_drawn:
+            # force a shmimage to be drawn if ShmPutImage requests might
+            # be in the queue
+            self.widget.Sync()
+        self.create_ximage()
+        ximage = self.ximage
+        x, y = pos
+        w, h = image.size
+        _sketch.copy_image_to_ximage(self.visual, image.im, ximage, x, y, w, h)
+        if use_shm_images:
+            self.gc.ShmPutImage(ximage, x, y, x, y, w, h, 0)
+            self.images_drawn = 1
+        else:
+            self.gc.PutImage(ximage, x, y, x, y, w, h)
 
     has_axial_gradient = 1
     def AxialGradient(self, gradient, p0, p1):
-	# p0 and p1 may be PointSpecs
-	image, trafo, pos = self.get_pattern_image()
-	if image is None:
-	    return
-	x0, y0 = trafo(p0)
-	x1, y1 = trafo(p1)
-	#import time
-	#_t = time.clock()
-	_sketch.fill_axial_gradient(image.im, gradient.Colors(), x0,y0, x1,y1)
-	#_t = time.clock() - _t
-	#print 'axial:', _t
-	self.draw_pattern_image(image, pos)
+        # p0 and p1 may be PointSpecs
+        image, trafo, pos = self.get_pattern_image()
+        if image is None:
+            return
+        x0, y0 = trafo(p0)
+        x1, y1 = trafo(p1)
+        #import time
+        #_t = time.clock()
+        _sketch.fill_axial_gradient(image.im, gradient.Colors(), x0,y0, x1,y1)
+        #_t = time.clock() - _t
+        #print 'axial:', _t
+        self.draw_pattern_image(image, pos)
 
     has_radial_gradient = 1
     def RadialGradient(self, gradient, p, r0, r1):
-	# p may be PointSpec
-	image, trafo, pos = self.get_pattern_image()
-	if image is None:
-	    return
-	x, y = trafo.DocToWin(p)
-	r0 = int(round(abs(trafo.DTransform(r0, 0))))
-	r1 = int(round(abs(trafo.DTransform(r1, 0))))
-	#import time
-	#_t = time.clock()
-	_sketch.fill_radial_gradient(image.im, gradient.Colors(), x, y, r0, r1)
-	#_t = time.clock() - _t
-	#print 'radial:', _t
-	self.draw_pattern_image(image, pos)
+        # p may be PointSpec
+        image, trafo, pos = self.get_pattern_image()
+        if image is None:
+            return
+        x, y = trafo.DocToWin(p)
+        r0 = int(round(abs(trafo.DTransform(r0, 0))))
+        r1 = int(round(abs(trafo.DTransform(r1, 0))))
+        #import time
+        #_t = time.clock()
+        _sketch.fill_radial_gradient(image.im, gradient.Colors(), x, y, r0, r1)
+        #_t = time.clock() - _t
+        #print 'radial:', _t
+        self.draw_pattern_image(image, pos)
 
 
     has_conical_gradient = 1
     def ConicalGradient(self, gradient, p, angle):
-	# p may be PointSpec
-	image, trafo, pos = self.get_pattern_image()
-	if image is None:
-	    return
-	cx, cy = trafo.DocToWin(p)
-	#import time
-	#_t = time.clock()
-	_sketch.fill_conical_gradient(image.im, gradient.Colors(), cx, cy,
-				      -angle)
-	#_t = time.clock() - _t
-	#print 'conical:', _t
-	self.draw_pattern_image(image, pos)
+        # p may be PointSpec
+        image, trafo, pos = self.get_pattern_image()
+        if image is None:
+            return
+        cx, cy = trafo.DocToWin(p)
+        #import time
+        #_t = time.clock()
+        _sketch.fill_conical_gradient(image.im, gradient.Colors(), cx, cy,
+                                      -angle)
+        #_t = time.clock() - _t
+        #print 'conical:', _t
+        self.draw_pattern_image(image, pos)
 
     use_pixmap_tile = 1
     def TileImage(self, tile, trafo):
-	# XXX this could be faster with some caching.
+        # XXX this could be faster with some caching.
         width, height = self.doc_to_win(trafo).DTransform(tile.size)
         width = int(round(width))
         height = int(round(height))
-	if self.use_pixmap_tile and trafo.m12 == 0 and trafo.m21 == 0 \
+        if self.use_pixmap_tile and trafo.m12 == 0 and trafo.m21 == 0 \
            and width * height < self.widget.width * self.widget.height:
-	    # the image is only scaled. Use a tile pixmap
-	    #
-	    # there are other cases where this could be done:
-	    # horizontal/vertical shearing, rotation by 90 degrees,...
-	    # This should also be done like in DrawImage, i.e. use the
-	    # integer coordintes of the transformed tile to determine if
-	    # pixmaps can be used. This would be a little less precise,
-	    # though.
-	    # degenerate cases
-	    if width == 0: width = 1
-	    if height == 0: height = 1
-	    ximage = self.create_sized_ximage(abs(width), abs(height))
-	    pixmap = self.widget.CreatePixmap(abs(width), abs(height),
-					      ximage.depth)
-	    _sketch.copy_image_to_ximage(self.visual, tile.im, ximage,
-					 0, 0, width, height)
-	    gc = pixmap.CreateGC()
-	    gc.PutImage(ximage, 0, 0, 0, 0, abs(width), abs(height))
-	    self.gc.SetForegroundAndFill(pixmap)
-	    x, y = trafo.DocToWin(0, 0)
-	    self.gc.SetTSOrigin(x, y)
-	    self.gc.FillRectangle(0, 0, self.widget.width, self.widget.height)
-	else:
-	    image, temp_trafo, pos = self.get_pattern_image()
-	    if image is None:
-		return
-	    trafo = temp_trafo(trafo)
-	    try:
-		_sketch.fill_transformed_tile(image.im, tile.im,
-					      trafo.inverse())
-		self.draw_pattern_image(image, pos)
-	    except SingularMatrix:
-		pass
+            # the image is only scaled. Use a tile pixmap
+            #
+            # there are other cases where this could be done:
+            # horizontal/vertical shearing, rotation by 90 degrees,...
+            # This should also be done like in DrawImage, i.e. use the
+            # integer coordintes of the transformed tile to determine if
+            # pixmaps can be used. This would be a little less precise,
+            # though.
+            # degenerate cases
+            if width == 0: width = 1
+            if height == 0: height = 1
+            ximage = self.create_sized_ximage(abs(width), abs(height))
+            pixmap = self.widget.CreatePixmap(abs(width), abs(height),
+                                              ximage.depth)
+            _sketch.copy_image_to_ximage(self.visual, tile.im, ximage,
+                                         0, 0, width, height)
+            gc = pixmap.CreateGC()
+            gc.PutImage(ximage, 0, 0, 0, 0, abs(width), abs(height))
+            self.gc.SetForegroundAndFill(pixmap)
+            x, y = trafo.DocToWin(0, 0)
+            self.gc.SetTSOrigin(x, y)
+            self.gc.FillRectangle(0, 0, self.widget.width, self.widget.height)
+        else:
+            image, temp_trafo, pos = self.get_pattern_image()
+            if image is None:
+                return
+            trafo = temp_trafo(trafo)
+            try:
+                _sketch.fill_transformed_tile(image.im, tile.im,
+                                              trafo.inverse())
+                self.draw_pattern_image(image, pos)
+            except SingularMatrix:
+                pass
 
 
     #
@@ -667,23 +667,23 @@
     allow_outline = 1
 
     def StartOutlineMode(self, color = None):
-	if self.allow_outline:
-	    self.outline_mode = (self.properties, self.outline_mode)
-	    if color is None:
-		properties = self.outline_style
-	    else:
-		properties = PropertyStack()
+        if self.allow_outline:
+            self.outline_mode = (self.properties, self.outline_mode)
+            if color is None:
+                properties = self.outline_style
+            else:
+                properties = PropertyStack()
                 properties.SetProperty(fill_pattern = EmptyPattern)
-		properties.AddStyle(SolidLine(color))
-	    self.set_properties(properties)
+                properties.AddStyle(SolidLine(color))
+            self.set_properties(properties)
 
     def EndOutlineMode(self):
-	if self.allow_outline and self.outline_mode:
-	    properties, self.outline_mode = self.outline_mode
-	    self.set_properties(properties)
+        if self.allow_outline and self.outline_mode:
+            properties, self.outline_mode = self.outline_mode
+            self.set_properties(properties)
 
     def IsOutlineActive(self):
-	return not not self.outline_mode
+        return not not self.outline_mode
 
 
     #
@@ -691,233 +691,233 @@
     #
 
     def Rectangle(self, trafo, clip = 0):
-	self.PushTrafo()
-	self.Concat(trafo)
-	pts = TransformRectangle(self.doc_to_win, UnitRect)
-	self.PopTrafo()
-	if type(pts) == TupleType:
-	    if self.proc_fill:
-		if not clip:
-		    self.PushClip()
-		self.ClipRect(pts)
-		self.properties.ExecuteFill(self, self.fill_rect)
-		if not clip:
-		    self.PopClip()
-		clip = 0
-	    elif self.fill:
-		self.properties.ExecuteFill(self, self.fill_rect)
-		apply(self.gc.FillRectangle, pts)
-	    if self.line:
-		self.properties.ExecuteLine(self)
-		apply(self.gc.DrawRectangle, pts)
-	else:
-	    if self.proc_fill:
-		if not clip:
-		    self.PushClip()
-		self.ClipPolygon(pts)
-		self.properties.ExecuteFill(self, self.fill_rect)
-		if not clip:
-		    self.PopClip()
-		clip = 0
-	    elif self.fill:
-		self.properties.ExecuteFill(self, self.fill_rect)
-		self.gc.FillPolygon(pts, X.Convex, X.CoordModeOrigin)
-	    if self.line:
-		self.properties.ExecuteLine(self)
-		self.gc.DrawLines(pts, X.CoordModeOrigin)
-	if clip:
-	    if type(pts) == TupleType:
-		self.ClipRect(pts)
-	    else:
-		self.ClipPolygon(pts)
+        self.PushTrafo()
+        self.Concat(trafo)
+        pts = TransformRectangle(self.doc_to_win, UnitRect)
+        self.PopTrafo()
+        if type(pts) == TupleType:
+            if self.proc_fill:
+                if not clip:
+                    self.PushClip()
+                self.ClipRect(pts)
+                self.properties.ExecuteFill(self, self.fill_rect)
+                if not clip:
+                    self.PopClip()
+                clip = 0
+            elif self.fill:
+                self.properties.ExecuteFill(self, self.fill_rect)
+                apply(self.gc.FillRectangle, pts)
+            if self.line:
+                self.properties.ExecuteLine(self)
+                apply(self.gc.DrawRectangle, pts)
+        else:
+            if self.proc_fill:
+                if not clip:
+                    self.PushClip()
+                self.ClipPolygon(pts)
+                self.properties.ExecuteFill(self, self.fill_rect)
+                if not clip:
+                    self.PopClip()
+                clip = 0
+            elif self.fill:
+                self.properties.ExecuteFill(self, self.fill_rect)
+                self.gc.FillPolygon(pts, X.Convex, X.CoordModeOrigin)
+            if self.line:
+                self.properties.ExecuteLine(self)
+                self.gc.DrawLines(pts, X.CoordModeOrigin)
+        if clip:
+            if type(pts) == TupleType:
+                self.ClipRect(pts)
+            else:
+                self.ClipPolygon(pts)
 
     def RoundedRectangle(self, trafo, radius1, radius2, clip = 0):
-	path = _sketch.RoundedRectanglePath(trafo, radius1, radius2)
-	self.MultiBezier((path,), None, clip)
+        path = _sketch.RoundedRectanglePath(trafo, radius1, radius2)
+        self.MultiBezier((path,), None, clip)
 
     def SimpleEllipse(self, trafo, start_angle, end_angle, arc_type,
-		      rect = None, clip = 0):
-	trafo2 = self.doc_to_win(trafo)
-	if trafo2.m12 == 0.0 and trafo2.m21 == 0.0 and not self.proc_fill \
-	   and start_angle == end_angle and not clip:
-	    x1, y1 = trafo2.DocToWin(1, 1)
-	    x2, y2 = trafo2.DocToWin(-1, -1)
-	    if x1 > x2:
-		t = x1; x1 = x2; x2 = t
-	    if y1 > y2:
-		t = y1; y1 = y2; y2 = t
-	    w = x2 - x1
-	    h = y2 - y1
-	    if self.fill:
-		self.properties.ExecuteFill(self, self.fill_rect)
-		self.gc.FillArc(x1, y1, w, h, 0, 23040) # 360 * 64
-	    if self.line:
-		self.properties.ExecuteLine(self)
-		self.gc.DrawArc(x1, y1, w, h, 0, 23040)
-	else:
-	    if self.line:
-		line = self.activate_line
-	    else:
-		line = None
-	    if self.fill:
-		fill = self.activate_fill
-	    else:
-		fill = None
+                      rect = None, clip = 0):
+        trafo2 = self.doc_to_win(trafo)
+        if trafo2.m12 == 0.0 and trafo2.m21 == 0.0 and not self.proc_fill \
+           and start_angle == end_angle and not clip:
+            x1, y1 = trafo2.DocToWin(1, 1)
+            x2, y2 = trafo2.DocToWin(-1, -1)
+            if x1 > x2:
+                t = x1; x1 = x2; x2 = t
+            if y1 > y2:
+                t = y1; y1 = y2; y2 = t
+            w = x2 - x1
+            h = y2 - y1
+            if self.fill:
+                self.properties.ExecuteFill(self, self.fill_rect)
+                self.gc.FillArc(x1, y1, w, h, 0, 23040) # 360 * 64
+            if self.line:
+                self.properties.ExecuteLine(self)
+                self.gc.DrawArc(x1, y1, w, h, 0, 23040)
+        else:
+            if self.line:
+                line = self.activate_line
+            else:
+                line = None
+            if self.fill:
+                fill = self.activate_fill
+            else:
+                fill = None
 
-	    if start_angle != end_angle:
-		arc = _sketch.approx_arc(start_angle, end_angle, arc_type)
-	    else:
-		arc = circle_path
-	    # pass rect as None, because trafo2 is not really the
-	    # viewport transformation
-	    _sketch.draw_multipath(self.gc, trafo2, line, fill,
-				   self.PushClip, self.PopClip,
-				   self.ClipRegion, None, (arc,),
-				   CreateRegion(), self.proc_fill, clip)
-	    self.draw_ellipse_arrows(trafo, start_angle, end_angle, arc_type,
-				     rect)
+            if start_angle != end_angle:
+                arc = _sketch.approx_arc(start_angle, end_angle, arc_type)
+            else:
+                arc = circle_path
+            # pass rect as None, because trafo2 is not really the
+            # viewport transformation
+            _sketch.draw_multipath(self.gc, trafo2, line, fill,
+                                   self.PushClip, self.PopClip,
+                                   self.ClipRegion, None, (arc,),
+                                   CreateRegion(), self.proc_fill, clip)
+            self.draw_ellipse_arrows(trafo, start_angle, end_angle, arc_type,
+                                     rect)
 
 
     def MultiBezier(self, paths, rect = None, clip = 0):
-	if self.line:
-	    line = self.activate_line
-	else:
-	    line = None
-	if self.fill:
-	    fill = self.activate_fill
-	else:
-	    fill = None
+        if self.line:
+            line = self.activate_line
+        else:
+            line = None
+        if self.fill:
+            fill = self.activate_fill
+        else:
+            fill = None
 
-	_sketch.draw_multipath(self.gc, self.doc_to_win, line, fill,
-			       self.PushClip, self.PopClip, self.ClipRegion,
-			       rect, paths, CreateRegion(), self.proc_fill,
-			       clip)
+        _sketch.draw_multipath(self.gc, self.doc_to_win, line, fill,
+                               self.PushClip, self.PopClip, self.ClipRegion,
+                               rect, paths, CreateRegion(), self.proc_fill,
+                               clip)
 
-	if self.line:
-	    self.draw_arrows(paths, rect)
+        if self.line:
+            self.draw_arrows(paths, rect)
 
     def draw_text_on_gc(self, gc, text, trafo, font, font_size, cache = None):
-	self.PushTrafo()
-	try:
-	    self.Concat(trafo)
-	    self.Scale(font_size)
-	    up = self.doc_to_win.DTransform(0, 1)
-	    if abs(up) >= config.preferences.greek_threshold:
-		ptrafo = FlipY(self.doc_to_win)
-		xlfd = font.GetXLFD(ptrafo)
-		if (ptrafo and (ptrafo.m12 != 0 or ptrafo.m21 != 0
-				or ptrafo.m11 > 40 or ptrafo.m11 < 0
-				or ptrafo.m22 > 40 or ptrafo.m22 < 0)):
-		    xlfd = '%s[%s]' % (xlfd, _sketch.xlfd_char_range(text))
-		try:
-		    xfont = self.load_font(xlfd, cache)
-		except RuntimeError, val:
-		    # We must be careful here when reporting this to the
-		    # user. If warn pops up a message box and the user
-		    # clicks OK, the window gets another expose event
-		    # and sketch tries to draw the text again which will
-		    # also fail. To avoid infinite loops we try to
-		    # report unknown fonts only once for a given font.
-		    if not self.unknown_fonts.has_key(font.PostScriptName()):
-			warn(USER, _("Cannot load %(font)s:\n%(text)s"),
-			     font = `xlfd`, text = val)
-			self.unknown_fonts[font.PostScriptName()] = 1
-		    # Use a font that will hopefully be always available.
-		    # XXX Is there a better way to handle this situation?
-		    # We might try times roman with the same size and trafo
-		    xfont = self.load_font('fixed', None)
-		gc.SetFont(xfont)
+        self.PushTrafo()
+        try:
+            self.Concat(trafo)
+            self.Scale(font_size)
+            up = self.doc_to_win.DTransform(0, 1)
+            if abs(up) >= config.preferences.greek_threshold:
+                ptrafo = FlipY(self.doc_to_win)
+                xlfd = font.GetXLFD(ptrafo)
+                if (ptrafo and (ptrafo.m12 != 0 or ptrafo.m21 != 0
+                                or ptrafo.m11 > 40 or ptrafo.m11 < 0
+                                or ptrafo.m22 > 40 or ptrafo.m22 < 0)):
+                    xlfd = '%s[%s]' % (xlfd, _sketch.xlfd_char_range(text))
+                try:
+                    xfont = self.load_font(xlfd, cache)
+                except RuntimeError, val:
+                    # We must be careful here when reporting this to the
+                    # user. If warn pops up a message box and the user
+                    # clicks OK, the window gets another expose event
+                    # and sketch tries to draw the text again which will
+                    # also fail. To avoid infinite loops we try to
+                    # report unknown fonts only once for a given font.
+                    if not self.unknown_fonts.has_key(font.PostScriptName()):
+                        warn(USER, _("Cannot load %(font)s:\n%(text)s"),
+                             font = `xlfd`, text = val)
+                        self.unknown_fonts[font.PostScriptName()] = 1
+                    # Use a font that will hopefully be always available.
+                    # XXX Is there a better way to handle this situation?
+                    # We might try times roman with the same size and trafo
+                    xfont = self.load_font('fixed', None)
+                gc.SetFont(xfont)
 
-		pos = font.TypesetText(text)
-		pos = map(self.DocToWin, pos)
-		for i in range(len(text)):
-		    x, y = pos[i]
-		    gc.DrawString(x, y, text[i])
-	    else:
-		# 'greek'. XXX is this really necessary. It avoids
-		# rendering fonts that are too small to read.
-		pos = font.TypesetText(text)
-		pos = map(self.DocToWin, pos)
-		ux, uy = up
-		lx = ux / 2; ly = uy / 2
-		uppercase = string.uppercase
-		draw = gc.DrawLine # we should draw rectangles...
-		for i in range(len(text)):
-		    x, y = pos[i]
-		    if text[i] in uppercase:
-			draw(x, y, int(round(x + ux)), int(round(y + uy)))
-		    else:
-			draw(x, y, int(round(x + lx)), int(round(y + ly)))
-	finally:
-	    self.PopTrafo()
+                pos = font.TypesetText(text)
+                pos = map(self.DocToWin, pos)
+                for i in range(len(text)):
+                    x, y = pos[i]
+                    gc.DrawString(x, y, text[i])
+            else:
+                # 'greek'. XXX is this really necessary. It avoids
+                # rendering fonts that are too small to read.
+                pos = font.TypesetText(text)
+                pos = map(self.DocToWin, pos)
+                ux, uy = up
+                lx = ux / 2; ly = uy / 2
+                uppercase = string.uppercase
+                draw = gc.DrawLine # we should draw rectangles...
+                for i in range(len(text)):
+                    x, y = pos[i]
+                    if text[i] in uppercase:
+                        draw(x, y, int(round(x + ux)), int(round(y + uy)))
+                    else:
+                        draw(x, y, int(round(x + lx)), int(round(y + ly)))
+        finally:
+            self.PopTrafo()
 
     def DrawText(self, text, trafo = None, clip = 0, cache = None):
-	if text and self.properties.font:
-	    if self.fill or clip:
-		if self.proc_fill or clip:
-		    bitmap, bitmapgc = self.create_clip_bitmap()
-		    self.draw_text_on_gc(bitmapgc, text, trafo,
-					 self.properties.font,
-					 self.properties.font_size,
-					 cache)
-		    if not clip:
-			self.PushClip()
-		    self.ClipBitmap(bitmap)
-		    self.properties.ExecuteFill(self, self.fill_rect)
-		    if not self.proc_fill:
-			w, h = bitmap.GetGeometry()[3:5]
-			bitmap.CopyPlane(self.widget, self.gc, 0, 0, w, h,
-					 0, 0, 1)
-		    if not clip:
-			self.PopClip()
-		else:
-		    self.properties.ExecuteFill(self)
-		    self.draw_text_on_gc(self.gc, text, trafo,
-					 self.properties.font,
-					 self.properties.font_size,
-					 cache)
-	    elif self.IsOutlineActive():
-		# in outline mode, draw text filled with the current
-		# outline color, because we can't draw outlined text at
-		# the moment. We could draw a rectangle, though. (?)
-		self.properties.ExecuteLine(self)
-		self.draw_text_on_gc(self.gc, text, trafo,
-				     self.properties.font,
-				     self.properties.font_size,
-				     cache)
+        if text and self.properties.font:
+            if self.fill or clip:
+                if self.proc_fill or clip:
+                    bitmap, bitmapgc = self.create_clip_bitmap()
+                    self.draw_text_on_gc(bitmapgc, text, trafo,
+                                         self.properties.font,
+                                         self.properties.font_size,
+                                         cache)
+                    if not clip:
+                        self.PushClip()
+                    self.ClipBitmap(bitmap)
+                    self.properties.ExecuteFill(self, self.fill_rect)
+                    if not self.proc_fill:
+                        w, h = bitmap.GetGeometry()[3:5]
+                        bitmap.CopyPlane(self.widget, self.gc, 0, 0, w, h,
+                                         0, 0, 1)
+                    if not clip:
+                        self.PopClip()
+                else:
+                    self.properties.ExecuteFill(self)
+                    self.draw_text_on_gc(self.gc, text, trafo,
+                                         self.properties.font,
+                                         self.properties.font_size,
+                                         cache)
+            elif self.IsOutlineActive():
+                # in outline mode, draw text filled with the current
+                # outline color, because we can't draw outlined text at
+                # the moment. We could draw a rectangle, though. (?)
+                self.properties.ExecuteLine(self)
+                self.draw_text_on_gc(self.gc, text, trafo,
+                                     self.properties.font,
+                                     self.properties.font_size,
+                                     cache)
 
     def ResetFontCache(self):
-	self.font_cache = {}
+        self.font_cache = {}
 
     def load_font(self, xlfd, cache):
-	font_cache = self.font_cache
-	complex_text = self.complex_text
-        
+        font_cache = self.font_cache
+        complex_text = self.complex_text
+
         if self.failed_fonts.has_key(xlfd):
             # the same xlfd failed before. use fixed as fallback
             # immediately to avoid delays. some servers apparantly take
             # very long to decide that they can't load a font.
             xlfd = 'fixed'
 
-	if cache and cache.has_key(id(self)):
-	    old_xlfd, old_font = cache[id(self)]
-	    if old_xlfd == xlfd:
-		font_cache[xlfd] = old_font
-		return old_font
+        if cache and cache.has_key(id(self)):
+            old_xlfd, old_font = cache[id(self)]
+            if old_xlfd == xlfd:
+                font_cache[xlfd] = old_font
+                return old_font
 
-	if complex_text is not None:
-	    cache = complex_text.cache
-	    key = id(self), complex_text.idx
-	    if cache.has_key(key):
-		old_xlfd, old_font = cache[key]
-		if old_xlfd == xlfd:
-		    font_cache[xlfd] = old_font
-		    return old_font
-	    cache = None
+        if complex_text is not None:
+            cache = complex_text.cache
+            key = id(self), complex_text.idx
+            if cache.has_key(key):
+                old_xlfd, old_font = cache[key]
+                if old_xlfd == xlfd:
+                    font_cache[xlfd] = old_font
+                    return old_font
+            cache = None
 
-	if font_cache is not None and font_cache.has_key(xlfd):
-	    font = font_cache[xlfd]
-	else:
+        if font_cache is not None and font_cache.has_key(xlfd):
+            font = font_cache[xlfd]
+        else:
             #print 'load font', xlfd
             try:
                 font = self.widget.LoadQueryFont(xlfd)
@@ -925,65 +925,65 @@
                 self.failed_fonts[xlfd] = 1
                 raise
 
-	if font_cache is not None:
-	    font_cache[xlfd] = font
-	if cache is not None:
-	    cache[id(self)] = (xlfd, font)
-	elif complex_text is not None:
-	    complex_text.cache[(id(self), complex_text.idx)] = (xlfd, font)
+        if font_cache is not None:
+            font_cache[xlfd] = font
+        if cache is not None:
+            cache[id(self)] = (xlfd, font)
+        elif complex_text is not None:
+            complex_text.cache[(id(self), complex_text.idx)] = (xlfd, font)
 
-	return font
+        return font
 
     complex_text = None
     def BeginComplexText(self, clip = 0, cache = None):
-	if self.fill or clip or self.IsOutlineActive():
-	    if cache is None:
-		cache = {}
-	    if self.proc_fill or clip:
-		bitmap, gc = self.create_clip_bitmap()
-		self.complex_text = Empty(bitmap = bitmap, gc = gc,
-					  clip = clip, cache = cache, idx = 0)
-	    else:
-		if self.fill:
-		    self.properties.ExecuteFill(self)
-		else:
-		    # outline mode
-		    self.properties.ExecuteLine(self)
-		self.complex_text = Empty(gc = self.gc, clip = 0,
-					  cache = cache, idx = 0)
-	else:
-	    self.complex_text = None
+        if self.fill or clip or self.IsOutlineActive():
+            if cache is None:
+                cache = {}
+            if self.proc_fill or clip:
+                bitmap, gc = self.create_clip_bitmap()
+                self.complex_text = Empty(bitmap = bitmap, gc = gc,
+                                          clip = clip, cache = cache, idx = 0)
+            else:
+                if self.fill:
+                    self.properties.ExecuteFill(self)
+                else:
+                    # outline mode
+                    self.properties.ExecuteLine(self)
+                self.complex_text = Empty(gc = self.gc, clip = 0,
+                                          cache = cache, idx = 0)
+        else:
+            self.complex_text = None
 
     def DrawComplexText(self, text, trafo, font, font_size):
-	if self.complex_text is not None:
-	    self.draw_text_on_gc(self.complex_text.gc, text, trafo, font,
-				 font_size)
-	    self.complex_text.idx = self.complex_text.idx + 1
+        if self.complex_text is not None:
+            self.draw_text_on_gc(self.complex_text.gc, text, trafo, font,
+                                 font_size)
+            self.complex_text.idx = self.complex_text.idx + 1
 
     def EndComplexText(self):
-	if self.complex_text is not None:
-	    if self.complex_text.clip or self.proc_fill:
-		bitmap = self.complex_text.bitmap
-		self.PushClip()
-		self.ClipBitmap(bitmap)
-		self.properties.ExecuteFill(self, self.fill_rect)
-		if not self.proc_fill:
-		    w, h = bitmap.GetGeometry()[3:5]
-		    bitmap.CopyPlane(self.widget, self.gc, 0, 0, w, h,
-				     0, 0, 1)
-		if not self.complex_text.clip:
-		    self.PopClip()
-	self.complex_text = None
+        if self.complex_text is not None:
+            if self.complex_text.clip or self.proc_fill:
+                bitmap = self.complex_text.bitmap
+                self.PushClip()
+                self.ClipBitmap(bitmap)
+                self.properties.ExecuteFill(self, self.fill_rect)
+                if not self.proc_fill:
+                    w, h = bitmap.GetGeometry()[3:5]
+                    bitmap.CopyPlane(self.widget, self.gc, 0, 0, w, h,
+                                     0, 0, 1)
+                if not self.complex_text.clip:
+                    self.PopClip()
+        self.complex_text = None
 
     def create_ximage(self):
         global use_shm_images
-	if not self.ximage:
-	    w = self.widget
-	    if use_shm_images and not shm_images_supported:
-		warn(INTERNAL,
-		     'tried to use unsupported shared memory images\n')
-		use_shm_images = 0
-	    if use_shm_images:
+        if not self.ximage:
+            w = self.widget
+            if use_shm_images and not shm_images_supported:
+                warn(INTERNAL,
+                     'tried to use unsupported shared memory images\n')
+                use_shm_images = 0
+            if use_shm_images:
                 try:
                     self.ximage = w.ShmCreateImage(w.depth, X.ZPixmap,
                                                    None, w.width, w.height, 1)
@@ -998,206 +998,206 @@
                          sys.exc_info()[1])
                     use_shm_images = 0
             if not self.ximage:
-		self.ximage = self.create_sized_ximage(w.width, w.height)
+                self.ximage = self.create_sized_ximage(w.width, w.height)
 
     def create_sized_ximage(self, width, height):
-	w = self.widget
-	depth = w.depth
-	if depth > 16:
-	    bpl = 4 * width
-	elif depth > 8:
-	    bpl = ((2 * width + 3) / 4) * 4
-	elif depth == 8:
-	    bpl = ((width + 3) / 4) * 4
-	else:
-	    raise SketchError('unsupported depth for images')
-	return w.CreateImage(w.depth, X.ZPixmap, 0, None, width, height,
-			     32, bpl)
+        w = self.widget
+        depth = w.depth
+        if depth > 16:
+            bpl = 4 * width
+        elif depth > 8:
+            bpl = ((2 * width + 3) / 4) * 4
+        elif depth == 8:
+            bpl = ((width + 3) / 4) * 4
+        else:
+            raise SketchError('unsupported depth for images')
+        return w.CreateImage(w.depth, X.ZPixmap, 0, None, width, height,
+                             32, bpl)
 
 
     def DrawImage(self, image, trafo, clip = 0):
-	w, h = image.size
-	if self.IsOutlineActive():
-	    self.PushTrafo()
-	    self.Concat(trafo)
-	    self.DrawRectangle(Point(0, 0), Point(w, h))
-	    self.PopTrafo()
-	    return
-	self.create_ximage()
-	ximage = self.ximage
-	if use_shm_images and self.IsClipping() and self.images_drawn:
-	    # force a shmimage to be drawn if complex clipping is done
-	    # or ShmPutImage requests might be in the queue.
-	    self.widget.Sync()
-	    self.images_drawn = 0
-	llx, lly = self.DocToWin(trafo.offset())
-	lrx, lry = self.DocToWin(trafo(w, 0))
-	ulx, uly = self.DocToWin(trafo(0, h))
-	urx, ury = self.DocToWin(trafo(w, h))
-	if llx == ulx and lly == lry:
-	    if llx < lrx:
-		sx = llx;	w = lrx - llx + 1
-	    else:
-		sx = lrx;	w = lrx - llx - 1
-	    if uly < lly:
-		sy = uly;	h = lly - uly + 1
-	    else:
-		sy = lly;	h = lly - uly - 1
+        w, h = image.size
+        if self.IsOutlineActive():
+            self.PushTrafo()
+            self.Concat(trafo)
+            self.DrawRectangle(Point(0, 0), Point(w, h))
+            self.PopTrafo()
+            return
+        self.create_ximage()
+        ximage = self.ximage
+        if use_shm_images and self.IsClipping() and self.images_drawn:
+            # force a shmimage to be drawn if complex clipping is done
+            # or ShmPutImage requests might be in the queue.
+            self.widget.Sync()
+            self.images_drawn = 0
+        llx, lly = self.DocToWin(trafo.offset())
+        lrx, lry = self.DocToWin(trafo(w, 0))
+        ulx, uly = self.DocToWin(trafo(0, h))
+        urx, ury = self.DocToWin(trafo(w, h))
+        if llx == ulx and lly == lry:
+            if llx < lrx:
+                sx = llx;	w = lrx - llx + 1
+            else:
+                sx = lrx;	w = lrx - llx - 1
+            if uly < lly:
+                sy = uly;	h = lly - uly + 1
+            else:
+                sy = lly;	h = lly - uly - 1
 
-	    _sketch.copy_image_to_ximage(self.visual, image.im, ximage,
-					 sx, sy, w, h)
-	    if w < 0:	w = -w
-	    if h < 0:	h = -h
-	    if not clip:
-		self.PushClip()
-	    self.ClipRect((sx, sy, w, h))
-	else:
-	    self.PushTrafo()
-	    self.Concat(trafo)
-	    self.Concat(Trafo(1, 0, 0, -1, 0, h))
-	    inverse = self.win_to_doc
-	    dtw = self.DocToWin
-	    ulx, uly = dtw(0, 0)
-	    urx, ury = dtw(0, h)
-	    llx, lly = dtw(w, 0)
-	    lrx, lry = dtw(w, h)
-	    self.PopTrafo()
-	    sx = min(ulx, llx, urx, lrx)
-	    ex = max(ulx, llx, urx, lrx)
-	    sy = min(uly, lly, ury, lry)
-	    ey = max(uly, lly, ury, lry)
+            _sketch.copy_image_to_ximage(self.visual, image.im, ximage,
+                                         sx, sy, w, h)
+            if w < 0:	w = -w
+            if h < 0:	h = -h
+            if not clip:
+                self.PushClip()
+            self.ClipRect((sx, sy, w, h))
+        else:
+            self.PushTrafo()
+            self.Concat(trafo)
+            self.Concat(Trafo(1, 0, 0, -1, 0, h))
+            inverse = self.win_to_doc
+            dtw = self.DocToWin
+            ulx, uly = dtw(0, 0)
+            urx, ury = dtw(0, h)
+            llx, lly = dtw(w, 0)
+            lrx, lry = dtw(w, h)
+            self.PopTrafo()
+            sx = min(ulx, llx, urx, lrx)
+            ex = max(ulx, llx, urx, lrx)
+            sy = min(uly, lly, ury, lry)
+            ey = max(uly, lly, ury, lry)
 
-	    if type(self.clip_region) == PaxRegionType:
-		cx, cy, cw, ch = self.clip_region.ClipBox()
-		cex = cx + cw; cey = cy + ch
-		if cx >= ex or cex <= sx or cy >= ey or cey <= sy:
-		    return
-		if cx  > sx and cx  < ex:	sx = cx
-		if cex < ex and cex > sx:	ex = cex
-		if cy  > sy and cy  < ey:	sy = cy
-		if cey < ey and cey > sy:	ey = cey
-	    w = ex - sx
-	    h = ey - sy
+            if type(self.clip_region) == PaxRegionType:
+                cx, cy, cw, ch = self.clip_region.ClipBox()
+                cex = cx + cw; cey = cy + ch
+                if cx >= ex or cex <= sx or cy >= ey or cey <= sy:
+                    return
+                if cx  > sx and cx  < ex:	sx = cx
+                if cex < ex and cex > sx:	ex = cex
+                if cy  > sy and cy  < ey:	sy = cy
+                if cey < ey and cey > sy:	ey = cey
+            w = ex - sx
+            h = ey - sy
 
-	    region = self.widget.CreateRegion()
-	    _sketch.transform_to_ximage(self.visual, inverse,
-					image.im, ximage, sx, sy, w, h, region)
-	    if not clip:
-		self.PushClip()
-	    self.ClipRegion(region)
+            region = self.widget.CreateRegion()
+            _sketch.transform_to_ximage(self.visual, inverse,
+                                        image.im, ximage, sx, sy, w, h, region)
+            if not clip:
+                self.PushClip()
+            self.ClipRegion(region)
 
-	if sx+w <= 0 or sx >= ximage.width or sy+h <= 0 or sy >= ximage.height:
-	    if not clip:
-		self.PopClip()
-	    return
+        if sx+w <= 0 or sx >= ximage.width or sy+h <= 0 or sy >= ximage.height:
+            if not clip:
+                self.PopClip()
+            return
 
-	if sx < 0:
-	    w = w + sx
-	    sx = 0
-	if sx + w > ximage.width:
-	    w = ximage.width - sx
-	if sy < 0:
-	    h = h + sy
-	    sy = 0
-	if sy + h > ximage.height:
-	    h = ximage.height - sy
+        if sx < 0:
+            w = w + sx
+            sx = 0
+        if sx + w > ximage.width:
+            w = ximage.width - sx
+        if sy < 0:
+            h = h + sy
+            sy = 0
+        if sy + h > ximage.height:
+            h = ximage.height - sy
 
-	if use_shm_images:
-	    self.gc.ShmPutImage(ximage, sx, sy, sx, sy, w, h, 0)
-	    self.images_drawn = 1
-	else:
-	    self.gc.PutImage(ximage, sx, sy, sx, sy, w, h)
-	if not clip:
-	    self.PopClip()
+        if use_shm_images:
+            self.gc.ShmPutImage(ximage, sx, sy, sx, sy, w, h, 0)
+            self.images_drawn = 1
+        else:
+            self.gc.PutImage(ximage, sx, sy, sx, sy, w, h)
+        if not clip:
+            self.PopClip()
 
 
     def DrawEps(self, data, trafo):
-	if not data.image or self.IsOutlineActive():
-	    w, h = data.Size()
-	    self.PushTrafo()
-	    self.Concat(trafo)
-	    self.DrawRectangle(Point(0, 0), Point(w, h))
-	    self.PopTrafo()
-	else:
-	    resolution = config.preferences.eps_preview_resolution
-	    self.DrawImage(data.image, trafo(Scale(72.0 / resolution)))
+        if not data.image or self.IsOutlineActive():
+            w, h = data.Size()
+            self.PushTrafo()
+            self.Concat(trafo)
+            self.DrawRectangle(Point(0, 0), Point(w, h))
+            self.PopTrafo()
+        else:
+            resolution = config.preferences.eps_preview_resolution
+            self.DrawImage(data.image, trafo(Scale(72.0 / resolution)))
 
     #
     #
 
     def WindowResized(self, width, height):
-	self.ximage = None
-	SimpleGC.WindowResized(self, width, height)
+        self.ximage = None
+        SimpleGC.WindowResized(self, width, height)
 
 
     #
     #
 
     def DrawGrid(self, orig_x, orig_y, xwidth, ywidth, rect):
-	# Draw a grid with a horitontal width XWIDTH and vertical width
-	# YWIDTH whose origin is at (ORIG_X, ORIG_Y). RECT gives the
-	# region of the document for which the grid has to be drawn.
-	# RECT is usually the parameter of the same name of the
-	# Draw/DrawShape methods of the various graphics objects and the
-	# document/layer Note: This functions assumes that doc_to_win is
-	# in its initial state
-	self.SetProperties(self.grid_style)
-	xwinwidth = self.LengthToWinFloat(xwidth)
-	if not xwinwidth:
-	    if __debug__:
-		pdebug(None, 'GraphicsDevice.DrawGrid: zero winwidth')
-	    return
-	ywinwidth = self.LengthToWinFloat(ywidth)
-	if not ywinwidth:
-	    if __debug__:
-		pdebug(None, 'GraphicsDevice.DrawGrid: zero winwidth')
-	    return
-	# make the minimum distance between drawn points at least 5
-	# pixels XXX: should be configurable
-	if xwinwidth < 5:
-	    xwinwidth = (int(5.0 / xwinwidth) + 1) * xwinwidth
-	    xwidth = self.LengthToDoc(xwinwidth)
-	if ywinwidth < 5:
-	    ywinwidth = (int(5.0 / ywinwidth) + 1) * ywinwidth
-	    ywidth = self.LengthToDoc(ywinwidth)
-	startx = int((rect.left - orig_x) / xwidth) * xwidth + orig_x
-	starty = int((rect.top - orig_y) / ywidth) * ywidth + orig_y
-	winx, winy = self.DocToWinPoint((startx, starty))
-	nx = int((rect.right - rect.left) / xwidth) + 2
-	ny = int((rect.top - rect.bottom) / ywidth) + 2
-	if self.line:
-	    self.properties.ExecuteLine(self)
-	_sketch.DrawGrid(self.gc, winx, winy, xwinwidth, ywinwidth, nx, ny)
+        # Draw a grid with a horitontal width XWIDTH and vertical width
+        # YWIDTH whose origin is at (ORIG_X, ORIG_Y). RECT gives the
+        # region of the document for which the grid has to be drawn.
+        # RECT is usually the parameter of the same name of the
+        # Draw/DrawShape methods of the various graphics objects and the
+        # document/layer Note: This functions assumes that doc_to_win is
+        # in its initial state
+        self.SetProperties(self.grid_style)
+        xwinwidth = self.LengthToWinFloat(xwidth)
+        if not xwinwidth:
+            if __debug__:
+                pdebug(None, 'GraphicsDevice.DrawGrid: zero winwidth')
+            return
+        ywinwidth = self.LengthToWinFloat(ywidth)
+        if not ywinwidth:
+            if __debug__:
+                pdebug(None, 'GraphicsDevice.DrawGrid: zero winwidth')
+            return
+        # make the minimum distance between drawn points at least 5
+        # pixels XXX: should be configurable
+        if xwinwidth < 5:
+            xwinwidth = (int(5.0 / xwinwidth) + 1) * xwinwidth
+            xwidth = self.LengthToDoc(xwinwidth)
+        if ywinwidth < 5:
+            ywinwidth = (int(5.0 / ywinwidth) + 1) * ywinwidth
+            ywidth = self.LengthToDoc(ywinwidth)
+        startx = int((rect.left - orig_x) / xwidth) * xwidth + orig_x
+        starty = int((rect.top - orig_y) / ywidth) * ywidth + orig_y
+        winx, winy = self.DocToWinPoint((startx, starty))
+        nx = int((rect.right - rect.left) / xwidth) + 2
+        ny = int((rect.top - rect.bottom) / ywidth) + 2
+        if self.line:
+            self.properties.ExecuteLine(self)
+        _sketch.DrawGrid(self.gc, winx, winy, xwinwidth, ywinwidth, nx, ny)
 
     def DrawGuideLine(self, point, horizontal):
-	if self.line:
-	    self.properties.ExecuteLine(self)
-	self.gc.line_style = X.LineOnOffDash
-	self.gc.dashes = 5
-	x, y = self.DocToWin(point)
-	if horizontal:
-	    self.gc.DrawLine(0, y, self.widget.width, y)
-	else:
-	    self.gc.DrawLine(x, 0, x, self.widget.height)
-	self.gc.line_style = X.LineSolid
+        if self.line:
+            self.properties.ExecuteLine(self)
+        self.gc.line_style = X.LineOnOffDash
+        self.gc.dashes = 5
+        x, y = self.DocToWin(point)
+        if horizontal:
+            self.gc.DrawLine(0, y, self.widget.width, y)
+        else:
+            self.gc.DrawLine(x, 0, x, self.widget.height)
+        self.gc.line_style = X.LineSolid
 
     def DrawPageOutline(self, width, height):
-	# Draw the outline of the page whose size is given by width and
-	# height. The page's lower left corner is at (0,0) and its upper
-	# right corner at (width, height) in doc coords. The outline is
-	# drawn as a rectangle with a thin shadow.
-	self.gc.line_width = 0
-	self.gc.line_style = X.LineSolid
-	left, bottom = self.DocToWin(0, 0)
-	right, top = self.DocToWin(width, height)
-	sw = 5	# shadow width	XXX: should be configurable ?
-	w = right - left
-	h = bottom - top
-	self.SetFillColor(StandardColors.gray)
-	self.gc.FillRectangles([(left + sw, bottom, w + 1, sw + 1),
-				(right, top + sw, sw + 1, h + 1)])
-	self.SetFillColor(StandardColors.black)
-	self.gc.DrawRectangle(left, top, w, h)
+        # Draw the outline of the page whose size is given by width and
+        # height. The page's lower left corner is at (0,0) and its upper
+        # right corner at (width, height) in doc coords. The outline is
+        # drawn as a rectangle with a thin shadow.
+        self.gc.line_width = 0
+        self.gc.line_style = X.LineSolid
+        left, bottom = self.DocToWin(0, 0)
+        right, top = self.DocToWin(width, height)
+        sw = 5	# shadow width	XXX: should be configurable ?
+        w = right - left
+        h = bottom - top
+        self.SetFillColor(StandardColors.gray)
+        self.gc.FillRectangles([(left + sw, bottom, w + 1, sw + 1),
+                                (right, top + sw, sw + 1, h + 1)])
+        self.SetFillColor(StandardColors.black)
+        self.gc.DrawRectangle(left, top, w, h)
 
 
 
@@ -1216,7 +1216,7 @@
 # DummyLineStyle is needed for the InvertingDevice and the HitTestDevice
 class DummyAttr(PropertyStack):
     def ExecuteLine(self, gc):
-	pass
+        pass
 
 
 dummyLineStyle = DummyAttr(SolidLine(color_0))
@@ -1231,135 +1231,135 @@
     caret_line_width = 2
 
     def __init__(self):
-	GraphicsDevice.__init__(self)
-	self.handle_size = 3
-	self.small_handle_size = 2
-	self.properties = dummyLineStyle
-	self.fill = 0
-	self.line = 1
-	self.gc = None
+        GraphicsDevice.__init__(self)
+        self.handle_size = 3
+        self.small_handle_size = 2
+        self.properties = dummyLineStyle
+        self.fill = 0
+        self.line = 1
+        self.gc = None
         self.font_cache = {}
 
     def init_gc(self, widget, **gcargs):
-	self.visual = color.skvisual
+        self.visual = color.skvisual
         line_width = config.preferences.editor_line_width
-	self.gc = widget.CreateGC(foreground = ~0,
-				  function = X.GXxor,
-				  background = 0,
-				  line_width = line_width,
-				  line_style = self.normal_line_style)
-	self.widget = widget
+        self.gc = widget.CreateGC(foreground = ~0,
+                                  function = X.GXxor,
+                                  background = 0,
+                                  line_width = line_width,
+                                  line_style = self.normal_line_style)
+        self.widget = widget
 
     # make sure that the properties are not changed
     def SetProperties(self, properties, rect = None):
-	pass
+        pass
 
     def IsOutlineActive(self):
-	return 1
+        return 1
 
     # Bezier and Line are currently only needed for the bezier objects
     # during a drag
     def Bezier(self, p1, p2, p3, p4):
-	dtw = self.DocToWin
-	pts = dtw(p1) + dtw(p2) + dtw(p3) + dtw(p4)
-	apply(_sketch.DrawBezier, (self.gc,) + pts)
+        dtw = self.DocToWin
+        pts = dtw(p1) + dtw(p2) + dtw(p3) + dtw(p4)
+        apply(_sketch.DrawBezier, (self.gc,) + pts)
 
     def Line(self, p1, p2):
-	if self.line:
-	    startx,	starty	= self.DocToWin(p1)
-	    endx,	endy	= self.DocToWin(p2)
-	    self.gc.DrawLine(startx, starty, endx, endy)
+        if self.line:
+            startx,	starty	= self.DocToWin(p1)
+            endx,	endy	= self.DocToWin(p2)
+            self.gc.DrawLine(startx, starty, endx, endy)
 
     # draw a rectangular 'handle' at P. The size of the handle is given
     # by self.handle_size and is always in window coordinates (i.e. is
     # independent of scaling)
 
     def DrawRectHandle(self, p, filled = 1):
-	x, y = self.DocToWin(p)
-	size = self.handle_size
-	x = x - size
-	y = y - size
-	if filled:
-	    self.gc.FillRectangle(x, y, 2 * size + 1, 2 * size + 1)
-	else:
-	    self.gc.DrawRectangle(x, y, 2 * size, 2 * size)
+        x, y = self.DocToWin(p)
+        size = self.handle_size
+        x = x - size
+        y = y - size
+        if filled:
+            self.gc.FillRectangle(x, y, 2 * size + 1, 2 * size + 1)
+        else:
+            self.gc.DrawRectangle(x, y, 2 * size, 2 * size)
 
     def DrawSmallRectHandle(self, p, filled = 1):
-	x, y = self.DocToWin(p)
-	size = self.small_handle_size
-	x = x - size
-	y = y - size
-	if filled:
-	    self.gc.FillRectangle(x, y, 2 * size + 1, 2 * size + 1)
-	else:
-	    self.gc.DrawRectangle(x, y, 2 * size, 2 * size)
+        x, y = self.DocToWin(p)
+        size = self.small_handle_size
+        x = x - size
+        y = y - size
+        if filled:
+            self.gc.FillRectangle(x, y, 2 * size + 1, 2 * size + 1)
+        else:
+            self.gc.DrawRectangle(x, y, 2 * size, 2 * size)
 
     def DrawCircleHandle(self, p, filled = 1):
-	x, y = self.DocToWin(p)
-	size = self.handle_size
-	x = x - size
-	y = y - size
-	if filled:
+        x, y = self.DocToWin(p)
+        size = self.handle_size
+        x = x - size
+        y = y - size
+        if filled:
             # 23040 = 360 * 64
-	    self.gc.FillArc(x, y, 2 * size + 1, 2 * size + 1, 0, 23040)
-	else:
-	    self.gc.DrawArc(x, y, 2 * size, 2 * size, 0, 23040)
+            self.gc.FillArc(x, y, 2 * size + 1, 2 * size + 1, 0, 23040)
+        else:
+            self.gc.DrawArc(x, y, 2 * size, 2 * size, 0, 23040)
 
     def DrawSmallCircleHandle(self, p, filled = 1):
-	x, y = self.DocToWin(p)
-	size = self.small_handle_size
-	x = x - size
-	y = y - size
-	if filled:
+        x, y = self.DocToWin(p)
+        size = self.small_handle_size
+        x = x - size
+        y = y - size
+        if filled:
             # 23040 = 360 * 64
-	    self.gc.FillArc(x, y, 2 * size + 1, 2 * size + 1, 0, 23040)
-	else:
-	    self.gc.DrawArc(x, y, 2 * size, 2 * size, 0, 23040)
+            self.gc.FillArc(x, y, 2 * size + 1, 2 * size + 1, 0, 23040)
+        else:
+            self.gc.DrawArc(x, y, 2 * size, 2 * size, 0, 23040)
 
     def DrawSmallRectHandleList(self, pts, filled = 1):
-	pts = map(self.doc_to_win.DocToWin, pts)
-	size = self.small_handle_size
-	size2 = 2 * size
-	if filled:
-	    size = size + 1
-	rects = []
-	pts.sort()
-	lx = ly = None
-	for x, y in pts:
-	    if y != ly or x != lx:
-		rects.append((x - size, y - size, size2, size2))
-		lx = x
-		ly = y
-	if rects:
-	    if filled:
-		self.gc.FillRectangles(rects)
-	    else:
-		self.gc.DrawRectangles(rects)
+        pts = map(self.doc_to_win.DocToWin, pts)
+        size = self.small_handle_size
+        size2 = 2 * size
+        if filled:
+            size = size + 1
+        rects = []
+        pts.sort()
+        lx = ly = None
+        for x, y in pts:
+            if y != ly or x != lx:
+                rects.append((x - size, y - size, size2, size2))
+                lx = x
+                ly = y
+        if rects:
+            if filled:
+                self.gc.FillRectangles(rects)
+            else:
+                self.gc.DrawRectangles(rects)
 
     def DrawHandleLine(self, start, end):
-	self.gc.line_style = self.handle_line_style
-	self.DrawLine(start, end)
-	self.gc.line_style = self.normal_line_style
+        self.gc.line_style = self.handle_line_style
+        self.DrawLine(start, end)
+        self.gc.line_style = self.normal_line_style
 
     def DrawRubberRect(self, start, end):
-	self.gc.line_style = self.handle_line_style
-	self.DrawRectangle(start, end)
-	self.gc.line_style = self.normal_line_style
+        self.gc.line_style = self.handle_line_style
+        self.DrawRectangle(start, end)
+        self.gc.line_style = self.normal_line_style
 
     def DrawPixmapHandle(self, p, pixmap):
-	x, y = self.DocToWin(p)
-	width, height = pixmap.GetGeometry()[3:5]
-	x = x - width / 2
-	y = y - height / 2
-	pixmap.CopyPlane(self.widget, self.gc, 0, 0, width, height, x, y, 1)
+        x, y = self.DocToWin(p)
+        width, height = pixmap.GetGeometry()[3:5]
+        x = x - width / 2
+        y = y - height / 2
+        pixmap.CopyPlane(self.widget, self.gc, 0, 0, width, height, x, y, 1)
 
     def DrawCaretHandle(self, p, up):
-	line_width = self.gc.line_width
-	self.gc.line_width = self.caret_line_width
-	self.gc.line_style = self.caret_line_style
-	self.DrawLine(p, p + up)
-	self.gc.line_style = self.normal_line_style
-	self.gc.line_width = line_width
+        line_width = self.gc.line_width
+        self.gc.line_width = self.caret_line_width
+        self.gc.line_style = self.caret_line_style
+        self.DrawLine(p, p + up)
+        self.gc.line_style = self.normal_line_style
+        self.gc.line_width = line_width
 
 
 #
@@ -1379,31 +1379,31 @@
     outline_style = hit_properties
 
     def __init__(self):
-	GraphicsDevice.__init__(self)
-	self.properties = hit_properties
-	self.fill = 1
-	self.line = 1
-	self.gc = None
+        GraphicsDevice.__init__(self)
+        self.properties = hit_properties
+        self.fill = 1
+        self.line = 1
+        self.gc = None
 
     def init_gc(self, widget, **gcargs):
-	self.pixmap = widget.CreatePixmap(pixmap_width, pixmap_width, 1)
-	self.gc = self.pixmap.CreateGC(foreground = 1, line_width = 3)
-	self.visual = color.skvisual
+        self.pixmap = widget.CreatePixmap(pixmap_width, pixmap_width, 1)
+        self.gc = self.pixmap.CreateGC(foreground = 1, line_width = 3)
+        self.visual = color.skvisual
 
     # make sure that the properties are not changed
     def SetProperties(self, properties, rect = None):
-	if properties.HasLine():
-	    self.line_width = properties.line_width
-	else:
-	    self.line_width = 0
+        if properties.HasLine():
+            self.line_width = properties.line_width
+        else:
+            self.line_width = 0
 
     #
     #
     def SetViewportTransform(self, scale, doc_to_win, win_to_doc):
-	GraphicsDevice.SetViewportTransform(self, scale, doc_to_win,
-					    win_to_doc)
-	self.hit_radius_doc = self.LengthToDoc(self.hit_radius)
-	hit_properties.SetProperty(line_width = self.hit_radius_doc * 2)
+        GraphicsDevice.SetViewportTransform(self, scale, doc_to_win,
+                                            win_to_doc)
+        self.hit_radius_doc = self.LengthToDoc(self.hit_radius)
+        hit_properties.SetProperty(line_width = self.hit_radius_doc * 2)
     #
     # Detect various `hits'
     #
@@ -1411,204 +1411,204 @@
     hit_radius = 2
 
     def SetHitRadius(self, radius):
-	self.hit_radius = radius
+        self.hit_radius = radius
 
     def HitRadiusDoc(self):
-	return self.LengthToDoc(self.hit_radius)
+        return self.LengthToDoc(self.hit_radius)
 
     def HitRectAroundPoint(self, p):
-	rad = self.HitRadiusDoc()
-	return Rect(p.x - rad, p.y - rad, p.x + rad, p.y + rad)
+        rad = self.HitRadiusDoc()
+        return Rect(p.x - rad, p.y - rad, p.x + rad, p.y + rad)
 
     def LineHit(self, start, end, p, line_width = 0):
-	radius = self.hit_radius / self.scale
-	if line_width:
-	    w = line_width / 2
-	    if radius < w:
-		radius = w
-	# check bounding box
-	if p.x < min(start.x, end.x) - radius:
-	    return 0
-	if p.x > max(start.x, end.x) + radius:
-	    return 0
-	if p.y < min(start.y, end.y) - radius:
-	    return 0
-	if p.y > max(start.y, end.y) + radius:
-	    return 0
-	# check if line is hit
-	try:
-	    d = end - start
-	    len = abs(d)
-	    if len < 1:
-		return abs(start.x - p.x) <= radius \
-		       and abs(start.y - p.y) <= radius
-	    off = p - start
-	    dist = abs((float(off.x) * d.y - float(off.y) * d.x) / len)
-	    linepos = (off * d) / len
-	    return dist <= radius and linepos > 0 and linepos < len
-	except OverflowError:
-	    warn(INTERNAL, 'HitTestDevice.LineHit: start = %s end = %s p = %s',
-		 start, end, p)
-	    return 0
+        radius = self.hit_radius / self.scale
+        if line_width:
+            w = line_width / 2
+            if radius < w:
+                radius = w
+        # check bounding box
+        if p.x < min(start.x, end.x) - radius:
+            return 0
+        if p.x > max(start.x, end.x) + radius:
+            return 0
+        if p.y < min(start.y, end.y) - radius:
+            return 0
+        if p.y > max(start.y, end.y) + radius:
+            return 0
+        # check if line is hit
+        try:
+            d = end - start
+            len = abs(d)
+            if len < 1:
+                return abs(start.x - p.x) <= radius \
+                       and abs(start.y - p.y) <= radius
+            off = p - start
+            dist = abs((float(off.x) * d.y - float(off.y) * d.x) / len)
+            linepos = (off * d) / len
+            return dist <= radius and linepos > 0 and linepos < len
+        except OverflowError:
+            warn(INTERNAL, 'HitTestDevice.LineHit: start = %s end = %s p = %s',
+                 start, end, p)
+            return 0
 
     def ParallelogramHit(self, p, trafo, maxx, maxy, filled, properties=None,
-			 ignore_outline_mode = 0):
-	filled = filled and (ignore_outline_mode or not self.outline_mode)
-	if filled:
-	    try:
-		inverse = trafo.inverse()
-		x, y = inverse(p)
-		return 0 <= x <= maxx and 0 <= y <= maxy
-	    except SingularMatrix:
-		if properties is not None and properties.HasLine():
-		    properties = defaultLineStyle
-		    return self.ParallelogramHit(p, trafo, maxx, maxy,
-						 0, properties)
+                         ignore_outline_mode = 0):
+        filled = filled and (ignore_outline_mode or not self.outline_mode)
+        if filled:
+            try:
+                inverse = trafo.inverse()
+                x, y = inverse(p)
+                return 0 <= x <= maxx and 0 <= y <= maxy
+            except SingularMatrix:
+                if properties is not None and properties.HasLine():
+                    properties = defaultLineStyle
+                    return self.ParallelogramHit(p, trafo, maxx, maxy,
+                                                 0, properties)
 
-	if self.outline_mode or (properties is not None
-				 and properties.HasLine()):
-	    p1 = trafo.offset()
-	    p2 = trafo(0, maxy)
-	    p3 = trafo(maxx, 0)
-	    p4 = trafo(maxx, maxy)
-	    if self.outline_mode:
-		line_width = 0
-	    else:
-		line_width = properties.line_width
-	    return self.LineHit(p1, p2, p, line_width)\
-		   or self.LineHit(p1, p3, p, line_width) \
-		   or self.LineHit(p2, p4, p, line_width) \
-		   or self.LineHit(p3, p4, p, line_width)
+        if self.outline_mode or (properties is not None
+                                 and properties.HasLine()):
+            p1 = trafo.offset()
+            p2 = trafo(0, maxy)
+            p3 = trafo(maxx, 0)
+            p4 = trafo(maxx, maxy)
+            if self.outline_mode:
+                line_width = 0
+            else:
+                line_width = properties.line_width
+            return self.LineHit(p1, p2, p, line_width)\
+                   or self.LineHit(p1, p3, p, line_width) \
+                   or self.LineHit(p2, p4, p, line_width) \
+                   or self.LineHit(p3, p4, p, line_width)
 
     def SimpleEllipseHit(self, p, trafo, start_angle, end_angle, arc_type,
-			 properties, filled, ignore_outline_mode = 0):
-	# Hmm, the ellipse is not that simple anymore, maybe we should
-	# change the name?
-	filled = filled and (ignore_outline_mode or not self.outline_mode)
-	try:
-	    inverse = trafo.inverse()
-	    p2 = inverse(p)
-	    dist, phi = p2.polar()
-	    has_line = properties.HasLine() or self.outline_mode
-	    if has_line:
-		# Check whether p is on the outline of the complete
-		# ellipse. This check is not entirely correct, but it
-		# works well enough for now.
-		if not self.outline_mode:
-		    line_width = properties.line_width
-		else:
-		    line_width = 0
-		d = max(line_width / 2, self.HitRadiusDoc())
-		d = abs(inverse.DTransform(Point(d, 0)))
-		border_hit = abs(1.0 - dist) < d
-	    else:
-		border_hit = 0
-	    if start_angle == end_angle:
-		# The most common case: a complete ellipse
-		if filled and dist <= 1.0:
-		    # p is inside of the ellipse -> Hit!
-		    return 1
-		# Either ellipse is not filled or dist > 1.0. NOw it
-		# only depends on the outline.
-		return border_hit
-	    else:
-		# The ellipse is not complete. Now it depends on the
-		# arc_type.
-		if phi < 0:
-		    phi = phi + pi + pi # map phi into the range 0 - 2*PI
-		if start_angle < end_angle:
-		    between = start_angle <= phi <= end_angle
-		else:
-		    between = start_angle <= phi or phi <= end_angle
-		center = trafo.offset()
-		start = Polar(start_angle)
-		end = Polar(end_angle)
-		if arc_type == ArcPieSlice:
-		    if between:
-			# p is somewhere in the painted sector. Just
-			# like for a full ellipse:
-			if filled and dist <= 1:
-			    return 1
-			return border_hit
-		    else:
-			# p is outside of the painted sector. It might
-			# still be on the lines:
-			if has_line:
-			    if (self.LineHit(center, trafo(start), p,
-					     line_width)
-				or self.LineHit(center, trafo(end), p,
-						line_width)):
-				return 1
-			# no line was hit
-			return 0
-		else:
-		    # ArcArc or ArcChord.
-		    if filled:
-			# this is identical for both arc_types.
-			# Strategy: p is inside of the ellipse if it is
-			# in the intersection of the full ellipse the
-			# half plane defined by the line through start
-			# and end (the plane to the left of the vector
-			# (start - end)).
-			v = start - end
-			d = p2 - end
-			in_plane = (v.x * d.y - v.y * d.x) > 0
-			if dist <= 1 and in_plane:
-			    return 1
-		    #
-		    if between and border_hit:
-			return 1
-		    if has_line and arc_type == ArcChord:
-			return self.LineHit(trafo(start), trafo(end), p,
-					    line_width)
-	    return 0
-	except SingularMatrix:
-	    # ellipse degenerates into a line
-	    # XXX we should use the eigenvectors. The following code is
-	    # incorrect.
-	    start = trafo.offset()
-	    right = Point(trafo.m11, trafo.m21)
-	    up = Point(trafo.m12, trafo.m22)
-	    if abs(up) > abs(right):
-		dir = up
-	    else:
-		dir = right
-	    return self.LineHit(start - dir, start + dir, p,
-				properties.line_width)
+                         properties, filled, ignore_outline_mode = 0):
+        # Hmm, the ellipse is not that simple anymore, maybe we should
+        # change the name?
+        filled = filled and (ignore_outline_mode or not self.outline_mode)
+        try:
+            inverse = trafo.inverse()
+            p2 = inverse(p)
+            dist, phi = p2.polar()
+            has_line = properties.HasLine() or self.outline_mode
+            if has_line:
+                # Check whether p is on the outline of the complete
+                # ellipse. This check is not entirely correct, but it
+                # works well enough for now.
+                if not self.outline_mode:
+                    line_width = properties.line_width
+                else:
+                    line_width = 0
+                d = max(line_width / 2, self.HitRadiusDoc())
+                d = abs(inverse.DTransform(Point(d, 0)))
+                border_hit = abs(1.0 - dist) < d
+            else:
+                border_hit = 0
+            if start_angle == end_angle:
+                # The most common case: a complete ellipse
+                if filled and dist <= 1.0:
+                    # p is inside of the ellipse -> Hit!
+                    return 1
+                # Either ellipse is not filled or dist > 1.0. NOw it
+                # only depends on the outline.
+                return border_hit
+            else:
+                # The ellipse is not complete. Now it depends on the
+                # arc_type.
+                if phi < 0:
+                    phi = phi + pi + pi # map phi into the range 0 - 2*PI
+                if start_angle < end_angle:
+                    between = start_angle <= phi <= end_angle
+                else:
+                    between = start_angle <= phi or phi <= end_angle
+                center = trafo.offset()
+                start = Polar(start_angle)
+                end = Polar(end_angle)
+                if arc_type == ArcPieSlice:
+                    if between:
+                        # p is somewhere in the painted sector. Just
+                        # like for a full ellipse:
+                        if filled and dist <= 1:
+                            return 1
+                        return border_hit
+                    else:
+                        # p is outside of the painted sector. It might
+                        # still be on the lines:
+                        if has_line:
+                            if (self.LineHit(center, trafo(start), p,
+                                             line_width)
+                                or self.LineHit(center, trafo(end), p,
+                                                line_width)):
+                                return 1
+                        # no line was hit
+                        return 0
+                else:
+                    # ArcArc or ArcChord.
+                    if filled:
+                        # this is identical for both arc_types.
+                        # Strategy: p is inside of the ellipse if it is
+                        # in the intersection of the full ellipse the
+                        # half plane defined by the line through start
+                        # and end (the plane to the left of the vector
+                        # (start - end)).
+                        v = start - end
+                        d = p2 - end
+                        in_plane = (v.x * d.y - v.y * d.x) > 0
+                        if dist <= 1 and in_plane:
+                            return 1
+                    #
+                    if between and border_hit:
+                        return 1
+                    if has_line and arc_type == ArcChord:
+                        return self.LineHit(trafo(start), trafo(end), p,
+                                            line_width)
+            return 0
+        except SingularMatrix:
+            # ellipse degenerates into a line
+            # XXX we should use the eigenvectors. The following code is
+            # incorrect.
+            start = trafo.offset()
+            right = Point(trafo.m11, trafo.m21)
+            up = Point(trafo.m12, trafo.m22)
+            if abs(up) > abs(right):
+                dir = up
+            else:
+                dir = right
+            return self.LineHit(start - dir, start + dir, p,
+                                properties.line_width)
 
     def MultiBezierHit(self, paths, p, properties, filled,
-		       ignore_outline_mode = 0):
-	x, y = self.DocToWin(p)
-	filled = filled and (ignore_outline_mode or not self.outline_mode)
-	result = _sketch.test_transformed(paths, self.doc_to_win, x, y,
-					  filled)
-	if properties.HasLine():
-	    line_width = properties.line_width
-	else:
-	    line_width = 0
-	if result or self.outline_mode or self.LengthToWin(line_width) <= 1:
-	    return result
-	odtw = self.doc_to_win
-	self.doc_to_win = Trafo(odtw.m11, odtw.m21, odtw.m12, odtw.m22,
-				-x + pixmap_width_2 + odtw.v1,
-				-y + pixmap_width_2 + odtw.v2)
-	top_left = self.WinToDoc(x - pixmap_width_2 - 1,
-				 y - pixmap_width_2 - 1)
-	bot_right = self.WinToDoc(x + pixmap_width_2 + 1,
-				  y + pixmap_width_2 + 1)
-	rect = Rect(top_left, bot_right)
-	self.gc.function = X.GXclear
-	self.gc.FillRectangle(0, 0, pixmap_width + 1, pixmap_width + 1)
-	self.gc.function = X.GXcopy
-	self.fill = 0
-	line_width = max(line_width, hit_properties.line_width)
-	undo = self.properties.SetProperty(line_width = line_width,
-					 line_pattern = SolidPattern(color_1))
-	self.MultiBezier(paths, rect)
-	self.doc_to_win = odtw
-	Undo(undo)
-	self.fill = 1
-	return _sketch.GetPixel(self.gc, pixmap_width_2, pixmap_width_2)
+                       ignore_outline_mode = 0):
+        x, y = self.DocToWin(p)
+        filled = filled and (ignore_outline_mode or not self.outline_mode)
+        result = _sketch.test_transformed(paths, self.doc_to_win, x, y,
+                                          filled)
+        if properties.HasLine():
+            line_width = properties.line_width
+        else:
+            line_width = 0
+        if result or self.outline_mode or self.LengthToWin(line_width) <= 1:
+            return result
+        odtw = self.doc_to_win
+        self.doc_to_win = Trafo(odtw.m11, odtw.m21, odtw.m12, odtw.m22,
+                                -x + pixmap_width_2 + odtw.v1,
+                                -y + pixmap_width_2 + odtw.v2)
+        top_left = self.WinToDoc(x - pixmap_width_2 - 1,
+                                 y - pixmap_width_2 - 1)
+        bot_right = self.WinToDoc(x + pixmap_width_2 + 1,
+                                  y + pixmap_width_2 + 1)
+        rect = Rect(top_left, bot_right)
+        self.gc.function = X.GXclear
+        self.gc.FillRectangle(0, 0, pixmap_width + 1, pixmap_width + 1)
+        self.gc.function = X.GXcopy
+        self.fill = 0
+        line_width = max(line_width, hit_properties.line_width)
+        undo = self.properties.SetProperty(line_width = line_width,
+                                           line_pattern = SolidPattern(color_1))
+        self.MultiBezier(paths, rect)
+        self.doc_to_win = odtw
+        Undo(undo)
+        self.fill = 1
+        return _sketch.GetPixel(self.gc, pixmap_width_2, pixmap_width_2)
 
 
 #
@@ -1626,29 +1626,29 @@
         print "Exception in ShmCheckExtension:", exc
         img = None
     if img is not None:
-	if img.depth not in (15, 16, 24, 32, 8):
-	    # XXX: warn
-	    print 'depth =', img.depth
-	    return
+        if img.depth not in (15, 16, 24, 32, 8):
+            # XXX: warn
+            print 'depth =', img.depth
+            return
 
-	if img.format != X.ZPixmap:
-	    # XXX: warn
-	    print 'format =', img.format
-	    return
+        if img.format != X.ZPixmap:
+            # XXX: warn
+            print 'format =', img.format
+            return
 
-	shm_images_supported = 1
+        shm_images_supported = 1
 
 
 def InitFromWidget(widget):
     global _init_from_widget_done, use_shm_images
     if not _init_from_widget_done:
-	color.InitFromWidget(widget) # make certain that color is initialized
-	check_for_shm_images(widget)
-	if shm_images_supported:
-	    warn(INTERNAL, 'shared memory images supported')
-	    use_shm_images = 1
-	else:
-	    warn(INTERNAL, 'shared memory images not supported')
-	    use_shm_images = 0
+        color.InitFromWidget(widget) # make certain that color is initialized
+        check_for_shm_images(widget)
+        if shm_images_supported:
+            warn(INTERNAL, 'shared memory images supported')
+            use_shm_images = 1
+        else:
+            warn(INTERNAL, 'shared memory images not supported')
+            use_shm_images = 0
     _init_from_widget_done = 1
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/group.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/group.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/group.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -26,24 +26,24 @@
     is_Group = 1
 
     def Info(self):
-	return _("Group with %d objects") % len(self.objects)
+        return _("Group with %d objects") % len(self.objects)
 
     def Blend(self, other, frac1, frac2):
-	try:
-	    objs = self.objects
-	    oobjs = other.objects
-	    blended = []
-	    for i in range(min(len(objs), len(oobjs))):
-		blended.append(Blend(objs[i], oobjs[i], frac1, frac2))
-	    return Group(blended)
-	except:
-	    warn_tb(INTERNAL)
-	    raise MismatchError
+        try:
+            objs = self.objects
+            oobjs = other.objects
+            blended = []
+            for i in range(min(len(objs), len(oobjs))):
+                blended.append(Blend(objs[i], oobjs[i], frac1, frac2))
+            return Group(blended)
+        except:
+            warn_tb(INTERNAL)
+            raise MismatchError
 
     Ungroup = EditableCompound.GetObjects
 
     def SaveToFile(self, file):
-	file.BeginGroup()
-	for obj in self.objects:
-	    obj.SaveToFile(file)
-	file.EndGroup()
+        file.BeginGroup()
+        for obj in self.objects:
+            obj.SaveToFile(file)
+        file.EndGroup()

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/guide.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/guide.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/guide.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -24,23 +24,23 @@
     is_GuideLine = 1
 
     def __init__(self, point, horizontal = 0):
-	self.point = point
-	self.horizontal = horizontal
+        self.point = point
+        self.horizontal = horizontal
 
     def DrawShape(self, device):
-	device.DrawGuideLine(self.point, self.horizontal)
+        device.DrawGuideLine(self.point, self.horizontal)
 
     def DrawDragged(self, device, partially):
-	device.DrawGuideLine(self.drag_cur, self.horizontal)
+        device.DrawGuideLine(self.drag_cur, self.horizontal)
 
     def Hit(self, p, rect, device):
-	if self.horizontal:
-	    return rect.contains_point(Point(p.x, self.point.y))
-	else:
-	    return rect.contains_point(Point(self.point.x, p.y))
+        if self.horizontal:
+            return rect.contains_point(Point(p.x, self.point.y))
+        else:
+            return rect.contains_point(Point(self.point.x, p.y))
 
     def ButtonDown(self, p, button, state):
-	self.DragStart(p)
+        self.DragStart(p)
         if self.horizontal:
             result = Point(0, p.y - self.point.y)
         else:
@@ -48,41 +48,41 @@
         return result
 
     def ButtonUp(self, p, button, state):
-	self.DragStop(p)
+        self.DragStop(p)
 
     def SetPoint(self, point):
-	undo = (self.SetPoint, self.point)
-	if type(point) != PointType:
-	    if type(point) == type(()):
-		point = apply(Point, point)
-	    else:
-		if self.horizontal:
-		    point = Point(self.point.x, point)
-		else:
-		    point = Point(point, self.point.y)
-	self.point = point
-	return undo
+        undo = (self.SetPoint, self.point)
+        if type(point) != PointType:
+            if type(point) == type(()):
+                point = apply(Point, point)
+            else:
+                if self.horizontal:
+                    point = Point(self.point.x, point)
+                else:
+                    point = Point(point, self.point.y)
+        self.point = point
+        return undo
 
     def update_rects(self):
-	self.bounding_rect = self.coord_rect = InfinityRect
+        self.bounding_rect = self.coord_rect = InfinityRect
 
     def get_clear_rect(self):
-	return (self.point, self.horizontal)
+        return (self.point, self.horizontal)
 
     def Snap(self, p):
-	if self.horizontal:
-	    return (abs(p.y - self.point.y), (None, self.point.y))
-	else:
-	    return (abs(p.x - self.point.x), (self.point.x, None))
+        if self.horizontal:
+            return (abs(p.y - self.point.y), (None, self.point.y))
+        else:
+            return (abs(p.x - self.point.x), (self.point.x, None))
 
     def SaveToFile(self, file):
-	file.GuideLine(self.point, self.horizontal)
+        file.GuideLine(self.point, self.horizontal)
 
     def Coordinates(self):
-	if self.horizontal:
-	    return (self.point.y, 1)
-	else:
-	    return (self.point.x, 0)
+        if self.horizontal:
+            return (self.point.y, 1)
+        else:
+            return (self.point.x, 0)
 
 
     def CurrentInfoText(self):

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/handle.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/handle.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/handle.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -67,20 +67,20 @@
 class Handle:
 
     def __init__(self, type, p, cursor = const.CurHandle, offset = None,
-		 p2 = None, list = None, pixmap = None, code = None):
-	self.type = type
-	self.p = p
-	self.cursor = cursor
-	self.p2 = p2
-	self.offset = offset
-	self.list = list
-	self.pixmap = pixmap
-	self.index = 0
+                 p2 = None, list = None, pixmap = None, code = None):
+        self.type = type
+        self.p = p
+        self.cursor = cursor
+        self.p2 = p2
+        self.offset = offset
+        self.list = list
+        self.pixmap = pixmap
+        self.index = 0
         self.code = code
 
     def __str__(self):
         return "Handle(%d, %s)" % (self.type, self.p)
-    
+
     def __repr__(self):
         return "Handle(%d, %s, index = %s)" % (self.type, self.p, self.index)
 
@@ -89,7 +89,7 @@
 
 def MakeNodeHandle(p, selected = 0, code = 0):
     if selected:
-	return Handle(const.HandleSelectedNode, p, code = code)
+        return Handle(const.HandleSelectedNode, p, code = code)
     return Handle(const.HandleNode, p, code = code)
 
 def MakeObjectHandleList(list):
@@ -109,7 +109,7 @@
 
 def MakePixmapHandle(p, offset, pixmap, cursor = const.CurHandle):
     return Handle(const.Handle_Pixmap, p, cursor, offset = offset,
-		  pixmap = pixmap)
+                  pixmap = pixmap)
 
 def MakeCaretHandle(p, up):
     return Handle(const.Handle_Caret, p, p2 = up)

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/image.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/image.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/image.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -36,43 +36,43 @@
     attributes = {'mode':0, 'size':0, 'im':0, 'info':0}
 
     def __init__(self, image, filename = '', cache = 1):
-	# convert image to mode 'L' or 'RGB' if necessary
-	if image.mode not in ('RGB', 'RGBA', 'L'):
-	    if image.mode == '1':
-		mode = 'L'
-	    else:
-		mode = 'RGB'
-	    image = image.convert(mode)
-	else:
-	    image.load()
-	self.image = image
-	ExternalData.__init__(self, filename, cache)
+        # convert image to mode 'L' or 'RGB' if necessary
+        if image.mode not in ('RGB', 'RGBA', 'L'):
+            if image.mode == '1':
+                mode = 'L'
+            else:
+                mode = 'RGB'
+            image = image.convert(mode)
+        else:
+            image.load()
+        self.image = image
+        ExternalData.__init__(self, filename, cache)
 
     def __getattr__(self, attr):
-	if self.attributes.has_key(attr):
-	    return getattr(self.image, attr)
-	raise AttributeError, attr
+        if self.attributes.has_key(attr):
+            return getattr(self.image, attr)
+        raise AttributeError, attr
 
     def AsEmbedded(self):
-	if self.filename:
-	    return ImageData(self.image)
-	else:
-	    return self
+        if self.filename:
+            return ImageData(self.image)
+        else:
+            return self
 
     def IsEmbedded(self):
-	return not self.filename
+        return not self.filename
 
     def Size(self):
-	return self.size
+        return self.size
 
     def Image(self):
         return self.image
 
     def Convert(self, mode):
-	if mode != self.image.mode:
-	    return ImageData(self.image.convert(mode))
-	else:
-	    return self
+        if mode != self.image.mode:
+            return ImageData(self.image.convert(mode))
+        else:
+            return self
 
     def Invert(self):
         return ImageData(PIL.ImageChops.invert(self.image))
@@ -81,12 +81,12 @@
 
 def load_image(filename, cache = 1):
     if type(filename) == StringType:
-	image = get_cached(filename)
-	if image:
-	    return image
+        image = get_cached(filename)
+        if image:
+            return image
     image = PIL.Image.open(filename)
     if type(filename) != StringType:
-	filename = ''
+        filename = ''
     return ImageData(image, filename = filename, cache = cache)
 
 class Image(ExternalGraphics):
@@ -97,53 +97,53 @@
     commands = ExternalGraphics.commands[:]
 
     def __init__(self, image = None, imagefile = '', trafo = None,
-		 duplicate = None):
-	if duplicate is None:
-	    if not image:
-		if not imagefile:
-		    raise ValueError, 'Image must be instantiated with'\
-				      ' either image or imagefile'
-		image = load_image(imagefile)
-	ExternalGraphics.__init__(self, image, trafo,
-				  duplicate = duplicate)
+                 duplicate = None):
+        if duplicate is None:
+            if not image:
+                if not imagefile:
+                    raise ValueError, 'Image must be instantiated with'\
+                          ' either image or imagefile'
+                image = load_image(imagefile)
+        ExternalGraphics.__init__(self, image, trafo,
+                                  duplicate = duplicate)
 
     def DrawShape(self, device, rect = None, clip = 0):
-	device.DrawImage(self.data, self.trafo, clip)
+        device.DrawImage(self.data, self.trafo, clip)
 
     def Info(self):
-	width, height = self.data.Size()
-	x, y = self.trafo.offset()
-	if self.IsEmbedded():
-	    return _("Embedded Image %(width)d x %(height)d "
-		     "at (%(x)d, %(y)d)") % locals()
-	else:
-	    filename = os.path.basename(self.data.Filename())
-	    return _("Linked Image `%(filename)s' %(width)d x %(height)d "
-		     "at (%(x)d, %(y)d)") % locals()
+        width, height = self.data.Size()
+        x, y = self.trafo.offset()
+        if self.IsEmbedded():
+            return _("Embedded Image %(width)d x %(height)d "
+                     "at (%(x)d, %(y)d)") % locals()
+        else:
+            filename = os.path.basename(self.data.Filename())
+            return _("Linked Image `%(filename)s' %(width)d x %(height)d "
+                     "at (%(x)d, %(y)d)") % locals()
 
     def SaveToFile(self, file):
-	file.Image(self.data, self.trafo)
+        file.Image(self.data, self.trafo)
 
     def IsEmbedded(self):
-	return self.data.IsEmbedded()
+        return self.data.IsEmbedded()
 
     def CanEmbed(self):
-	return not self.IsEmbedded()
+        return not self.IsEmbedded()
 
     def Embed(self):
-	return self.SetData(self.data.AsEmbedded())
+        return self.SetData(self.data.AsEmbedded())
     AddCmd(commands, 'EmbedImage', _("Embed Image"), Embed,
            sensitive_cb = 'CanEmbed')
 
     def CallImageFunction(self, function, args = ()):
-	if type(args) != type(()):
-	    args = (args,)
-	data = apply(getattr(self.data, function), args)
-	return self.SetData(data)
+        if type(args) != type(()):
+            args = (args,)
+        data = apply(getattr(self.data, function), args)
+        return self.SetData(data)
     AddCmd(commands, 'GrayscaleImage', _("Grayscale Image"),
-	   CallImageFunction, args = ('Convert', 'L'))
+           CallImageFunction, args = ('Convert', 'L'))
     AddCmd(commands, 'InvertImage', _("Invert Image"), CallImageFunction,
-	   args = 'Invert')
+           args = 'Invert')
 
     context_commands = ('EmbedImage', 'GrayscaleImage', 'InvertImage')
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/layer.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/layer.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/layer.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -38,188 +38,188 @@
     is_GuideLayer = 0
 
     def __init__(self, name = _("New Layer"),
-		 visible = 1, printable = 1, locked = 0,
-		 outlined = 0, outline_color = (0, 0, 0)):
-	EditableCompound.__init__(self, [])
-	self.name = name
-	self.visible = visible
-	self.printable = printable
-	self.locked = locked
-	self.outlined = outlined
-	if type(outline_color) == TupleType:
-	    self.outline_color = apply(color.CreateRGBColor, outline_color)
-	else:
-	    self.outline_color = outline_color
+                 visible = 1, printable = 1, locked = 0,
+                 outlined = 0, outline_color = (0, 0, 0)):
+        EditableCompound.__init__(self, [])
+        self.name = name
+        self.visible = visible
+        self.printable = printable
+        self.locked = locked
+        self.outlined = outlined
+        if type(outline_color) == TupleType:
+            self.outline_color = apply(color.CreateRGBColor, outline_color)
+        else:
+            self.outline_color = outline_color
 
     def Draw(self, device, rect = None):
-	# Draw all objects on the device device. RECT, if provided,
-	# gives the bounding rect of the region to be drawn allowing to
-	# optimize the redisplay by drawing only those objects that
-	# overlap with this rect.
-	if device.draw_visible and self.visible \
-	   or device.draw_printable and self.printable:
-	    outlined = self.outlined or device.IsOutlineActive()
-	    if outlined:
-		device.StartOutlineMode(self.outline_color)
-	    EditableCompound.DrawShape(self, device, rect)
-	    if outlined:
-		device.EndOutlineMode()
+        # Draw all objects on the device device. RECT, if provided,
+        # gives the bounding rect of the region to be drawn allowing to
+        # optimize the redisplay by drawing only those objects that
+        # overlap with this rect.
+        if device.draw_visible and self.visible \
+           or device.draw_printable and self.printable:
+            outlined = self.outlined or device.IsOutlineActive()
+            if outlined:
+                device.StartOutlineMode(self.outline_color)
+            EditableCompound.DrawShape(self, device, rect)
+            if outlined:
+                device.EndOutlineMode()
 
     def SelectSubobject(self, p, rect, device, path = (), *rest):
-	if not self.CanSelect():
-	    return None
-	if self.outlined:
-	    device.StartOutlineMode()
-	try:
-	    result = EditableCompound.SelectSubobject(self, p, rect, device,
-						      path)
-	finally:
-	    if self.outlined:
-		device.EndOutlineMode()
+        if not self.CanSelect():
+            return None
+        if self.outlined:
+            device.StartOutlineMode()
+        try:
+            result = EditableCompound.SelectSubobject(self, p, rect, device,
+                                                      path)
+        finally:
+            if self.outlined:
+                device.EndOutlineMode()
 
-	return result
+        return result
 
     def SelectRect(self, rect):
-	if not self.CanSelect():
-	    return []
-	test = rect.contains_rect
-	build_info = selinfo.build_info
-	selected = []
-	objects = self.objects
-	for idx in range(len(objects)):
-	    obj = objects[idx]
-	    if test(obj.bounding_rect):
-		selected.append(build_info(idx, obj))
-	return selected
+        if not self.CanSelect():
+            return []
+        test = rect.contains_rect
+        build_info = selinfo.build_info
+        selected = []
+        objects = self.objects
+        for idx in range(len(objects)):
+            obj = objects[idx]
+            if test(obj.bounding_rect):
+                selected.append(build_info(idx, obj))
+        return selected
 
     def SelectAll(self):
-	if self.CanSelect():
-	    return selinfo.select_all(self.objects)
-	else:
-	    return []
+        if self.CanSelect():
+            return selinfo.select_all(self.objects)
+        else:
+            return []
 
     def SelectionInfo(self, child, cache = None):
-	info = selinfo.build_info(_sketch.IdIndex(self.objects, child), child)
-	return selinfo.prepend_idx(self.document.LayerIndex(self), info)
+        info = selinfo.build_info(_sketch.IdIndex(self.objects, child), child)
+        return selinfo.prepend_idx(self.document.LayerIndex(self), info)
 
     def PickObject(self, p, rect, device):
-	if not self.visible:
-	    return None
-	if self.outlined:
-	    device.StartOutlineMode()
-	result = EditableCompound.PickObject(self, p, rect, device)
-	if self.outlined:
-	    device.EndOutlineMode()
-	return result
+        if not self.visible:
+            return None
+        if self.outlined:
+            device.StartOutlineMode()
+        result = EditableCompound.PickObject(self, p, rect, device)
+        if self.outlined:
+            device.EndOutlineMode()
+        return result
 
     def SetName(self, name):
-	undo = (self.SetName, self.name)
-	self.name = name
-	return undo
+        undo = (self.SetName, self.name)
+        self.name = name
+        return undo
 
     def Name(self):
-	return self.name
+        return self.name
 
     def NumObjects(self):
-	return len(self.objects)
+        return len(self.objects)
 
     def Visible(self):
-	return self.visible
+        return self.visible
 
     def Printable(self):
-	return self.printable
+        return self.printable
 
     def Locked(self):
         return self.locked
 
     def CanSelect(self):
-	return not self.locked and self.visible
+        return not self.locked and self.visible
 
     def get_state(self):
-	return (self.visible, self.printable, self.locked, self.outlined)
+        return (self.visible, self.printable, self.locked, self.outlined)
 
     def SetState(self, visible, printable, locked, outlined):
-	# set the layer state. Return undo info.
-	#
-	# Side Effect:
-	# Queue a LAYER message with parameter LAYER_STATE + tuple.
-	# The tuple has the form
-	#
-	# (layer, visible_changed, printable_changed, outline_changed)
-	#
-	# We assume here that the receiver (usually SketchCanvas or
-	# SketchView) uses this to determine whether to repaint parts of
-	# the screen. If the receiver shows only visible layers and
-	# allows outline, it should use the following expression to
-	# determine whether to redraw or not:
-	#
-	#    layer.NumObjects() and (visible_changed or
-	#				(outlined_changed and layer.Visible()))
-	#
-	# If you only show printable layers:
-	#
-	#    layer.NumObjects() and printable_changed
-	#
-	# (in that case outline mode should be ignored as it is only
-	# meant for quicker or clearer display while editing)
-	#
-	# The bounding rect of the now invalid region is
-	# layer.bounding_rect
+        # set the layer state. Return undo info.
+        #
+        # Side Effect:
+        # Queue a LAYER message with parameter LAYER_STATE + tuple.
+        # The tuple has the form
+        #
+        # (layer, visible_changed, printable_changed, outline_changed)
+        #
+        # We assume here that the receiver (usually SketchCanvas or
+        # SketchView) uses this to determine whether to repaint parts of
+        # the screen. If the receiver shows only visible layers and
+        # allows outline, it should use the following expression to
+        # determine whether to redraw or not:
+        #
+        #    layer.NumObjects() and (visible_changed or
+        #				(outlined_changed and layer.Visible()))
+        #
+        # If you only show printable layers:
+        #
+        #    layer.NumObjects() and printable_changed
+        #
+        # (in that case outline mode should be ignored as it is only
+        # meant for quicker or clearer display while editing)
+        #
+        # The bounding rect of the now invalid region is
+        # layer.bounding_rect
 
-	oldstate = self.get_state()
-	visible_changed = self.visible != visible
-	self.visible = visible
-	printable_changed = self.printable != printable
-	self.printable = printable
+        oldstate = self.get_state()
+        visible_changed = self.visible != visible
+        self.visible = visible
+        printable_changed = self.printable != printable
+        self.printable = printable
         locked_changed = self.locked != locked
-	self.locked = locked
-	outlined_changed = self.outlined != outlined
-	self.outlined = outlined
+        self.locked = locked
+        outlined_changed = self.outlined != outlined
+        self.outlined = outlined
 
-	if oldstate != self.get_state():
-	    undo = (self.SetState,) + oldstate
-	    visibility = (self, visible_changed, printable_changed,
-			  outlined_changed)
-	    if self.document is not None:
-		self.document.queue_layer(LAYER_STATE, visibility)
+        if oldstate != self.get_state():
+            undo = (self.SetState,) + oldstate
+            visibility = (self, visible_changed, printable_changed,
+                          outlined_changed)
+            if self.document is not None:
+                self.document.queue_layer(LAYER_STATE, visibility)
             if locked_changed:
                 self.document.update_active_layer()
-	    return undo
-        
-	return NullUndo
+            return undo
 
+        return NullUndo
+
     def SetOutlineColor(self, color):
-	undo = (self.SetOutlineColor, self.outline_color)
-	self.outline_color = color
-	if self.document is not None:
-	    self.document.queue_layer(LAYER_COLOR, self)
-	return undo
+        undo = (self.SetOutlineColor, self.outline_color)
+        self.outline_color = color
+        if self.document is not None:
+            self.document.queue_layer(LAYER_COLOR, self)
+        return undo
 
     def OutlineColor(self):
-	return self.outline_color
+        return self.outline_color
 
     def Outlined(self):
         return self.outlined
 
     def SaveToFile(self, file):
-	file.BeginLayer(self.name, self.visible, self.printable, self.locked,
-			self.outlined, self.outline_color)
-	for obj in self.objects:
-	    obj.SaveToFile(file)
-	file.EndLayer()
+        file.BeginLayer(self.name, self.visible, self.printable, self.locked,
+                        self.outlined, self.outline_color)
+        for obj in self.objects:
+            obj.SaveToFile(file)
+        file.EndLayer()
 
 class SpecialLayer(Layer):
 
     is_SpecialLayer = 1
 
     def __none(self, *args):
-	return None
+        return None
 
     SelectSubobject = __none
     PickObject = __none
 
     def SelectRect(self, *rect):
-	return []
+        return []
 
     SelectAll = SelectRect
 
@@ -229,94 +229,94 @@
     is_GuideLayer = 1
 
     def __init__(self, name = _("Guides"), visible = 1, printable = 0,
-		 locked = 0, outlined = 1, outline_color = None):
-	if outline_color is None:
-	    outline_color = config.preferences.guide_color
-	SpecialLayer.__init__(self, name, visible, 0, locked, 1,
-			      outline_color)
+                 locked = 0, outlined = 1, outline_color = None):
+        if outline_color is None:
+            outline_color = config.preferences.guide_color
+        SpecialLayer.__init__(self, name, visible, 0, locked, 1,
+                              outline_color)
 
     def SetState(self, visible, printable, locked, outlined):
-	return SpecialLayer.SetState(self, visible, 0, locked, outlined)
+        return SpecialLayer.SetState(self, visible, 0, locked, outlined)
 
     def Draw(self, device, rect = None):
-	if device.draw_visible and self.visible \
-	   or device.draw_printable and self.printable:
-	    device.StartOutlineMode(self.outline_color)
-	    SpecialLayer.DrawShape(self, device)
-	    device.EndOutlineMode()
+        if device.draw_visible and self.visible \
+           or device.draw_printable and self.printable:
+            device.StartOutlineMode(self.outline_color)
+            SpecialLayer.DrawShape(self, device)
+            device.EndOutlineMode()
 
     def SelectSubobject(self, p, rect, device, path = (), *rest):
-	if not self.CanSelect():
-	    return None
-	device.StartOutlineMode()
-	try:
-	    objects = self.objects
-	    for obj_idx in range(len(objects) - 1, -1, -1):
-		obj = objects[obj_idx]
-		if obj.Hit(p, rect, device):
-		    result = obj.SelectSubobject(p, rect, device)
-		    return selinfo.prepend_idx(obj_idx, result)
-	    return None
-	finally:
-	    device.EndOutlineMode()
+        if not self.CanSelect():
+            return None
+        device.StartOutlineMode()
+        try:
+            objects = self.objects
+            for obj_idx in range(len(objects) - 1, -1, -1):
+                obj = objects[obj_idx]
+                if obj.Hit(p, rect, device):
+                    result = obj.SelectSubobject(p, rect, device)
+                    return selinfo.prepend_idx(obj_idx, result)
+            return None
+        finally:
+            device.EndOutlineMode()
 
     def SelectRect(self, rect):
-	if not self.CanSelect():
-	    return []
-	test = rect.contains_rect
-	build_info = selinfo.build_info
-	selected = []
-	objects = self.objects
-	for idx in range(len(objects)):
-	    obj = objects[idx]
-	    if not obj.is_GuideLine and test(obj.bounding_rect):
-		selected.append(build_info(idx, obj))
-	return selected
+        if not self.CanSelect():
+            return []
+        test = rect.contains_rect
+        build_info = selinfo.build_info
+        selected = []
+        objects = self.objects
+        for idx in range(len(objects)):
+            obj = objects[idx]
+            if not obj.is_GuideLine and test(obj.bounding_rect):
+                selected.append(build_info(idx, obj))
+        return selected
 
     def SelectAll(self):
-	return self.SelectRect(InfinityRect)
+        return self.SelectRect(InfinityRect)
 
     def compute_rects(self):
-	if self.objects:
-	    self.bounding_rect = self.coord_rect = InfinityRect
-	else:
-	    self.bounding_rect = self.coord_rect = EmptyRect
+        if self.objects:
+            self.bounding_rect = self.coord_rect = InfinityRect
+        else:
+            self.bounding_rect = self.coord_rect = EmptyRect
 
     def SaveToFile(self, file):
-	file.BeginGuideLayer(self.name, self.visible, self.printable,
-			     self.locked, self.outlined, self.outline_color)
-	for obj in self.objects:
-	    obj.SaveToFile(file)
-	file.EndGuideLayer()
+        file.BeginGuideLayer(self.name, self.visible, self.printable,
+                             self.locked, self.outlined, self.outline_color)
+        for obj in self.objects:
+            obj.SaveToFile(file)
+        file.EndGuideLayer()
 
     def Snap(self, p):
-	default = (1e100, p)
-	horizontal = [default]
-	vertical = [default]
-	result = [default]
-	for obj in self.objects:
-	    dist, snapped = obj.Snap(p)
-	    if type(snapped) == TupleType:
-		if snapped[0] is None:
-		    horizontal.append((dist, snapped))
-		else:
-		    vertical.append((dist, snapped))
-	    else:
-		result.append((dist, snapped))
+        default = (1e100, p)
+        horizontal = [default]
+        vertical = [default]
+        result = [default]
+        for obj in self.objects:
+            dist, snapped = obj.Snap(p)
+            if type(snapped) == TupleType:
+                if snapped[0] is None:
+                    horizontal.append((dist, snapped))
+                else:
+                    vertical.append((dist, snapped))
+            else:
+                result.append((dist, snapped))
 
-	return min(horizontal), min(vertical), min(result)
+        return min(horizontal), min(vertical), min(result)
 
     def GuideLines(self):
-	result = self.objects[:]
-	for idx in range(len(result) - 1, -1, -1):
-	    if not result[idx].is_GuideLine:
-		del result[idx]
-	return result
+        result = self.objects[:]
+        for idx in range(len(result) - 1, -1, -1):
+            if not result[idx].is_GuideLine:
+                del result[idx]
+        return result
 
     def issue_changed(self):
-	Layer.issue_changed(self)
-	if self.document is not None:
-	    self.document.GuideLayerChanged(self)
+        Layer.issue_changed(self)
+        if self.document is not None:
+            self.document.GuideLayerChanged(self)
 
 class GridLayer(SpecialLayer):
 
@@ -324,56 +324,56 @@
     geometry = (0, 0, 20, 20)
 
     def __init__(self, geometry = None, visible = None, outline_color = None,
-		 name = _("Grid")):
-	# The grid is locked, outlined and not printable
-	if geometry is None:
-	    geometry = config.preferences.grid_geometry
-	if visible is None:
-	    visible = config.preferences.grid_visible
-	if outline_color is None:
-	    outline_color = config.preferences.grid_color
-	SpecialLayer.__init__(self, name, visible, 0, 1, 1, outline_color)
-	if len(geometry) == 2:
-	    self.geometry = (0, 0) + geometry
-	elif len(geometry) == 4:
-	    self.geometry = geometry
-	else:
-	    raise ValueError, "grid tuple must have length 2 or 4"
+                 name = _("Grid")):
+        # The grid is locked, outlined and not printable
+        if geometry is None:
+            geometry = config.preferences.grid_geometry
+        if visible is None:
+            visible = config.preferences.grid_visible
+        if outline_color is None:
+            outline_color = config.preferences.grid_color
+        SpecialLayer.__init__(self, name, visible, 0, 1, 1, outline_color)
+        if len(geometry) == 2:
+            self.geometry = (0, 0) + geometry
+        elif len(geometry) == 4:
+            self.geometry = geometry
+        else:
+            raise ValueError, "grid tuple must have length 2 or 4"
 
     def Draw(self, device, rect = None):
-	if device.draw_visible and self.visible \
-	   or device.draw_printable and self.printable:
-	    device.StartOutlineMode(self.outline_color)
-	    xorg, yorg, xwidth, ywidth = self.geometry
-	    device.DrawGrid(xorg, yorg, xwidth, ywidth, rect)
-	    device.EndOutlineMode()
+        if device.draw_visible and self.visible \
+           or device.draw_printable and self.printable:
+            device.StartOutlineMode(self.outline_color)
+            xorg, yorg, xwidth, ywidth = self.geometry
+            device.DrawGrid(xorg, yorg, xwidth, ywidth, rect)
+            device.EndOutlineMode()
 
     def update_rects(self):
-	self.bounding_rect = self.coord_rect = InfinityRect
+        self.bounding_rect = self.coord_rect = InfinityRect
 
     def SaveToFile(self, file):
-	file.BeginGridLayer(self.geometry, self.visible, self.outline_color,
+        file.BeginGridLayer(self.geometry, self.visible, self.outline_color,
                             self.name)
         file.EndGridLayer()
 
     def Snap(self, p):
-	xorg, yorg, xwidth, ywidth = self.geometry
-	sx = round((p.x - xorg) / xwidth) * xwidth + xorg
-	sy = round((p.y - yorg) / ywidth) * ywidth + yorg
-	result = Point(sx, sy)
-	return (abs(result - p), result)
+        xorg, yorg, xwidth, ywidth = self.geometry
+        sx = round((p.x - xorg) / xwidth) * xwidth + xorg
+        sy = round((p.y - yorg) / ywidth) * ywidth + yorg
+        result = Point(sx, sy)
+        return (abs(result - p), result)
 
     def SetState(self, visible, printable, locked, outlined):
-	return SpecialLayer.SetState(self, visible, 0, 1, 1)
+        return SpecialLayer.SetState(self, visible, 0, 1, 1)
 
     def Geometry(self):
-	return self.geometry
+        return self.geometry
 
     def SetGeometry(self, geometry):
-	undo = (self.SetGeometry, self.geometry)
-	self.geometry = geometry
-	if self.document:
-	    # a hack...
-	    self.document.queue_layer(LAYER_COLOR, self)
-	return undo
+        undo = (self.SetGeometry, self.geometry)
+        self.geometry = geometry
+        if self.document:
+            # a hack...
+            self.document.queue_layer(LAYER_COLOR, self)
+        return undo
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/maskgroup.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/maskgroup.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/maskgroup.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -42,27 +42,27 @@
     commands = EditableCompound.commands[:]
 
     def __init__(self, objects = None, duplicate = None):
-	EditableCompound.__init__(self, objects,
-				  duplicate = duplicate)
+        EditableCompound.__init__(self, objects,
+                                  duplicate = duplicate)
 
     def update_mask_attrs(self):
-	if self.objects:
-	    mask = self.objects[0]
-	    if mask.has_properties:
-		self.mask_fill = mask.Properties().Duplicate()
-		self.mask_fill.AddStyle(EmptyLineStyle)
-		if mask.has_line and mask.Properties().HasLine():
-		    self.mask_line = mask.Properties().Duplicate()
-		    self.mask_line.AddStyle(EmptyFillStyle)
-		else:
-		    self.mask_line = None
-	    else:
-		self.mask_line = self.mask_fill = None
+        if self.objects:
+            mask = self.objects[0]
+            if mask.has_properties:
+                self.mask_fill = mask.Properties().Duplicate()
+                self.mask_fill.AddStyle(EmptyLineStyle)
+                if mask.has_line and mask.Properties().HasLine():
+                    self.mask_line = mask.Properties().Duplicate()
+                    self.mask_line.AddStyle(EmptyFillStyle)
+                else:
+                    self.mask_line = None
+            else:
+                self.mask_line = self.mask_fill = None
 
     def update_rects(self):
-	if self.objects:
-	    self.bounding_rect = self.objects[0].bounding_rect
-	    self.coord_rect = self.objects[0].coord_rect
+        if self.objects:
+            self.bounding_rect = self.objects[0].bounding_rect
+            self.coord_rect = self.objects[0].coord_rect
 
     def ChildChanged(self, child):
         if child is self.objects[0]:
@@ -71,23 +71,23 @@
         EditableCompound.ChildChanged(self, child)
 
     def Info(self):
-	return _("MaskGroup with %d objects") % len(self.objects)
+        return _("MaskGroup with %d objects") % len(self.objects)
 
     def Hit(self, p, rect, device):
-	if self.objects[0].Hit(p, rect, device, clip = 1):
-	    return EditableCompound.Hit(self, p, rect, device)
+        if self.objects[0].Hit(p, rect, device, clip = 1):
+            return EditableCompound.Hit(self, p, rect, device)
 
     def Blend(self, other, frac1, frac2):
-	try:
-	    objs = self.objects
-	    oobjs = other.objects
-	    blended = []
-	    for i in range(min(len(objs), len(oobjs))):
-		blended.append(Blend(objs[i], oobjs[i], frac1, frac2))
-	    return MaskGroup(blended)
-	except:
-	    warn_tb(INTERNAL)
-	    raise MismatchError
+        try:
+            objs = self.objects
+            oobjs = other.objects
+            blended = []
+            for i in range(min(len(objs), len(oobjs))):
+                blended.append(Blend(objs[i], oobjs[i], frac1, frac2))
+            return MaskGroup(blended)
+        except:
+            warn_tb(INTERNAL)
+            raise MismatchError
 
     def Ungroup(self):
         objects = EditableCompound.GetObjects(self)
@@ -106,49 +106,49 @@
         return objects
 
     def SaveToFile(self, file):
-	file.BeginMaskGroup()
-	for obj in self.objects:
-	    obj.SaveToFile(file)
-	file.EndMaskGroup()
+        file.BeginMaskGroup()
+        for obj in self.objects:
+            obj.SaveToFile(file)
+        file.EndMaskGroup()
 
     def DrawShape(self, device, rect = None):
-	if not self.objects:
-	    return
-	mask = self.objects[0]
-	if mask.has_properties:
-	    attr = mask.properties
-	    mask.properties = self.mask_fill
-	device.PushClip()
-	clipped = 1
-	try:
-	    mask.DrawShape(device, rect, clip = 1)
-	    if rect:
-		rect = IntersectRects(rect, mask.bounding_rect)
-		test = rect.overlaps
-		for o in self.objects[1:]:
-		    if test(o.bounding_rect):
-			o.DrawShape(device, rect)
-	    else:
-		for obj in self.objects[1:]:
-		    obj.DrawShape(device)
-	    if self.mask_line is not None:
-		device.PopClip()
-		clipped = 0
-		mask.properties = self.mask_line
-		mask.DrawShape(device, rect)
-	finally:
-	    if clipped:
-		device.PopClip()
-	    if mask.has_properties:
-		mask.properties = attr
+        if not self.objects:
+            return
+        mask = self.objects[0]
+        if mask.has_properties:
+            attr = mask.properties
+            mask.properties = self.mask_fill
+        device.PushClip()
+        clipped = 1
+        try:
+            mask.DrawShape(device, rect, clip = 1)
+            if rect:
+                rect = IntersectRects(rect, mask.bounding_rect)
+                test = rect.overlaps
+                for o in self.objects[1:]:
+                    if test(o.bounding_rect):
+                        o.DrawShape(device, rect)
+            else:
+                for obj in self.objects[1:]:
+                    obj.DrawShape(device)
+            if self.mask_line is not None:
+                device.PopClip()
+                clipped = 0
+                mask.properties = self.mask_line
+                mask.DrawShape(device, rect)
+        finally:
+            if clipped:
+                device.PopClip()
+            if mask.has_properties:
+                mask.properties = attr
 
     def permute_objects(self, permutation):
-	# make sure the mask stays at index 0
-	if permutation[0] != 0:
-	    permutation = list(permutation)
-	    permutation.remove(0)
-	    permutation.insert(0, 0)
-	return EditableCompound.permute_objects(self, permutation)
+        # make sure the mask stays at index 0
+        if permutation[0] != 0:
+            permutation = list(permutation)
+            permutation.remove(0)
+            permutation.insert(0, 0)
+        return EditableCompound.permute_objects(self, permutation)
 
     def Mask(self):
         return self.objects[0]
@@ -157,8 +157,8 @@
         return self.objects[1:]
 
     def SelectMask(self):
-	if self.document is not None:
-	    self.document.SelectObject(self.objects[0])
+        if self.document is not None:
+            self.document.SelectObject(self.objects[0])
     AddCmd(commands, SelectMask, _("Select Mask"), key_stroke = 'm')
 
     context_commands = ('SelectMask',)

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/pagelayout.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/pagelayout.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/pagelayout.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -34,49 +34,49 @@
 class PageLayout:
 
     def __init__(self, paperformat = None, width = None, height = None,
-		 orientation = None):
-	if width and height:
-	    self.width = width
-	    self.height = height
-	    self.paperformat = ''
-	else:
-	    if paperformat is None:
-		self.paperformat = config.preferences.default_paper_format
-	    else:
-		self.paperformat = paperformat
-	    self.width, self.height = Papersize[self.paperformat]
-	if orientation is None:
-	    self.orientation = config.preferences.default_page_orientation
-	else:
-	    self.orientation = orientation
-	if self.orientation not in (Portrait, Landscape):
-	    self.orientation = Portrait
+                 orientation = None):
+        if width and height:
+            self.width = width
+            self.height = height
+            self.paperformat = ''
+        else:
+            if paperformat is None:
+                self.paperformat = config.preferences.default_paper_format
+            else:
+                self.paperformat = paperformat
+            self.width, self.height = Papersize[self.paperformat]
+        if orientation is None:
+            self.orientation = config.preferences.default_page_orientation
+        else:
+            self.orientation = orientation
+        if self.orientation not in (Portrait, Landscape):
+            self.orientation = Portrait
 
     def Width(self):
-	if self.orientation == Portrait:
-	    return self.width
-	else:
-	    return self.height
+        if self.orientation == Portrait:
+            return self.width
+        else:
+            return self.height
 
     def Height(self):
-	if self.orientation == Portrait:
-	    return self.height
-	else:
-	    return self.width
+        if self.orientation == Portrait:
+            return self.height
+        else:
+            return self.width
 
     def Size(self):
-	if self.orientation == Portrait:
-	    return (self.width, self.height)
-	else:
-	    return (self.height, self.width)
+        if self.orientation == Portrait:
+            return (self.width, self.height)
+        else:
+            return (self.height, self.width)
 
     def FormatName(self):
-	return self.paperformat
+        return self.paperformat
 
     def Orientation(self):
-	return self.orientation
+        return self.orientation
 
 
     def SaveToFile(self, file):
-	file.PageLayout(self.paperformat, self.width, self.height,
-			self.orientation)
+        file.PageLayout(self.paperformat, self.width, self.height,
+                        self.orientation)

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/papersize.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/papersize.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/papersize.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -54,8 +54,8 @@
     width = 0.5**0.25
     height = 2.0**0.25
     for i in range(8):
-	sizes.append(('A' + `i`, width * m_to_pt, height * m_to_pt))
-	width, height = height / 2, width
+        sizes.append(('A' + `i`, width * m_to_pt, height * m_to_pt))
+        width, height = height / 2, width
     return sizes[3:]
 
 # The more accurate way to specify the european sizes, contributed by
@@ -65,12 +65,12 @@
 #    ('A0', 0.841 * m_to_pt, 1.189 * m_to_pt),
 #    ('A1', 0.594 * m_to_pt, 0.841 * m_to_pt),
 #    ('A2', 0.420 * m_to_pt, 0.594 * m_to_pt),
-    ('A3', 0.297 * m_to_pt, 0.420 * m_to_pt),
-    ('A4', 0.210 * m_to_pt, 0.297 * m_to_pt),
-    ('A5', 0.148 * m_to_pt, 0.210 * m_to_pt),
-    ('A6', 0.105 * m_to_pt, 0.148 * m_to_pt),
-    ('A7', 0.074 * m_to_pt, 0.105 * m_to_pt),
-    ]
+('A3', 0.297 * m_to_pt, 0.420 * m_to_pt),
+('A4', 0.210 * m_to_pt, 0.297 * m_to_pt),
+('A5', 0.148 * m_to_pt, 0.210 * m_to_pt),
+('A6', 0.105 * m_to_pt, 0.148 * m_to_pt),
+('A7', 0.074 * m_to_pt, 0.105 * m_to_pt),
+]
 
 
 
@@ -78,7 +78,7 @@
     ('letter',		8.5  * in_to_pt, 11   * in_to_pt),
     ('legal',		8.5  * in_to_pt, 14   * in_to_pt),
     ('executive',	7.25 * in_to_pt, 10.5 * in_to_pt)
-    ]
+]
 
 
 Papersize = {}

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/pattern.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/pattern.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/pattern.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -41,23 +41,23 @@
     name = ''
 
     def __init__(self, duplicate = None):
-	pass
+        pass
 
     def SetName(self, name):
-	self.name = name
+        self.name = name
 
     def Name(self):
-	return self.name
+        return self.name
 
     def Execute(self, device, rect = None):
-	pass
+        pass
 
     def Transform(self, trafo, rects = None):
-	# This method is usually called by a primitives Transform method.
-	return NullUndo
+        # This method is usually called by a primitives Transform method.
+        return NullUndo
 
     def Duplicate(self):
-	return self.__class__(duplicate = self)
+        return self.__class__(duplicate = self)
 
     Copy = Duplicate
 
@@ -67,18 +67,18 @@
     is_Empty = 1
 
     def Duplicate(self):
-	return self
+        return self
 
     Copy = Duplicate
 
     def Blend(self, *args):
-	return self
+        return self
 
     def SaveToFile(self, file):
-	file.EmptyPattern()
+        file.EmptyPattern()
 
     def __str__(self):
-	return 'EmptyPattern'
+        return 'EmptyPattern'
 
 EmptyPattern = EmptyPattern_()
 
@@ -88,58 +88,58 @@
     is_Solid = 1
 
     def __init__(self, color = None, duplicate = None):
-	if duplicate is not None:
-	    self.color = duplicate.color
-	elif color is not None:
-	    self.color = color
-	else:
-	    raise ValueError,'SolidPattern be must created with color argument'
+        if duplicate is not None:
+            self.color = duplicate.color
+        elif color is not None:
+            self.color = color
+        else:
+            raise ValueError,'SolidPattern be must created with color argument'
 
     def __cmp__(self, other):
-	if self.__class__ == other.__class__:
-	    return cmp(self.color, other.color)
-	else:
-	    return cmp(id(self), id(other))
+        if self.__class__ == other.__class__:
+            return cmp(self.color, other.color)
+        else:
+            return cmp(id(self), id(other))
 
     def __str__(self):
-	return 'SolidPattern(%s)' % `self.color`
+        return 'SolidPattern(%s)' % `self.color`
 
     def Execute(self, device, rect = None):
-	device.SetFillColor(self.color)
+        device.SetFillColor(self.color)
 
     def Blend(self, other, frac1, frac2):
-	if other.__class__ == self.__class__:
-	    return SolidPattern(Blend(self.color, other.color, frac1, frac2))
-	else:
-	    raise MismatchError
+        if other.__class__ == self.__class__:
+            return SolidPattern(Blend(self.color, other.color, frac1, frac2))
+        else:
+            raise MismatchError
 
     def Color(self):
-	return self.color
+        return self.color
 
     def SaveToFile(self, file):
-	file.SolidPattern(self.color)
+        file.SolidPattern(self.color)
 
 class GradientPattern(Pattern):
 
     is_Gradient = 1
 
     def __init__(self, gradient, duplicate = None):
-	if duplicate is not None:
-	    Pattern.__init__(self, duplicate = duplicate)
-	    self.gradient = duplicate.gradient.Duplicate()
-	elif gradient:
-	    self.gradient = gradient
-	else:
-	    raise ValueError,\
-		  'GradientPattern must be created with gradient argument'
+        if duplicate is not None:
+            Pattern.__init__(self, duplicate = duplicate)
+            self.gradient = duplicate.gradient.Duplicate()
+        elif gradient:
+            self.gradient = gradient
+        else:
+            raise ValueError,\
+                  'GradientPattern must be created with gradient argument'
 
     def Gradient(self):
-	return self.gradient
+        return self.gradient
 
     def SetGradient(self, gradient):
-	undo = (self.SetGradient, self.gradient)
-	self.gradient = gradient
-	return undo
+        undo = (self.SetGradient, self.gradient)
+        self.gradient = gradient
+        return undo
 
 
 class LinearGradient(GradientPattern):
@@ -147,106 +147,106 @@
     is_AxialGradient = 1
 
     def __init__(self, gradient = None, direction = Point(0, -1),
-		 border = 0, duplicate = None):
-	GradientPattern.__init__(self, gradient,
-				 duplicate = duplicate)
-	self.direction = direction
-	self.border = border
-	if duplicate is not None:
-	    if duplicate.__class__ == self.__class__:
-		self.direction = duplicate.direction
-		self.border = duplicate.border
-	    elif duplicate.__class__ == ConicalGradient:
-		self.direction = duplicate.direction
-	    elif duplicate.__class__ == RadialGradient:
-		self.border = duplicate.border
+                 border = 0, duplicate = None):
+        GradientPattern.__init__(self, gradient,
+                                 duplicate = duplicate)
+        self.direction = direction
+        self.border = border
+        if duplicate is not None:
+            if duplicate.__class__ == self.__class__:
+                self.direction = duplicate.direction
+                self.border = duplicate.border
+            elif duplicate.__class__ == ConicalGradient:
+                self.direction = duplicate.direction
+            elif duplicate.__class__ == RadialGradient:
+                self.border = duplicate.border
 
     def SetDirection(self, dir):
-	undo = (self.SetDirection, self.direction)
-	self.direction = dir
-	return undo
+        undo = (self.SetDirection, self.direction)
+        self.direction = dir
+        return undo
 
     def Direction(self):
-	return self.direction
+        return self.direction
 
     def Border(self):
-	return self.border
+        return self.border
 
     def SetBorder(self, border):
-	undo = (self.SetBorder, self.border)
-	self.border = border
-	return undo
+        undo = (self.SetBorder, self.border)
+        self.border = border
+        return undo
 
     def Transform(self, trafo, rects = None):
-	dx, dy = self.direction
-	dx, dy = trafo.DTransform(dy, -dx)
-	dir = Point(dy, -dx).normalized()
-	if dir * trafo.DTransform(self.direction) < 0:
-	    dir = -dir
-	return self.SetDirection(dir)
+        dx, dy = self.direction
+        dx, dy = trafo.DTransform(dy, -dx)
+        dir = Point(dy, -dx).normalized()
+        if dir * trafo.DTransform(self.direction) < 0:
+            dir = -dir
+        return self.SetDirection(dir)
 
     def Execute(self, device, rect):
-	if device.has_axial_gradient:
-	    self.execute_axial_gradient(device, rect)
-	    return
+        if device.has_axial_gradient:
+            self.execute_axial_gradient(device, rect)
+            return
 
-	SetFillColor = device.SetFillColor
-	FillRectangle = device.FillRectangle
-	steps = device.gradient_steps
+        SetFillColor = device.SetFillColor
+        FillRectangle = device.FillRectangle
+        steps = device.gradient_steps
 
-	colors = self.gradient.Sample(steps)
-	SetFillColor(colors[0])
-	apply(device.FillRectangle, tuple(rect))
+        colors = self.gradient.Sample(steps)
+        SetFillColor(colors[0])
+        apply(device.FillRectangle, tuple(rect))
 
-	device.PushTrafo()
-	vx, vy = self.direction
-	angle = atan2(vy, vx) - pi / 2
-	center = rect.center()
-	rot = Rotation(angle, center)
-	left, bottom, right, top = rot(rect)
-	device.Concat(rot)
-	device.Translate(center)
-	height = top - bottom
-	miny = -height / 2
-	height = height * (1.0 - self.border)
-	width = right - left
-	dy = height / steps
-	y = height / 2
-	x = width / 2
-	for i in range(steps):
-	    SetFillColor(colors[i])
-	    FillRectangle(-x, y, +x, miny)
-	    y = y - dy
-	device.PopTrafo()
+        device.PushTrafo()
+        vx, vy = self.direction
+        angle = atan2(vy, vx) - pi / 2
+        center = rect.center()
+        rot = Rotation(angle, center)
+        left, bottom, right, top = rot(rect)
+        device.Concat(rot)
+        device.Translate(center)
+        height = top - bottom
+        miny = -height / 2
+        height = height * (1.0 - self.border)
+        width = right - left
+        dy = height / steps
+        y = height / 2
+        x = width / 2
+        for i in range(steps):
+            SetFillColor(colors[i])
+            FillRectangle(-x, y, +x, miny)
+            y = y - dy
+        device.PopTrafo()
 
     def execute_axial_gradient(self, device, rect):
-	vx, vy = self.direction
-	angle = atan2(vy, vx) - pi / 2
-	center = rect.center()
-	rot = Rotation(angle, center)
-	left, bottom, right, top = rot(rect)
-	height = (top - bottom) * (1.0 - self.border)
-	trafo = rot(Translation(center))
-	device.AxialGradient(self.gradient, trafo(0, height / 2),
-			     trafo(0, -height / 2))
+        vx, vy = self.direction
+        angle = atan2(vy, vx) - pi / 2
+        center = rect.center()
+        rot = Rotation(angle, center)
+        left, bottom, right, top = rot(rect)
+        height = (top - bottom) * (1.0 - self.border)
+        trafo = rot(Translation(center))
+        device.AxialGradient(self.gradient, trafo(0, height / 2),
+                             trafo(0, -height / 2))
 
     def Blend(self, other, frac1, frac2):
-	if other.__class__ == self.__class__:
-	    gradient = other.gradient
-	    dir = other.direction
-	    border = other.border
-	elif other.__class__ == SolidPattern:
-	    gradient = other.Color()
-	    dir = self.direction
-	    border = self.border
-	else:
-	    raise MismatchError
-	return LinearGradient(Blend(self.gradient, gradient, frac1, frac2),
-			      frac1 * self.direction + frac2 * dir,
-			      frac1 * self.border + frac2 * border)
+        if other.__class__ == self.__class__:
+            gradient = other.gradient
+            dir = other.direction
+            border = other.border
+        elif other.__class__ == SolidPattern:
+            gradient = other.Color()
+            dir = self.direction
+            border = self.border
+        else:
+            raise MismatchError
+        return LinearGradient(Blend(self.gradient, gradient, frac1, frac2),
+                              frac1 * self.direction + frac2 * dir,
+                              frac1 * self.border + frac2 * border)
 
     def SaveToFile(self, file):
-	file.LinearGradientPattern(self.gradient, self.direction, self.border)
+        file.LinearGradientPattern(self.gradient, self.direction, self.border)
 
 
 class RadialGradient(GradientPattern):
@@ -254,117 +254,117 @@
     is_RadialGradient = 1
 
     def __init__(self, gradient = None, center = Point(0.5, 0.5),
-		 border = 0, duplicate = None):
-	GradientPattern.__init__(self, gradient,
-				 duplicate = duplicate)
-	self.center = center
-	self.border = border
-	if duplicate is not None:
-	    if duplicate.__class__ == self.__class__:
-		self.center = duplicate.center
-		self.border = duplicate.border
-	    elif duplicate.__class__ == ConicalGradient:
-		self.center = duplicate.center
-	    elif duplicate.__class__ == LinearGradient:
-		self.border = duplicate.border
+                 border = 0, duplicate = None):
+        GradientPattern.__init__(self, gradient,
+                                 duplicate = duplicate)
+        self.center = center
+        self.border = border
+        if duplicate is not None:
+            if duplicate.__class__ == self.__class__:
+                self.center = duplicate.center
+                self.border = duplicate.border
+            elif duplicate.__class__ == ConicalGradient:
+                self.center = duplicate.center
+            elif duplicate.__class__ == LinearGradient:
+                self.border = duplicate.border
 
     def SetCenter(self, center):
-	undo = (self.SetCenter, self.center)
-	self.center = center
-	return undo
+        undo = (self.SetCenter, self.center)
+        self.center = center
+        return undo
 
     def Center(self):
-	return self.center
+        return self.center
 
     def Border(self):
-	return self.border
+        return self.border
 
     def SetBorder(self, border):
-	undo = (self.SetBorder, self.border)
-	self.border = border
-	return undo
+        undo = (self.SetBorder, self.border)
+        self.border = border
+        return undo
 
     def Transform(self, trafo, rects = None):
-	if rects:
-	    r1, r2 = rects
-	    left, bottom, right, top = r1
-	    cx, cy = self.center
-	    cx = cx * right + (1 - cx) * left
-	    cy = cy * top   + (1 - cy) * bottom
-	    cx, cy = trafo(cx, cy)
-	    left, bottom, right, top = r2
-	    len = right - left
-	    if len:
-		cx = (cx - left) / len
-	    else:
-		cx = 0
-	    len = top - bottom
-	    if len:
-		cy = (cy - bottom) / len
-	    else:
-		cy = 0
-	    center = Point(cx, cy)
-	else:
-	    center = self.center
+        if rects:
+            r1, r2 = rects
+            left, bottom, right, top = r1
+            cx, cy = self.center
+            cx = cx * right + (1 - cx) * left
+            cy = cy * top   + (1 - cy) * bottom
+            cx, cy = trafo(cx, cy)
+            left, bottom, right, top = r2
+            len = right - left
+            if len:
+                cx = (cx - left) / len
+            else:
+                cx = 0
+            len = top - bottom
+            if len:
+                cy = (cy - bottom) / len
+            else:
+                cy = 0
+            center = Point(cx, cy)
+        else:
+            center = self.center
 
-	return self.SetCenter(center)
+        return self.SetCenter(center)
 
     def Execute(self, device, rect):
-	if device.has_radial_gradient:
-	    self.execute_radial(device, rect)
-	    return
-	steps = device.gradient_steps
-	cx, cy = self.center
-	cx = cx * rect.right + (1 - cx) * rect.left
-	cy = cy * rect.top   + (1 - cy) * rect.bottom
-	radius = max(hypot(rect.left - cx, rect.top - cy),
-		     hypot(rect.right - cx, rect.top - cy),
-		     hypot(rect.right - cx, rect.bottom - cy),
-		     hypot(rect.left - cx, rect.bottom - cy))
-	color = self.gradient.ColorAt
-	SetFillColor = device.SetFillColor
-	FillCircle = device.FillCircle
-	SetFillColor(color(0))
-	apply(device.FillRectangle, tuple(rect))
-	radius = radius * (1.0 - self.border)
-	dr = radius / steps
-	device.PushTrafo()
-	device.Translate(cx, cy)
-	center = NullPoint
-	for i in range(steps):
-	    SetFillColor(color(float(i) / (steps - 1)))
-	    FillCircle(center, radius)
-	    radius = radius - dr
-	device.PopTrafo()
+        if device.has_radial_gradient:
+            self.execute_radial(device, rect)
+            return
+        steps = device.gradient_steps
+        cx, cy = self.center
+        cx = cx * rect.right + (1 - cx) * rect.left
+        cy = cy * rect.top   + (1 - cy) * rect.bottom
+        radius = max(hypot(rect.left - cx, rect.top - cy),
+                     hypot(rect.right - cx, rect.top - cy),
+                     hypot(rect.right - cx, rect.bottom - cy),
+                     hypot(rect.left - cx, rect.bottom - cy))
+        color = self.gradient.ColorAt
+        SetFillColor = device.SetFillColor
+        FillCircle = device.FillCircle
+        SetFillColor(color(0))
+        apply(device.FillRectangle, tuple(rect))
+        radius = radius * (1.0 - self.border)
+        dr = radius / steps
+        device.PushTrafo()
+        device.Translate(cx, cy)
+        center = NullPoint
+        for i in range(steps):
+            SetFillColor(color(float(i) / (steps - 1)))
+            FillCircle(center, radius)
+            radius = radius - dr
+        device.PopTrafo()
 
     def execute_radial(self, device, rect):
-	cx, cy = self.center
-	cx = cx * rect.right + (1 - cx) * rect.left
-	cy = cy * rect.top   + (1 - cy) * rect.bottom
-	radius = max(hypot(rect.left - cx, rect.top - cy),
-		     hypot(rect.right - cx, rect.top - cy),
-		     hypot(rect.right - cx, rect.bottom - cy),
-		     hypot(rect.left - cx, rect.bottom - cy))
-	radius = radius * (1.0 - self.border)
-	device.RadialGradient(self.gradient, (cx, cy), radius, 0)
+        cx, cy = self.center
+        cx = cx * rect.right + (1 - cx) * rect.left
+        cy = cy * rect.top   + (1 - cy) * rect.bottom
+        radius = max(hypot(rect.left - cx, rect.top - cy),
+                     hypot(rect.right - cx, rect.top - cy),
+                     hypot(rect.right - cx, rect.bottom - cy),
+                     hypot(rect.left - cx, rect.bottom - cy))
+        radius = radius * (1.0 - self.border)
+        device.RadialGradient(self.gradient, (cx, cy), radius, 0)
 
     def Blend(self, other, frac1, frac2):
-	if other.__class__ == self.__class__:
-	    gradient = other.gradient
-	    center = other.center
-	    border = other.border
-	elif other.__class__ == SolidPattern:
-	    gradient = other.Color()
-	    center = self.center
-	    border = self.border
-	else:
-	    raise MismatchError
-	return RadialGradient(Blend(self.gradient, gradient, frac1, frac2),
-			      frac1 * self.center + frac2 * center,
-			      frac1 * self.border + frac2 * border)
+        if other.__class__ == self.__class__:
+            gradient = other.gradient
+            center = other.center
+            border = other.border
+        elif other.__class__ == SolidPattern:
+            gradient = other.Color()
+            center = self.center
+            border = self.border
+        else:
+            raise MismatchError
+        return RadialGradient(Blend(self.gradient, gradient, frac1, frac2),
+                              frac1 * self.center + frac2 * center,
+                              frac1 * self.border + frac2 * border)
 
     def SaveToFile(self, file):
-	file.RadialGradientPattern(self.gradient, self.center, self.border)
+        file.RadialGradientPattern(self.gradient, self.center, self.border)
 
 
 
@@ -373,92 +373,92 @@
     is_ConicalGradient = 1
 
     def __init__(self, gradient = None,
-		 center = Point(0.5, 0.5), direction = Point(1, 0),
-		 duplicate = None):
-	GradientPattern.__init__(self, gradient, duplicate = duplicate)
-	self.center = center
-	self.direction = direction
-	if duplicate is not None:
-	    if duplicate.__class__ == self.__class__:
-		self.center = duplicate.center
-		self.direction = duplicate.direction
-	    elif duplicate.__class__ == LinearGradient:
-		self.direction = duplicate.direction
-	    elif duplicate.__class__ == RadialGradient:
-		self.center = duplicate.center
+                 center = Point(0.5, 0.5), direction = Point(1, 0),
+                 duplicate = None):
+        GradientPattern.__init__(self, gradient, duplicate = duplicate)
+        self.center = center
+        self.direction = direction
+        if duplicate is not None:
+            if duplicate.__class__ == self.__class__:
+                self.center = duplicate.center
+                self.direction = duplicate.direction
+            elif duplicate.__class__ == LinearGradient:
+                self.direction = duplicate.direction
+            elif duplicate.__class__ == RadialGradient:
+                self.center = duplicate.center
 
     def __set_center_and_dir(self, center, dir):
-	undo = (self.__set_center_and_dir, self.center, self.direction)
-	self.center = center
-	self.direction = dir
-	return undo
+        undo = (self.__set_center_and_dir, self.center, self.direction)
+        self.center = center
+        self.direction = dir
+        return undo
 
     def Transform(self, trafo, rects = None):
-	dir = trafo.DTransform(self.direction).normalized()
-	if rects:
-	    r1, r2 = rects
-	    left, bottom, right, top = r1
-	    cx, cy = self.center
-	    cx = cx * right + (1 - cx) * left
-	    cy = cy * top   + (1 - cy) * bottom
-	    cx, cy = trafo(cx, cy)
-	    left, bottom, right, top = r2
-	    len = right - left
-	    if len:
-		cx = (cx - left) / len
-	    else:
-		cx = 0
-	    len = top - bottom
-	    if len:
-		cy = (cy - bottom) / len
-	    else:
-		cy = 0
-	    center = Point(cx, cy)
-	else:
-	    center = self.center
+        dir = trafo.DTransform(self.direction).normalized()
+        if rects:
+            r1, r2 = rects
+            left, bottom, right, top = r1
+            cx, cy = self.center
+            cx = cx * right + (1 - cx) * left
+            cy = cy * top   + (1 - cy) * bottom
+            cx, cy = trafo(cx, cy)
+            left, bottom, right, top = r2
+            len = right - left
+            if len:
+                cx = (cx - left) / len
+            else:
+                cx = 0
+            len = top - bottom
+            if len:
+                cy = (cy - bottom) / len
+            else:
+                cy = 0
+            center = Point(cx, cy)
+        else:
+            center = self.center
 
-	return self.__set_center_and_dir(center, dir)
+        return self.__set_center_and_dir(center, dir)
 
     def SetCenter(self, center):
-	undo = (self.SetCenter, self.center)
-	self.center = center
-	return undo
+        undo = (self.SetCenter, self.center)
+        self.center = center
+        return undo
 
     def Center(self):
-	return self.center
+        return self.center
 
     def SetDirection(self, dir):
-	undo = (self.SetDirection, self.direction)
-	self.direction = dir
-	return undo
+        undo = (self.SetDirection, self.direction)
+        self.direction = dir
+        return undo
 
     def Direction(self):
-	return self.direction
+        return self.direction
 
     def Execute(self, device, rect):
-	if device.has_conical_gradient:
-	    self.execute_conical(device, rect)
-	    return
-	steps = device.gradient_steps
-	cx, cy = self.center
-	left, bottom, right, top = rect
-	cx = cx * right + (1 - cx) * left
-	cy = cy * top	+ (1 - cy) * bottom
-	vx, vy = self.direction
-	angle = atan2(vy, vx)
-	rot = Rotation(angle, cx, cy)
-	radius = max(hypot(left - cx, top - cy),
-		     hypot(right - cx, top - cy),
-		     hypot(right - cx, bottom - cy),
-		     hypot(left-cx,bottom-cy)) + 10
-	device.PushTrafo()
-	device.Concat(rot)
-	device.Translate(cx, cy)
-	device.Scale(radius)
-	colors = self.gradient.Sample(steps)
-	SetFillColor = device.SetFillColor
-	FillPolygon = device.FillPolygon
-	da = pi / steps
+        if device.has_conical_gradient:
+            self.execute_conical(device, rect)
+            return
+        steps = device.gradient_steps
+        cx, cy = self.center
+        left, bottom, right, top = rect
+        cx = cx * right + (1 - cx) * left
+        cy = cy * top	+ (1 - cy) * bottom
+        vx, vy = self.direction
+        angle = atan2(vy, vx)
+        rot = Rotation(angle, cx, cy)
+        radius = max(hypot(left - cx, top - cy),
+                     hypot(right - cx, top - cy),
+                     hypot(right - cx, bottom - cy),
+                     hypot(left-cx,bottom-cy)) + 10
+        device.PushTrafo()
+        device.Concat(rot)
+        device.Translate(cx, cy)
+        device.Scale(radius)
+        colors = self.gradient.Sample(steps)
+        SetFillColor = device.SetFillColor
+        FillPolygon = device.FillPolygon
+        da = pi / steps
         points = [(1, 0)]
         for i in range(steps):
             a = da * (i + 1)
@@ -477,151 +477,151 @@
         device.PopTrafo()
 
     def execute_conical(self, device, rect):
-	cx, cy = self.center
-	left, bottom, right, top = rect
-	cx = cx * right + (1 - cx) * left
-	cy = cy * top	+ (1 - cy) * bottom
-	angle = self.direction.polar()[1]
-	device.ConicalGradient(self.gradient, (cx, cy), angle)
+        cx, cy = self.center
+        left, bottom, right, top = rect
+        cx = cx * right + (1 - cx) * left
+        cy = cy * top	+ (1 - cy) * bottom
+        angle = self.direction.polar()[1]
+        device.ConicalGradient(self.gradient, (cx, cy), angle)
 
     def Blend(self, other, frac1, frac2):
-	if other.__class__ == self.__class__:
-	    gradient = other.gradient
-	    dir = other.direction
-	    center = other.center
-	elif other.__class__ == SolidPattern:
-	    gradient = other.Color()
-	    dir = self.direction
-	    center = self.center
-	else:
-	    raise MismatchError
-	return ConicalGradient(Blend(self.gradient, gradient, frac1, frac2),
-			       frac1 * self.center +  frac2 * center,
-			       frac1 * self.direction + frac2 * dir)
+        if other.__class__ == self.__class__:
+            gradient = other.gradient
+            dir = other.direction
+            center = other.center
+        elif other.__class__ == SolidPattern:
+            gradient = other.Color()
+            dir = self.direction
+            center = self.center
+        else:
+            raise MismatchError
+        return ConicalGradient(Blend(self.gradient, gradient, frac1, frac2),
+                               frac1 * self.center +  frac2 * center,
+                               frac1 * self.direction + frac2 * dir)
 
     def SaveToFile(self, file):
-	file.ConicalGradientPattern(self.gradient, self.center, self.direction)
+        file.ConicalGradientPattern(self.gradient, self.center, self.direction)
 
-        
+
 class HatchingPattern(Pattern):
 
     is_Hatching = 1
 
     def __init__(self, foreground = None, background = None,
-		 direction = Point(1, 0),
-		 spacing = 5.0, width = 0.5, duplicate = None):
-	if duplicate is not None:
-	    self.foreground = duplicate.foreground
-	    self.background = duplicate.background
-	    self.spacing = duplicate.spacing
-	    self.width = duplicate.width
-	    self.direction = duplicate.direction
-	elif foreground:
-	    self.foreground = foreground
-	    if not background:
-		background = color.StandardColors.white
-	    self.background = background
-	    self.spacing = spacing
-	    self.width = width
-	    self.direction = direction
-	else:
-	    raise ValueError,\
-		  'HatchingPattern must be created with color argument'
+                 direction = Point(1, 0),
+                 spacing = 5.0, width = 0.5, duplicate = None):
+        if duplicate is not None:
+            self.foreground = duplicate.foreground
+            self.background = duplicate.background
+            self.spacing = duplicate.spacing
+            self.width = duplicate.width
+            self.direction = duplicate.direction
+        elif foreground:
+            self.foreground = foreground
+            if not background:
+                background = color.StandardColors.white
+            self.background = background
+            self.spacing = spacing
+            self.width = width
+            self.direction = direction
+        else:
+            raise ValueError,\
+                  'HatchingPattern must be created with color argument'
 
     def SetDirection(self, dir):
-	undo = (self.SetDirection, self.direction)
-	self.direction = dir
-	return undo
+        undo = (self.SetDirection, self.direction)
+        self.direction = dir
+        return undo
 
     def Direction(self):
-	return self.direction
+        return self.direction
 
     def SetSpacing(self, spacing):
-	undo = (self.SetSpacing, self.spacing)
-	self.spacing = spacing
-	return undo
+        undo = (self.SetSpacing, self.spacing)
+        self.spacing = spacing
+        return undo
 
     def Spacing(self):
-	return self.spacing
+        return self.spacing
 
     def Width(self):
         return self.width
 
     def Transform(self, trafo, rects = None):
-	# XXX: should spacing be transformed as well? Should the pattern be
-	# transformed at all?
-	dir = trafo.DTransform(self.direction).normalized()
-	return self.SetDirection(dir)
+        # XXX: should spacing be transformed as well? Should the pattern be
+        # transformed at all?
+        dir = trafo.DTransform(self.direction).normalized()
+        return self.SetDirection(dir)
 
     def SetForeground(self, foreground):
-	undo = (self.SetForeground, self.foreground)
-	self.foreground = foreground
-	return undo
+        undo = (self.SetForeground, self.foreground)
+        self.foreground = foreground
+        return undo
 
     def Foreground(self):
-	return self.foreground
+        return self.foreground
 
     def SetBackground(self, color):
-	undo = (self.SetBackground, self.background)
-	self.background = color
-	return undo
+        undo = (self.SetBackground, self.background)
+        self.background = color
+        return undo
 
     def Background(self):
-	return self.background
+        return self.background
 
     def Execute(self, device, rect):
-	left, bottom, right, top = rect
-	dy = self.spacing
-	if dy > 0:
-	    device.SetFillColor(self.background)
-	    device.FillRectangle(left, top, right, bottom)
-	    device.PushTrafo()
-	    vx, vy = self.direction
-	    angle = atan2(vy, vx)
-	    center = rect.center()
-	    rot = Rotation(angle, center)
-	    left, bottom, right, top = rot(rect)
-	    device.Concat(rot)
-	    device.Translate(center)
-	    height = top - bottom
-	    width = right - left
-	    steps = int(height / dy + 1)
-	    y = height / 2
-	    x = width / 2
-	    device.SetLineColor(self.foreground)
-	    device.SetLineAttributes(self.width)
-	    drawline = device.DrawLineXY
-	    for i in range(steps):
-		drawline(-x, y, +x, y)
-		y = y - dy
-	    device.PopTrafo()
-	else:
-	    device.SetFillColor(self.foreground)
-	    device.FillRectangle(left, bottom, right, top)
+        left, bottom, right, top = rect
+        dy = self.spacing
+        if dy > 0:
+            device.SetFillColor(self.background)
+            device.FillRectangle(left, top, right, bottom)
+            device.PushTrafo()
+            vx, vy = self.direction
+            angle = atan2(vy, vx)
+            center = rect.center()
+            rot = Rotation(angle, center)
+            left, bottom, right, top = rot(rect)
+            device.Concat(rot)
+            device.Translate(center)
+            height = top - bottom
+            width = right - left
+            steps = int(height / dy + 1)
+            y = height / 2
+            x = width / 2
+            device.SetLineColor(self.foreground)
+            device.SetLineAttributes(self.width)
+            drawline = device.DrawLineXY
+            for i in range(steps):
+                drawline(-x, y, +x, y)
+                y = y - dy
+            device.PopTrafo()
+        else:
+            device.SetFillColor(self.foreground)
+            device.FillRectangle(left, bottom, right, top)
 
     def Blend(self, other, frac1, frac2):
-	if other.__class__ == self.__class__:
-	    fg = other.foreground
-	    bg = other.background
-	    dir = other.direction
-	    spacing = other.spacing
-	    width = other.width
-	elif other.__class__ == SolidPattern:
-	    fg = bg = other.Color()
-	    dir = self.direction
-	    spacing = self.spacing
-	    width = self.width
-	else:
-	    raise MismatchError
-	return HatchingPattern(Blend(self.foreground, fg, frac1, frac2),
-			       Blend(self.background, bg, frac1, frac2),
-			       frac1 * self.direction + frac2 * dir,
-			       frac1 * self.spacing + frac2 * spacing,
-			       frac1 * self.width + frac2 * width)
+        if other.__class__ == self.__class__:
+            fg = other.foreground
+            bg = other.background
+            dir = other.direction
+            spacing = other.spacing
+            width = other.width
+        elif other.__class__ == SolidPattern:
+            fg = bg = other.Color()
+            dir = self.direction
+            spacing = self.spacing
+            width = self.width
+        else:
+            raise MismatchError
+        return HatchingPattern(Blend(self.foreground, fg, frac1, frac2),
+                               Blend(self.background, bg, frac1, frac2),
+                               frac1 * self.direction + frac2 * dir,
+                               frac1 * self.spacing + frac2 * spacing,
+                               frac1 * self.width + frac2 * width)
 
     def SaveToFile(self, file):
-	file.HatchingPattern(self.foreground, self.background,
-			     self.direction, self.spacing, self.width)
+        file.HatchingPattern(self.foreground, self.background,
+                             self.direction, self.spacing, self.width)
 
 
 class ImageTilePattern(Pattern):
@@ -631,39 +631,39 @@
     data = None
 
     def __init__(self, data = None, trafo = None, duplicate = None):
-	if duplicate is not None:
-	    data = duplicate.data
-	    self.trafo = duplicate.trafo
-	else:
-	    if trafo is None:
-		#width, height = data.size
-		trafo = Trafo(1, 0, 0, -1, 0, 0)
-	    self.trafo = trafo
-	self.data = data
+        if duplicate is not None:
+            data = duplicate.data
+            self.trafo = duplicate.trafo
+        else:
+            if trafo is None:
+                #width, height = data.size
+                trafo = Trafo(1, 0, 0, -1, 0, 0)
+            self.trafo = trafo
+        self.data = data
 
     def set_transformation(self, trafo):
-	undo = (self.set_transformation, self.trafo)
-	self.trafo = trafo
-	return undo
+        undo = (self.set_transformation, self.trafo)
+        self.trafo = trafo
+        return undo
 
     def Transform(self, trafo, rects = None):
-	if rects:
-	    r1, r2 = rects
-	    trafo = trafo(Translation(r1.left, r1.top))
-	    trafo = Translation(-r2.left, -r2.top)(trafo)
-	return self.set_transformation(trafo(self.trafo))
+        if rects:
+            r1, r2 = rects
+            trafo = trafo(Translation(r1.left, r1.top))
+            trafo = Translation(-r2.left, -r2.top)(trafo)
+        return self.set_transformation(trafo(self.trafo))
 
     def Execute(self, device, rect):
-	device.TileImage(self.data,
-			 Translation(rect.left, rect.top)(self.trafo))
+        device.TileImage(self.data,
+                         Translation(rect.left, rect.top)(self.trafo))
 
     def Blend(self, other, frac1, frac2):
-	if self.__class__ == other.__class__:
-	    if self.data is other.data:
-		return self.__class__(self.data,
-				      BlendTrafo(self.trafo, other.trafo,
-						 frac1, frac2))
-	raise MismatchError
+        if self.__class__ == other.__class__:
+            if self.data is other.data:
+                return self.__class__(self.data,
+                                      BlendTrafo(self.trafo, other.trafo,
+                                                 frac1, frac2))
+        raise MismatchError
 
     def SaveToFile(self, file):
-	file.ImageTilePattern(self.data, self.trafo)
+        file.ImageTilePattern(self.data, self.trafo)

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/plugobj.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/plugobj.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/plugobj.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -29,81 +29,81 @@
     is_Plugin = 1
 
     def SetParameters(self, kw = None):
-	# XXX could be extended to handle keyword arguments.
-	undo = {}
-	for key, value in kw.items():
-	    undo[key] = getattr(self, key)
-	    setattr(self, key, value)
-	return self.SetParameters, undo
+        # XXX could be extended to handle keyword arguments.
+        undo = {}
+        for key, value in kw.items():
+            undo[key] = getattr(self, key)
+            setattr(self, key, value)
+        return self.SetParameters, undo
 
     def SaveToFile(self, file, *args, **kw):
-	if self.class_name:
-	    apply(file.BeginPluginCompound, (self.class_name,) + args, kw)
-	    for obj in self.objects:
-		obj.SaveToFile(file)
-	    file.EndPluginCompound()
-	else:
-	    raise SketchError("Plugin %s doesn't define a class name"
-			      % self.__class__)
+        if self.class_name:
+            apply(file.BeginPluginCompound, (self.class_name,) + args, kw)
+            for obj in self.objects:
+                obj.SaveToFile(file)
+            file.EndPluginCompound()
+        else:
+            raise SketchError("Plugin %s doesn't define a class name"
+                              % self.__class__)
 
 class TrafoPlugin(PluginCompound):
 
     def __init__(self, trafo = None, duplicate = None, loading = 0):
-	PluginCompound.__init__(self, duplicate = duplicate)
-	if duplicate is not None:
-	    self.trafo = duplicate.trafo
-	else:
-	    if trafo is None:
-		trafo = Identity
-	    elif type(trafo) == TupleType:
-		trafo = apply(Trafo, trafo)
+        PluginCompound.__init__(self, duplicate = duplicate)
+        if duplicate is not None:
+            self.trafo = duplicate.trafo
+        else:
+            if trafo is None:
+                trafo = Identity
+            elif type(trafo) == TupleType:
+                trafo = apply(Trafo, trafo)
             elif isinstance(trafo, TrafoType):
                 # trafo is already a trafo object
                 pass
-	    else:
-		# assume a number and interpret it as a scaling transformation
-		trafo = Scale(trafo)
-	    self.trafo = trafo
+            else:
+                # assume a number and interpret it as a scaling transformation
+                trafo = Scale(trafo)
+            self.trafo = trafo
 
     def recompute(self):
-	# Implement this in the derived class to update the children.
-	pass
+        # Implement this in the derived class to update the children.
+        pass
 
     def SetParameters(self, kw):
-	undo = PluginCompound.SetParameters(self, kw)
-	try:
-	    self.recompute()
-	except:
-	    Undo(undo)
-	    raise
-	return undo
+        undo = PluginCompound.SetParameters(self, kw)
+        try:
+            self.recompute()
+        except:
+            Undo(undo)
+            raise
+        return undo
 
     def set_transformation(self, trafo):
-	undo = (self.set_transformation, self.trafo)
-	self.trafo = trafo
-	self.recompute()
-	return undo
+        undo = (self.set_transformation, self.trafo)
+        self.trafo = trafo
+        self.recompute()
+        return undo
 
     def Transform(self, trafo):
-	undo = [self.begin_change_children()]
-	try:
-	    undo.append(PluginCompound.Transform(self, trafo))
-	    undo.append(self.set_transformation(trafo(self.trafo)))
-	    undo.append(self.end_change_children())
-	except:
-	    undo.reverse()
-	    map(Undo, undo)
-	    raise
-	return CreateListUndo(undo)
+        undo = [self.begin_change_children()]
+        try:
+            undo.append(PluginCompound.Transform(self, trafo))
+            undo.append(self.set_transformation(trafo(self.trafo)))
+            undo.append(self.end_change_children())
+        except:
+            undo.reverse()
+            map(Undo, undo)
+            raise
+        return CreateListUndo(undo)
 
     def Translate(self, offset):
-	return self.Transform(Translation(offset))
+        return self.Transform(Translation(offset))
 
     def RemoveTransformation(self):
-	return self.set_transformation(Translation(self.trafo.offset()))
+        return self.set_transformation(Translation(self.trafo.offset()))
 
     def LayoutPoint(self):
-	return self.trafo.offset()
+        return self.trafo.offset()
 
     def Trafo(self):
         return self.trafo
@@ -115,58 +115,58 @@
     changed = 0
 
     def __init__(self, class_name = '', *args, **kw):
-	if kw.has_key('loading'):
-	    del kw['loading']
-	duplicate = kw.get('duplicate')
-	if duplicate is not None:
-	    self.class_name = duplicate.class_name
-	    self.args = duplicate.args
-	    self.kw = duplicate.kw
-	else:
-	    self.class_name = class_name
-	    self.args = args
-	    self.kw = kw
-	PluginCompound.__init__(self, duplicate = duplicate)
-	self.disguise()
+        if kw.has_key('loading'):
+            del kw['loading']
+        duplicate = kw.get('duplicate')
+        if duplicate is not None:
+            self.class_name = duplicate.class_name
+            self.args = duplicate.args
+            self.kw = duplicate.kw
+        else:
+            self.class_name = class_name
+            self.args = args
+            self.kw = kw
+        PluginCompound.__init__(self, duplicate = duplicate)
+        self.disguise()
 
     def disguise(self):
-	# If self has only one child, try to behave like it:
-	if len(self.objects) == 1:
-	    object = self.objects[0]
-	    if object.is_curve:
-		self.is_curve = object.is_curve
-		self.AsBezier = object.AsBezier
-		self.Paths = object.Paths
+        # If self has only one child, try to behave like it:
+        if len(self.objects) == 1:
+            object = self.objects[0]
+            if object.is_curve:
+                self.is_curve = object.is_curve
+                self.AsBezier = object.AsBezier
+                self.Paths = object.Paths
 
     def _changed(self):
-	PluginCompound._changed(self)
-	self.changed = 1
+        PluginCompound._changed(self)
+        self.changed = 1
 
     def load_Done(self):
-	PluginCompound.load_Done(self)
-	self.disguise()
+        PluginCompound.load_Done(self)
+        self.disguise()
 
     def SaveToFile(self, file):
-	if not self.changed:
-	    apply(PluginCompound.SaveToFile, (self, file) + self.args, self.kw)
-	else:
-	    # XXX an alternative approach for a changed UnknownPlugin
-	    # might be to store explicitly as an 'UnknownPlugin' so that
-	    # always is represented by this class.
-	    if len(self.objects) == 1:
-		self.objects[0].SaveToFile(file)
-	    else:
-		# Save as ordinary group. This might not be a good idea,
-		# since the UnknownPlugin may (in the future) have some
-		# special behaviour, that the group doesn't have.
-		file.BeginGroup()
-		for obj in self.objects:
-		    obj.SaveToFile(file)
-		file.EndGroup()
+        if not self.changed:
+            apply(PluginCompound.SaveToFile, (self, file) + self.args, self.kw)
+        else:
+            # XXX an alternative approach for a changed UnknownPlugin
+            # might be to store explicitly as an 'UnknownPlugin' so that
+            # always is represented by this class.
+            if len(self.objects) == 1:
+                self.objects[0].SaveToFile(file)
+            else:
+                # Save as ordinary group. This might not be a good idea,
+                # since the UnknownPlugin may (in the future) have some
+                # special behaviour, that the group doesn't have.
+                file.BeginGroup()
+                for obj in self.objects:
+                    obj.SaveToFile(file)
+                file.EndGroup()
 
 
     def Info(self):
-	return _("Unknown Plugin Object `%s'") % self.class_name
+        return _("Unknown Plugin Object `%s'") % self.class_name
 
     Ungroup = PluginCompound.GetObjects
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/properties.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/properties.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/properties.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -32,70 +32,70 @@
     name = ''
 
     def __init__(self, name = '', duplicate = None, **kw):
-	if duplicate is not None:
-	    self.__dict__ = duplicate.__dict__.copy()
-	    if hasattr(self, 'fill_pattern'):
-		self.fill_pattern = self.fill_pattern.Copy()
-	    if hasattr(self, 'line_pattern'):
-		self.line_pattern = self.line_pattern.Copy()
-	else:
-	    if name:
-		self.name = name
-	    for key, value in kw.items():
-		setattr(self, key, value)
+        if duplicate is not None:
+            self.__dict__ = duplicate.__dict__.copy()
+            if hasattr(self, 'fill_pattern'):
+                self.fill_pattern = self.fill_pattern.Copy()
+            if hasattr(self, 'line_pattern'):
+                self.line_pattern = self.line_pattern.Copy()
+        else:
+            if name:
+                self.name = name
+            for key, value in kw.items():
+                setattr(self, key, value)
 
     def SetProperty(self, prop, value):
-	dict = self.__dict__
-	if dict.has_key(prop):
-	    undo = (self.SetProperty, prop, dict[prop])
-	else:
-	    undo = (self.DelProperty, prop)
+        dict = self.__dict__
+        if dict.has_key(prop):
+            undo = (self.SetProperty, prop, dict[prop])
+        else:
+            undo = (self.DelProperty, prop)
         if prop == 'fill_pattern' or prop == 'line_pattern':
             value = value.Copy()
-	dict[prop] = value
-	self.issue(CHANGED, self)
-	return undo
+        dict[prop] = value
+        self.issue(CHANGED, self)
+        return undo
 
     def DelProperty(self, prop):
-	undo = (self.SetProperty, prop, getattr(self, prop))
-	delattr(self, prop)
-	self.issue(CHANGED, self)
-	return undo
+        undo = (self.SetProperty, prop, getattr(self, prop))
+        delattr(self, prop)
+        self.issue(CHANGED, self)
+        return undo
 
     def Duplicate(self):
-	if self.is_dynamic:
-	    return self
-	return self.__class__(duplicate = self)
+        if self.is_dynamic:
+            return self
+        return self.__class__(duplicate = self)
 
     def Copy(self):
-	return self.__class__(duplicate = self)
+        return self.__class__(duplicate = self)
 
     def Name(self):
-	return self.name
+        return self.name
 
     def SetName(self, name):
-	undo = self.SetName, self.name
-	self.name = name
-	return undo
+        undo = self.SetName, self.name
+        self.name = name
+        return undo
 
     def AsDynamicStyle(self):
-	result = self.Copy()
-	result.is_dynamic = 1
-	return result
+        result = self.Copy()
+        result.is_dynamic = 1
+        return result
 
     def AsUndynamicStyle(self):
-	result = self.Copy()
-	if self.is_dynamic:
-	    del result.is_dynamic
-	    del result.name
-	return result
+        result = self.Copy()
+        if self.is_dynamic:
+            del result.is_dynamic
+            del result.name
+        return result
 
     def SaveToFile(self, file):
-	if self.is_dynamic:
-	    file.DynamicStyle(self)
+        if self.is_dynamic:
+            file.DynamicStyle(self)
 
     def IsEmpty(self):
-	return not self.__dict__
+        return not self.__dict__
 
 def FillStyle(pattern):
     return Style(fill_pattern = pattern)
@@ -103,11 +103,11 @@
 EmptyFillStyle = Style(fill_pattern = EmptyPattern)
 
 def LineStyle(color = None, width = 0, cap  = const.CapButt,
-	      join  = const.JoinMiter, dashes = None,
-	      arrow1 = None, arrow2 = None):
+              join  = const.JoinMiter, dashes = None,
+              arrow1 = None, arrow2 = None):
     return Style(line_pattern = SolidPattern(color), line_width = width,
-		 line_cap = cap, line_join = join, line_dashes = dashes,
-		 line_arrow1 = arrow1, line_arrow2 = arrow2)
+                 line_cap = cap, line_join = join, line_dashes = dashes,
+                 line_arrow1 = arrow1, line_arrow2 = arrow2)
 
 SolidLine = LineStyle
 EmptyLineStyle = Style(line_pattern = EmptyPattern)
@@ -117,246 +117,246 @@
     update_cache = 1
 
     def __init__(self, base = None, duplicate = None):
-	if duplicate is not None:
-	    self.stack = []
-	    for layer in duplicate.stack:
-		self.stack.append(layer.Duplicate())
-	else:
-	    if base is None:
-		base = factory_defaults.Duplicate()
-	    self.stack = [base]
+        if duplicate is not None:
+            self.stack = []
+            for layer in duplicate.stack:
+                self.stack.append(layer.Duplicate())
+        else:
+            if base is None:
+                base = factory_defaults.Duplicate()
+            self.stack = [base]
 
     def __getattr__(self, attr):
-	if self.update_cache:
-	    cache = self.__dict__
-	    stack = self.stack[:]
-	    stack.reverse()
-	    for layer in stack:
-		cache.update(layer.__dict__)
-	    self.update_cache = 0
-	try:
-	    return self.__dict__[attr]
-	except KeyError:
-	    raise AttributeError, attr
+        if self.update_cache:
+            cache = self.__dict__
+            stack = self.stack[:]
+            stack.reverse()
+            for layer in stack:
+                cache.update(layer.__dict__)
+            self.update_cache = 0
+        try:
+            return self.__dict__[attr]
+        except KeyError:
+            raise AttributeError, attr
 
     def _clear_cache(self):
-	self.__dict__ = {'stack' : self.stack}
-	return (self._clear_cache,)
+        self.__dict__ = {'stack' : self.stack}
+        return (self._clear_cache,)
 
     def prop_layer(self, prop):
-	# return property layer containing PROP
-	for item in self.stack:
-	    if hasattr(item, prop):
-		return item
-	# we should never reach this...
-	raise SketchInternalError('unknown graphics property "%s"' % prop)
+        # return property layer containing PROP
+        for item in self.stack:
+            if hasattr(item, prop):
+                return item
+        # we should never reach this...
+        raise SketchInternalError('unknown graphics property "%s"' % prop)
 
     def set_property(self, prop, value):
-	layer = self.prop_layer(prop)
-	if layer.is_dynamic:
-	    if self.stack[0].is_dynamic:
-		layer = Style()
-		setattr(layer, prop, value)
-		return self.add_layer(layer)
-	    else:
-		layer = self.stack[0]
-	return layer.SetProperty(prop, value)
+        layer = self.prop_layer(prop)
+        if layer.is_dynamic:
+            if self.stack[0].is_dynamic:
+                layer = Style()
+                setattr(layer, prop, value)
+                return self.add_layer(layer)
+            else:
+                layer = self.stack[0]
+        return layer.SetProperty(prop, value)
 
     def SetProperty(self, **kw):
-	stack = self.stack
-	undo = []
-	append = undo.append
-	if len(stack) == 1 and not stack[0].is_dynamic:
-	    set = stack[0].SetProperty
-	    for prop, value in kw.items():
-		append(set(prop, value))
-	else:
-	    set = self.set_property
-	    for prop, value in kw.items():
-		append(set(prop, value))
+        stack = self.stack
+        undo = []
+        append = undo.append
+        if len(stack) == 1 and not stack[0].is_dynamic:
+            set = stack[0].SetProperty
+            for prop, value in kw.items():
+                append(set(prop, value))
+        else:
+            set = self.set_property
+            for prop, value in kw.items():
+                append(set(prop, value))
 
-	if len(self.stack) > 1:
-	    undo_stack = (self.set_stack, self.stack[:])
-	    if self.delete_shadowed_layers():
-		undo.append(undo_stack)
-	undo = CreateListUndo(undo)
-	undo = (UndoAfter, undo, self._clear_cache())
-	return undo
+        if len(self.stack) > 1:
+            undo_stack = (self.set_stack, self.stack[:])
+            if self.delete_shadowed_layers():
+                undo.append(undo_stack)
+        undo = CreateListUndo(undo)
+        undo = (UndoAfter, undo, self._clear_cache())
+        return undo
 
     def set_stack(self, stack):
-	undo = (self.set_stack, self.stack)
-	self.stack = stack
-	self._clear_cache()
-	return undo
+        undo = (self.set_stack, self.stack)
+        self.stack = stack
+        self._clear_cache()
+        return undo
 
     def delete_shadowed_layers(self):
-	# check if some styles are completely hidden now
-	stack = self.stack
-	layers = []
-	dict = {'name':1, 'is_dynamic':0}
-	dict.update(stack[0].__dict__)
-	length = len(dict)
-	for layer in stack[1:]:
-	    dict.update(layer.__dict__)
-	    if length != len(dict):
-		layers.append(layer)
-	    length = len(dict)
-	length = len(stack)
-	stack[1:] = layers
-	return length != len(stack)
+        # check if some styles are completely hidden now
+        stack = self.stack
+        layers = []
+        dict = {'name':1, 'is_dynamic':0}
+        dict.update(stack[0].__dict__)
+        length = len(dict)
+        for layer in stack[1:]:
+            dict.update(layer.__dict__)
+            if length != len(dict):
+                layers.append(layer)
+            length = len(dict)
+        length = len(stack)
+        stack[1:] = layers
+        return length != len(stack)
 
     def add_layer(self, layer):
-	undo = (self.set_stack, self.stack[:])
-	self.stack.insert(0, layer)
-	return undo
+        undo = (self.set_stack, self.stack[:])
+        self.stack.insert(0, layer)
+        return undo
     load_AddStyle = add_layer
 
     def AddStyle(self, style):
-	if style.is_dynamic:
-	    undo = self.add_layer(style)
-	    self.delete_shadowed_layers()
-	    self._clear_cache()
-	    return undo
-	else:
-	    return apply(self.SetProperty, (), style.__dict__)
+        if style.is_dynamic:
+            undo = self.add_layer(style)
+            self.delete_shadowed_layers()
+            self._clear_cache()
+            return undo
+        else:
+            return apply(self.SetProperty, (), style.__dict__)
 
 
     def HasFill(self):
-	return self.fill_pattern is not EmptyPattern
+        return self.fill_pattern is not EmptyPattern
 
     def IsAlgorithmicFill(self):
-	return self.fill_pattern.is_procedural
+        return self.fill_pattern.is_procedural
 
     def ExecuteFill(self, device, rect = None):
-	self.fill_pattern.Execute(device, rect)
+        self.fill_pattern.Execute(device, rect)
 
     def HasLine(self):
-	return self.line_pattern is not EmptyPattern
+        return self.line_pattern is not EmptyPattern
 
     def IsAlgorithmicLine(self):
-	return self.line_pattern.is_procedural
+        return self.line_pattern.is_procedural
 
     def ExecuteLine(self, device, rect = None):
-	line_pattern = self.line_pattern
-	if line_pattern is not EmptyPattern:
-	    line_pattern.Execute(device, rect)
-	    device.SetLineAttributes(self.line_width, self.line_cap,
-				     self.line_join, self.line_dashes)
+        line_pattern = self.line_pattern
+        if line_pattern is not EmptyPattern:
+            line_pattern.Execute(device, rect)
+            device.SetLineAttributes(self.line_width, self.line_cap,
+                                     self.line_join, self.line_dashes)
 
     def HasFont(self):
-	return self.font is not None
+        return self.font is not None
 
     def ObjectChanged(self, object):
-	if object in self.stack:
-	    self._clear_cache()
-	    return 1
-	return 0
+        if object in self.stack:
+            self._clear_cache()
+            return 1
+        return 0
 
     def ObjectRemoved(self, object):
-	if object in self.stack:
-	    idx = self.stack.index(object)
-	    undo = (self.set_stack, self.stack[:])
-	    self.stack[idx] = self.stack[idx].AsUndynamicStyle()
-	    pdebug('properties', 'made style undynamic')
-	    return undo
-	return NullUndo
+        if object in self.stack:
+            idx = self.stack.index(object)
+            undo = (self.set_stack, self.stack[:])
+            self.stack[idx] = self.stack[idx].AsUndynamicStyle()
+            pdebug('properties', 'made style undynamic')
+            return undo
+        return NullUndo
 
     def Untie(self):
-	info = []
-	for i in range(len(self.stack)):
-	    style = self.stack[i]
-	    if style.is_dynamic:
-		self.stack[i] = style.AsUndynamicStyle()
-		info.append((i, style))
-	self._clear_cache()
-	return info
+        info = []
+        for i in range(len(self.stack)):
+            style = self.stack[i]
+            if style.is_dynamic:
+                self.stack[i] = style.AsUndynamicStyle()
+                info.append((i, style))
+        self._clear_cache()
+        return info
 
     def Tie(self, document, info):
-	for i, style in info:
-	    s = document.GetDynamicStyle(style.Name())
-	    if s == style:
-		self.stack[i] = s
-	self._clear_cache()
+        for i, style in info:
+            s = document.GetDynamicStyle(style.Name())
+            if s == style:
+                self.stack[i] = s
+        self._clear_cache()
 
     def Duplicate(self):
-	return self.__class__(duplicate = self)
+        return self.__class__(duplicate = self)
 
 
     grow_join = [5.240843064, 0.5, 0.5]
     grow_cap = [None, 0.5, 0.5, 0.70710678]
 
     def GrowAmount(self):
-	return self.line_width * max(self.grow_cap[self.line_cap],
-				     self.grow_join[self.line_join])
+        return self.line_width * max(self.grow_cap[self.line_cap],
+                                     self.grow_join[self.line_join])
 
     def Blend(self, other, frac1, frac2):
-	result = {}
-	for prop, func in blend_functions:
-	    if func:
-		result[prop] = func(getattr(self, prop), getattr(other, prop),
-				    frac1, frac2)
-	    else:
-		result[prop] = getattr(self, prop)
-	return PropertyStack(apply(Style, (), result))
+        result = {}
+        for prop, func in blend_functions:
+            if func:
+                result[prop] = func(getattr(self, prop), getattr(other, prop),
+                                    frac1, frac2)
+            else:
+                result[prop] = getattr(self, prop)
+        return PropertyStack(apply(Style, (), result))
 
     def Transform(self, trafo, rects):
-	# XXX hardcoding which properties may need to be transformed is
-	# not really a good idea, but it's significantly faster.
-	undo = NullUndo
-	if len(self.stack) == 1 and not self.stack[0].is_dynamic:
-	    if self.fill_transform:
-		pattern = self.fill_pattern
-		if pattern.is_procedural:
-		    undo = pattern.Transform(trafo, rects)
-	elif self.fill_transform:
-	    pattern = self.fill_pattern
-	    if pattern.is_procedural:
-		pattern = pattern.Duplicate()
-		if pattern.Transform(trafo, rects) is not NullUndo:
-		    undo = self.set_property('fill_pattern', pattern)
-	if undo is not NullUndo:
-	    undo = (UndoAfter, undo, self._clear_cache())
-	return undo
+        # XXX hardcoding which properties may need to be transformed is
+        # not really a good idea, but it's significantly faster.
+        undo = NullUndo
+        if len(self.stack) == 1 and not self.stack[0].is_dynamic:
+            if self.fill_transform:
+                pattern = self.fill_pattern
+                if pattern.is_procedural:
+                    undo = pattern.Transform(trafo, rects)
+        elif self.fill_transform:
+            pattern = self.fill_pattern
+            if pattern.is_procedural:
+                pattern = pattern.Duplicate()
+                if pattern.Transform(trafo, rects) is not NullUndo:
+                    undo = self.set_property('fill_pattern', pattern)
+        if undo is not NullUndo:
+            undo = (UndoAfter, undo, self._clear_cache())
+        return undo
 
     def CreateStyle(self, which_properties):
-	properties = {}
-	for prop in which_properties:
+        properties = {}
+        for prop in which_properties:
             if property_types[prop] == FontProperty and not self.HasFont():
                 continue
             properties[prop] = getattr(self, prop)
-	return apply(Style, (), properties)
+        return apply(Style, (), properties)
 
     def DynamicStyleNames(self):
-	names = []
-	for style in self.stack:
-	    if style.is_dynamic:
-		names.append(style.Name())
-	return names
+        names = []
+        for style in self.stack:
+            if style.is_dynamic:
+                names.append(style.Name())
+        return names
 
     def condense(self):
-	stack = self.stack
-	last = stack[0]
-	for style in stack[1:]:
-	    if not last.is_dynamic and not style.is_dynamic:
-		dict = style.__dict__.copy()
-		dict.update(last.__dict__)
-		last.__dict__ = dict
-	    last = style
-	length = len(stack)
-	self.delete_shadowed_layers()
+        stack = self.stack
+        last = stack[0]
+        for style in stack[1:]:
+            if not last.is_dynamic and not style.is_dynamic:
+                dict = style.__dict__.copy()
+                dict.update(last.__dict__)
+                last.__dict__ = dict
+            last = style
+        length = len(stack)
+        self.delete_shadowed_layers()
 
     def SaveToFile(self, file):
-	file.Properties(self)
+        file.Properties(self)
 
 
 class _EmptyProperties:
     def HasFill(self):
-	return 0
+        return 0
     HasLine = HasFill
     HasFont = HasFill
 
     def DynamicStyleNames(self):
-	return []
+        return []
 
 EmptyProperties = _EmptyProperties()
 
@@ -382,38 +382,38 @@
 OtherProperty = -1
 
 def _set_defaults(prop, title, short_title, type, value,
-		  blend = None, transform = 0):
+                  blend = None, transform = 0):
     factory_defaults.SetProperty(prop, value)
     property_names.append(prop)
     property_titles[prop] = (title, short_title)
     property_types[prop] = type
     blend_functions.append((prop, blend))
     if transform:
-	transform_properties.append(prop)
+        transform_properties.append(prop)
 
 black = StandardColors.black
 
 # XXX the default properties should be defined by the user.
 _set_defaults('fill_pattern', _("Fill Pattern"), _("Pattern"), FillProperty,
-	      EmptyPattern, blend = Blend, transform = 1)
+              EmptyPattern, blend = Blend, transform = 1)
 _set_defaults('fill_transform', _("Fill Transform Pattern"),
-	      _("Transform pattern"), FillProperty, 1)
+              _("Transform pattern"), FillProperty, 1)
 _set_defaults('line_pattern', _("Line Pattern"), _("Pattern"), LineProperty,
-	      SolidPattern(black), blend = Blend, transform = 1)
+              SolidPattern(black), blend = Blend, transform = 1)
 _set_defaults('line_width', _("Line Width"), _("Width"), LineProperty, 1 ,
-	      blend = blend_number)
+              blend = blend_number)
 _set_defaults('line_cap', _("Line Cap"), _("Cap"), LineProperty,
-	      const.CapButt)
+              const.CapButt)
 _set_defaults('line_join', _("Line Join"), _("Join"), LineProperty,
-	      const.JoinMiter)
+              const.JoinMiter)
 _set_defaults('line_dashes', _("Line Dashes"), _("Dashes"), LineProperty, ())
 _set_defaults('line_arrow1', _("Line Arrow 1"), _("Arrow 1"), LineProperty,
-	      None)
+              None)
 _set_defaults('line_arrow2', _("Line Arrow 2"), _("Arrow 2"), LineProperty,
-	      None)
+              None)
 _set_defaults('font', _("Font"), _("Font"), FontProperty, None)
 _set_defaults('font_size', _("Font Size"), _("Size"), FontProperty, 12,
-	      blend = blend_number)
+              blend = blend_number)
 
 factory_text_style = factory_defaults.Copy()
 factory_text_style.fill_pattern = SolidPattern(black)
@@ -457,4 +457,4 @@
             if key == 'fill_pattern':
                 value = value.Copy()
             default_text_style.SetProperty(key, value)
-    
+

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/psdevice.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/psdevice.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/psdevice.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -44,8 +44,8 @@
 
 class _DummyLineStyle:
     def Execute(device):
-	device.SetLineColor(color.StandardColors.black)
-	device.SetLineAttributes(1, 0, 1, 0)
+        device.SetLineColor(color.StandardColors.black)
+        device.SetLineAttributes(1, 0, 1, 0)
 
 defaultLineStyle = _DummyLineStyle()
 
@@ -54,8 +54,8 @@
 
 # header comments. Currently the type of all parameters is <textline>
 HeaderComments = [('For', '%%%%For: %s\n'),
-		  ('CreationDate', '%%%%CreationDate: %s\n'),
-		  ('Title', '%%%%Title: %s\n')]
+                  ('CreationDate', '%%%%CreationDate: %s\n'),
+                  ('Title', '%%%%Title: %s\n')]
 
 class PostScriptDevice(CommonDevice):
 
@@ -63,30 +63,30 @@
     draw_printable = 1
 
     file = None # default value for file in case open fails.
-    
+
     def __init__(self, file, as_eps = 1, bounding_box = None,
-		 document = None, printable = 1, visible = 0, rotate = 0,
+                 document = None, printable = 1, visible = 0, rotate = 0,
                  embed_fonts = 0, **options):
-	if as_eps and not bounding_box:
-	    raise ValueError, 'bounding_box required for EPS'
+        if as_eps and not bounding_box:
+            raise ValueError, 'bounding_box required for EPS'
 
-	self.fill = 0; self.line = 0
-	self.properties = None
-	self.line = defaultLineStyle
-	self.as_eps = as_eps
-	self.needed_resources = {}
-	self.include_resources = {}
-	self.supplied_resources = []
-	self.draw_visible = visible
-	self.draw_printable = printable
-	self.gradient_steps = config.preferences.gradient_steps_print
-	self.init_props()
+        self.fill = 0; self.line = 0
+        self.properties = None
+        self.line = defaultLineStyle
+        self.as_eps = as_eps
+        self.needed_resources = {}
+        self.include_resources = {}
+        self.supplied_resources = []
+        self.draw_visible = visible
+        self.draw_printable = printable
+        self.gradient_steps = config.preferences.gradient_steps_print
+        self.init_props()
 
-	if document:
-	    document.WalkHierarchy(self.add_obj_resources,
-				   visible = self.draw_visible,
-				   printable = self.draw_printable)
-	    self.needed_resources.update(self.include_resources)
+        if document:
+            document.WalkHierarchy(self.add_obj_resources,
+                                   visible = self.draw_visible,
+                                   printable = self.draw_printable)
+            self.needed_resources.update(self.include_resources)
 
         # take care of the case where we're writing to an EPS that's
         # referenced by the document. This is a bit tricky. If the file
@@ -111,74 +111,74 @@
                                    printable = self.draw_printable)
 
         if type(file) == StringType:
-	    file = open(file, 'w')
-	    self.close_file = 1
-	else:
-	    self.close_file = 0
-	self.file = file
+            file = open(file, 'w')
+            self.close_file = 1
+        else:
+            self.close_file = 0
+        self.file = file
 
-	if rotate:
-	    width, height = document.PageSize()
-	    llx, lly, urx, ury = bounding_box
-	    bounding_box = (height - ury, llx, height - lly, urx)
+        if rotate:
+            width, height = document.PageSize()
+            llx, lly, urx, ury = bounding_box
+            bounding_box = (height - ury, llx, height - lly, urx)
 
-	write = file.write
-	if as_eps:
-	    write("%!PS-Adobe-3.0 EPSF-3.0\n")
-	else:
-	    write("%!PS-Adobe-3.0\n")
-	# header comments
-	for name, format in HeaderComments:
-	    if options.has_key(name):
-		value = options[name]
-		if value:
-		    write(format % make_textline(value))
-	write("%%%%Creator: Skencil %s\n" % SketchVersion)
-	write("%%Pages: 1\n")	# there is exactly one page
-	if bounding_box:
-	    [llx, lly, urx, ury] = map(int, bounding_box)
-	    write('%%%%BoundingBox: %d %d %d %d\n'
-		  % (llx - 1, lly - 1, urx + 1, ury + 1))
+        write = file.write
+        if as_eps:
+            write("%!PS-Adobe-3.0 EPSF-3.0\n")
+        else:
+            write("%!PS-Adobe-3.0\n")
+        # header comments
+        for name, format in HeaderComments:
+            if options.has_key(name):
+                value = options[name]
+                if value:
+                    write(format % make_textline(value))
+        write("%%%%Creator: Skencil %s\n" % SketchVersion)
+        write("%%Pages: 1\n")	# there is exactly one page
+        if bounding_box:
+            [llx, lly, urx, ury] = map(int, bounding_box)
+            write('%%%%BoundingBox: %d %d %d %d\n'
+                  % (llx - 1, lly - 1, urx + 1, ury + 1))
 
         if rotate and document.Layout().Orientation() == pagelayout.Landscape:
             write("%%Orientation: Landscape\n")
 
-	# XXX The Extensions comment should take embedded EPS files into
-	# account. (the colorimage operator should be optional)
-	write("%%Extensions: CMYK\n")
+        # XXX The Extensions comment should take embedded EPS files into
+        # account. (the colorimage operator should be optional)
+        write("%%Extensions: CMYK\n")
 
-	write("%%DocumentSuppliedResources: (atend)\n")
+        write("%%DocumentSuppliedResources: (atend)\n")
 
-	if self.needed_resources:
+        if self.needed_resources:
             start_written = 0
-	    for restype, value in self.needed_resources.keys():
+            for restype, value in self.needed_resources.keys():
                 if restype == 'font' and embed_fonts:
                     continue
-		if not start_written:
-		    write('%%%%DocumentNeededResources: %s %s\n'
+                if not start_written:
+                    write('%%%%DocumentNeededResources: %s %s\n'
                           % (restype, value))
-		else:
-		    write('%%%%+ %s %s\n' % (restype, value))
+                else:
+                    write('%%%%+ %s %s\n' % (restype, value))
 
-	write("%%EndComments\n\n")
+        write("%%EndComments\n\n")
 
-	write('%%BeginProlog\n')
-	procfile = os.path.join(config.sketch_dir, config.postscript_prolog)
-	procfile = open(procfile, 'r')
-	line = procfile.readline()
-	self.supplied_resources.append(join(split(strip(line))[1:]))
-	write(line)
-	for line in map(lstrip, procfile.readlines()):
-	    if line and line[0] != '%':
-		write(line)
-	write('%%EndResource\n')
-	procfile.close()
+        write('%%BeginProlog\n')
+        procfile = os.path.join(config.sketch_dir, config.postscript_prolog)
+        procfile = open(procfile, 'r')
+        line = procfile.readline()
+        self.supplied_resources.append(join(split(strip(line))[1:]))
+        write(line)
+        for line in map(lstrip, procfile.readlines()):
+            if line and line[0] != '%':
+                write(line)
+        write('%%EndResource\n')
+        procfile.close()
 
-	write('%%EndProlog\n\n')
+        write('%%EndProlog\n\n')
 
-	write('%%BeginSetup\n')
-	if self.needed_resources:
-	    for res in self.include_resources.keys():
+        write('%%BeginSetup\n')
+        if self.needed_resources:
+            for res in self.include_resources.keys():
                 restype, value = res
                 if restype == 'font' and embed_fonts:
                     fontfile = font.GetFont(value).FontFileName()
@@ -199,27 +199,27 @@
                              _("Can't find file for font '%s' for embedding")
                              % value)
                 write('%%%%IncludeResource: %s %s\n' % res)
-	write('\n10.433 setmiterlimit\n')	# 11 degree
-	write('%%EndSetup\n\n')
+        write('\n10.433 setmiterlimit\n')	# 11 degree
+        write('%%EndSetup\n\n')
 
-	write('%%Page: 1 1\n')
-	write('SketchDict begin\n')
-	if rotate:
-	    self.Rotate(pi/2)
-	    self.Translate(0, -height)
+        write('%%Page: 1 1\n')
+        write('SketchDict begin\n')
+        if rotate:
+            self.Rotate(pi/2)
+            self.Translate(0, -height)
 
     def init_props(self):
-	self.init_line_props()
-	self.init_color_props()
-	self.init_font_props()
+        self.init_line_props()
+        self.init_color_props()
+        self.init_font_props()
 
     def add_obj_resources(self, obj):
-	# append reources from OBJ to self.needed_resources
-	if obj.has_font:
-	    res = ('font', obj.Font().PostScriptName())
-	    self.include_resources[res] = 1
-	if obj.is_Eps:
-	    self.needed_resources.update(obj.PSNeededResources())
+        # append reources from OBJ to self.needed_resources
+        if obj.has_font:
+            res = ('font', obj.Font().PostScriptName())
+            self.include_resources[res] = 1
+        if obj.is_Eps:
+            self.needed_resources.update(obj.PSNeededResources())
 
     def handle_writes_to_embedded_eps(self, obj):
         if obj.is_Eps:
@@ -235,360 +235,360 @@
 
     trailer_written = 0
     def Close(self):
-	if self.file is not None and not self.file.closed:
-	    if not self.trailer_written:
-		write = self.file.write
-		write('%%PageTrailer\n')
-		write('showpage\n')
-		write('%%Trailer\n')
-		write('end\n')
-		if self.supplied_resources:
-		    write('%%%%DocumentSuppliedResources: %s\n'
-			  % self.supplied_resources[0])
-		    for res in self.supplied_resources[1:]:
-			write('%%%%+ %s\n' % res)
+        if self.file is not None and not self.file.closed:
+            if not self.trailer_written:
+                write = self.file.write
+                write('%%PageTrailer\n')
+                write('showpage\n')
+                write('%%Trailer\n')
+                write('end\n')
+                if self.supplied_resources:
+                    write('%%%%DocumentSuppliedResources: %s\n'
+                          % self.supplied_resources[0])
+                    for res in self.supplied_resources[1:]:
+                        write('%%%%+ %s\n' % res)
 
-		write('%%EOF\n')
-		self.trailer_written = 1
-	    if self.close_file:
-		self.file.close()
+                write('%%EOF\n')
+                self.trailer_written = 1
+            if self.close_file:
+                self.file.close()
 
     def __del__(self):
-	try:
-	    self.Close()
-	except:
-	    warn_tb(INTERNAL, "In __del__ of psdevice")
+        try:
+            self.Close()
+        except:
+            warn_tb(INTERNAL, "In __del__ of psdevice")
 
     def PushTrafo(self):
-	self.file.write('pusht\n')
+        self.file.write('pusht\n')
 
     def Concat(self, trafo):
-	self.file.write('[%g %g %g %g %g %g] concat\n'
-			% (trafo.m11, trafo.m21, trafo.m12, trafo.m22,
-			   trafo.v1, trafo.v2))
+        self.file.write('[%g %g %g %g %g %g] concat\n'
+                        % (trafo.m11, trafo.m21, trafo.m12, trafo.m22,
+                           trafo.v1, trafo.v2))
 
     def Translate(self, x, y = None):
-	if y is None:
-	    x, y = x
-	self.file.write('%g %g translate\n' % (x, y))
+        if y is None:
+            x, y = x
+        self.file.write('%g %g translate\n' % (x, y))
 
     def Rotate(self, angle):
-	self.file.write('%g rotate\n' % (angle * 180 / pi))
+        self.file.write('%g rotate\n' % (angle * 180 / pi))
 
     def Scale(self, scale):
-	self.file.write('%g dup scale\n' % scale)
+        self.file.write('%g dup scale\n' % scale)
 
     def PopTrafo(self):
-	self.file.write('popt\n')
+        self.file.write('popt\n')
 
     def PushClip(self):
-	self.file.write('pushc\n')
+        self.file.write('pushc\n')
 
     def PopClip(self):
-	self.file.write('popc\n')
-	# popc is grestore. make sure properties are set properly again
-	# after this.
-	self.init_props()
+        self.file.write('popc\n')
+        # popc is grestore. make sure properties are set properly again
+        # after this.
+        self.init_props()
 
     def init_color_props(self):
-	self.current_color = None
+        self.current_color = None
 
     def _set_color(self, color):
-	if self.current_color != color:
-	    r, g, b = color
-	    self.file.write('%g %g %g rgb\n'
-			    % (round(r, 3), round(g, 3), round(b, 3)))
-	    self.current_color = color
+        if self.current_color != color:
+            r, g, b = color
+            self.file.write('%g %g %g rgb\n'
+                            % (round(r, 3), round(g, 3), round(b, 3)))
+            self.current_color = color
 
     SetFillColor = _set_color
     SetLineColor = _set_color
 
     def init_line_props(self):
-	self.current_width = self.current_cap = self.current_join = None
-	self.current_dash = None
+        self.current_width = self.current_cap = self.current_join = None
+        self.current_dash = None
 
     def SetLineAttributes(self, width, cap = 1, join = 0, dashes = ()):
-	write = self.file.write
-	if self.current_width != width:
+        write = self.file.write
+        if self.current_width != width:
             width_changed = 1
-	    write('%g w\n' % width)
-	    self.current_width = width
+            write('%g w\n' % width)
+            self.current_width = width
         else:
             width_changed = 0
-	join = ps_join[join]
-	if self.current_join != join:
-	    write('%d j\n' % join)
-	    self.current_join = join
-	cap = ps_cap[cap]
-	if self.current_cap != cap:
-	    write('%d J\n' % cap)
-	    self.current_cap = cap
+        join = ps_join[join]
+        if self.current_join != join:
+            write('%d j\n' % join)
+            self.current_join = join
+        cap = ps_cap[cap]
+        if self.current_cap != cap:
+            write('%d J\n' % cap)
+            self.current_cap = cap
 
-	if self.current_dash != dashes or width_changed:
-	    # for long dashes tuples this could theoretically produce
-	    # lines longer than 255 chars, which means that the file
-	    # would not conform to the DSC
-	    if width < 1:
-		width = 1
-	    write('[')
-	    for dash in dashes:
-		dash = width * dash
-		if dash < 0.001:
-		    dash = 0.001
-		write('%g ' % dash)
-	    write('] 0 d\n')
-	    self.current_dash = dashes
+        if self.current_dash != dashes or width_changed:
+            # for long dashes tuples this could theoretically produce
+            # lines longer than 255 chars, which means that the file
+            # would not conform to the DSC
+            if width < 1:
+                width = 1
+            write('[')
+            for dash in dashes:
+                dash = width * dash
+                if dash < 0.001:
+                    dash = 0.001
+                write('%g ' % dash)
+            write('] 0 d\n')
+            self.current_dash = dashes
 
     def SetLineSolid(self):
-	self.file.write('[ ] 0 d\n')
-	self.current_dash = ()
+        self.file.write('[ ] 0 d\n')
+        self.current_dash = ()
 
     def DrawLine(self, start, end):
-	self.file.write('%g %g m %g %g l s\n' % (tuple(start) + tuple(end)))
+        self.file.write('%g %g m %g %g l s\n' % (tuple(start) + tuple(end)))
 
     def DrawLineXY(self, x1, y1, x2, y2):
-	self.file.write('%g %g m %g %g l s\n' % (x1, y1, x2, y2))
+        self.file.write('%g %g m %g %g l s\n' % (x1, y1, x2, y2))
 
     def DrawRectangle(self, start, end):
-	self.file.write('%g %g %g %g R s\n' % (tuple(start) + tuple(end)))
+        self.file.write('%g %g %g %g R s\n' % (tuple(start) + tuple(end)))
 
     def FillRectangle(self, left, bottom, right, top):
-	self.file.write('%g %g %g %g R f\n' % (left, bottom, right, top))
+        self.file.write('%g %g %g %g R f\n' % (left, bottom, right, top))
 
     def DrawCircle(self, center, radius):
-	self.file.write('%g %g %g C s\n' % (center.x, center.y, radius))
+        self.file.write('%g %g %g C s\n' % (center.x, center.y, radius))
 
     def FillCircle(self, center, radius):
-	self.file.write('%g %g %g C f\n' % (center.x, center.y, radius))
+        self.file.write('%g %g %g C f\n' % (center.x, center.y, radius))
 
     def FillPolygon(self, pts):
-	write = self.file.write
-	if len(pts) > 1:
-	    write('%g %g m\n' % pts[0])
-	    for p in pts[1:]:
-		write('%g %g l\n' % p)
-	    write('f\n')
+        write = self.file.write
+        if len(pts) > 1:
+            write('%g %g m\n' % pts[0])
+            for p in pts[1:]:
+                write('%g %g l\n' % p)
+            write('f\n')
 
     def DrawBezierPath(self, path, rect = None):
-	self.write_path(path.get_save())
-	self.file.write('S\n')
+        self.write_path(path.get_save())
+        self.file.write('S\n')
 
     def FillBezierPath(self, path, rect = None):
-	self.write_path(path.get_save())
-	self.file.write('F\n')
+        self.write_path(path.get_save())
+        self.file.write('F\n')
 
     def fill_path(self, clip = 0):
-	write = self.file.write
-	if self.proc_fill:
-	    if not clip:
-		self.PushClip()
-	    write('eoclip newpath\n')
-	    self.properties.ExecuteFill(self, self.pattern_rect)
-	    if not clip:
-		self.PopClip()
-		write('newpath\n')
-	else:
-	    self.properties.ExecuteFill(self, self.pattern_rect)
-	    if not clip:
-		write('F\n')
-	    else:
-		write('gsave F grestore eoclip newpath\n')
+        write = self.file.write
+        if self.proc_fill:
+            if not clip:
+                self.PushClip()
+            write('eoclip newpath\n')
+            self.properties.ExecuteFill(self, self.pattern_rect)
+            if not clip:
+                self.PopClip()
+                write('newpath\n')
+        else:
+            self.properties.ExecuteFill(self, self.pattern_rect)
+            if not clip:
+                write('F\n')
+            else:
+                write('gsave F grestore eoclip newpath\n')
 
     def stroke_path(self):
-	self.properties.ExecuteLine(self, self.pattern_rect)
-	self.file.write('S\n')
+        self.properties.ExecuteLine(self, self.pattern_rect)
+        self.file.write('S\n')
 
     def fill_and_stroke(self, clip = 0):
-	write = self.file.write
+        write = self.file.write
 
-	if not clip and self.line:
-	    if self.fill:
-		write('gsave\n')
-		self.fill_path()
-		write('grestore\n')
+        if not clip and self.line:
+            if self.fill:
+                write('gsave\n')
+                self.fill_path()
+                write('grestore\n')
                 self.init_props()
-		self.stroke_path()
-	    else:
-		self.stroke_path()
-	else:
-	    if self.fill:
-		self.fill_path(clip)
-	    elif clip:
-		write('eoclip newpath\n')
+                self.stroke_path()
+            else:
+                self.stroke_path()
+        else:
+            if self.fill:
+                self.fill_path(clip)
+            elif clip:
+                write('eoclip newpath\n')
 
 
     def write_path(self, list):
-	write = self.file.write
-	write('%g %g m\n' % list[0][:-1])
-	for item in list[1:]:
-	    if len(item) == 3:
-		write('%g %g l\n' % item[:-1])
-	    elif len(item) == 7:
-		write('%g %g %g %g %g %g c\n' % item[:-1])
-	    else:
-		if __debug__:
-		    pdebug('PS', 'PostScriptDevice: invalid bezier item:',item)
+        write = self.file.write
+        write('%g %g m\n' % list[0][:-1])
+        for item in list[1:]:
+            if len(item) == 3:
+                write('%g %g l\n' % item[:-1])
+            elif len(item) == 7:
+                write('%g %g %g %g %g %g c\n' % item[:-1])
+            else:
+                if __debug__:
+                    pdebug('PS', 'PostScriptDevice: invalid bezier item:',item)
 
     def MultiBezier(self, paths, rect = None, clip = 0):
-	# XXX: try to write path only once
-	write = self.file.write
-	line = self.line; fill = self.fill
+        # XXX: try to write path only once
+        write = self.file.write
+        line = self.line; fill = self.fill
 
-	if line or fill or clip:
-	    open = 0
-	    for path in paths:
-		open = open or not path.closed
+        if line or fill or clip:
+            open = 0
+            for path in paths:
+                open = open or not path.closed
 
-	    write('newpath\n')
-	    if fill or clip:
-		if not open:
-		    # all subpaths are closed
-		    for path in paths:
-			self.write_path(path.get_save())
-			write('closepath\n')
-		    self.fill_and_stroke(clip)
-		    line = 0
-		else:
-		    # some but not all sub paths are closed
-		    for path in paths:
-			self.write_path(path.get_save())
-			if not path.closed:
-			    write('closepath\n')
-		    self.fill_path(clip)
+            write('newpath\n')
+            if fill or clip:
+                if not open:
+                    # all subpaths are closed
+                    for path in paths:
+                        self.write_path(path.get_save())
+                        write('closepath\n')
+                    self.fill_and_stroke(clip)
+                    line = 0
+                else:
+                    # some but not all sub paths are closed
+                    for path in paths:
+                        self.write_path(path.get_save())
+                        if not path.closed:
+                            write('closepath\n')
+                    self.fill_path(clip)
 
-	    if line:
-		for path in paths:
-		    self.write_path(path.get_save())
-		    if path.closed:
-			write('closepath\n')
-		self.stroke_path()
-		self.draw_arrows(paths)
+            if line:
+                for path in paths:
+                    self.write_path(path.get_save())
+                    if path.closed:
+                        write('closepath\n')
+                self.stroke_path()
+                self.draw_arrows(paths)
 
     def Rectangle(self, trafo, clip = 0):
-	if self.fill or self.line or clip:
-	    self.file.write('[%g %g %g %g %g %g] rect\n' % trafo.coeff())
-	    self.fill_and_stroke(clip)
+        if self.fill or self.line or clip:
+            self.file.write('[%g %g %g %g %g %g] rect\n' % trafo.coeff())
+            self.fill_and_stroke(clip)
 
     def RoundedRectangle(self, trafo, radius1, radius2, clip = 0):
-	if self.fill or self.line or clip:
-	    self.file.write('[%g %g %g %g %g %g] %g %g rect\n'
+        if self.fill or self.line or clip:
+            self.file.write('[%g %g %g %g %g %g] %g %g rect\n'
                             % (trafo.coeff() + (radius1, radius2)))
-	    self.fill_and_stroke(clip)
+            self.fill_and_stroke(clip)
 
     def SimpleEllipse(self, trafo, start_angle, end_angle, arc_type,
-		      rect = None, clip = 0):
-	if self.fill or self.line or clip:
-	    if start_angle == end_angle:
-		self.file.write('[%g %g %g %g %g %g] ellipse\n'
-				% trafo.coeff())
-		self.fill_and_stroke(clip)
-	    else:
-		self.file.write('[%g %g %g %g %g %g] %g %g %d ellipse\n' %
-				(trafo.coeff()
-				 + (start_angle, end_angle, arc_type)))
-		self.fill_and_stroke(clip)
-	    self.draw_ellipse_arrows(trafo, start_angle, end_angle, arc_type,
-				     rect)
+                      rect = None, clip = 0):
+        if self.fill or self.line or clip:
+            if start_angle == end_angle:
+                self.file.write('[%g %g %g %g %g %g] ellipse\n'
+                                % trafo.coeff())
+                self.fill_and_stroke(clip)
+            else:
+                self.file.write('[%g %g %g %g %g %g] %g %g %d ellipse\n' %
+                                (trafo.coeff()
+                                 + (start_angle, end_angle, arc_type)))
+                self.fill_and_stroke(clip)
+            self.draw_ellipse_arrows(trafo, start_angle, end_angle, arc_type,
+                                     rect)
 
     def init_font_props(self):
-	self.current_font = None
+        self.current_font = None
 
     def set_font(self, font, size):
-	spec = (font.PostScriptName(), size)
-	if self.current_font != spec:
-	    self.file.write('/%s %g sf\n' % spec)
-	    self.current_font = spec
+        spec = (font.PostScriptName(), size)
+        if self.current_font != spec:
+            self.file.write('/%s %g sf\n' % spec)
+            self.current_font = spec
 
     def DrawText(self, text, trafo, clip = 0, cache = None):
-	# XXX: should make sure that lines in eps file will not be
-	# longer than 255 characters.
-	font = self.properties.font
-	if font:
-	    write = self.file.write
-	    self.set_font(font, self.properties.font_size)
-	    write('(%s)\n' % quote_ps_string(text))
-	    if trafo.matrix() == IdentityMatrix:
-		write('%g %g ' % tuple(trafo.offset()))
-	    else:
-		write('[%g %g %g %g %g %g] ' % trafo.coeff())
-	    if self.proc_fill:
-		write('P ')
-		write('gsave clip newpath\n')
-		self.properties.ExecuteFill(self, self.pattern_rect)
-		write('grestore ')
-		if clip:
-		    write('clip ')
-		write('newpath\n')
-	    else:
-		self.properties.ExecuteFill(self, self.pattern_rect)
-		if clip:
-		    write('TP clip newpath\n')
-		else:
-		    write('T\n')
+        # XXX: should make sure that lines in eps file will not be
+        # longer than 255 characters.
+        font = self.properties.font
+        if font:
+            write = self.file.write
+            self.set_font(font, self.properties.font_size)
+            write('(%s)\n' % quote_ps_string(text))
+            if trafo.matrix() == IdentityMatrix:
+                write('%g %g ' % tuple(trafo.offset()))
+            else:
+                write('[%g %g %g %g %g %g] ' % trafo.coeff())
+            if self.proc_fill:
+                write('P ')
+                write('gsave clip newpath\n')
+                self.properties.ExecuteFill(self, self.pattern_rect)
+                write('grestore ')
+                if clip:
+                    write('clip ')
+                write('newpath\n')
+            else:
+                self.properties.ExecuteFill(self, self.pattern_rect)
+                if clip:
+                    write('TP clip newpath\n')
+                else:
+                    write('T\n')
 
     complex_text = None
     def BeginComplexText(self, clip = 0, cache = None):
-	# XXX clip does not work yet...
-	self.complex_text = Empty(clip = clip, fontname = '', size = None)
-	if self.proc_fill or clip:
-	    self.PushClip()
-	else:
-	    self.properties.ExecuteFill(self, self.pattern_rect)
+        # XXX clip does not work yet...
+        self.complex_text = Empty(clip = clip, fontname = '', size = None)
+        if self.proc_fill or clip:
+            self.PushClip()
+        else:
+            self.properties.ExecuteFill(self, self.pattern_rect)
 
     def DrawComplexText(self, text, trafo, font, font_size):
-	write = self.file.write
-	complex_text = self.complex_text
-	self.set_font(font, font_size)
-	write('(%s) ' % quote_ps_string(text))
-	if trafo.matrix() == IdentityMatrix:
-	    write('%g %g ' % tuple(trafo.offset()))
-	else:
-	    write('[%g %g %g %g %g %g] ' % trafo.coeff())
-	if self.proc_fill:
-	    write('P\n')
-	else:
-	    write('T\n')
+        write = self.file.write
+        complex_text = self.complex_text
+        self.set_font(font, font_size)
+        write('(%s) ' % quote_ps_string(text))
+        if trafo.matrix() == IdentityMatrix:
+            write('%g %g ' % tuple(trafo.offset()))
+        else:
+            write('[%g %g %g %g %g %g] ' % trafo.coeff())
+        if self.proc_fill:
+            write('P\n')
+        else:
+            write('T\n')
 
     def EndComplexText(self):
-	if self.proc_fill:
-	    self.file.write('eoclip newpath\n')
-	    self.properties.ExecuteFill(self, self.pattern_rect)
-	    self.PopClip()
-	self.complex_text = None
+        if self.proc_fill:
+            self.file.write('eoclip newpath\n')
+            self.properties.ExecuteFill(self, self.pattern_rect)
+            self.PopClip()
+        self.complex_text = None
 
 
     def DrawImage(self, image, trafo, clip = 0):
-	write = self.file.write
-	w, h = image.size
-	if len(image.mode) >= 3:
-	    # compute number of hex lines. 80 hex digits per line. 3 bytes
-	    # per pixel
-	    digits = w * h * 6	# 3 bytes per pixel, 2 digits per byte
-	    if digits <= 0:
-		# an empty image. (it should never be < 0 ...)
-		return
-	    lines = (digits - 1) / 80 + 1
-	    write('%d %d ' % image.size)
-	    write('[%g %g %g %g %g %g] true\n' % trafo.coeff())
-	    write('%%%%BeginData: %d Hex Lines\n' % (lines + 1))
-	    write('skcimg\n')
-	else:
-	    digits = w * h * 2	# 2 digits per byte
-	    if digits <= 0:
-		# an empty image. (it should never be < 0 ...)
-		return
-	    lines = (digits - 1) / 80 + 1
-	    write('%d %d ' % image.size)
-	    write('[%g %g %g %g %g %g] true\n' % trafo.coeff())
-	    write('%%%%BeginData: %d Hex Lines\n' % (lines + 1))
-	    write('skgimg\n')
+        write = self.file.write
+        w, h = image.size
+        if len(image.mode) >= 3:
+            # compute number of hex lines. 80 hex digits per line. 3 bytes
+            # per pixel
+            digits = w * h * 6	# 3 bytes per pixel, 2 digits per byte
+            if digits <= 0:
+                # an empty image. (it should never be < 0 ...)
+                return
+            lines = (digits - 1) / 80 + 1
+            write('%d %d ' % image.size)
+            write('[%g %g %g %g %g %g] true\n' % trafo.coeff())
+            write('%%%%BeginData: %d Hex Lines\n' % (lines + 1))
+            write('skcimg\n')
+        else:
+            digits = w * h * 2	# 2 digits per byte
+            if digits <= 0:
+                # an empty image. (it should never be < 0 ...)
+                return
+            lines = (digits - 1) / 80 + 1
+            write('%d %d ' % image.size)
+            write('[%g %g %g %g %g %g] true\n' % trafo.coeff())
+            write('%%%%BeginData: %d Hex Lines\n' % (lines + 1))
+            write('skgimg\n')
 
-	_sketch.write_ps_hex(image.im, self.file)
-	write('%%EndData\n')
-	if clip:
-	    write('pusht [%g %g %g %g %g %g] concat\n' % trafo.coeff())
-	    write('%d %d scale\n' % image.size)
-	    write('0 0 m  1 0 l	 1 1 l	0 1 l closepath popt clip\n')
+        _sketch.write_ps_hex(image.im, self.file)
+        write('%%EndData\n')
+        if clip:
+            write('pusht [%g %g %g %g %g %g] concat\n' % trafo.coeff())
+            write('%d %d scale\n' % image.size)
+            write('0 0 m  1 0 l	 1 1 l	0 1 l closepath popt clip\n')
 
 
     def DrawEps(self, data, trafo):
@@ -608,82 +608,82 @@
         pass
 
     def DrawGuideLine(self, *args):
-	pass
+        pass
 
     def SetProperties(self, properties, rect = None):
-	self.properties = properties
-	self.line = properties.HasLine()
-	self.fill = properties.HasFill()
-	self.pattern_rect = rect
-	self.proc_fill = properties.IsAlgorithmicFill()
-	self.proc_line = properties.IsAlgorithmicLine()
+        self.properties = properties
+        self.line = properties.HasLine()
+        self.fill = properties.HasFill()
+        self.pattern_rect = rect
+        self.proc_fill = properties.IsAlgorithmicFill()
+        self.proc_line = properties.IsAlgorithmicLine()
 
 
     def write_gradient(self, gradient):
-	# self.current_color is implicitly reset because gradients are
-	# nested in a PushClip/PopClip, so we don't have to update that
-	write = self.file.write
-	samples = gradient.Sample(self.gradient_steps)
-	write('%d gradient\n' % len(samples))
-	last = None
-	for color in samples:
-	    if color != last:
-		r, g, b = last = color
-		write('%g %g %g $\n' % (round(r, 3), round(g, 3), round(b, 3)))
-	    else:
-		write('!\n')
+        # self.current_color is implicitly reset because gradients are
+        # nested in a PushClip/PopClip, so we don't have to update that
+        write = self.file.write
+        samples = gradient.Sample(self.gradient_steps)
+        write('%d gradient\n' % len(samples))
+        last = None
+        for color in samples:
+            if color != last:
+                r, g, b = last = color
+                write('%g %g %g $\n' % (round(r, 3), round(g, 3), round(b, 3)))
+            else:
+                write('!\n')
 
     has_axial_gradient = 1
     def AxialGradient(self, gradient, p0, p1):
-	# must accept p0 and p1 as PointSpecs
-	self.write_gradient(gradient)
-	self.file.write('%g %g %g %g axial\n' % (tuple(p0) + tuple(p1)))
+        # must accept p0 and p1 as PointSpecs
+        self.write_gradient(gradient)
+        self.file.write('%g %g %g %g axial\n' % (tuple(p0) + tuple(p1)))
 
     has_radial_gradient = 1
     def RadialGradient(self, gradient, p, r0, r1):
-	# must accept p as PointSpec
-	self.write_gradient(gradient)
-	self.file.write('%g %g %g %g radial\n' % (tuple(p) + (r0, r1)))
+        # must accept p as PointSpec
+        self.write_gradient(gradient)
+        self.file.write('%g %g %g %g radial\n' % (tuple(p) + (r0, r1)))
 
     has_conical_gradient = 1
     def ConicalGradient(self, gradient, p, angle):
-	# must accept p as PointSpec
-	self.write_gradient(gradient)
-	self.file.write('%g %g %g conical\n' % (tuple(p) + (angle,)))
+        # must accept p as PointSpec
+        self.write_gradient(gradient)
+        self.file.write('%g %g %g conical\n' % (tuple(p) + (angle,)))
 
     def TileImage(self, image, trafo):
-	width, height = image.size
+        width, height = image.size
         if image.mode == 'RGBA':
             # We don't support transparency in textures, so we simply
             # treat RGBA as as RGB images
             mode = 'RGB'
         else:
             mode = image.mode
-	length = width * height * len(mode)
-	if length > 65536:
-	    # the tile image is too large to fit into a PostScript
-	    # string. Resize it.
-	    #warn(USER, "Image data to big for tiling, resizing...")
-	    ratio = float(width) / height
-	    max_size = 65536 / len(mode)
-	    width = int(sqrt(max_size * ratio))
-	    height = int(sqrt(max_size / ratio))
-	    tile = image.im.resize((width, height))
-	    length = width * height * len(mode)
-	    trafo = trafo(Scale(float(image.size[0]) / width,
-				float(image.size[1]) / height))
-	else:
-	    tile = image.im
-	write = self.file.write
-	write('%d %d %d [%g %g %g %g %g %g]\n'
-	      % ((width, height, len(mode)) + trafo.coeff()))
-	digits = length * 2	# 2 digits per byte
-	lines = (digits - 1) / 80 + 1
-	write('%%%%BeginData: %d Hex Lines\n' % (lines + 1))
-	write("tileimage\n")
+        length = width * height * len(mode)
+        if length > 65536:
+            # the tile image is too large to fit into a PostScript
+            # string. Resize it.
+            #warn(USER, "Image data to big for tiling, resizing...")
+            ratio = float(width) / height
+            max_size = 65536 / len(mode)
+            width = int(sqrt(max_size * ratio))
+            height = int(sqrt(max_size / ratio))
+            tile = image.im.resize((width, height))
+            length = width * height * len(mode)
+            trafo = trafo(Scale(float(image.size[0]) / width,
+                                float(image.size[1]) / height))
+        else:
+            tile = image.im
+        write = self.file.write
+        write('%d %d %d [%g %g %g %g %g %g]\n'
+              % ((width, height, len(mode)) + trafo.coeff()))
+        digits = length * 2	# 2 digits per byte
+        lines = (digits - 1) / 80 + 1
+        write('%%%%BeginData: %d Hex Lines\n' % (lines + 1))
+        write("tileimage\n")
         # write_ps_hex treats RGBA like RGB
-	_sketch.write_ps_hex(tile, self.file)
-	write('%%EndData\n')
+        _sketch.write_ps_hex(tile, self.file)
+        write('%%EndData\n')
 
     #
     #	Outline Mode
@@ -691,10 +691,10 @@
     #
 
     def StartOutlineMode(self, *rest):
-	pass
+        pass
 
     def EndOutlineMode(self, *rest):
-	pass
+        pass
 
     def IsOutlineActive(self, *rest):
-	return 0
+        return 0

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/rectangle.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/rectangle.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/rectangle.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -51,7 +51,7 @@
 
     def __init__(self, trafo = None, radius1 = 0, radius2 = 0,
                  properties = None, duplicate = None):
-	RectangularPrimitive.__init__(self, trafo, properties = properties,
+        RectangularPrimitive.__init__(self, trafo, properties = properties,
                                       duplicate = duplicate)
         if duplicate is not None:
             self.radius1 = duplicate.radius1
@@ -81,7 +81,7 @@
         return undo
 
     def DrawShape(self, device, rect = None, clip = 0):
-	Primitive.DrawShape(self, device)
+        Primitive.DrawShape(self, device)
         if self.radius1 == self.radius2 == 0:
             device.Rectangle(self.trafo, clip)
         else:
@@ -99,7 +99,7 @@
         return self.rect_path
 
     def AsBezier(self):
-	return PolyBezier(paths = self.rect_path,
+        return PolyBezier(paths = self.rect_path,
                           properties = self.properties.Duplicate())
 
     def Hit(self, p, rect, device, clip = 0):
@@ -116,16 +116,16 @@
         return map(self.trafo, corners + [(0.5, 0.5)])
 
     def Snap(self, p):
-	try:
-	    x, y = self.trafo.inverse()(p)
+        try:
+            x, y = self.trafo.inverse()(p)
             minx = self.radius1
             maxx = 1 - self.radius1
             miny = self.radius2
             maxy = 1 - self.radius2
-	    if minx < x < maxx:
-		if miny < y < maxy:
+            if minx < x < maxx:
+                if miny < y < maxy:
                     ratio = hypot(self.trafo.m11, self.trafo.m21) \
-                            / hypot(self.trafo.m12, self.trafo.m22)
+                          / hypot(self.trafo.m12, self.trafo.m22)
                     if x < 0.5:
                         dx = x
                     else:
@@ -142,7 +142,7 @@
                     y = 1
                 else:
                     y = 0
-	    elif miny < y < maxy:
+            elif miny < y < maxy:
                 if x > maxx:
                     x = 1
                 else:
@@ -165,27 +165,27 @@
                 x = round(min(max(x, 0), 1))
                 y = round(min(max(y, 0), 1))
 
-	    p2 = self.trafo(x, y)
-	    return (abs(p - p2), p2)
-	except SingularMatrix:
-	    return (1e200, p)
+            p2 = self.trafo(x, y)
+            return (abs(p - p2), p2)
+        except SingularMatrix:
+            return (1e200, p)
 
     def update_rects(self):
-	rect = PointsToRect(map(self.trafo, corners))
-	self.coord_rect = rect
-	if self.properties.HasLine():
-	    self.bounding_rect = rect.grown(self.properties.GrowAmount())
-	else:
-	    self.bounding_rect = rect
+        rect = PointsToRect(map(self.trafo, corners))
+        self.coord_rect = rect
+        if self.properties.HasLine():
+            self.bounding_rect = rect.grown(self.properties.GrowAmount())
+        else:
+            self.bounding_rect = rect
 
     def Info(self):
-	trafo = self.trafo
-	w = hypot(trafo.m11, trafo.m21)
-	h = hypot(trafo.m12, trafo.m22)
-	return _("Rectangle %(size)[size]"), {'size': (w, h)}
+        trafo = self.trafo
+        w = hypot(trafo.m11, trafo.m21)
+        h = hypot(trafo.m12, trafo.m22)
+        return _("Rectangle %(size)[size]"), {'size': (w, h)}
 
     def SaveToFile(self, file):
-	Primitive.SaveToFile(self, file)
+        Primitive.SaveToFile(self, file)
         file.Rectangle(self.trafo, self.radius1, self.radius2)
 
     def Blend(self, other, p, q):
@@ -195,7 +195,7 @@
         return result
 
     def Editor(self):
-	return RectangleEditor(self)
+        return RectangleEditor(self)
 
 
 
@@ -204,11 +204,11 @@
     creation_text = _("Create Rectangle")
 
     state = 0
-    
+
     def MouseMove(self, p, state):
         self.state = state
         RectangularCreator.MouseMove(self, p, state)
-    
+
     def ButtonUp(self, p, button, state):
         if self.state & AlternateMask:
             p = self.apply_constraint(p, state)
@@ -223,7 +223,7 @@
         start = self.drag_start
         if self.state & AlternateMask:
             start = start - self.off
-	device.DrawRectangle(start, self.drag_cur)
+        device.DrawRectangle(start, self.drag_cur)
 
     def CurrentInfoText(self):
         start = self.drag_start
@@ -233,7 +233,7 @@
         return 'Rectangle: %(size)[size]', {'size': (abs(width), abs(height))}
 
     def CreatedObject(self):
-	return Rectangle(self.trafo,
+        return Rectangle(self.trafo,
                          properties = DefaultGraphicsProperties())
 
 
@@ -345,7 +345,7 @@
                 ratio = height / width
             else:
                 ratio = radius1 / radius2
-            
+
             if ratio > 1:
                 max1 = 0.5
                 max2 = max1 / ratio
@@ -363,14 +363,14 @@
                 radius2 = max(min(y, max2), 0)
                 radius1 = radius2 * ratio
         return trafo, radius1, radius2
-    
+
     def DrawDragged(self, device, partially):
         if self.selection is not None:
             trafo, radius1, radius2 = self.resize()
             device.RoundedRectangle(trafo, radius1, radius2)
 
     def GetHandles(self):
-	trafo = self.trafo; radius1 = self.radius1; radius2 = self.radius2
+        trafo = self.trafo; radius1 = self.radius1; radius2 = self.radius2
         handles = []
 
         if radius1 == radius2 == 0:
@@ -416,9 +416,9 @@
         return handles
 
     def SelectHandle(self, handle, mode):
-	self.selection = handle
+        self.selection = handle
 
     def SelectPoint(self, p, rect, device, mode):
-	return 0
+        return 0
 
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/selection.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/selection.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/selection.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -64,183 +64,183 @@
     handle_idx_to_sel = (7, 6, 5, 8, 4, 1, 2, 3)
 
     def __init__(self):
-	SelectAndDrag.__init__(self)
-	self.outline_object = None
+        SelectAndDrag.__init__(self)
+        self.outline_object = None
 
     def update_rects(self):
-	self.coord_rect = Rect(self.start, self.end)
-	self.bounding_rect = self.coord_rect
+        self.coord_rect = Rect(self.start, self.end)
+        self.bounding_rect = self.coord_rect
 
     def SetOutlineObject(self, obj):
-	# XXX: this is a hack...
-	if obj is not None:
-	    if obj.is_Compound:
-		objects = obj.GetObjects()
-		if len(objects) == 1:
-		    obj = objects[0]
-		else:
-		    return
-	    if not obj.is_Compound and not obj.is_Text:
-		self.outline_object = obj
+        # XXX: this is a hack...
+        if obj is not None:
+            if obj.is_Compound:
+                objects = obj.GetObjects()
+                if len(objects) == 1:
+                    obj = objects[0]
+                else:
+                    return
+            if not obj.is_Compound and not obj.is_Text:
+                self.outline_object = obj
 
 
 class SelectionRectangle(SelRectBase):
 
     def __init__(self, rect, anchor = None):
-	SelRectBase.__init__(self)
-	if type(rect) == RectType:
-	    self.start = Point(rect.left, rect.bottom)
-	    self.end = Point(rect.right, rect.top)
-	    self.Normalize()
-	    self.anchor = anchor
-	else:
-	    # assume type Point and interactive creation
-	    self.start = rect
-	    self.end = rect
-	    self.anchor = None
-	    self.selection = 5
+        SelRectBase.__init__(self)
+        if type(rect) == RectType:
+            self.start = Point(rect.left, rect.bottom)
+            self.end = Point(rect.right, rect.top)
+            self.Normalize()
+            self.anchor = anchor
+        else:
+            # assume type Point and interactive creation
+            self.start = rect
+            self.end = rect
+            self.anchor = None
+            self.selection = 5
 
     def DrawDragged(self, device, partially):
-	sel = self.selection
+        sel = self.selection
 
-	if sel == -1:
-	    sx, sy = self.start + self.off
-	    ex, ey = self.end + self.off
-	else:
-	    if sel in self.selTop:
-		sy = self.drag_cur.y
-	    else:
-		sy = self.start.y
+        if sel == -1:
+            sx, sy = self.start + self.off
+            ex, ey = self.end + self.off
+        else:
+            if sel in self.selTop:
+                sy = self.drag_cur.y
+            else:
+                sy = self.start.y
 
-	    if sel in self.selBottom:
-		ey = self.drag_cur.y
-	    else:
-		ey = self.end.y
+            if sel in self.selBottom:
+                ey = self.drag_cur.y
+            else:
+                ey = self.end.y
 
-	    if sel in self.selLeft:
-		sx = self.drag_cur.x
-	    else:
-		sx = self.start.x
+            if sel in self.selLeft:
+                sx = self.drag_cur.x
+            else:
+                sx = self.start.x
 
-	    if sel in self.selRight:
-		ex = self.drag_cur.x
-	    else:
-		ex = self.end.x
+            if sel in self.selRight:
+                ex = self.drag_cur.x
+            else:
+                ex = self.end.x
 
-	if sx > ex:
-	    tmp = sx; sx = ex; ex = tmp
-	if sy < ey:
-	    tmp = sy; sy = ey; ey = tmp
+        if sx > ex:
+            tmp = sx; sx = ex; ex = tmp
+        if sy < ey:
+            tmp = sy; sy = ey; ey = tmp
 
-	device.DrawRubberRect(Point(sx, sy), Point(ex, ey))
+        device.DrawRubberRect(Point(sx, sy), Point(ex, ey))
 
     def ButtonDown(self, p, button, state):
-	SelectAndDrag.DragStart(self, p)
-	sel = self.selection
-	if sel == -1:
-	    if self.anchor: #XXX shouldn't this be 'if self.anchor is not None'
-		start = self.anchor
-	    else:
-		start = self.start
-	    self.drag_start = self.drag_cur = start
-	    return (p - start, self.coord_rect.translated(-start))
-	ds_x , ds_y = (self.start + self.end) / 2
-	if sel in self.selLeft:
-	    ds_x = self.start.x
-	if sel in self.selTop:
-	    ds_y = self.start.y
-	if sel in self.selRight:
-	    ds_x = self.end.x
-	if sel in self.selBottom:
-	    ds_y = self.end.y
-	self.drag_cur = self.drag_start = ds = Point(ds_x, ds_y)
-	self.init_constraint()
-	return p - ds
+        SelectAndDrag.DragStart(self, p)
+        sel = self.selection
+        if sel == -1:
+            if self.anchor: #XXX shouldn't this be 'if self.anchor is not None'
+                start = self.anchor
+            else:
+                start = self.start
+            self.drag_start = self.drag_cur = start
+            return (p - start, self.coord_rect.translated(-start))
+        ds_x , ds_y = (self.start + self.end) / 2
+        if sel in self.selLeft:
+            ds_x = self.start.x
+        if sel in self.selTop:
+            ds_y = self.start.y
+        if sel in self.selRight:
+            ds_x = self.end.x
+        if sel in self.selBottom:
+            ds_y = self.end.y
+        self.drag_cur = self.drag_start = ds = Point(ds_x, ds_y)
+        self.init_constraint()
+        return p - ds
 
     def init_constraint(self):
-	pass
+        pass
 
     def apply_constraint(self, p, state):
-	return p
+        return p
 
     def MouseMove(self, p, state):
-	p = self.apply_constraint(p, state)
-	SelectAndDrag.MouseMove(self, p, state)
+        p = self.apply_constraint(p, state)
+        SelectAndDrag.MouseMove(self, p, state)
 
     def compute_endpoints(self):
-	cur = self.drag_cur
-	start = self.start
-	end = self.end
-	sel = self.selection
-	if sel in self.selTop:
-	    start = Point(start.x, cur.y)
-	if sel in self.selBottom:
-	    end	  = Point(end.x,   cur.y)
-	if sel in self.selLeft:
-	    start = Point(cur.x, start.y)
-	if sel in self.selRight:
-	    end = Point(cur.x, end.y)
-	if sel == -1:
-	    start = start + self.off
-	    end = end + self.off
+        cur = self.drag_cur
+        start = self.start
+        end = self.end
+        sel = self.selection
+        if sel in self.selTop:
+            start = Point(start.x, cur.y)
+        if sel in self.selBottom:
+            end	  = Point(end.x,   cur.y)
+        if sel in self.selLeft:
+            start = Point(cur.x, start.y)
+        if sel in self.selRight:
+            end = Point(cur.x, end.y)
+        if sel == -1:
+            start = start + self.off
+            end = end + self.off
         return start, end
 
     def ButtonUp(self, p, button, state):
-	p = self.apply_constraint(p, state)
-	SelectAndDrag.DragStop(self, p)
-	cur = self.drag_cur
-	oldstart = self.start
-	oldend = self.end
-	start, end = self.compute_endpoints()
-	self.start = start
-	self.end = end
-	result = self.ComputeTrafo(oldstart, oldend, start, end)
-	self.Normalize()
-	return result
+        p = self.apply_constraint(p, state)
+        SelectAndDrag.DragStop(self, p)
+        cur = self.drag_cur
+        oldstart = self.start
+        oldend = self.end
+        start, end = self.compute_endpoints()
+        self.start = start
+        self.end = end
+        result = self.ComputeTrafo(oldstart, oldend, start, end)
+        self.Normalize()
+        return result
 
     def ComputeTrafo(self, oldStart, oldEnd, start, end):
-	pass
+        pass
 
     def Normalize(self):
-	sx, sy = self.start
-	ex, ey = self.end
-	if sx > ex:
-	    sx, ex = ex, sx
-	if sy > ey:
-	    sy, ey = ey, sy
-	self.start = Point(sx, sy)
-	self.end = Point(ex, ey)
+        sx, sy = self.start
+        ex, ey = self.end
+        if sx > ex:
+            sx, ex = ex, sx
+        if sy > ey:
+            sy, ey = ey, sy
+        self.start = Point(sx, sy)
+        self.end = Point(ex, ey)
 
     def Hit(self, p, rect, device):
-	pass
+        pass
 
     def Select(self):
-	self.selection = -1
+        self.selection = -1
 
     def SelectPoint(self, p, rect, device, mode = SelectSet):
-	if p:
-	    self.selection = 0
-	else:
-	    self.selection = -1
-	return self.selection
+        if p:
+            self.selection = 0
+        else:
+            self.selection = -1
+        return self.selection
 
     def SelectHandle(self, handle, mode = SelectSet):
-	self.selection = self.handle_idx_to_sel[handle.index]
+        self.selection = self.handle_idx_to_sel[handle.index]
 
     def GetHandles(self):
-	sx = self.start.x
-	sy = self.start.y
-	ex = self.end.x
-	ey = self.end.y
-	x2 = (sx + ex) / 2
-	y2 = (sy + ey) / 2
-	return map(handle.MakeOffsetHandle,
-		   [Point(sx, ey),	Point(x2, ey),	Point(ex, ey),
-		    Point(sx, y2),			Point(ex, y2),
-		    Point(sx, sy),	Point(x2, sy),	Point(ex, sy)],
-		   [(-1,  1),		(0,  1),	( 1,  1),
-		    (-1,  0),				( 1,  0),
-		    (-1, -1),		(0, -1),	( 1, -1)])
+        sx = self.start.x
+        sy = self.start.y
+        ex = self.end.x
+        ey = self.end.y
+        x2 = (sx + ex) / 2
+        y2 = (sy + ey) / 2
+        return map(handle.MakeOffsetHandle,
+                   [Point(sx, ey),	Point(x2, ey),	Point(ex, ey),
+                    Point(sx, y2),			Point(ex, y2),
+                    Point(sx, sy),	Point(x2, sy),	Point(ex, sy)],
+                   [(-1,  1),		(0,  1),	( 1,  1),
+                    (-1,  0),				( 1,  0),
+                    (-1, -1),		(0, -1),	( 1, -1)])
 
 
 
@@ -250,46 +250,46 @@
 
     _lazy_attrs = Bounded._lazy_attrs.copy()
     _lazy_attrs['rect'] = 'update_rectangle'
-    
+
     def __init__(self, copy_from = None):
-	if copy_from is not None:
-	    if type(copy_from) == ListType:
-		self.objects = copy_from[:]
-	    else:
-		# assume copy_from is another instance of a selection class
-		self.objects = copy_from.objects
-		self.coord_rect = copy_from.coord_rect
-		self.bounding_rect = copy_from.bounding_rect
-		self.anchor = copy_from.anchor
-	else:
-	    self.objects = []
-	    self.anchor = None
+        if copy_from is not None:
+            if type(copy_from) == ListType:
+                self.objects = copy_from[:]
+            else:
+                # assume copy_from is another instance of a selection class
+                self.objects = copy_from.objects
+                self.coord_rect = copy_from.coord_rect
+                self.bounding_rect = copy_from.bounding_rect
+                self.anchor = copy_from.anchor
+        else:
+            self.objects = []
+            self.anchor = None
 
     def normalize(self):
-	# make sure that self.objects contains no object more than once
-	# and that no two objects have a direct or indirect parent/child
-	# relationship.
-	objs = self.objects
-	changed = 0
-	if len(objs) > 1:
-	    objs.sort()
-	    last_info, obj = objs[-1]
-	    for idx in range(len(objs) - 2, -1, -1):
-		info, obj = objs[idx]
-		if info == last_info:
-		    del objs[idx]
-		    changed = 1
-		    continue
-		if len(info) < len(last_info):
-		    while info == last_info[:len(info)]:
-			del objs[idx + 1]
-			changed = 1
-			if idx + 1 < len(objs):
-			    last_info = objs[idx + 1][0]
-			else:
-			    break
-		last_info = info
-	return changed
+        # make sure that self.objects contains no object more than once
+        # and that no two objects have a direct or indirect parent/child
+        # relationship.
+        objs = self.objects
+        changed = 0
+        if len(objs) > 1:
+            objs.sort()
+            last_info, obj = objs[-1]
+            for idx in range(len(objs) - 2, -1, -1):
+                info, obj = objs[idx]
+                if info == last_info:
+                    del objs[idx]
+                    changed = 1
+                    continue
+                if len(info) < len(last_info):
+                    while info == last_info[:len(info)]:
+                        del objs[idx + 1]
+                        changed = 1
+                        if idx + 1 < len(objs):
+                            last_info = objs[idx + 1][0]
+                        else:
+                            break
+                last_info = info
+        return changed
 
     def update_selinfo(self):
         objs = self.objects
@@ -297,185 +297,185 @@
             objs[i] = objs[i][-1].SelectionInfo()
 
     def SetSelection(self, info):
-	old_objs = self.objects
-	if info:
-	    if type(info) == ListType:
-		self.objects = info
-		self.objects.sort()
-	    else:
-		self.objects = [info]
-	else:
-	    self.objects = []
-	self.del_lazy_attrs()
-	return old_objs != self.objects
+        old_objs = self.objects
+        if info:
+            if type(info) == ListType:
+                self.objects = info
+                self.objects.sort()
+            else:
+                self.objects = [info]
+        else:
+            self.objects = []
+        self.del_lazy_attrs()
+        return old_objs != self.objects
 
     def SetSelectionTree(self, info):
-	return self.SetSelection(selinfo.tree_to_list(info))
+        return self.SetSelection(selinfo.tree_to_list(info))
 
     def Add(self, info):
-	if not info:
-	    return 0
-	old_len = len(self.objects)
-	if type(info) == ListType:
-	    self.objects = self.objects + info
-	elif info:
-	    self.objects.append(info)
-	changed = self.normalize()
-	self.del_lazy_attrs()
-	return changed or old_len != len(self.objects)
+        if not info:
+            return 0
+        old_len = len(self.objects)
+        if type(info) == ListType:
+            self.objects = self.objects + info
+        elif info:
+            self.objects.append(info)
+        changed = self.normalize()
+        self.del_lazy_attrs()
+        return changed or old_len != len(self.objects)
 
     def Subtract(self, info):
-	if not info:
-	    return 0
-	old_len = len(self.objects)
-	if type(info) != ListType:
-	    info = [info]
-	objects = self.objects
-	for item in info:
-	    if item in objects:
-		objects.remove(item)
-	self.del_lazy_attrs()
-	return old_len != len(self.objects)
+        if not info:
+            return 0
+        old_len = len(self.objects)
+        if type(info) != ListType:
+            info = [info]
+        objects = self.objects
+        for item in info:
+            if item in objects:
+                objects.remove(item)
+        self.del_lazy_attrs()
+        return old_len != len(self.objects)
 
     def GetObjects(self):
-	return map(operator.getitem, self.objects, [-1] * len(self.objects))
+        return map(operator.getitem, self.objects, [-1] * len(self.objects))
 
     def GetInfo(self):
-	return self.objects
+        return self.objects
 
     def GetInfoTree(self):
-	return selinfo.list_to_tree(self.objects)
+        return selinfo.list_to_tree(self.objects)
 
     def Depth(self):
-	if self.objects:
-	    lengths = map(len, map(operator.getitem, self.objects,
-				   [0] * len(self.objects)))
-	    lmin = min(lengths)
-	    lmax = max(lengths)
-	    if lmin == lmax:
-		return lmin
-	    return (lmin, lmax)
-	return 0
+        if self.objects:
+            lengths = map(len, map(operator.getitem, self.objects,
+                                   [0] * len(self.objects)))
+            lmin = min(lengths)
+            lmax = max(lengths)
+            if lmin == lmax:
+                return lmin
+            return (lmin, lmax)
+        return 0
 
     def IsSingleDepth(self):
-	if self.objects:
-	    return type(self.Depth()) != TupleType
-	return 1
+        if self.objects:
+            return type(self.Depth()) != TupleType
+        return 1
 
     def GetPath(self):
-	if len(self.objects) == 1:
-	    return self.objects[0][0]
-	return ()
+        if len(self.objects) == 1:
+            return self.objects[0][0]
+        return ()
 
     def for_all(self, func):
-	return map(func, self.GetObjects())
+        return map(func, self.GetObjects())
 
     def ForAllUndo(self, func):
-	undoinfo = self.for_all(func)
-	self.del_lazy_attrs()
-	if len(undoinfo) == 1:
-	    undoinfo = undoinfo[0]
-	if type(undoinfo) == ListType:
-	    return CreateListUndo(undoinfo)
-	return undoinfo
+        undoinfo = self.for_all(func)
+        self.del_lazy_attrs()
+        if len(undoinfo) == 1:
+            undoinfo = undoinfo[0]
+        if type(undoinfo) == ListType:
+            return CreateListUndo(undoinfo)
+        return undoinfo
 
     def ForAllUndo2(self, method, *args):
-	t = time.clock()
-	methods = map(getattr, self.GetObjects(), [method] * len(self.objects))
-	#print time.clock() - t,
-	#undoinfo = self.for_all(func)
-	undoinfo = map(apply, methods, [args] * len(methods))
-	#print time.clock() - t
-	self.del_lazy_attrs()
-	if len(undoinfo) == 1:
-	    undoinfo = undoinfo[0]
-	if type(undoinfo) == ListType:
-	    return CreateListUndo(undoinfo)
-	return undoinfo
+        t = time.clock()
+        methods = map(getattr, self.GetObjects(), [method] * len(self.objects))
+        #print time.clock() - t,
+        #undoinfo = self.for_all(func)
+        undoinfo = map(apply, methods, [args] * len(methods))
+        #print time.clock() - t
+        self.del_lazy_attrs()
+        if len(undoinfo) == 1:
+            undoinfo = undoinfo[0]
+        if type(undoinfo) == ListType:
+            return CreateListUndo(undoinfo)
+        return undoinfo
 
     def __len__(self):
-	return len(self.objects)
+        return len(self.objects)
 
     __nonzero__ = __len__
 
     def update_rects(self):
-	objects = self.GetObjects()
-	boxes = map(lambda o: o.coord_rect, objects)
-	if boxes:
-	    self.coord_rect = reduce(UnionRects, boxes)
-	else:
-	    self.coord_rect = None
-	boxes = map(lambda o: o.bounding_rect, objects)
-	if boxes:
-	    self.bounding_rect = reduce(UnionRects, boxes)
-	else:
-	    self.bounding_rect = None
-	if len(objects) == 1:
-	    self.anchor = objects[0].LayoutPoint()
-	else:
-	    self.anchor = None
+        objects = self.GetObjects()
+        boxes = map(lambda o: o.coord_rect, objects)
+        if boxes:
+            self.coord_rect = reduce(UnionRects, boxes)
+        else:
+            self.coord_rect = None
+        boxes = map(lambda o: o.bounding_rect, objects)
+        if boxes:
+            self.bounding_rect = reduce(UnionRects, boxes)
+        else:
+            self.bounding_rect = None
+        if len(objects) == 1:
+            self.anchor = objects[0].LayoutPoint()
+        else:
+            self.anchor = None
 
     def ChangeRect(self):
-	return self.bounding_rect
+        return self.bounding_rect
 
     def ResetRectangle(self):
-	self.del_lazy_attrs()
+        self.del_lazy_attrs()
 
     def Hit(self, p, rect, device):
-	test = rect.overlaps
-	for obj in self.GetObjects():
-	    if test(obj.bounding_rect):
-		if obj.Hit(p, rect, device):
-		    return 1
-	return 0
+        test = rect.overlaps
+        for obj in self.GetObjects():
+            if test(obj.bounding_rect):
+                if obj.Hit(p, rect, device):
+                    return 1
+        return 0
 
     def DragCancel(self):
-	self.rect.DragCancel()
+        self.rect.DragCancel()
 
     def GetHandles(self):
-	rect_handles = self.rect.GetHandles()
-	multiple = len(self.objects) > 1
-	handles = flatten(self.for_all(lambda o, m = multiple:
-				       o.GetObjectHandle(m)))
-	rect_handles.append(handle.MakeObjectHandleList(handles))
-	return rect_handles
+        rect_handles = self.rect.GetHandles()
+        multiple = len(self.objects) > 1
+        handles = flatten(self.for_all(lambda o, m = multiple:
+                                       o.GetObjectHandle(m)))
+        rect_handles.append(handle.MakeObjectHandleList(handles))
+        return rect_handles
 
     def CallObjectMethod(self, aclass, methodname, args):
-	if len(self.objects) == 1:
-	    obj = self.objects[0][-1]
-	    if not isinstance(obj, aclass):
-		return NullUndo
-	    try:
-		method = getattr(obj, methodname)
-	    except AttributeError:
-		return NullUndo
+        if len(self.objects) == 1:
+            obj = self.objects[0][-1]
+            if not isinstance(obj, aclass):
+                return NullUndo
+            try:
+                method = getattr(obj, methodname)
+            except AttributeError:
+                return NullUndo
 
-	    undo = apply(method, args)
-	    if undo is None:
-		undo = NullUndo
-	    return undo
-	return NullUndo
+            undo = apply(method, args)
+            if undo is None:
+                undo = NullUndo
+            return undo
+        return NullUndo
 
     def GetObjectMethod(self, aclass, method):
-	if len(self.objects) == 1:
-	    obj = self.objects[0][-1]
-	    if isinstance(obj, aclass):
-		try:
-		    return getattr(obj, method)
-		except AttributeError:
-		    pass
-	return None
+        if len(self.objects) == 1:
+            obj = self.objects[0][-1]
+            if isinstance(obj, aclass):
+                try:
+                    return getattr(obj, method)
+                except AttributeError:
+                    pass
+        return None
 
     def InfoText(self):
-	# Return a string describing the selected object(s)
+        # Return a string describing the selected object(s)
         result = _("No Selection")
-	if self.objects:
-	    sel_info = self.objects
-	    document = sel_info[0][1].document
-	    if len(sel_info) == 1:
+        if self.objects:
+            sel_info = self.objects
+            document = sel_info[0][1].document
+            if len(sel_info) == 1:
                 path, obj = sel_info[0]
                 dict = {'layer': document[path[0]].Name()}
-		info = obj.Info()
+                info = obj.Info()
                 if type(info) == TupleType:
                     dict.update(info[1])
                     # the %% is correct here. The result has to be a
@@ -485,15 +485,15 @@
                     dict['object'] = info
                     text = _("%(object)s on `%(layer)s'")
                 result = text, dict
-	    else:
-		layer = sel_info[0][0][0]
-		if layer == sel_info[-1][0][0]:
-		    # a single layer
-		    layer_name = document.layers[layer].Name()
-		    result = _("%(number)d objects on `%(layer)s'") \
-                             % {'number':len(sel_info), 'layer':layer_name}
-		else:
-		    result = _("%d objects on several layers") % len(sel_info)
+            else:
+                layer = sel_info[0][0][0]
+                if layer == sel_info[-1][0][0]:
+                    # a single layer
+                    layer_name = document.layers[layer].Name()
+                    result = _("%(number)d objects on `%(layer)s'") \
+                           % {'number':len(sel_info), 'layer':layer_name}
+                else:
+                    result = _("%d objects on several layers") % len(sel_info)
 
         return result
 
@@ -501,7 +501,7 @@
         return ''
 
     def _dummy(self, *args):
-	pass
+        pass
 
     Hide	 = _dummy
     DragStart	 = None
@@ -519,98 +519,98 @@
 class SizeRectangle(SelectionRectangle):
 
     def init_constraint(self):
-	sel = self.selection
-	if sel == 1:
-	    self.reference = tuple(self.end)
-	elif sel == 3:
-	    self.reference = (self.start.x, self.end.y)
-	elif sel == 5:
-	    self.reference = tuple(self.start)
-	elif sel == 7:
-	    self.reference = (self.end.x, self.start.y)
-	else:
-	    return
-	width = abs(self.start.x - self.end.x)
-	height = abs(self.start.y - self.end.y)
-	if width >= 1e-10:
-	    self.aspect = height / width
-	else:
-	    self.aspect = None
+        sel = self.selection
+        if sel == 1:
+            self.reference = tuple(self.end)
+        elif sel == 3:
+            self.reference = (self.start.x, self.end.y)
+        elif sel == 5:
+            self.reference = tuple(self.start)
+        elif sel == 7:
+            self.reference = (self.end.x, self.start.y)
+        else:
+            return
+        width = abs(self.start.x - self.end.x)
+        height = abs(self.start.y - self.end.y)
+        if width >= 1e-10:
+            self.aspect = height / width
+        else:
+            self.aspect = None
 
     def apply_constraint(self, p, state):
-	if state & const.ConstraintMask:
-	    if self.selection in self.selAspect:
-		ref_x, ref_y = self.reference
-		aspect = self.aspect
-		if aspect is None:
-		    # width is 0
-		    p = Point(self.drag_start.x, p.y)
-		else:
-		    w = p.x - ref_x
-		    h = p.y - ref_y
-		    if w == 0:
-			w = 0.00001
-		    a = h / w
-		    if a > 0:
-			sign = 1
-		    else:
-			sign = -1
-		    if abs(a) > aspect:
-			h = sign * w * aspect
-		    else:
-			w = sign * h / aspect
-		    p = Point(ref_x + w, ref_y + h)
-	    elif self.selection == -1:
-		pi4 = math.pi / 4
-		off = p - self.drag_start
+        if state & const.ConstraintMask:
+            if self.selection in self.selAspect:
+                ref_x, ref_y = self.reference
+                aspect = self.aspect
+                if aspect is None:
+                    # width is 0
+                    p = Point(self.drag_start.x, p.y)
+                else:
+                    w = p.x - ref_x
+                    h = p.y - ref_y
+                    if w == 0:
+                        w = 0.00001
+                    a = h / w
+                    if a > 0:
+                        sign = 1
+                    else:
+                        sign = -1
+                    if abs(a) > aspect:
+                        h = sign * w * aspect
+                    else:
+                        w = sign * h / aspect
+                    p = Point(ref_x + w, ref_y + h)
+            elif self.selection == -1:
+                pi4 = math.pi / 4
+                off = p - self.drag_start
                 d = Polar(pi4 * round(math.atan2(off.y, off.x) / pi4))
                 p = self.drag_start + (off * d) * d
-	return p
+        return p
 
     def ButtonDown(self, p, button, state):
         self.trafo = Identity
         return SelectionRectangle.ButtonDown(self, p, button, state)
 
     def MouseMove(self, p, state):
-	p = self.apply_constraint(p, state)
-	SelectAndDrag.MouseMove(self, p, state)
+        p = self.apply_constraint(p, state)
+        SelectAndDrag.MouseMove(self, p, state)
         start, end = self.compute_endpoints()
         text, self.trafo = self.ComputeTrafo(self.start, self.end, start, end)
 
     def ComputeTrafo(self, oldStart, oldEnd, start, end):
-	oldDelta = oldEnd - oldStart
-	delta	 = end - start
-	if self.selection == -1:
-	    # a translation.
-	    return _("Move Objects"), start - oldStart
-	else:
-	    try:
-		m11 = delta.x / oldDelta.x
-	    except ZeroDivisionError:
-		m11 = 0
-		if __debug__:
-		    pdebug(None, 'ComputeTrafo: ZeroDivisionError')
-	    try:
-		m22 = delta.y / oldDelta.y
-	    except ZeroDivisionError:
-		m22 = 0
-		if __debug__:
-		    pdebug(None, 'ComputeTrafo: ZeroDivisionError')
-	    offx = start.x - m11 * oldStart.x
-	    offy = start.y - m22 * oldStart.y
-	    return _("Resize Objects"), Trafo(m11, 0, 0, m22, offx, offy)
+        oldDelta = oldEnd - oldStart
+        delta	 = end - start
+        if self.selection == -1:
+            # a translation.
+            return _("Move Objects"), start - oldStart
+        else:
+            try:
+                m11 = delta.x / oldDelta.x
+            except ZeroDivisionError:
+                m11 = 0
+                if __debug__:
+                    pdebug(None, 'ComputeTrafo: ZeroDivisionError')
+            try:
+                m22 = delta.y / oldDelta.y
+            except ZeroDivisionError:
+                m22 = 0
+                if __debug__:
+                    pdebug(None, 'ComputeTrafo: ZeroDivisionError')
+            offx = start.x - m11 * oldStart.x
+            offy = start.y - m22 * oldStart.y
+            return _("Resize Objects"), Trafo(m11, 0, 0, m22, offx, offy)
 
     def DrawDragged(self, device, partial):
-	SelectionRectangle.DrawDragged(self, device, partial)
-	if self.outline_object is not None:
-	    trafo = self.trafo
-	    device.PushTrafo()
-	    if type(trafo) == TrafoType:
-		device.Concat(trafo)
-	    else:
-		device.Translate(trafo.x, trafo.y)
-	    self.outline_object.DrawShape(device)
-	    device.PopTrafo()
+        SelectionRectangle.DrawDragged(self, device, partial)
+        if self.outline_object is not None:
+            trafo = self.trafo
+            device.PushTrafo()
+            if type(trafo) == TrafoType:
+                device.Concat(trafo)
+            else:
+                device.Translate(trafo.x, trafo.y)
+            self.outline_object.DrawShape(device)
+            device.PopTrafo()
 
     def CurrentInfoText(self):
         t = self.trafo
@@ -636,60 +636,60 @@
 class SizeSelection(Selection):
 
     def __init__(self, arg = None):
-	Selection.__init__(self, arg)
+        Selection.__init__(self, arg)
 
     def update_rectangle(self):
-	if self:
-	    self.rect = SizeRectangle(self.coord_rect, self.anchor)
-	else:
-	    self.rect = SizeRectangle(Rect(0, 0, 0, 0))
+        if self:
+            self.rect = SizeRectangle(self.coord_rect, self.anchor)
+        else:
+            self.rect = SizeRectangle(Rect(0, 0, 0, 0))
 
     def ButtonDown(self, p, button, state):
-	if len(self.objects) == 1:
-	    self.rect.SetOutlineObject(self.objects[0][-1])
-	return self.rect.ButtonDown(p, button, state)
+        if len(self.objects) == 1:
+            self.rect.SetOutlineObject(self.objects[0][-1])
+        return self.rect.ButtonDown(p, button, state)
 
     def MouseMove(self, p, state):
-	self.rect.MouseMove(p, state)
+        self.rect.MouseMove(p, state)
 
     def ButtonUp(self, p, button, state, forget_trafo = 0):
-	self.rect.SetOutlineObject(None)
-	undo_text, trafo = self.rect.ButtonUp(p, button, state)
-	if forget_trafo:
-	    return None, None
-	t = time.clock()
-	if type(trafo) == TrafoType:
-	    #undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
-	    undo = self.ForAllUndo2('Transform', trafo)
-	else:
-	    # trafo is point representing a translation
-	    undo = self.ForAllUndo2('Translate', trafo)
-	#print 'transform/translate', time.clock() - t
-	self.del_lazy_attrs()
-	return undo_text, undo
+        self.rect.SetOutlineObject(None)
+        undo_text, trafo = self.rect.ButtonUp(p, button, state)
+        if forget_trafo:
+            return None, None
+        t = time.clock()
+        if type(trafo) == TrafoType:
+            #undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
+            undo = self.ForAllUndo2('Transform', trafo)
+        else:
+            # trafo is point representing a translation
+            undo = self.ForAllUndo2('Translate', trafo)
+        #print 'transform/translate', time.clock() - t
+        self.del_lazy_attrs()
+        return undo_text, undo
 
     def Show(self, device, partially = 0):
-	self.rect.Show(device, partially)
+        self.rect.Show(device, partially)
 
     def Hide(self, device, partially = 0):
-	self.rect.Hide(device, partially)
+        self.rect.Hide(device, partially)
 
     def DrawDragged(self, device, partial):
-	self.rect.DrawDragged(device, partial)
+        self.rect.DrawDragged(device, partial)
 
     def SelectPoint(self, p, rect, device, mode = SelectSet):
-	if not self.rect.SelectPoint(p, rect, device, mode):
-	    if self.Hit(p, rect, device):
-		self.rect.Select()
+        if not self.rect.SelectPoint(p, rect, device, mode):
+            if self.Hit(p, rect, device):
+                self.rect.Select()
 
     def SelectHandle(self, handle, mode = SelectSet):
-	self.rect.SelectHandle(handle, mode)
+        self.rect.SelectHandle(handle, mode)
 
     def Hit(self, p, rect, device):
-	if self.objects:
-	    return (rect.overlaps(self.bounding_rect)
-		    and Selection.Hit(self, p, rect, device))
-	return 0
+        if self.objects:
+            return (rect.overlaps(self.bounding_rect)
+                    and Selection.Hit(self, p, rect, device))
+        return 0
 
     def CurrentInfoText(self):
         return self.rect.CurrentInfoText()
@@ -701,133 +701,133 @@
     selCenter = 100
 
     def __init__(self, rect, center = None):
-	SelRectBase.__init__(self)
-	self.start = Point(rect.left, rect.bottom)
-	self.end = Point(rect.right, rect.top)
-	if center is None:
-	    self.center = rect.center()
-	else:
-	    self.center = center
+        SelRectBase.__init__(self)
+        self.start = Point(rect.left, rect.bottom)
+        self.end = Point(rect.right, rect.top)
+        if center is None:
+            self.center = rect.center()
+        else:
+            self.center = center
 
     def compute_trafo(self, state = 0):
-	sel = self.selection
-	if sel in self.selTurn:
-	    # rotation
-	    vec = self.drag_cur - self.center
-	    angle = math.atan2(vec.y, vec.x)
-	    angle = angle - self.start_angle + 2 * math.pi
-	    if state & const.ConstraintMask:
-		pi12 = math.pi / 12
-		angle = pi12 * int(angle / pi12 + 0.5)
+        sel = self.selection
+        if sel in self.selTurn:
+            # rotation
+            vec = self.drag_cur - self.center
+            angle = math.atan2(vec.y, vec.x)
+            angle = angle - self.start_angle + 2 * math.pi
+            if state & const.ConstraintMask:
+                pi12 = math.pi / 12
+                angle = pi12 * int(angle / pi12 + 0.5)
             self.trafo = Rotation(angle, self.center)
             self.trafo_desc = (1, angle)
-	elif sel in self.selShear:
-	    if sel in (2,6):
-		# horiz. shear
-		height = self.drag_start.y - self.reference
-		if height:
-		    ratio = self.off.x / height
-		    self.trafo = Trafo(1, 0, ratio, 1,
+        elif sel in self.selShear:
+            if sel in (2,6):
+                # horiz. shear
+                height = self.drag_start.y - self.reference
+                if height:
+                    ratio = self.off.x / height
+                    self.trafo = Trafo(1, 0, ratio, 1,
                                        - ratio * self.reference, 0)
                     self.trafo_desc = (2, ratio)
-	    else:
-		# vert. shear
-		width = self.drag_start.x - self.reference
-		if width:
-		    ratio = self.off.y / width
-		    self.trafo = Trafo(1, ratio, 0, 1, 0,
+            else:
+                # vert. shear
+                width = self.drag_start.x - self.reference
+                if width:
+                    ratio = self.off.y / width
+                    self.trafo = Trafo(1, ratio, 0, 1, 0,
                                        - ratio * self.reference)
                     self.trafo_desc = (3, ratio)
 
     def DrawDragged(self, device, partially):
-	sel = self.selection
-	if sel == self.selCenter:
-	    device.DrawPixmapHandle(self.drag_cur, pixmaps.Center)
-	else:
-	    trafo = self.trafo
-	    if trafo:
-		device.PushTrafo()
-		device.Concat(trafo)
-		device.DrawRubberRect(self.start, self.end)
-		if self.outline_object is not None:
-		    self.outline_object.DrawShape(device)
-		device.PopTrafo()
+        sel = self.selection
+        if sel == self.selCenter:
+            device.DrawPixmapHandle(self.drag_cur, pixmaps.Center)
+        else:
+            trafo = self.trafo
+            if trafo:
+                device.PushTrafo()
+                device.Concat(trafo)
+                device.DrawRubberRect(self.start, self.end)
+                if self.outline_object is not None:
+                    self.outline_object.DrawShape(device)
+                device.PopTrafo()
 
     def ButtonDown(self, p, button, state):
-	self.drag_state = state
+        self.drag_state = state
         self.trafo = Identity
         self.trafo_desc = (0, 0)
-	SelectAndDrag.DragStart(self, p)
-	sel = self.selection
-	if sel == self.selCenter:
-	    self.drag_cur = self.drag_start = self.center
-	    return p - self.center
-	ds_x = ds_y = 0
-	if sel in self.selLeft:
-	    ds_x = self.start.x
-	if sel in self.selTop:
-	    ds_y = self.start.y
-	if sel in self.selRight:
-	    ds_x = self.end.x
-	if sel in self.selBottom:
-	    ds_y = self.end.y
-	self.drag_cur = self.drag_start = ds = Point(ds_x, ds_y)
-	if sel in self.selTurn:
-	    vec = ds - self.center
-	    self.start_angle = math.atan2(vec.y, vec.x)
-	else:
-	    if sel == 2:
-		self.reference = self.end.y
-	    elif sel == 4:
-		self.reference = self.start.x
-	    elif sel == 6:
-		self.reference = self.start.y
-	    elif sel == 8:
-		self.reference = self.end.x
-	return p - ds
+        SelectAndDrag.DragStart(self, p)
+        sel = self.selection
+        if sel == self.selCenter:
+            self.drag_cur = self.drag_start = self.center
+            return p - self.center
+        ds_x = ds_y = 0
+        if sel in self.selLeft:
+            ds_x = self.start.x
+        if sel in self.selTop:
+            ds_y = self.start.y
+        if sel in self.selRight:
+            ds_x = self.end.x
+        if sel in self.selBottom:
+            ds_y = self.end.y
+        self.drag_cur = self.drag_start = ds = Point(ds_x, ds_y)
+        if sel in self.selTurn:
+            vec = ds - self.center
+            self.start_angle = math.atan2(vec.y, vec.x)
+        else:
+            if sel == 2:
+                self.reference = self.end.y
+            elif sel == 4:
+                self.reference = self.start.x
+            elif sel == 6:
+                self.reference = self.start.y
+            elif sel == 8:
+                self.reference = self.end.x
+        return p - ds
 
     def constrain_center(self, p, state):
-	if state & const.ConstraintMask:
-	    start = self.start
-	    end = self.end
-	    if p.x < 0.75 * start.x + 0.25 * end.x:
-		x = start.x
-	    elif p.x > 0.25 * start.x + 0.75 * end.x:
-		x = end.x
-	    else:
-		x = (start.x + end.x) / 2
-	    if p.y < 0.75 * start.y + 0.25 * end.y:
-		y = start.y
-	    elif p.y > 0.25 * start.y + 0.75 * end.y:
-		y = end.y
-	    else:
-		y = (start.y + end.y) / 2
-	    return Point(x, y)
-	return p
+        if state & const.ConstraintMask:
+            start = self.start
+            end = self.end
+            if p.x < 0.75 * start.x + 0.25 * end.x:
+                x = start.x
+            elif p.x > 0.25 * start.x + 0.75 * end.x:
+                x = end.x
+            else:
+                x = (start.x + end.x) / 2
+            if p.y < 0.75 * start.y + 0.25 * end.y:
+                y = start.y
+            elif p.y > 0.25 * start.y + 0.75 * end.y:
+                y = end.y
+            else:
+                y = (start.y + end.y) / 2
+            return Point(x, y)
+        return p
 
     def MouseMove(self, p, state):
-	self.drag_state = state
-	if self.selection == self.selCenter:
-	    p = self.constrain_center(p, state)
-	SelectAndDrag.MouseMove(self, p, state)
+        self.drag_state = state
+        if self.selection == self.selCenter:
+            p = self.constrain_center(p, state)
+        SelectAndDrag.MouseMove(self, p, state)
         self.compute_trafo(state)
 
     def ButtonUp(self, p, button, state):
-	if self.selection == self.selCenter:
-	    p = self.constrain_center(p, state)
-	SelectAndDrag.DragStop(self, p)
-	sel = self.selection
-	if sel == self.selCenter:
-	    self.center = self.drag_cur
-	    return '', None
-	else:
+        if self.selection == self.selCenter:
+            p = self.constrain_center(p, state)
+        SelectAndDrag.DragStop(self, p)
+        sel = self.selection
+        if sel == self.selCenter:
+            self.center = self.drag_cur
+            return '', None
+        else:
             self.compute_trafo(state)
-	    trafo = self.trafo
-	    if self.selection in self.selShear:
-		text = _("Shear Objects")
-	    else:
-		text = _("Rotate Objects")
-	    return text, trafo
+            trafo = self.trafo
+            if self.selection in self.selShear:
+                text = _("Shear Objects")
+            else:
+                text = _("Rotate Objects")
+            return text, trafo
 
     def CurrentInfoText(self):
         if self.selection == self.selCenter:
@@ -850,100 +850,100 @@
         return text, data
 
     def Hit(self, p, rect, device):
-	pass
+        pass
 
     def Select(self):
-	pass
+        pass
 
     def SelectPoint(self, p, rect, device, mode = SelectSet):
-	self.selection = 0
-	return self.selection
+        self.selection = 0
+        return self.selection
 
     def SelectHandle(self, handle, mode = SelectSet):
-	handle = handle.index
-	if handle == len(self.handle_idx_to_sel):
-	    self.selection = self.selCenter
-	else:
-	    self.selection = self.handle_idx_to_sel[handle]
+        handle = handle.index
+        if handle == len(self.handle_idx_to_sel):
+            self.selection = self.selCenter
+        else:
+            self.selection = self.handle_idx_to_sel[handle]
 
     def GetHandles(self):
-	sx = self.start.x
-	sy = self.start.y
-	ex = self.end.x
-	ey = self.end.y
-	x2 = (sx + ex) / 2
-	y2 = (sy + ey) / 2
-	return map(handle.MakePixmapHandle,
-		   [Point(sx, ey),	Point(x2, ey),	Point(ex, ey),
-		    Point(sx, y2),			Point(ex, y2),
-		    Point(sx, sy),	Point(x2, sy),	Point(ex, sy)],
-		   [(-1,  1),		(0,  1),	( 1,  1),
-		    (-1,  0),				( 1,  0),
-		    (-1, -1),		(0, -1),	( 1, -1)],
-		   [pixmaps.TurnTL, pixmaps.ShearLR,	pixmaps.TurnTR,
-		    pixmaps.ShearUD,			pixmaps.ShearUD,
-		    pixmaps.TurnBL, pixmaps.ShearLR,	pixmaps.TurnBR],
-		   [const.CurTurn] * 8) \
-	     + [handle.MakePixmapHandle(self.center, (0, 0), pixmaps.Center)]
+        sx = self.start.x
+        sy = self.start.y
+        ex = self.end.x
+        ey = self.end.y
+        x2 = (sx + ex) / 2
+        y2 = (sy + ey) / 2
+        return map(handle.MakePixmapHandle,
+                   [Point(sx, ey),	Point(x2, ey),	Point(ex, ey),
+                    Point(sx, y2),			Point(ex, y2),
+                    Point(sx, sy),	Point(x2, sy),	Point(ex, sy)],
+                   [(-1,  1),		(0,  1),	( 1,  1),
+                    (-1,  0),				( 1,  0),
+                    (-1, -1),		(0, -1),	( 1, -1)],
+                   [pixmaps.TurnTL, pixmaps.ShearLR,	pixmaps.TurnTR,
+                    pixmaps.ShearUD,			pixmaps.ShearUD,
+                    pixmaps.TurnBL, pixmaps.ShearLR,	pixmaps.TurnBR],
+                   [const.CurTurn] * 8) \
+               + [handle.MakePixmapHandle(self.center, (0, 0), pixmaps.Center)]
 
 
 class TrafoSelection(Selection):
 
     def __init__(self, copy_from = None):
-	Selection.__init__(self, copy_from)
-	self.center = None
+        Selection.__init__(self, copy_from)
+        self.center = None
 
     def update_rectangle(self, same_center = 1):
-	if self:
-	    self.rect = TrafoRectangle(self.coord_rect, self.center)
-	else:
-	    self.rect = TrafoRectangle(Rect(0, 0, 0, 0))
+        if self:
+            self.rect = TrafoRectangle(self.coord_rect, self.center)
+        else:
+            self.rect = TrafoRectangle(Rect(0, 0, 0, 0))
 
     def ButtonDown(self, p, button, state):
-	if len(self.objects) == 1:
-	    self.rect.SetOutlineObject(self.objects[0][-1])
-	return self.rect.ButtonDown(p, button, state)
+        if len(self.objects) == 1:
+            self.rect.SetOutlineObject(self.objects[0][-1])
+        return self.rect.ButtonDown(p, button, state)
 
     def MouseMove(self, p, state):
-	self.rect.MouseMove(p, state)
+        self.rect.MouseMove(p, state)
 
     def ButtonUp(self, p, button, state, forget_trafo = 0):
-	self.rect.SetOutlineObject(None)
-	undo_text, trafo = self.rect.ButtonUp(p, button, state)
-	self.center = self.rect.center
-	if forget_trafo:
-	    return None, None
-	if trafo is not None:
-	    t = time.clock()
-	    #undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
-	    undo = self.ForAllUndo2('Transform', trafo)
-	    self.del_lazy_attrs()
-	    #print 'transform/translate', time.clock() - t
-	    return undo_text, undo
-	return '', None
+        self.rect.SetOutlineObject(None)
+        undo_text, trafo = self.rect.ButtonUp(p, button, state)
+        self.center = self.rect.center
+        if forget_trafo:
+            return None, None
+        if trafo is not None:
+            t = time.clock()
+            #undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
+            undo = self.ForAllUndo2('Transform', trafo)
+            self.del_lazy_attrs()
+            #print 'transform/translate', time.clock() - t
+            return undo_text, undo
+        return '', None
 
     def Show(self, device, partially = 0):
-	self.rect.Show(device, partially)
+        self.rect.Show(device, partially)
 
     def Hide(self, device, partially = 0):
-	self.rect.Hide(device, partially)
+        self.rect.Hide(device, partially)
 
     def DrawDragged(self, device, partial):
-	self.rect.DrawDragged(device, partial)
+        self.rect.DrawDragged(device, partial)
 
     def SelectPoint(self, p, rect, device, mode = SelectSet):
-	if not self.rect.SelectPoint(p, rect, device, mode):
-	    if self.Hit(p, rect, device):
-		self.rect.Select()
+        if not self.rect.SelectPoint(p, rect, device, mode):
+            if self.Hit(p, rect, device):
+                self.rect.Select()
 
     def SelectHandle(self, handle, mode = SelectSet):
-	self.rect.SelectHandle(handle, mode)
+        self.rect.SelectHandle(handle, mode)
 
     def Hit(self, p, rect, device):
-	if self.objects:
-	    return (rect.overlaps(self.rect.bounding_rect)
-		    and Selection.Hit(self, p, rect, device))
-	return 0
+        if self.objects:
+            return (rect.overlaps(self.rect.bounding_rect)
+                    and Selection.Hit(self, p, rect, device))
+        return 0
 
     def CurrentInfoText(self):
         return self.rect.CurrentInfoText()
@@ -951,179 +951,179 @@
 class EditorWrapper:
 
     def __init__(self, editor):
-	self.editor = editor
+        self.editor = editor
 
     def __del__(self):
-	self.editor.Destroy()
+        self.editor.Destroy()
 
     def __getattr__(self, attr):
-	return getattr(self.editor, attr)
+        return getattr(self.editor, attr)
 
     def compatible(self, aclass):
-	obj = self.editor
-	return isinstance(obj, aclass) or issubclass(obj.EditedClass, aclass)
+        obj = self.editor
+        return isinstance(obj, aclass) or issubclass(obj.EditedClass, aclass)
 
 
 
 class EditSelection(Selection):
 
     is_EditSelection = 1
-    
+
     drag_this = None
     editor = None
 
     def __init__(self, copy_from = None):
-	Selection.__init__(self, copy_from)
-	self.check_edit_mode()
-	if type(copy_from) == InstanceType \
-	   and copy_from.__class__ == self.__class__:
-	    self.editor = copy_from.editor
-	else:
-	    self.get_editor()
+        Selection.__init__(self, copy_from)
+        self.check_edit_mode()
+        if type(copy_from) == InstanceType \
+           and copy_from.__class__ == self.__class__:
+            self.editor = copy_from.editor
+        else:
+            self.get_editor()
 
     def check_edit_mode(self):
-	# allow only one object for editing at a time
-	if self.objects:
-	    if len(self.objects) > 1 or not self.objects[0][-1].has_edit_mode:
-		self.objects = []
+        # allow only one object for editing at a time
+        if self.objects:
+            if len(self.objects) > 1 or not self.objects[0][-1].has_edit_mode:
+                self.objects = []
 
     def get_editor(self):
-	if self.objects:
-	    self.editor = EditorWrapper(self.objects[0][-1].Editor())
-	else:
-	    self.editor = None
+        if self.objects:
+            self.editor = EditorWrapper(self.objects[0][-1].Editor())
+        else:
+            self.editor = None
 
     def GetHandles(self):
-	if self.editor is not None:
-	    return self.editor.GetHandles()
-	return []
+        if self.editor is not None:
+            return self.editor.GetHandles()
+        return []
 
     def ButtonDown(self, p, button, state):
-	if self.drag_this is not None:
-	    return self.drag_this.ButtonDown(p, button, state)
-	else:
-	    return None
+        if self.drag_this is not None:
+            return self.drag_this.ButtonDown(p, button, state)
+        else:
+            return None
 
     def MouseMove(self, p, state):
-	if self.drag_this is not None:
-	    self.drag_this.MouseMove(p, state)
+        if self.drag_this is not None:
+            self.drag_this.MouseMove(p, state)
 
     def ButtonUp(self, p, button, state, forget_trafo = 0):
-	if self.drag_this is not None:
-	    self.del_lazy_attrs()
-	    return _("Edit Object"), self.drag_this.ButtonUp(p, button, state)
-	return ('', None)
-	# XXX make the undo text more general by a method of graphics objects
+        if self.drag_this is not None:
+            self.del_lazy_attrs()
+            return _("Edit Object"), self.drag_this.ButtonUp(p, button, state)
+        return ('', None)
+        # XXX make the undo text more general by a method of graphics objects
 
     def Show(self, device, partially = 0):
-	if self.editor is not None:
-	    self.editor.Show(device, partially)
+        if self.editor is not None:
+            self.editor.Show(device, partially)
 
     def Hide(self, device, partially = 0):
-	if self.editor is not None:
-	    self.editor.Hide(device, partially)
+        if self.editor is not None:
+            self.editor.Hide(device, partially)
 
     def DrawDragged(self, device, partial):
-	if self.editor is not None:
+        if self.editor is not None:
             self.editor.DrawDragged(device, partial)
 
     def SetSelection(self, info):
-	old_sel = self.objects
-	Selection.SetSelection(self, info)
-	self.check_edit_mode()
-	if old_sel != self.objects:
-	    self.get_editor()
-	    return 1
-	return 0
+        old_sel = self.objects
+        Selection.SetSelection(self, info)
+        self.check_edit_mode()
+        if old_sel != self.objects:
+            self.get_editor()
+            return 1
+        return 0
 
     def SelectPoint(self, p, rect, device, mode = const.SelectSet):
-	self.drag_this = None
-	if self.editor is not None:
-	    if self.editor.SelectPoint(p, rect, device, mode):
-		self.drag_this = self.editor
-	return self.drag_this != None
+        self.drag_this = None
+        if self.editor is not None:
+            if self.editor.SelectPoint(p, rect, device, mode):
+                self.drag_this = self.editor
+        return self.drag_this != None
 
     def SelectHandle(self, handle, mode = SelectSet):
-	if self.editor is not None:
-	    self.editor.SelectHandle(handle, mode)
-	    self.drag_this = self.editor
-	else:
-	    self.drag_this = None
+        if self.editor is not None:
+            self.editor.SelectHandle(handle, mode)
+            self.drag_this = self.editor
+        else:
+            self.drag_this = None
 
     def SelectRect(self, rect, mode = SelectSet):
-	self.drag_this = None
-	if self.editor is not None:
-	    if self.editor.SelectRect(rect, mode):
-		self.drag_this = self.editor
-	return self.drag_this != None
+        self.drag_this = None
+        if self.editor is not None:
+            if self.editor.SelectRect(rect, mode):
+                self.drag_this = self.editor
+        return self.drag_this != None
 
     def CallObjectMethod(self, aclass, methodname, args):
-	if len(self.objects) == 1:
-	    if self.editor is not None:
-		obj = self.editor
-		if not obj.compatible(aclass):
-		    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
-			 'editor %s is not compatible with class %s',
-			 self.editor, aclass)
-		    return NullUndo
-	    else:
-		obj = self.objects[0][-1]
-		if not isinstance(obj, aclass):
-		    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
-			 'object is not instance of %s', aclass)
-		    return NullUndo
-	    try:
-		method = getattr(obj, methodname)
-	    except AttributeError:
-		warn(INTERNAL, 'EditSelection.GetObjectMethod: '
-		     'no method %s for class %s', methodname, aclass)
-		return NullUndo
+        if len(self.objects) == 1:
+            if self.editor is not None:
+                obj = self.editor
+                if not obj.compatible(aclass):
+                    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
+                         'editor %s is not compatible with class %s',
+                         self.editor, aclass)
+                    return NullUndo
+            else:
+                obj = self.objects[0][-1]
+                if not isinstance(obj, aclass):
+                    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
+                         'object is not instance of %s', aclass)
+                    return NullUndo
+            try:
+                method = getattr(obj, methodname)
+            except AttributeError:
+                warn(INTERNAL, 'EditSelection.GetObjectMethod: '
+                     'no method %s for class %s', methodname, aclass)
+                return NullUndo
 
-	    undo = apply(method, args)
-	    if undo is None:
-		undo = NullUndo
-	    return undo
-	return NullUndo
+            undo = apply(method, args)
+            if undo is None:
+                undo = NullUndo
+            return undo
+        return NullUndo
 
     def GetObjectMethod(self, aclass, method):
-	if len(self.objects) == 1:
-	    if self.editor is not None:
-		obj = self.editor
-		if not obj.compatible(aclass):
-		    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
-			 'editor is not compatible with class %s', aclass)
-		    return None
-	    else:
-		obj = self.objects[0][-1]
-		if not isinstance(obj, aclass):
-		    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
-			 'object is not instance of %s', aclass)
-		    return None
-	    try:
-		return getattr(obj, method)
-	    except AttributeError:
-		warn(INTERNAL, 'EditSelection.GetObjectMethod: '
-		     'no method %s for class %s', method, aclass)
-		pass
-	return None
+        if len(self.objects) == 1:
+            if self.editor is not None:
+                obj = self.editor
+                if not obj.compatible(aclass):
+                    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
+                         'editor is not compatible with class %s', aclass)
+                    return None
+            else:
+                obj = self.objects[0][-1]
+                if not isinstance(obj, aclass):
+                    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
+                         'object is not instance of %s', aclass)
+                    return None
+            try:
+                return getattr(obj, method)
+            except AttributeError:
+                warn(INTERNAL, 'EditSelection.GetObjectMethod: '
+                     'no method %s for class %s', method, aclass)
+                pass
+        return None
 
 
     def ChangeRect(self):
-	if self.editor is not None:
-	    return self.editor.ChangeRect()
-	return self.bounding_rect
+        if self.editor is not None:
+            return self.editor.ChangeRect()
+        return self.bounding_rect
 
     def InfoText(self):
-	# Return a string describing the selected object(s)
-	# XXX we shouldn't access document.layers directly
-	if self.editor is not None:
-	    return self.editor.Info()
-	else:
-	    return _("No Selection")
+        # Return a string describing the selected object(s)
+        # XXX we shouldn't access document.layers directly
+        if self.editor is not None:
+            return self.editor.Info()
+        else:
+            return _("No Selection")
 
     def CurrentInfoText(self):
-	if self.editor is not None:
-	    return self.editor.CurrentInfoText()
-	else:
-	    return ""
-        
+        if self.editor is not None:
+            return self.editor.CurrentInfoText()
+        else:
+            return ""
+

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/selinfo.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/selinfo.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/selinfo.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -122,14 +122,14 @@
 def prepend_idx(idx, info):
     # prepend idx to the path of info.
     if type(info) == TupleType:
-	return ((idx,) + info[0], info[1])
+        return ((idx,) + info[0], info[1])
 
     if type(info) == ListType:
-	idx = (idx,)
-	for i in range(len(info)):
-	    tmp = info[i]
-	    info[i] = (idx + tmp[0], tmp[1])
-	return info
+        idx = (idx,)
+        for i in range(len(info)):
+            tmp = info[i]
+            info[i] = (idx + tmp[0], tmp[1])
+        return info
 
     # assume info is an instance object
     return ((idx,), info)
@@ -139,14 +139,14 @@
 
 def select_range(min, objects):
     return map(None, map(lambda *t: t, range(min, min + len(objects))),
-	       objects)
+               objects)
 
 def get_parent(info):
     path, obj = info
     if len(path) > 1:
-	parent = obj.parent
-	if parent is not None:
-	    return (path[:-1], parent)
+        parent = obj.parent
+        if parent is not None:
+            return (path[:-1], parent)
     return None
 
 
@@ -154,42 +154,42 @@
     # convert standard representation to Tree1 representation
     dict = {}
     for info in infolist:
-	path, obj = info
-	idx = path[0]
-	info = (path[1:], obj)
-	try:
-	    dict[idx].append(info)
-	except KeyError:
-	    dict[idx] = [info]
+        path, obj = info
+        idx = path[0]
+        info = (path[1:], obj)
+        try:
+            dict[idx].append(info)
+        except KeyError:
+            dict[idx] = [info]
     result = dict.items()
     result.sort()
     for idx, info in result:
-	info.sort()
+        info.sort()
     return result
 
 def list_to_tree2(infolist):
     # convert standard representation to Tree2 representation
     dict = {}
     for info in infolist:
-	path, obj = info
-	idx = path[0]
-	path = path[1:]
-	if path:
-	    info = (path, obj)
-	else:
-	    info = obj
-	try:
-	    dict[idx].append(info)
-	except KeyError:
-	    dict[idx] = [info]
+        path, obj = info
+        idx = path[0]
+        path = path[1:]
+        if path:
+            info = (path, obj)
+        else:
+            info = obj
+        try:
+            dict[idx].append(info)
+        except KeyError:
+            dict[idx] = [info]
     result = dict.items()
     result.sort()
     for i in range(len(result)):
-	idx, info = result[i]
-	if len(info) == 1 and type(info[0]) != TupleType:
-	    result[i] = (idx, info[0])
-	else:
-	    info.sort()
+        idx, info = result[i]
+        if len(info) == 1 and type(info[0]) != TupleType:
+            result[i] = (idx, info[0])
+        else:
+            info.sort()
     return result
 
 def list_to_tree_sliced(infolist):
@@ -198,36 +198,36 @@
     slice_start = slice_end = -1
     last_obj = None
     for idx, list in list_to_tree2(infolist):
-	if type(list) != ListType:
-	    # list is a child
-	    if idx == slice_end:
-		slice_end = idx + 1
-	    else:
-		if slice_start > -1:
-		    if slice_end > slice_start + 1:
-			result.append((slice_start, slice_end))
-		    else:
-			result.append((slice_start, last_obj))
-		slice_start = idx
-		slice_end = idx + 1
-		last_obj = list
-	else:
-	    # list is a list of children of child
-	    if slice_start > -1:
-		if slice_end > slice_start + 1:
-		    result.append((slice_start, slice_end))
-		else:
-		    result.append((slice_start, last_obj))
-	    slice_start = -1
-	    slice_end = -1
-	    last_obj = None
-	    result.append((idx, list))
+        if type(list) != ListType:
+            # list is a child
+            if idx == slice_end:
+                slice_end = idx + 1
+            else:
+                if slice_start > -1:
+                    if slice_end > slice_start + 1:
+                        result.append((slice_start, slice_end))
+                    else:
+                        result.append((slice_start, last_obj))
+                slice_start = idx
+                slice_end = idx + 1
+                last_obj = list
+        else:
+            # list is a list of children of child
+            if slice_start > -1:
+                if slice_end > slice_start + 1:
+                    result.append((slice_start, slice_end))
+                else:
+                    result.append((slice_start, last_obj))
+            slice_start = -1
+            slice_end = -1
+            last_obj = None
+            result.append((idx, list))
     else:
-	if slice_start > -1:
-	    if slice_end > slice_start + 1:
-		result.append((slice_start, slice_end))
-	    else:
-		result.append((slice_start, last_obj))
+        if slice_start > -1:
+            if slice_end > slice_start + 1:
+                result.append((slice_start, slice_end))
+            else:
+                result.append((slice_start, last_obj))
     return result
 
 
@@ -235,9 +235,9 @@
 def tree_to_list(tree):
     result = []
     for idx, info in tree:
-	idx = (idx,)
-	for path, obj in info:
-	    result.append((idx + path, obj))
+        idx = (idx,)
+        for path, obj in info:
+            result.append((idx + path, obj))
     return result
 
 
@@ -246,20 +246,20 @@
     # LIST is in standard representation. Since that is a sorted list,
     # we just have to compare the first and last elements.
     if not list:
-	return ()
+        return ()
     if len(list) == 1:
-	return list[0][0]
+        return list[0][0]
     first = list[0][0]
     last = list[-1][0]
     if len(first) > len(last):
-	length = len(last)
-	first = first[:length]
+        length = len(last)
+        first = first[:length]
     else:
-	length = len(first)
-	last = last[:length]
+        length = len(first)
+        last = last[:length]
     for i in range(length):
-	if first[i] != last[i]:
-	    return first[:i]
+        if first[i] != last[i]:
+            return first[:i]
     return first
 
 

Modified: skencil/branches/skencil-0.6/src/Sketch/Graphics/text.py
===================================================================
--- skencil/branches/skencil-0.6/src/Sketch/Graphics/text.py	2010-09-22 19:13:59 UTC (rev 726)
+++ skencil/branches/skencil-0.6/src/Sketch/Graphics/text.py	2010-09-22 21:52:28 UTC (rev 727)
@@ -77,7 +77,7 @@
 
 from string import split
 from math import sin, cos, atan2, hypot, pi, fmod, floor
-        
+
 from Sketch import _, Rect, UnionRects, EmptyRect, NullPoint, Polar, \
      IdentityMatrix, SingularMatrix, Identity, Trafo, Scale, Translation, \
      Rotation, NullUndo, CreateMultiUndo, RegisterCommands
@@ -104,7 +104,7 @@
 printable = ''
 for n in range(len(iso_latin_1)):
     if iso_latin_1[n] != encoding.notdef:
-	printable = printable + chr(n)
+        printable = printable + chr(n)
 
 
 # Alignment. Defaults are 0
@@ -121,50 +121,50 @@
     commands = []
 
     def __init__(self, text = '', duplicate = None):
-	if duplicate is not None:
-	    self.text = duplicate.text
-	else:
-	    self.text = text
+        if duplicate is not None:
+            self.text = duplicate.text
+        else:
+            self.text = text
 
     def SetText(self, text, caret = None):
-	if self.editor is not None:
-	    oldcaret = self.editor.Caret()
-	else:
-	    oldcaret = 0
-	undo = (self.SetText, self.text, oldcaret)
-	self.text = text
-	if caret is not None and self.editor is not None:
-	    self.editor.SetCaret(caret)
-	self._changed()
-	return undo
+        if self.editor is not None:
+            oldcaret = self.editor.Caret()
+        else:
+            oldcaret = 0
+        undo = (self.SetText, self.text, oldcaret)
+        self.text = text
+        if caret is not None and self.editor is not None:
+            self.editor.SetCaret(caret)
+        self._changed()
+        return undo
 
     def Text(self):
-	return self.text
+        return self.text
 
     editor = None
     def set_editor(self, editor):
-	self.editor = editor
+        self.editor = editor
 
     def unset_editor(self, editor):
-	if self.editor is editor:
-	    self.editor = None
+        if self.editor is editor:
+            self.editor = None
 
     def SetFont(self, font, size = None):
-	if size is not None:
-	    undo = self.properties.SetProperty(font = font, font_size = size)
-	else:
-	    undo = self.properties.SetProperty(font = font)
-	return self.properties_changed(undo)
+        if size is not None:
+            undo = self.properties.SetProperty(font = font, font_size = size)
+        else:
+            undo = self.properties.SetProperty(font = font)
+        return self.properties_changed(undo)
 
     def SetFontSize(self, size):
-	undo = self.properties.SetProperty(font_size = size)
-	return self.properties_changed(undo)
+        undo = self.properties.SetProperty(font_size = size)
+        return self.properties_changed(undo)
 
     def Font(self):
-	return self.properties.font
+        return self.properties.font
 
     def FontSize(self):
-	return self.properties.font_size
+        return self.properties.font_size
 
 
 class CommonTextEditor(Editor):
@@ -173,81 +173,81 @@
     commands = []
 
     def __init__(self, object):
-	Editor.__init__(self, object)
-	self.caret = 0
-	object.set_editor(self)
+        Editor.__init__(self, object)
+        self.caret = 0
+        object.set_editor(self)
 
     def Destroy(self):
-	self.object.unset_editor(self)
+        self.object.unset_editor(self)
 
     def ButtonDown(self, p, button, state):
-	Editor.DragStart(self, p)
+        Editor.DragStart(self, p)
 
     def ButtonUp(self, p, button, state):
-	Editor.DragStop(self, p)
+        Editor.DragStop(self, p)
 
     def update_selection(self):
-	# a bit ugly...
-	if self.document is not None:
-	    self.document.queue_selection()
+        # a bit ugly...
+        if self.document is not None:
+            self.document.queue_selection()
 
     def SetCaret(self, caret):
         if caret > len(self.text):
             caret = len(self.text)
-	self.caret = caret
+        self.caret = caret
 
     def Caret(self):
-	return self.caret
+        return self.caret
 
     def InsertCharacter(self, char):
-	if len(char) == 1 and self.properties.font.IsPrintable(char):
-	    text = self.text;	caret = self.caret
-	    text = text[:caret] + char + text[caret:]
-	    return self.SetText(text, caret + 1)
-	return NullUndo
+        if len(char) == 1 and self.properties.font.IsPrintable(char):
+            text = self.text;	caret = self.caret
+            text = text[:caret] + char + text[caret:]
+            return self.SetText(text, caret + 1)
+        return NullUndo
     AddCmd(commands, InsertCharacter, '', key_stroke = tuple(printable),
-	   invoke_with_keystroke = 1)
+           invoke_with_keystroke = 1)
 
     def DeleteCharBackward(self):
-	if self.text and self.caret > 0:
-	    text = self.text; caret = self.caret
-	    text = text[:caret - 1] + text[caret:]
-	    return self.SetText(text, caret - 1)
-	return NullUndo
+        if self.text and self.caret > 0:
+            text = self.text; caret = self.caret
+            text = text[:caret - 1] + text[caret:]
+            return self.SetText(text, caret - 1)
+        return NullUndo
     AddCmd(commands, DeleteCharBackward, '', key_stroke = 'BackSpace')
 
     def DeleteCharForward(self):
-	if self.text and self.caret < len(self.text):
-	    text = self.text; caret = self.caret
-	    text = text[:caret] + text[caret + 1:]
-	    return self.SetText(text, caret)
-	return NullUndo
+        if self.text and self.caret < len(self.text):
+            text = self.text; caret = self.caret
+            text = text[:caret] + text[caret + 1:]
+            return self.SetText(text, caret)
+        return NullUndo
     AddCmd(commands, DeleteCharForward, '', key_stroke = ('Delete', 'C-d'))
 
     def MoveForwardChar(self):
-	if self.caret < len(self.text):
-	    self.SetCaret(self.caret + 1)
-	    self.update_selection()
-	return NullUndo
+        if self.caret < len(self.text):
+            self.SetCaret(self.caret + 1)
+            self.update_selection()
+        return NullUndo
     AddCmd(commands, MoveForwardChar, '', key_stroke = ('Right', 'C-f'))
 
     def MoveBackwardChar(self):
-	if self.caret > 0:
-	    self.SetCaret(self.caret - 1)
-	    self.update_selection()
-	return NullUndo
+        if self.caret > 0:
+            self.SetCaret(self.caret - 1)
+            self.update_selection()
+        return NullUndo
     AddCmd(commands, MoveBackwardChar, '', key_stroke = ('Left', 'C-b'))
 
     def MoveToBeginningOfLine(self):
-	self.SetCaret(0)
-	self.update_selection()
-	return NullUndo
+        self.SetCaret(0)
+        self.update_selection()
+        return NullUndo
     AddCmd(commands, MoveToBeginningOfLine, '', key_stroke = ('Home', 'C-a'))
 
     def MoveToEndOfLine(self):
-	self.SetCaret(len(self.text))
-	self.update_selection()
-	return NullUndo
+        self.SetCaret(len(self.text))
+        self.update_selection()
+        return NullUndo
     AddCmd(commands, MoveToEndOfLine, '', key_stroke = ('End', 'C-e'))
 
 
@@ -272,115 +272,115 @@
 
     def __init__(self, trafo = None, text = '', halign = ALIGN_LEFT,
                  valign = ALIGN_BASE, properties = None, duplicate = None):
-	CommonText.__init__(self, text, duplicate)
-	RectangularPrimitive.__init__(self, trafo, properties = properties,
-				      duplicate = duplicate)
-	if duplicate != None:
-	    self.halign = duplicate.halign
-	    self.valign = duplicate.valign
-	    self.atrafo = duplicate.atrafo
-	else:
-	    self.halign = halign
-	    self.valign = valign
-	    if properties is None:
+        CommonText.__init__(self, text, duplicate)
+        RectangularPrimitive.__init__(self, trafo, properties = properties,
+                                      duplicate = duplicate)
+        if duplicate != None:
+            self.halign = duplicate.halign
+            self.valign = duplicate.valign
+            self.atrafo = duplicate.atrafo
+        else:
+            self.halign = halign
+            self.valign = valign
+            if properties is None:
                 self.properties = PropertyStack(base=FactoryTextStyle())
-	self.cache = {}
+        self.cache = {}
 
     def Disconnect(self):
-	self.cache = {}
-	RectangularPrimitive.Disconnect(self)
+        self.cache = {}
+        RectangularPrimitive.Disconnect(self)
 
     def Hit(self, p, rect, device, clip = 0):
-	a = self.properties
-	llx, lly, urx, ury = a.font.TextBoundingBox(self.text, a.font_size)
-	trafo = self.trafo(self.atrafo)
-	trafo = trafo(Trafo(urx - llx, 0, 0, ury - lly, llx, lly))
-	return device.ParallelogramHit(p, trafo, 1, 1, 1,
-				       ignore_outline_mode = 1)
+        a = self.properties
+        llx, lly, urx, ury = a.font.TextBoundingBox(self.text, a.font_size)
+        trafo = self.trafo(self.atrafo)
+        trafo = trafo(Trafo(urx - llx, 0, 0, ury - lly, llx, lly))
+        return device.ParallelogramHit(p, trafo, 1, 1, 1,
+                                       ignore_outline_mode = 1)
 
     def GetObjectHandle(self, multiple):
-	trafo = self.trafo(self.atrafo(Scale(self.properties.font_size)))
-	if multiple:
-	    return trafo(NullPoint)
-	else:
-	    pts = self.properties.font.TypesetText(self.text)
-	    return map(trafo, pts)
+        trafo = self.trafo(self.atrafo(Scale(self.properties.font_size)))
+        if multiple:
+            return trafo(NullPoint)
+        else:
+            pts = self.properties.font.TypesetText(self.text)
+            return map(trafo, pts)
 
 
     def SetAlignment(self, horizontal, vertical):
-	undo = (self.SetAlignment, self.halign, self.valign)
-	if horizontal is not None:
-	    self.halign = horizontal
-	if vertical is not None:
-	    self.valign = vertical
-	self._changed()
-	return undo
+        undo = (self.SetAlignment, self.halign, self.valign)
+        if horizontal is not None:
+            self.halign = horizontal
+        if vertical is not None:
+            self.valign = vertical
+        self._changed()
+        return undo
     AddCmd(commands, 'AlignLeft', _("Align Left"), SetAlignment,
-	   args = (ALIGN_LEFT, None))
+           args = (ALIGN_LEFT, None))
     AddCmd(commands, 'AlignRight', _("Align Right"), SetAlignment,
-	   args =(ALIGN_RIGHT,None))
+           args =(ALIGN_RIGHT,None))
     AddCmd(commands, 'AlignHCenter', _("Align H. Center"), SetAlignment,
-	   args = (ALIGN_CENTER, None))
+           args = (ALIGN_CENTER, None))
     AddCmd(commands, 'AlignTop', _("Align Top"), SetAlignment,
-	   args = (None, ALIGN_TOP))
+           args = (None, ALIGN_TOP))
     AddCmd(commands, 'AlignVCenter', _("Align V. Center"), SetAlignment,
-	   args =(None, ALIGN_CENTER))
+           args =(None, ALIGN_CENTER))
     AddCmd(commands, 'AlignBase', _("Align Baseline"), SetAlignment,
-	   args = (None, ALIGN_BASE))
+           args = (None, ALIGN_BASE))
     AddCmd(commands, 'AlignBottom', _("Align Bottom"), SetAlignment,
-	   args = (None, ALIGN_BOTTOM))
+           args = (None, ALIGN_BOTTOM))
 
     def Alignment(self):
-	return self.halign, self.valign
+        return self.halign, self.valign
 
     def RemoveTransformation(self):
-	if self.trafo.matrix() != IdentityMatrix:
-	    a = self.properties
-	    trafo = self.trafo
-	    llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size)
-	    try:
-		undostyle = Primitive.Transform(self, trafo.inverse())
-	    except SingularMatrix:
-		undostyle = None
-	    undotrafo = self.set_transformation(Translation(trafo.offset()))
-	    return CreateMultiUndo(undostyle, undotrafo)
-	return NullUndo
+        if self.trafo.matrix() != IdentityMatrix:
+            a = self.properties
+            trafo = self.trafo
+            llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size)
+            try:
+                undostyle = Primitive.Transform(self, trafo.inverse())
+            except SingularMatrix:
+                undostyle = None
+            undotrafo = self.set_transformation(Translation(trafo.offset()))
+            return CreateMultiUndo(undostyle, undotrafo)
+        return NullUndo
 
     def DrawShape(self, device, rect = None, clip = 0):
-	RectangularPrimitive.DrawShape(self, device)
+        RectangularPrimitive.DrawShape(self, device)
         # Workaround for a bug in my Xserver.
         text = split(self.text, '\n')[0]
-	device.DrawText(self.text, self.trafo(self.atrafo), clip,
-			cache = self.cache)
+        device.DrawText(self.text, self.trafo(self.atrafo), clip,
+                        cache = self.cache)
 
     def update_atrafo(self):
-	a = self.properties
-	llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size)
-	hj = self.halign
-	if hj == ALIGN_RIGHT:
-	    xoff = llx - urx
-	elif hj == ALIGN_CENTER:
-	    xoff = (llx - urx) / 2
-	else:
-	    xoff = 0
-	vj = self.valign
-	if vj == ALIGN_TOP:
-	    yoff = -ury
-	elif vj == ALIGN_CENTER:
-	    yoff = (lly - ury) / 2 - lly
-	elif vj == ALIGN_BOTTOM:
-	    yoff = -lly
-	else:
-	    yoff = 0
-	self.atrafo = Translation(xoff, yoff)
+        a = self.properties
+        llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size)
+        hj = self.halign
+        if hj == ALIGN_RIGHT:
+            xoff = llx - urx
+        elif hj == ALIGN_CENTER:
+            xoff = (llx - urx) / 2
+        else:
+            xoff = 0
+        vj = self.valign
+        if vj == ALIGN_TOP:
+            yoff = -ury
+        elif vj == ALIGN_CENTER:
+            yoff = (lly - ury) / 2 - lly
+        elif vj == ALIGN_BOTTOM:
+            yoff = -lly
+        else:
+            yoff = 0
+        self.atrafo = Translation(xoff, yoff)
 
     def update_rects(self):
-	trafo = self.trafo(self.atrafo)
-	a = self.properties
-	rect = apply(Rect, a.font.TextBoundingBox(self.text, a.font_size))
-	self.bounding_rect = trafo(rect).grown(2)
-	rect = apply(Rect, a.font.TextCoordBox(self.text, a.font_size))
-	self.coord_rect = trafo(rect)
+        trafo = self.trafo(self.atrafo)
+        a = self.properties
+        rect = apply(Rect, a.font.TextBoundingBox(self.text, a.font_size))
+        self.bounding_rect = trafo(rect).grown(2)
+        rect = apply(Rect, a.font.TextCoordBox(self.text, a.font_size))
+        self.coord_rect = trafo(rect)
 
     def Info(self):
         return (_("Text `%(text)s' at %(position)[position]"),
@@ -392,43 +392,43 @@
         return self.trafo(self.atrafo)
 
     def SaveToFile(self, file):
-	RectangularPrimitive.SaveToFile(self, file)
-	file.SimpleText(self.text, self.trafo, self.halign, self.valign)
+        RectangularPrimitive.SaveToFile(self, file)
+        file.SimpleText(self.text, self.trafo, self.halign, self.valign)
 
     def Blend(self, other, p, q):
-	if self.__class__ != other.__class__ \
-	   or self.properties.font != other.properties.font \
-	   or self.text != other.text:
-	    raise MismatchError
-	blended = self.__class__(BlendTrafo(self.trafo, other.trafo, p, q),
-				 self.text)
-	self.set_blended_properties(blended, other, p, q)
-	return blended
+        if self.__class__ != other.__class__ \
+           or self.properties.font != other.properties.font \
+           or self.text != other.text:
+            raise MismatchError
+        blended = self.__class__(BlendTrafo(self.trafo, other.trafo, p, q),
+                                 self.text)
+        self.set_blended_properties(blended, other, p, q)
+        return blended
 
     def AsBezier(self):
-	if self.text:
-	    objects = []
-	    base_trafo = self.trafo(self.atrafo)
-	    base_trafo = base_trafo(Scale(self.properties.font_size))
-	    pos = self.properties.font.TypesetText(self.text)
-	    for i in range(len(self.text)):
-		paths = self.properties.font.GetOutline(self.text[i])
-		if paths:
+        if self.text:
+            objects = []
+            base_trafo = self.trafo(self.atrafo)
+            base_trafo = base_trafo(Scale(self.properties.font_size))
+            pos = self.properties.font.TypesetText(self.text)
+            for i in range(len(self.text)):
+                paths = self.properties.font.GetOutline(self.text[i])
+                if paths:
                     obj = PolyBezier(paths = paths,
-				     properties = self.properties.Duplicate())
-		    trafo = base_trafo(Translation(pos[i]))
-		    obj.Transform(trafo)
-		    objects.append(obj)
-	    return Group(objects)
+                                     properties = self.properties.Duplicate())
+                    trafo = base_trafo(Translation(pos[i]))
+                    obj.Transform(trafo)
+                    objects.append(obj)
+            return Group(objects)
 
     def Paths(self):
         paths = []
         if self.text:
-	    base_trafo = self.trafo(self.atrafo)
-	    base_trafo = base_trafo(Scale(self.properties.font_size))
-	    pos = self.properties.font.TypesetText(self.text)
-	    for i in range(len(self.text)):
-		outline = self.properties.font.GetOutline(self.text[i])
+            base_trafo = self.trafo(self.atrafo)
+            base_trafo = base_trafo(Scale(self.properties.font_size))
+            pos = self.properties.font.TypesetText(self.text)
+            for i in range(len(self.text)):
+                outline = self.properties.font.GetOutline(self.text[i])
                 trafo = base_trafo(Translation(pos[i]))
                 for path in outline:
                     path.Transform(trafo)
@@ -436,10 +436,10 @@
         return tuple(paths)            
 
     def Editor(self):
-	return SimpleTextEditor(self)
+        return SimpleTextEditor(self)
 
     context_commands = ('AlignLeft', 'AlignRight', 'AlignHCenter', None,
-			'AlignTop', 'AlignVCenter', 'AlignBase', 'AlignBottom')
+                        'AlignTop', 'AlignVCenter', 'AlignBase', 'AlignBottom')
 
 RegisterCommands(SimpleText)
 
@@ -450,24 +450,24 @@
     creation_text = _("Create Text")
 
     def __init__(self, start):
-	Creator.__init__(self, start)
+        Creator.__init__(self, start)
 
     def ButtonDown(self, p, button, state):
-	Creator.DragStart(self, p)
+        Creator.DragStart(self, p)
 
     def MouseMove(self, p, state):
-	p = self.apply_constraint(p, state)
-	Creator.MouseMove(self, p, state)
-        
+        p = self.apply_constraint(p, state)
+        Creator.MouseMove(self, p, state)
+
     def ButtonUp(self, p, button, state):
         p = self.apply_constraint(p, state)
-	Creator.DragStop(self, p)
+        Creator.DragStop(self, p)
 
     def DrawDragged(self, device, partially):
-	device.DrawLine(self.start, self.drag_cur)
+        device.DrawLine(self.start, self.drag_cur)
 
     def apply_constraint(self, p, state):
-	if state & const.ConstraintMask:
+        if state & const.ConstraintMask:
             r, phi = (p - self.start).polar()
             pi12 = pi / 12
             phi = pi12 * floor(phi / pi12 + 0.5)
@@ -475,10 +475,10 @@
         return p
 
     def CreatedObject(self):
-	trafo = Translation(self.start)
-	r, phi = (self.drag_cur - self.start).polar()
-	if r:
-	    trafo = trafo(Rotation(phi))
+        trafo = Translation(self.start)
+        r, phi = (self.drag_cur - self.start).polar()
+        if r:
+            trafo = trafo(Rotation(phi))
         return SimpleText(trafo = trafo, properties = DefaultTextProperties())
 
 class SimpleTextEditor(CommonTextEditor):
@@ -487,11 +487,11 @@
     commands = CommonTextEditor.commands[:]
 
     def GetHandles(self):
-	a = self.properties
-	pos, up = a.font.TextCaretData(self.text, self.caret, a.font_size)
-	pos = self.trafo(self.atrafo(pos))
-	up = self.trafo.DTransform(up)
-	return [handle.MakeCaretHandle(pos, up)]
+        a = self.properties
+        pos, up = a.font.TextCaretData(self.text, self.caret, a.font_size)
+        pos = self.trafo(self.atrafo(pos))
+        up = self.trafo.DTransform(up)
+        return [handle.MakeCaretHandle(pos, up)]
 
     def SelectPoint(self, p, rect, device, mode):
         trafo = self.trafo(self.atrafo(Scale(self.properties.font_size)))
@@ -530,7 +530,7 @@
     if len(lengths) < 2:
         return None
     for idx in range(len(lengths)):
-	if lengths[idx][0] > pos:
+        if lengths[idx][0] > pos:
             d2, p2 = lengths[idx]
             d1, p1 = lengths[idx - 1]
             if d2 != d1 and p1 != p2:
@@ -542,9 +542,9 @@
     diff = (p2 - p1).normalized()
     del lengths[:idx - 1]
     if type == PATHTEXT_SKEW:
-	return Trafo(diff.x, diff.y, 0, 1, p.x, p.y)
+        return Trafo(diff.x, diff.y, 0, 1, p.x, p.y)
     else:
-	return Trafo(diff.x, diff.y, -diff.y, diff.x, p.x, p.y)
+        return Trafo(diff.x, diff.y, -diff.y, diff.x, p.x, p.y)
 
 
 def pathtext(path, start_pos, text, font, size, type):
@@ -555,10 +555,10 @@
     pos = map(scale, pos)
     trafos = []
     for idx in range(len(text)):
-	char = text[idx]
-	width2 = metric.char_width(ord(char)) * factor
-	x = pos[idx].x + width2
-	trafo = coord_sys_at(lengths, x, type)
+        char = text[idx]
+        width2 = metric.char_width(ord(char)) * factor
+        x = pos[idx].x + width2
+        trafo = coord_sys_at(lengths, x, type)
         if trafo is not None:
             trafos.append(trafo(Translation(-width2, 0)))
         else:
@@ -587,154 +587,154 @@
     commands = CommonText.commands + Primitive.commands
 
     def __init__(self, text = '', trafo = None, model = PATHTEXT_ROTATE,
-		 start_pos = 0.0, properties = None, duplicate = None):
-	CommonText.__init__(self, text, duplicate = duplicate)
-	Primitive.__init__(self, properties = properties,
-			   duplicate = duplicate)
-	if duplicate is not None and isinstance(duplicate, self.__class__):
-	    # dont copy paths, update it from parent
-	    self.trafo = duplicate.trafo
-	    self.model = duplicate.model
-	    self.start_pos = duplicate.start_pos
-	else:
-	    if trafo is None:
-		self.trafo = Identity
-	    else:
-		self.trafo = trafo
-	    self.model = model
-	    self.start_pos = start_pos
-	self.cache = {}
+                 start_pos = 0.0, properties = None, duplicate = None):
+        CommonText.__init__(self, text, duplicate = duplicate)
+        Primitive.__init__(self, properties = properties,
+                           duplicate = duplicate)
+        if duplicate is not None and isinstance(duplicate, self.__class__):
+            # dont copy paths, update it from parent
+            self.trafo = duplicate.trafo
+            self.model = duplicate.model
+            self.start_pos = duplicate.start_pos
+        else:
+            if trafo is None:
+                self.trafo = Identity
+            else:
+                self.trafo = trafo
+            self.model = model
+            self.start_pos = start_pos
+        self.cache = {}
 
 
     def update_rects(self):
-	a = self.properties
-	length = len(self.trafos)
-	sizes = [a.font_size] * length
+        a = self.properties
+        length = len(self.trafos)
+        sizes = [a.font_size] * length
 
         boxes = map(a.font.TextBoundingBox, self.text[:length], sizes)
-	rects = map(lambda *a:a, map(apply, [Rect] * length, boxes))
-	self.bounding_rect = reduce(UnionRects, map(apply, self.trafos, rects),
-				    EmptyRect)
+        rects = map(lambda *a:a, map(apply, [Rect] * length, boxes))
+        self.bounding_rect = reduce(UnionRects, map(apply, self.trafos, rects),
+                                    EmptyRect)
 
         boxes = map(a.font.TextCoordBox, self.text[:length], sizes)
-	rects = map(lambda *a:a, map(apply, [Rect] * length, boxes))
-	self.coord_rect = reduce(UnionRects, map(apply, self.trafos, rects),
-				 EmptyRect)
+        rects = map(lambda *a:a, map(apply, [Rect] * length, boxes))
+        self.coord_rect = reduce(UnionRects, map(apply, self.trafos, rects),
+                                 EmptyRect)
 
     def update_trafos(self):
-	self.trafos = map(self.trafo, pathtext(self.paths[0], self.start_pos,
-					       self.text, self.properties.font,
-					       self.properties.font_size,
-					       self.model))
+        self.trafos = map(self.trafo, pathtext(self.paths[0], self.start_pos,
+                                               self.text, self.properties.font,
+                                               self.properties.font_size,
+                                               self.model))
     def update_paths(self):
-	paths = self.parent.get_paths()
-	try:
-	    itrafo = self.trafo.inverse()
-	    transformed = []
-	    for path in paths:
-		path = path.Duplicate()
-		path.Transform(itrafo)
-		transformed.append(path)
-	    paths = tuple(transformed)
-	except SingularMatrix:
-	    # XXX what do we do?
-	    pass
-	self.paths = paths
+        paths = self.parent.get_paths()
+        try:
+            itrafo = self.trafo.inverse()
+            transformed = []
+            for path in paths:
+                path = path.Duplicate()
+                path.Transform(itrafo)
+                transformed.append(path)
+            paths = tuple(transformed)
+        except SingularMatrix:
+            # XXX what do we do?
+            pass
+        self.paths = paths
 
     def SetText(self, text, caret = None):
-	self.cache = {}
-	return CommonText.SetText(self, text, caret)
+        self.cache = {}
+        return CommonText.SetText(self, text, caret)
 
     def PathChanged(self):
-	self.del_lazy_attrs()
+        self.del_lazy_attrs()
 
     def SetModel(self, model):
-	undo = (self.SetModel, self.model)
-	self.model = model
-	self._changed()
-	return undo
+        undo = (self.SetModel, self.model)
+        self.model = model
+        self._changed()
+        return undo
 
     def Model(self):
-	return self.model
+        return self.model
 
     def SetStartPos(self, start_pos):
-	undo = (self.SetStartPos, self.start_pos)
-	self.start_pos = start_pos
-	self._changed()
-	return undo
+        undo = (self.SetStartPos, self.start_pos)
+        self.start_pos = start_pos
+        self._changed()
+        return undo
 
     def StartPos(self):
-	return self.start_pos
+        return self.start_pos
 
     def CharacterTransformations(self):
         return self.trafos
 
     def DrawShape(self, device, rect = None, clip = 0):
-	text = self.text; trafos = self.trafos
-	font = self.properties.font; font_size = self.properties.font_size
+        text = self.text; trafos = self.trafos
+        font = self.properties.font; font_size = self.properties.font_size
 
-	Primitive.DrawShape(self, device)
-	device.BeginComplexText(clip, self.cache)
-	for idx in range(len(trafos)):
+        Primitive.DrawShape(self, device)
+        device.BeginComplexText(clip, self.cache)
+        for idx in range(len(trafos)):
             char = text[idx]
             if char not in '\r\n': # avoid control chars
                 device.DrawComplexText(text[idx], trafos[idx], font, font_size)
-	device.EndComplexText()
+        device.EndComplexText()
 
     def Disconnect(self):
-	self.cache = {}
-	Primitive.Disconnect(self)
+        self.cache = {}
+        Primitive.Disconnect(self)
 
     def Hit(self, p, rect, device, clip = 0):
-	bbox = self.properties.font.TextBoundingBox
-	font_size = self.properties.font_size
-	text = self.text; trafos = self.trafos
+        bbox = self.properties.font.TextBoundingBox
+        font_size = self.properties.font_size
+        text = self.text; trafos = self.trafos
 
-	for idx in range(len(trafos)):
-	    llx, lly, urx, ury = bbox(text[idx], font_size)
-	    trafo = trafos[idx](Trafo(urx - llx, 0, 0, ury - lly, llx, lly))
-	    if device.ParallelogramHit(p, trafo, 1, 1, 1,
-				       ignore_outline_mode = 1):
-		return 1
-	return 0
+        for idx in range(len(trafos)):
+            llx, lly, urx, ury = bbox(text[idx], font_size)
+            trafo = trafos[idx](Trafo(urx - llx, 0, 0, ury - lly, llx, lly))
+            if device.ParallelogramHit(p, trafo, 1, 1, 1,
+                                       ignore_outline_mode = 1):
+                return 1
+        return 0
 
     def Translate(self, offset):
-	return NullUndo
+        return NullUndo
 
     def Transform(self, trafo):
-	return self.set_transformation(trafo(self.trafo))
+        return self.set_transformation(trafo(self.trafo))
 
     def set_transformation(self, trafo):
-	undo = (self.set_transformation, self.trafo)
-	self.trafo = trafo
-	self._changed()
-	return undo
+        undo = (self.set_transformation, self.trafo)
+        self.trafo = trafo
+        self._changed()
+        return undo
 
     def RemoveTransformation(self):
-	return self.set_transformation(Identity)
+        return self.set_transformation(Identity)
 
     def Blend(self, other, p, q):
-	if self.__class__ != other.__class__ \
-	   or self.properties.font != other.properties.font \
-	   or self.text != other.text:
-	    raise MismatchError
+        if self.__class__ != other.__class__ \
+           or self.properties.font != other.properties.font \
+           or self.text != other.text:
+            raise MismatchError
         trafo = BlendTrafo(self.trafo, other.trafo, p, q)
         start_pos = p * self.start_pos + q * other.start_pos
-	blended = self.__class__(self.text, trafo = trafo,
+        blended = self.__class__(self.text, trafo = trafo,
                                  start_pos = start_pos, model = self.model)
-	self.set_blended_properties(blended, other, p, q)
-	return blended
+        self.set_blended_properties(blended, other, p, q)
+        return blended
 
     def SaveToFile(self, file):
-	Primitive.SaveToFile(self, file)
-	file.InternalPathText(self.text, self.trafo, self.model,
+        Primitive.SaveToFile(self, file)
+        file.InternalPathText(self.text, self.trafo, self.model,
                               self.start_pos)
 
     def Info(self):
-	return _("Text on Path: `%(text)s'") % {'text':self.text[:10]}
+        return _("Text on Path: `%(text)s'") % {'text':self.text[:10]}
 
     def Editor(self):
-	return InternalPathTextEditor(self)
+        return InternalPathTextEditor(self)
 
 class InternalPathTextEditor(CommonTextEditor):
 
@@ -742,31 +742,31 @@
     commands = CommonTextEditor.commands
 
     def GetHandles(self):
-	a = self.properties
-	if self.caret > 0 and self.trafos:
+        a = self.properties
+        if self.caret > 0 and self.trafos:
             # special case to deal with here: the characters that fall
             # off the end of the path are not visible. If the caret is
             # in this invisible area, display the caret after the last
             # visible character
-	    caret = 1
+            caret = 1
             index = min(self.caret, len(self.text), len(self.trafos)) - 1
             text = self.text[index]
-	    trafo = self.trafos[index]
-	else:
-	    caret = 0
-	    if self.text and self.trafos:
-		text = self.text[0]
-		trafo = self.trafos[0]
-	    else:
-		# XXX fix this
+            trafo = self.trafos[index]
+        else:
+            caret = 0
+            if self.text and self.trafos:
+                text = self.text[0]
+                trafo = self.trafos[0]
+            else:
+                # XXX fix this
                 self.start_point = self.paths[0].point_at(self.start_pos)
-		return [handle.MakeNodeHandle(self.start_point, 1)]
-	pos, up = a.font.TextCaretData(text, caret, a.font_size)
-	pos = trafo(pos)
-	up = trafo.DTransform(up)
+                return [handle.MakeNodeHandle(self.start_point, 1)]
+        pos, up = a.font.TextCaretData(text, caret, a.font_size)
+        pos = trafo(pos)
+        up = trafo.DTransform(up)
         self.start_point = self.trafos[0].offset()
-	return [handle.MakeCaretHandle(pos, up),
-		handle.MakeNodeHandle(self.start_point, 1)]
+        return [handle.MakeCaretHandle(pos, up),
+                handle.MakeNodeHandle(self.start_point, 1)]
 
     selection = None
     def SelectHandle(self, handle, mode = const.SelectSet):
@@ -777,7 +777,7 @@
             dists = []
             for i in range(len(self.trafos)):
                 dists.append((abs(p - self.trafos[i].offset()), i))
-                
+
             char = self.text[len(self.trafos) - 1]
             width = self.properties.font.metric.char_width(ord(char)) / 1000.0
             pos = self.trafos[-1](width * self.properties.font_size, 0)
@@ -800,7 +800,7 @@
 
     def DrawDragged(self, device, partially):
         text = self.text; trafos = self.trafos
-	font = self.properties.font; font_size = self.properties.font_size
+        font = self.properties.font; font_size = self.properties.font_size
         t = self.nearest_start_pos(self.drag_cur)
         trafos = map(self.trafo, pathtext(self.paths[0], t, text, font,
                                           font_size, self.model))
@@ -828,55 +828,55 @@
     commands = Compound.commands[:]
 
     def __init__(self, text = None, path = None, model = PATHTEXT_ROTATE,
-		 start_pos = 0.0, duplicate = None, _blended_text = None):
-	if duplicate is not None:
-	    Compound.__init__(self, duplicate = duplicate)
-	    self.text = self.objects[0]
-	    self.path = self.objects[1]
-	else:
+                 start_pos = 0.0, duplicate = None, _blended_text = None):
+        if duplicate is not None:
+            Compound.__init__(self, duplicate = duplicate)
+            self.text = self.objects[0]
+            self.path = self.objects[1]
+        else:
             if _blended_text is not None:
                 self.text = _blended_text
                 self.path = path
                 Compound.__init__(self, [self.text, self.path])
             elif text is not None:
-		self.text = InternalPathText(text.Text(),
+                self.text = InternalPathText(text.Text(),
                                              start_pos = start_pos,
                                              model = model,
                                              duplicate = text)
-		self.path = path
-		Compound.__init__(self, [self.text, self.path])
-	    else:
-		# we're being loaded
-		self.text = self.path = None
-		Compound.__init__(self)
+                self.path = path
+                Compound.__init__(self, [self.text, self.path])
+            else:
+                # we're being loaded
+                self.text = self.path = None
+                Compound.__init__(self)
 
     def ChildChanged(self, child):
         if self.document is not None:
             self.document.AddClearRect(self.bounding_rect)
-	Compound.ChildChanged(self, child)
-	if child is self.path:
-	    self.text.PathChanged()
+        Compound.ChildChanged(self, child)
+        if child is self.path:
+            self.text.PathChanged()
         if self.document is not None:
             self.document.AddClearRect(self.bounding_rect)
 
     def load_AppendObject(self, object):
-	Compound.load_AppendObject(self, object)
-	if len(self.objects) == 2:
-	    self.text, self.path = self.objects
+        Compound.load_AppendObject(self, object)
+        if len(self.objects) == 2:
+            self.text, self.path = self.objects
 
     def SelectSubobject(self, p, rect, device, path = None, *rest):
-	idx = self.Hit(p, rect, device) - 1
-	obj = self.objects[idx]
-	if path:
-	    path_idx = path[0]
-	    path = path[1:]
-	    if path_idx == idx:
-		obj = obj.SelectSubobject(p, rect, device, path)
-	elif path == ():
-	    obj = obj.SelectSubobject(p, rect, device)
-	else:
-	    return  self
-	return selinfo.prepend_idx(idx, obj)
+        idx = self.Hit(p, rect, device) - 1
+        obj = self.objects[idx]
+        if path:
+            path_idx = path[0]
+            path = path[1:]
+            if path_idx == idx:
+                obj = obj.SelectSubobject(p, rect, device, path)
+        elif path == ():
+            obj = obj.SelectSubobject(p, rect, device)
+        else:
+            return  self
+        return selinfo.prepend_idx(idx, obj)
 
     def ReplaceChild(self, child, object):
         if child is self.path and object.is_curve:
@@ -892,64 +892,64 @@
             raise SketchError('Cannot replace child')
 
     def Info(self):
-	return _("Path Text: `%(text)s'") % {'text':self.text.Text()[:10]}
+        return _("Path Text: `%(text)s'") % {'text':self.text.Text()[:10]}
 
     def SaveToFile(self, file):
-	file.BeginPathText()
-	self.text.SaveToFile(file)
-	self.path.SaveToFile(file)
-	file.EndPathText()
+        file.BeginPathText()
+        self.text.SaveToFile(file)
+        self.path.SaveToFile(file)
+        file.EndPathText()
 
     def SelectTextObject(self):
-	self.document.SelectObject(self.text)
+        self.document.SelectObject(self.text)
     AddCmd(commands, SelectTextObject, _("Select Text"), key_stroke = 't')
 
     def SelectPathObject(self):
-	self.document.SelectObject(self.path)
+        self.document.SelectObject(self.path)
     AddCmd(commands, SelectPathObject, _("Select Path"), key_stroke = 'p')
 
     def get_paths(self):
         return self.path.Paths()
 
     def SetModel(self, model):
-	return self.text.SetModel(model)
+        return self.text.SetModel(model)
     AddCmd(commands, 'SetModelRotate', _("Rotate Letters"), SetModel,
-	   args = PATHTEXT_ROTATE)
+           args = PATHTEXT_ROTATE)
     AddCmd(commands, 'SetModelSkew', _("Skew Letters"), SetModel,
-	   args = PATHTEXT_SKEW)
+           args = PATHTEXT_SKEW)
 
     def Model(self):
-	return self.text.Model()
+        return self.text.Model()
 
     def Blend(self, other, p, q):
         if self.__class__ != other.__class__:
-	    raise MismatchError
+            raise MismatchError
         return self.__class__(_blended_text = Blend(self.text,other.text, p,q),
                               path = Blend(self.path, other.path, p, q))
 
     context_commands = ('SelectTextObject', 'SelectPathObject', None,
-			'SetModelRotate', 'SetModelSkew')
+                        'SetModelRotate', 'SetModelSkew')
 
 
 RegisterCommands(PathText)
 
 def CanCreatePathText(objects):
     if len(objects) == 2:
-	if objects[0].is_Text:
-	    return objects[1].is_curve
-	elif objects[0].is_curve:
-	    return objects[1].is_Text
+        if objects[0].is_Text:
+            return objects[1].is_curve
+        elif objects[0].is_curve:
+            return objects[1].is_Text
 
 
 def CreatePathText(objects):
     if len(objects) == 2:
-	if objects[0].is_Text:
-	    text, curve = objects
-	elif objects[1].is_Text:
-	    curve, text = objects
+        if objects[0].is_Text:
+            text, curve = objects
+        elif objects[1].is_Text:
+            curve, text = objects
         if not curve.is_curve:
-		# XXX what do we do here?
-                return text
-	return PathText(text, curve)
+            # XXX what do we do here?
+            return text
+        return PathText(text, curve)
 
 



More information about the Skencil-commits mailing list