diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniEyeClosed.xpm sketch2/Sketch/Pixmaps/MiniEyeClosed.xpm
--- sketch_base/Sketch/Pixmaps/MiniEyeClosed.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniEyeClosed.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniEyeClosed_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+"            ",
+"     +++    ",
+"   ++.+.++  ",
+" ++.+++++.+ ",
+"+.++++++++++",
+"+++++++++++.",
+"..++++++++..",
+"....++++....",
+"++........++",
+"  ++....++  ",
+"    ++++    ",
+"            "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniEyeOpen.xpm sketch2/Sketch/Pixmaps/MiniEyeOpen.xpm
--- sketch_base/Sketch/Pixmaps/MiniEyeOpen.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniEyeOpen.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniEyeOpen_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+"            ",
+"    ++++    ",
+"  ++....++  ",
+" +..+..+..+ ",
+"+.++....++.+",
+".+++....+++.",
+"..+++..+++..",
+"++..++++..++",
+"  ++....++  ",
+"    ++++    ",
+"            ",
+"            "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniLockClosed.xpm sketch2/Sketch/Pixmaps/MiniLockClosed.xpm
--- sketch_base/Sketch/Pixmaps/MiniLockClosed.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniLockClosed.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniLockClosed_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+" +....+     ",
+"+......+    ",
+"+..++..+    ",
+"+..++..+    ",
+"........+   ",
+"........+   ",
+"...++...+   ",
+"...++...+   ",
+"........+   ",
+"...++...+   ",
+"........+   ",
+"+++++++++   "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniLockOpen.xpm sketch2/Sketch/Pixmaps/MiniLockOpen.xpm
--- sketch_base/Sketch/Pixmaps/MiniLockOpen.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniLockOpen.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniLockOpen_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+"     +....+ ",
+"    +......+",
+"    +..++..+",
+"+++++..++..+",
+"........++++",
+"........+   ",
+"...++...+   ",
+"...++...+   ",
+"........+   ",
+"...++...+   ",
+"........+   ",
+"+++++++++   "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniOutlineOff.xpm sketch2/Sketch/Pixmaps/MiniOutlineOff.xpm
--- sketch_base/Sketch/Pixmaps/MiniOutlineOff.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniOutlineOff.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniOutlineOff_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+" +....+     ",
+"+......+    ",
+"........+++ ",
+"..........+ ",
+".....++++.+ ",
+".....++++.+ ",
+"+....++++.+ ",
+" +...++++.+ ",
+"  ++.++++.+ ",
+"   +.++++.+ ",
+"   +......+ ",
+"   ++++++++ "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniOutlineOn.xpm sketch2/Sketch/Pixmaps/MiniOutlineOn.xpm
--- sketch_base/Sketch/Pixmaps/MiniOutlineOn.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniOutlineOn.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniOutlineOn_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+" +....+     ",
+"+.++++.+    ",
+".+ ++++.+++ ",
+".+ +......+ ",
+".+ +.++.+.+ ",
+".+ +.++.+.+ ",
+"+.++.+.++.+ ",
+" +....+ +.+ ",
+"  ++.+  +.+ ",
+"   +.++++.+ ",
+"   +......+ ",
+"   ++++++++ "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniPrintOff.xpm sketch2/Sketch/Pixmaps/MiniPrintOff.xpm
--- sketch_base/Sketch/Pixmaps/MiniPrintOff.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniPrintOff.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniPrintOff_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+"++++++++    ",
+"+......++++ ",
+"+..+++....+ ",
+"+...++....+ ",
+"++...+...++ ",
+"++.......+  ",
+"++.+...+.+  ",
+"++.......+  ",
+"++...+...++ ",
+"+...+++...+ ",
+"+.........+ ",
+"+++++++++++ "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/Pixmaps/MiniPrintOn.xpm sketch2/Sketch/Pixmaps/MiniPrintOn.xpm
--- sketch_base/Sketch/Pixmaps/MiniPrintOn.xpm	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/Pixmaps/MiniPrintOn.xpm	2005-03-23 20:43:41.000000000 +0100
@@ -0,0 +1,18 @@
+/* XPM */
+static char * MiniPrintOn_xpm[] = {
+"12 12 3 1",
+"       c None",
+".      c #000000",
+"+      c #FFFFFF",
+" +++++++    ",
+" +.....+    ",
+" +.+++..++  ",
+" +.+++...+  ",
+" +.+++++.+  ",
+" +.+++++.+  ",
+" +.+++++.+  ",
+" +.+++++.+  ",
+" +.+++++.+  ",
+" +.+++++.+  ",
+" +.......+  ",
+" +++++++++  "};
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/UI/layerspanel.py sketch2/Sketch/UI/layerspanel.py
--- sketch_base/Sketch/UI/layerspanel.py	1970-01-01 01:00:00.000000000 +0100
+++ sketch2/Sketch/UI/layerspanel.py	2005-03-23 23:17:29.000000000 +0100
@@ -0,0 +1,554 @@
+# Sketch - A Python-based interactive drawing program
+# Copyright (C) 1997, 1998, 2000 by Bernhard Herzog
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+# A dialog to rearrange the layers of the document and change some of
+# their properties.
+
+
+from types import StringType, TupleType
+
+import gtk, gobject
+
+import Sketch
+from Sketch import _, Rect, Trafo, Identity
+from Sketch.Graphics import StandardColors, EmptyLineStyle, PropertyStack,\
+     EmptyPattern
+from Sketch.Base import Publisher
+from Sketch.const import CHANGED, LAYER, LAYER_ACTIVE, LAYER_ORDER, \
+     SelectSubtract, SelectAdd 
+from Sketch.Editor.command import Command
+#from menu import SketchMenu, BuildMenuTree
+from tmpmenu import SketchMenu, BuildMenuTree
+
+from gtkmisc import SketchDrawingArea, get_color, CommandButton
+from skpanel import MultiPanel, Card
+from gtkdevice import PatternDevice
+from contextproxy import ContextProxy
+from skpixmaps import pixmaps
+from rendermisc import ColorSample, SketchCellRenderer
+
+            
+class CellRendererColor(ColorSample, SketchCellRenderer):
+    default_size = (10, 10)
+    expand = 0
+
+class CellRendererPixmap(gtk.GenericCellRenderer):
+    default_size = (10, 10)
+    __gproperties__ = {
+        "data": (gobject.TYPE_PYOBJECT, "data",
+                 "cell data", 
+                 gobject.PARAM_READWRITE),
+    }
+
+    def __init__(self, converter):
+        self.__gobject_init__()
+        self.converter = converter
+        self.gc = None
+        
+    def do_set_property(self, pspec, value):
+        setattr(self, pspec.name, value)
+ 
+    def do_get_property(self, pspec):
+        return getattr(self, pspec.name)
+                
+    def on_render(self, window, widget, background_area,
+                  cell_area, expose_area, flags):
+        tmp = self.converter(self.get_property("data"))
+        if tmp is None:
+            return
+        image, mask = tmp 
+        w, h, = image.get_size()
+        if self.gc is None:
+            self.gc = window.new_gc()
+
+        cx, cy, cw, ch = cell_area
+        x0 = cx+(cw-w)/2
+        y0 = cy+(ch-h)/2
+        self.gc.set_clip_origin(x0, y0)
+        self.gc.set_clip_mask(mask)
+        window.draw_drawable(self.gc, image, 0, 0, x0, y0, w, h)
+        
+    def on_get_size(self, widget, cell_area):
+        tmp = self.converter(self.get_property("data"))
+        if tmp is None:
+            w, h = self.default_size
+        else:
+            image, mask = tmp 
+            w, h, = image.get_size()
+        return 0, 0, w, h
+        
+gobject.type_register(CellRendererPixmap)
+
+        
+def convert_active(value):
+    if value:
+        return getattr(pixmaps, 'LightBulbOn')
+
+def convert_visible(value):
+    return getattr(pixmaps, ('MiniEyeClosed', 'MiniEyeOpen')[value])
+
+def convert_printable(value):
+    return getattr(pixmaps, ('MiniPrintOff', 'MiniPrintOn')[value])
+
+def convert_locked(value):
+    return getattr(pixmaps, ('MiniLockOpen', 'MiniLockClosed')[value])
+
+def convert_outlined(value):
+    return getattr(pixmaps, ('MiniOutlineOff', 'MiniOutlineOn')[value])
+
+
+# table columns definition
+property_defs = [
+    ('active',        _('Active'),  "pixmap", convert_active),
+    ('name',          _('Name'),    "text",   None), 
+    ('visible',       _('Visible'), "pixmap", convert_visible),
+    ('printable',     _('Print'),   "pixmap", convert_printable),
+    ('locked',        _('Locked'),  "pixmap", convert_locked),
+    ('outlined',      _('Fill'),    "pixmap", convert_outlined),
+    ('outline_color', _('Color'),   "color",  None),
+]
+
+
+WIDGET = "WIDGET"
+def make_command(label, func = None, args = (), sensitive = None,
+                 channels = (WIDGET,)):
+    if type(label) == TupleType:
+            return apply(make_command, label)
+
+    if label is None:
+        return None
+    return Command("", label, func, args, sensitive=sensitive,
+                   channels=channels)
+    
+
+class LayersContext(ContextProxy):
+    def __init__(self, widget, app_context):
+        self.widget = widget        
+        ContextProxy.__init__(self, app_context)
+        widget.Subscribe(CHANGED, self.forward, WIDGET)
+
+        
+class LayersWidget(gtk.TreeView, Publisher):
+    """LayersWidget displays and allows to change layer properties."""
+
+    def __init__(self, context):
+        gtk.TreeView.__init__(self)
+        
+        self.layersList = ()
+        self.selected_idx = -1
+        self.context = LayersContext(self, context)
+        self.context.Subscribe(CHANGED, self.update)
+        
+
+        model = gtk.ListStore(gobject.TYPE_PYOBJECT,
+                              gobject.TYPE_STRING,
+                              gobject.TYPE_PYOBJECT,
+                              gobject.TYPE_PYOBJECT,
+                              gobject.TYPE_PYOBJECT,
+                              gobject.TYPE_PYOBJECT,
+                              gobject.TYPE_PYOBJECT)
+
+        # add columns
+        for index in range(len(property_defs)):
+            name, title, ctype, converter = property_defs[index]            
+            if ctype == "color":
+                renderer = self.cell_renderer_color = CellRendererColor()
+                column = gtk.TreeViewColumn(title, renderer, data=index)
+                
+            elif ctype == "text":
+                renderer = gtk.CellRendererText()
+                renderer.set_property("editable", gtk.TRUE)
+                renderer.connect('edited', self.edited, (model, name))
+                column = gtk.TreeViewColumn(title, renderer, text=index)
+
+            else:
+                assert ctype == 'pixmap'
+                renderer = CellRendererPixmap(converter)
+                column = gtk.TreeViewColumn(title, renderer, data=index)
+                
+            self.append_column(column)
+        self.set_model(model)
+        
+        self.show_all()
+        self.set_reorderable(1)
+        self.set_headers_visible(1)
+        self.set_reorderable(0)
+        sel = self.get_selection()
+        sel.set_mode(gtk.SELECTION_SINGLE)
+        sel.connect("changed", self.selected_changed)
+        
+        self._subscribe()
+        self.context_menu = self.build_context_menu()
+        self.connect("button_press_event", self.clicked)
+        self.connect("destroy_event", self.destroyed)
+        self.update()
+
+    def destroyed(self, *args):
+        self._unsubscribe()
+        
+    def _subscribe(self):
+        self.context.Subscribe(Sketch.Base.const.SELECTION,
+                               self.update)
+        self.context.Subscribe(Sketch.Base.const.LAYER,
+                               self.update)
+        self.context.Subscribe(Sketch.Base.const.TRANSACTION_END,
+                               self.update)
+
+
+    def _unsubscribe(self):
+        self.context.Unsubscribe(Sketch.Base.const.SELECTION,
+                                 self.update)
+        self.context.Unsubscribe(Sketch.Base.const.LAYER,
+                                 self.update)
+        self.context.Unsubscribe(Sketch.Base.const.TRANSACTION_END,
+                                 self.update)
+        
+    def update(self, *args):        
+        doc = self.Document()
+        if doc is None:
+            return
+        layersList = doc.layers
+        active = doc.ActiveLayerIdx()
+        
+        sel = self.get_selection()
+        model, sel_iter = sel.get_selected()
+        if sel_iter is None:
+            sel_path = None
+        else:
+            sel_path = model.get_path(sel_iter)
+        
+        self.layersList = layersList ## I need it later
+        model = self.get_model()
+        model.freeze_notify()
+        model.clear()
+        
+        row = 0
+        layersList = layersList[:]
+        layersList.reverse()
+        for layer in layersList:
+            col = 0
+            iter = model.append()
+            for name, title, ctype, data in property_defs:
+                if name == 'active':
+                    value = (active == len(layersList)-row-1)
+                elif name == 'name':
+                    value = layer.Name() or _('<unnamed>')
+                elif hasattr(layer, name):
+                    value = getattr(layer, name)
+
+                model.set_value(iter, col, value)
+                col += 1
+            row += 1
+                                        
+        model.thaw_notify()
+        if sel_path is not None:
+            sel.select_path(sel_path)
+
+        self.issue(CHANGED)
+        
+    def Document(self):
+        return self.context.document
+
+    def HasDocument(self):
+        if self.context.document is None:
+            return 0
+        return 1
+
+    def build_context_menu(self):
+        entries = [
+            (_("Toggle Visible"), self.ToggleVisible, (), self.HasSelected),
+            (_("Toggle Printable"), self.TogglePrintable, (), self.HasSelected),
+            (_("Toggle Filled"), self.ToggleFilled, (), self.HasSelected),
+            (_("Change Outline Color"), self.SelectOutlineColor, (),
+             self.HasSelected),
+            None,
+            (_("Lower Layer"), self.LowerLayer, (), self.CanLower),
+            (_("Raise Layer"), self.RaiseLayer, (), self.CanRaise),
+            (_("Delete Layer"), self.DeleteLayer, (), self.CanDelete),
+            None,
+            (_("Move Selection Here"), self.MoveSelectionHere, (),
+             self.CanMoveSelection),
+            (_("Select All Children"), self.SelectLayerChildren, SelectAdd,
+             self.IsNotLocked),
+            (_("Deselect All Children"), self.SelectLayerChildren, SelectSubtract,
+             self.CanDeselectChildren)
+            ]
+        
+        descr = map(make_command, entries)
+        tree = BuildMenuTree('', '<layerspanel>', descr)
+        return SketchMenu(self.context, tree, allow_tearoff = 0)
+
+    def clicked(self, widget, event):
+        if event.button == 1 and event.type != gtk.gdk._2BUTTON_PRESS:
+            return
+        x, y = map(int, event.get_coords())
+        columns = self.get_columns()
+        path, column, rx, ry = self.get_path_at_pos(x,y)
+        col = list(columns).index(column)
+        row = path[0]
+        layer_index = len(self.layersList)-row-1
+
+        sel = self.get_selection()
+        model, iter = sel.get_selected()
+        
+        if event.button == 1:
+            iter = model.get_iter(path)
+            sel.select_iter(iter)
+             
+        if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
+            # note: from pygtk 2.4 on the column has a method
+            # "cell_get_position(cell_renderer)" which returns size and
+            # coords of the cell
+
+            if col == 0:
+                self.set_active_layer(layer_index)
+            elif col == 1:
+                # this will trigger the editing of the text
+                return                 
+            elif col < 6:
+                self.toggle_property(layer_index, col-2)
+            else:
+                layer = self.Document().layers[layer_index]
+                color = get_color(_('Choose Color'), layer.outline_color)
+                if color is not None:
+                    self.set_outline_color(layer_index, color)
+        elif event.button == 3:
+            # open context menu            
+            context_menu = self.context_menu
+            context_menu.popup(None, None, None, event.button, event.time)
+            
+    def selected_changed(self, *args):
+        sel = self.get_selection()
+        model, iter = sel.get_selected()
+        if iter is None:
+            idx = None            
+        else:
+            idx = len(self.layersList)-model.get_path(iter)[0]-1
+        self.selected_idx = idx
+        self.issue(CHANGED)
+
+    def edited(self, cell, path, new_text, user_data):
+        """Called after a cell entry has been edited. Currently this
+        is only used for the layer titles."""
+        store, descr = user_data
+        if descr == 'name':
+            self.set_layer_name(len(self.layersList)-int(path)-1, new_text)
+        self.issue(CHANGED)
+        
+    def set_layer_name(self, idx, name):
+        self.Document().SetLayerName(idx, name)
+                                     
+    def set_layer_state(self, idx, visible, printable, locked, outlined):
+        self.Document().SetLayerState(idx,
+                                         visible, printable,
+                                         locked, outlined )
+        
+    def toggle_property(self, idx, prop_idx):
+        layer = self.Document().layers[idx]
+
+        visible = layer.visible
+        printable = layer.printable
+        locked = layer.locked
+        outlined = layer.outlined
+        outline_color = layer.outline_color
+
+        if prop_idx>=0 and prop_idx<=3:
+            if prop_idx == 0:
+                visible = not visible
+            elif prop_idx == 1:
+                printable = not printable
+            elif prop_idx == 2:
+                locked = not locked
+            elif prop_idx == 3:
+                outlined = not outlined
+        self.set_layer_state(idx, visible, printable, locked, outlined)
+                
+    def set_active_layer(self, idx):
+        doc = self.Document()
+        layer = doc.layers[idx]
+        doc.SetActiveLayer(layer)
+
+    def set_outline_color(self, idx, color):
+        self.Document().SetLayerColor(idx, color );
+
+    def SelectLayer(self, layer):
+        layers = self.layersList
+        idx = layers.index(layer)
+        self.SelectLayerIdx(idx)
+                    
+    def SelectLayerIdx(self, idx):
+        sel = self.get_selection()
+        path = (len(self.layersList)-idx-1,)
+        sel.select_path(path)
+
+    def HasSelected(self, *args):
+        return self.selected_idx > -1
+        
+    def Selected(self):
+        layers = self.Document().layers
+        return layers[self.selected_idx]
+    
+    def SelectedIdx(self ):
+        return self.selected_idx
+    
+    def CanDelete(self, *args):        
+        if not self.HasSelected():
+            return 0
+        idx = self.SelectedIdx()
+        return self.Document().CanDeleteLayer(idx)
+    
+    def DeleteLayer(self, event = None ):
+        self.Document().DeleteLayer(self.SelectedIdx() )
+
+    def NewLayer(self, event = None ):
+        self.Document().NewLayer()
+
+    def CanRaise(self, *args):
+        n = len(self.layersList)
+        if self.HasSelected() and self.SelectedIdx() < n-1:
+            return 1
+        return 0
+
+    def RaiseLayer(self, event = None ):        
+        doc = self.Document()
+        idx = self.SelectedIdx()
+        layer = self.Selected()
+        doc.MoveLayerUp(idx)
+        self.update()
+        self.SelectLayer(layer)
+                
+    def CanLower(self, *args):        
+        if self.HasSelected() and self.SelectedIdx() > 0:
+            return 1
+        return 0
+    
+    def LowerLayer(self, event = None ):
+        doc = self.Document()
+        idx = self.SelectedIdx()
+        layer = self.Selected()
+        doc.MoveLayerDown(idx)
+        self.SelectLayer(layer)
+
+    def IsNotLocked(self, *args):        
+        if self.HasSelected() and not self.Selected().Locked():
+            return 1
+        return 0
+        
+    def CanMoveSelection(self, *args):
+        return self.IsNotLocked() and self.context.editor.HasSelection()
+
+    def CanDeselectChildren(self, *args):
+        return self.IsNotLocked() and self.context.editor.HasSelection()
+
+    def SelectLayerChildren(self, context, mode):
+        idx = self.SelectedIdx()
+        self.context.editor.SelectLayer(idx, mode)
+
+    def MoveSelectionHere(self, *args):
+        idx = self.SelectedIdx()
+        self.context.editor.MoveSelectionToLayer(idx)
+
+    def ToggleVisible(self, *args):
+        self.toggle_property(self.selected_idx, 0)
+
+    def TogglePrintable(self, *args):
+        self.toggle_property(self.selected_idx, 1)
+
+    def ToggleLocked(self, *args):
+        self.toggle_property(self.selected_idx, 2)
+
+    def ToggleFilled(self, *args):
+        self.toggle_property(self.selected_idx, 3)
+        
+    def SelectOutlineColor(self, *args):
+        layer = self.Selected()
+        color = get_color(_('Choose Color'), layer.outline_color)
+        if color is not None:
+            self.set_outline_color(layer_index, color)
+        
+            
+class LayersCard(Card):
+    def __init__(self, application):
+        Card.__init__(self, application, _('Layers'))
+        
+    def build_card(self):
+        swin = gtk.ScrolledWindow()
+        swin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+
+        layers = self.layers = LayersWidget(self.context)
+        layers.set_headers_visible(0)
+        layers_context = layers.context # XXX ugly
+        swin.add(self.layers)
+        self.pack_start(swin)
+
+        hbox = gtk.HBox();
+
+        def _stock_button(command, descr):            
+            button = CommandButton(command, layers_context)
+            image = gtk.Image()
+            image.set_from_stock(descr, gtk.ICON_SIZE_BUTTON)
+            button.set_use_stock(gtk.TRUE)
+            button.add(image)
+            button.connect('clicked', lambda arg: command.Execute)
+            return button
+
+        entries = [
+            (_("New Layer"), layers.NewLayer, (), None),
+            (_("Lower Layer"), layers.LowerLayer, (), layers.CanLower),
+            (_("Raise Layer"), layers.RaiseLayer, (), layers.CanRaise),
+            (_("Delete Layer"), layers.DeleteLayer, (), layers.CanDelete),
+            ]
+        
+        newlayer, lowerlayer, raiselayer, deletelayer = \
+                  map(make_command, entries)
+        
+        button = _stock_button(newlayer, gtk.STOCK_NEW)
+        hbox.pack_start(button )
+
+        button = _stock_button(raiselayer, gtk.STOCK_GO_UP)
+        hbox.pack_start(button )
+
+        button = _stock_button(lowerlayer, gtk.STOCK_GO_DOWN)
+        hbox.pack_start(button )
+
+        button = _stock_button(deletelayer, gtk.STOCK_DELETE)
+        hbox.pack_start(button )
+
+        self.pack_start(hbox, expand=0 )
+        self.show_all()
+
+
+class LayersPanel(MultiPanel):
+    multiple = 1
+    def __init__(self, context):
+        MultiPanel.__init__(self, context, _("Layers"))
+
+    def build_window(self):
+        MultiPanel.build_window(self)
+        self.set_default_size(-1, 180)
+        self.build_menu()
+
+        card = LayersCard(self.context.application)
+        self.attach_card(card)
+
+    def build_menu(self):        
+        items = ('close_panel',
+                 'duplicate_panel')
+        menudata = BuildMenuTree('<layersmenu>', '', items)
+        self.set_menudata(menudata)
+
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/UI/rendermisc.py sketch2/Sketch/UI/rendermisc.py
--- sketch_base/Sketch/UI/rendermisc.py	2005-03-23 23:25:24.000000000 +0100
+++ sketch2/Sketch/UI/rendermisc.py	2005-03-23 23:01:02.000000000 +0100
@@ -272,6 +272,7 @@
 
 class PatternSample:
     default_size = 16, 16
+    expand = 1
     def SetData(self, pattern):        
         if pattern != self._data:
             self._data = pattern
@@ -279,18 +280,21 @@
             self.gc.SetProperties(self.properties)
 
     def draw(self, width, height):
-        w = width
-        h = height
+        if self.expand:
+            w = width
+            h = height
+            x = y = 0
+        else:
+            w, h = self.default_size
+            x = (width-w)/2
+            y = (height-h)/2
+        
         if self.properties.HasFill():
-            self.gc.Rectangle(Trafo(w, 0, 0, h, 0, 0))
+            self.gc.Rectangle(Trafo(w, 0, 0, h, x, y))
         else:
             self.gc.SetLineColor(StandardColors.black)
-            self.gc.DrawLineXY(0, h, w, 0)
-        
-        self.gc.DrawLineXY(0, 0, w-1, 0)
-        self.gc.DrawLineXY(0, h-1, w-1, h-1)
-        self.gc.DrawLineXY(0, 0, 0, h-1)
-        self.gc.DrawLineXY(w-1, 0, w-1, h-1)
+            self.gc.DrawLineXY(x, y+h, x+w, y)
+
 
 class ColorSample(PatternSample):
     default_size = 16, 16
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/UI/skapp.py sketch2/Sketch/UI/skapp.py
--- sketch_base/Sketch/UI/skapp.py	2005-03-23 23:25:24.000000000 +0100
+++ sketch2/Sketch/UI/skapp.py	2005-03-23 20:21:17.000000000 +0100
@@ -520,6 +520,12 @@
 
 Sketch.Editor.Add(Sketch.Editor.Command('inspector_panel',
                                         _("Inspector Panel"), inspector_panel))
+def layers_panel(context):
+    import layerspanel
+    context.application.InstantiatePanel(layerspanel.LayersPanel)
+
+Sketch.Editor.Add(Sketch.Editor.Command('layers_panel',
+                                        _("Layers Panel"), layers_panel))
 
 # import some development commands
 
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/UI/skpixmaps.py sketch2/Sketch/UI/skpixmaps.py
--- sketch_base/Sketch/UI/skpixmaps.py	2005-03-23 23:25:03.000000000 +0100
+++ sketch2/Sketch/UI/skpixmaps.py	2005-03-23 20:52:39.000000000 +0100
@@ -69,7 +69,12 @@
                  'MiniFill', 'MiniTransform', 'MiniLine', 'MiniWidth',
                  'MiniCap', 'MiniJoin', 'MiniDashes',
                  'MiniArrowRight', 'MiniArrowLeft',
-                 'MiniFont', 'MiniFontSize']
+                 'MiniFont', 'MiniFontSize',
+                 
+                 'MiniEyeOpen', 'MiniEyeClosed',
+                 'MiniLockOpen', 'MiniLockClosed',
+                 'MiniOutlineOn', 'MiniOutlineOff',
+                 'MiniPrintOn', 'MiniPrintOff',]
 
 class SketchPixmaps:
 
@@ -99,7 +104,6 @@
         setattr(cursors, name, cursor)
         
     
-
 def init_from_widget(widget):
     bitmaps.InitFromWidget(widget)
     pixmaps.InitFromWidget(widget)
diff -trNau -U 3 -x '*o' -x '*.pyc' -x '*~*' -x '*Log' -x NEWS -x CVS -x build -x '*orig' sketch_base/Sketch/UI/toolbox.py sketch2/Sketch/UI/toolbox.py
--- sketch_base/Sketch/UI/toolbox.py	2005-03-23 23:25:24.000000000 +0100
+++ sketch2/Sketch/UI/toolbox.py	2005-03-23 20:21:44.000000000 +0100
@@ -158,7 +158,7 @@
         descr = ['message_panel', 'reload_panel',
                  None, 'property_panel', 'fill_panel', 'meta_panel',
                  'palette_panel', 'object_panel', 'history_panel',
-                 'inspector_panel', 'color_panel']
+                 'inspector_panel', 'color_panel', 'layers_panel']
         tree = Sketch.Editor.BuildMenuTree('<toolbox>', descr)
         return menu.make_menu(tree, None, self.context)
 
