From 60560a030fda3c539ff9dc1563b9926414a193da Mon Sep 17 00:00:00 2001
From: Alessandro Ghedini <al3xbio@gmail.com>
Date: Sat, 21 Jan 2012 19:07:09 +0100
Subject: Imported Upstream version 0.4.0

---
 src/CMakeLists.txt                    |   15 +-
 src/actionGroups/actionGroup.vala     |   21 +
 src/actionGroups/bookmarkGroup.vala   |   11 +-
 src/actionGroups/clipboardGroup.vala  |   11 +-
 src/actionGroups/devicesGroup.vala    |   11 +-
 src/actionGroups/groupRegistry.vala   |   86 +--
 src/actionGroups/menuGroup.vala       |   11 +-
 src/actionGroups/sessionGroup.vala    |   11 +-
 src/actionGroups/windowListGroup.vala |   11 +-
 src/actions/action.vala               |   10 +-
 src/actions/actionRegistry.vala       |  102 ++-
 src/actions/appAction.vala            |   16 +-
 src/actions/keyAction.vala            |   18 +-
 src/actions/pieAction.vala            |   16 +-
 src/actions/sigAction.vala            |    4 +-
 src/actions/uriAction.vala            |   18 +-
 src/deamon.vala                       |   28 +-
 src/gui/about.vala                    |   69 --
 src/gui/aboutWindow.vala              |   76 +++
 src/gui/cellRendererIcon.vala         |  132 ----
 src/gui/cellRendererTrigger.vala      |   84 ---
 src/gui/iconSelectWindow.vala         |  428 ++++++-------
 src/gui/indicator.vala                |   14 +-
 src/gui/newSliceWindow.vala           |  394 ++++++++++++
 src/gui/pieComboList.vala             |  155 +++++
 src/gui/pieList.vala                  | 1105 +++++----------------------------
 src/gui/piePreview.vala               |  369 +++++++++++
 src/gui/piePreviewAddSign.vala        |  220 +++++++
 src/gui/piePreviewCenter.vala         |  108 ++++
 src/gui/piePreviewDeleteSign.vala     |  195 ++++++
 src/gui/piePreviewRenderer.vala       |  436 +++++++++++++
 src/gui/piePreviewSliceRenderer.vala  |  276 ++++++++
 src/gui/preferences.vala              |  325 ----------
 src/gui/preferencesWindow.vala        |  311 ++++++++++
 src/gui/renameWindow.vala             |  109 ++++
 src/gui/settingsWindow.vala           |  174 ++++++
 src/gui/sliceTypeList.vala            |  172 +++++
 src/gui/themeList.vala                |   74 ++-
 src/gui/tipViewer.vala                |  172 -----
 src/gui/triggerSelectButton.vala      |  161 +++++
 src/gui/triggerSelectWindow.vala      |  257 +++-----
 src/images/icon.vala                  |   12 +-
 src/images/image.vala                 |   67 +-
 src/images/renderedText.vala          |   75 ++-
 src/images/themedIcon.vala            |    2 +-
 src/pies/load.vala                    |   31 +-
 src/pies/pie.vala                     |   38 +-
 src/pies/pieManager.vala              |   54 +-
 src/pies/save.vala                    |    8 +-
 src/renderers/pieRenderer.vala        |   74 +--
 src/renderers/pieWindow.vala          |   69 +-
 src/renderers/sliceRenderer.vala      |   23 +-
 src/themes/theme.vala                 |    3 +
 src/utilities/animatedValue.vala      |   13 +-
 src/utilities/bindingManager.vala     |   34 +-
 src/utilities/config.vala             |    5 -
 src/utilities/focusGrabber.vala       |   99 ++-
 src/utilities/key.vala                |   26 +-
 src/utilities/paths.vala              |   68 +-
 src/utilities/trigger.vala            |   36 +-
 60 files changed, 4427 insertions(+), 2526 deletions(-)
 delete mode 100644 src/gui/about.vala
 create mode 100644 src/gui/aboutWindow.vala
 delete mode 100644 src/gui/cellRendererIcon.vala
 delete mode 100644 src/gui/cellRendererTrigger.vala
 create mode 100644 src/gui/newSliceWindow.vala
 create mode 100644 src/gui/pieComboList.vala
 create mode 100644 src/gui/piePreview.vala
 create mode 100644 src/gui/piePreviewAddSign.vala
 create mode 100644 src/gui/piePreviewCenter.vala
 create mode 100644 src/gui/piePreviewDeleteSign.vala
 create mode 100644 src/gui/piePreviewRenderer.vala
 create mode 100644 src/gui/piePreviewSliceRenderer.vala
 delete mode 100644 src/gui/preferences.vala
 create mode 100644 src/gui/preferencesWindow.vala
 create mode 100644 src/gui/renameWindow.vala
 create mode 100644 src/gui/settingsWindow.vala
 create mode 100644 src/gui/sliceTypeList.vala
 delete mode 100644 src/gui/tipViewer.vala
 create mode 100644 src/gui/triggerSelectButton.vala

(limited to 'src')

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 23b9474..b809c48 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -9,6 +9,10 @@ if (${INDICATOR_FOUND})
   SET(DEFINES --define HAVE_APPINDICATOR)
 endif(${INDICATOR_FOUND})
 
+if (${GTK3_FOUND})
+  SET(DEFINES --define HAVE_GTK_3)
+endif(${GTK3_FOUND})
+
 if (${GMENU3_FOUND})
     LIST(APPEND DEFINES --define HAVE_GMENU_3)
 endif (${GMENU3_FOUND})
@@ -39,7 +43,7 @@ install(
 # install credits
 install(
 	FILES
-		${CMAKE_SOURCE_DIR}/README
+		${CMAKE_SOURCE_DIR}/README.md
 	DESTINATION
 		${CMAKE_INSTALL_PREFIX}/share/doc/gnome-pie
 )
@@ -63,11 +67,18 @@ install(
 		${CMAKE_INSTALL_PREFIX}/share/gnome-pie
 )
 
+# install UI files
+install(
+	DIRECTORY
+		${CMAKE_SOURCE_DIR}/resources/ui
+	DESTINATION
+		${CMAKE_INSTALL_PREFIX}/share/gnome-pie
+)
+
 # install icons
 install(
 	FILES
 		${CMAKE_SOURCE_DIR}/resources/gnome-pie.svg
-		${CMAKE_SOURCE_DIR}/resources/gnome-pie-indicator.svg
 	DESTINATION
 		${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps
 )
diff --git a/src/actionGroups/actionGroup.vala b/src/actionGroups/actionGroup.vala
index a6b52ff..c54be2f 100644
--- a/src/actionGroups/actionGroup.vala
+++ b/src/actionGroups/actionGroup.vala
@@ -70,6 +70,27 @@ public class ActionGroup : GLib.Object {
     public void delete_all() {
         actions.clear();
     }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes all contained Slices no Quick Actions.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void disable_quickactions() {
+        foreach (var action in actions)
+            action.is_quickaction = false;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Returns true, if one o the contained Slices is a Quick Action
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool has_quickaction() {
+        foreach (var action in actions)
+            if (action.is_quickaction)
+                return true;
+                
+        return false;
+    }
 }
 
 }
diff --git a/src/actionGroups/bookmarkGroup.vala b/src/actionGroups/bookmarkGroup.vala
index 389b14a..0a560c5 100644
--- a/src/actionGroups/bookmarkGroup.vala
+++ b/src/actionGroups/bookmarkGroup.vala
@@ -31,10 +31,13 @@ public class BookmarkGroup : ActionGroup {
     /// the pies.conf file for this kind of ActionGroups.
     /////////////////////////////////////////////////////////////////////
     
-    public static void register(out string name, out string icon, out string settings_name) {
-        name = _("Bookmarks");
-        icon = "user-bookmarks";
-        settings_name = "bookmarks";
+    public static GroupRegistry.TypeDescription register() {
+        var description = new GroupRegistry.TypeDescription();
+        description.name = _("Group: Bookmarks");
+        description.icon = "user-bookmarks";
+        description.description = _("Shows a Slice for each of your directory Bookmarks.");
+        description.id = "bookmarks";
+        return description;
     }
 
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actionGroups/clipboardGroup.vala b/src/actionGroups/clipboardGroup.vala
index cd1da36..836c927 100644
--- a/src/actionGroups/clipboardGroup.vala
+++ b/src/actionGroups/clipboardGroup.vala
@@ -59,10 +59,13 @@ public class ClipboardGroup : ActionGroup {
     /// the pies.conf file for this kind of ActionGroups.
     /////////////////////////////////////////////////////////////////////
     
-    public static void register(out string name, out string icon, out string settings_name) {
-        name = _("Clipboard");
-        icon = "edit-paste";
-        settings_name = "clipboard";
+    public static GroupRegistry.TypeDescription register() {
+        var description = new GroupRegistry.TypeDescription();
+        description.name = _("Group: Clipboard");
+        description.icon = "edit-paste";
+        description.description = _("Manages your Clipboard.");
+        description.id = "clipboard";
+        return description;
     }
     
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actionGroups/devicesGroup.vala b/src/actionGroups/devicesGroup.vala
index 3d2ced0..dee6a6e 100644
--- a/src/actionGroups/devicesGroup.vala
+++ b/src/actionGroups/devicesGroup.vala
@@ -30,10 +30,13 @@ public class DevicesGroup : ActionGroup {
     /// the pies.conf file for this kind of ActionGroups.
     /////////////////////////////////////////////////////////////////////
     
-    public static void register(out string name, out string icon, out string settings_name) {
-        name = _("Devices");
-        icon = "harddrive";
-        settings_name = "devices";
+    public static GroupRegistry.TypeDescription register() {
+        var description = new GroupRegistry.TypeDescription();
+        description.name = _("Group: Devices");
+        description.icon = "harddrive";
+        description.description = _("Shows a Slice for each plugged in devices, like USB-Sticks.");
+        description.id = "devices";
+        return description;
     }
 
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actionGroups/groupRegistry.vala b/src/actionGroups/groupRegistry.vala
index a9f8d06..7510a03 100644
--- a/src/actionGroups/groupRegistry.vala
+++ b/src/actionGroups/groupRegistry.vala
@@ -27,67 +27,67 @@ public class GroupRegistry : GLib.Object {
     /// A list containing all available ActionGroup types.
     /////////////////////////////////////////////////////////////////////
     
-    public static Gee.ArrayList<Type> types { get; private set; }
+    public static Gee.ArrayList<string> types { get; private set; }
     
     /////////////////////////////////////////////////////////////////////
-    /// Three maps associating a displayable name for each ActionGroup, 
+    /// A map associating a displayable name for each ActionGroup, 
     /// an icon name and a name for the pies.conf file with it's type.
     /////////////////////////////////////////////////////////////////////
     
-    public static Gee.HashMap<Type, string> names { get; private set; }
-    public static Gee.HashMap<Type, string> icons { get; private set; }
-    public static Gee.HashMap<Type, string> settings_names { get; private set; }
+    public static Gee.HashMap<string, TypeDescription?> descriptions { get; private set; }
+    
+    public class TypeDescription {
+        public string name { get; set; default=""; }
+        public string icon { get; set; default=""; }
+        public string description { get; set; default=""; }
+        public string id { get; set; default=""; }
+    }
     
     /////////////////////////////////////////////////////////////////////
     /// Registers all ActionGroup types.
     /////////////////////////////////////////////////////////////////////
     
     public static void init() {
-        types = new Gee.ArrayList<Type>();
+        types = new Gee.ArrayList<string>();
+        descriptions = new Gee.HashMap<string, TypeDescription?>();
     
-        names = new Gee.HashMap<Type, string>();
-        icons = new Gee.HashMap<Type, string>();
-        settings_names = new Gee.HashMap<Type, string>();
-    
-        string name = "";
-        string icon = "";
-        string settings_name = "";
+        TypeDescription type_description;
         
-        BookmarkGroup.register(out name, out icon, out settings_name);
-        types.add(typeof(BookmarkGroup));
-        names.set(typeof(BookmarkGroup), name);
-        icons.set(typeof(BookmarkGroup), icon);
-        settings_names.set(typeof(BookmarkGroup), settings_name);
+        type_description = BookmarkGroup.register();
+        types.add(typeof(BookmarkGroup).name());
+        descriptions.set(typeof(BookmarkGroup).name(), type_description);
         
-        DevicesGroup.register(out name, out icon, out settings_name);
-        types.add(typeof(DevicesGroup));
-        names.set(typeof(DevicesGroup), name);
-        icons.set(typeof(DevicesGroup), icon);
-        settings_names.set(typeof(DevicesGroup), settings_name);
+        type_description = DevicesGroup.register();
+        types.add(typeof(DevicesGroup).name());
+        descriptions.set(typeof(DevicesGroup).name(), type_description);
         
-        MenuGroup.register(out name, out icon, out settings_name);
-        types.add(typeof(MenuGroup));
-        names.set(typeof(MenuGroup), name);
-        icons.set(typeof(MenuGroup), icon);
-        settings_names.set(typeof(MenuGroup), settings_name);
+        type_description = MenuGroup.register();
+        types.add(typeof(MenuGroup).name());
+        descriptions.set(typeof(MenuGroup).name(), type_description);
         
-        SessionGroup.register(out name, out icon, out settings_name);
-        types.add(typeof(SessionGroup));
-        names.set(typeof(SessionGroup), name);
-        icons.set(typeof(SessionGroup), icon);
-        settings_names.set(typeof(SessionGroup), settings_name);
+        type_description = SessionGroup.register();
+        types.add(typeof(SessionGroup).name());
+        descriptions.set(typeof(SessionGroup).name(), type_description);
         
-        WindowListGroup.register(out name, out icon, out settings_name);
-        types.add(typeof(WindowListGroup));
-        names.set(typeof(WindowListGroup), name);
-        icons.set(typeof(WindowListGroup), icon);
-        settings_names.set(typeof(WindowListGroup), settings_name);
+        type_description = WindowListGroup.register();
+        types.add(typeof(WindowListGroup).name());
+        descriptions.set(typeof(WindowListGroup).name(), type_description);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Creates a Group for a given type name.
+    /////////////////////////////////////////////////////////////////////
+    
+    public static ActionGroup? create_group(string type_id, string parent_id) {
+        switch (type_id) {
+            case "bookmarks": return new BookmarkGroup(parent_id);
+            case "devices": return new DevicesGroup(parent_id);
+            case "menu": return new MenuGroup(parent_id);
+            case "session": return new SessionGroup(parent_id);
+            case "window_list": return new WindowListGroup(parent_id);
+        }
         
-//        ClipboardGroup.register(out name, out icon, out settings_name);
-//        types.add(typeof(ClipboardGroup));
-//        names.set(typeof(ClipboardGroup), name);
-//        icons.set(typeof(ClipboardGroup), icon);
-//        settings_names.set(typeof(ClipboardGroup), settings_name);
+        return null;
     }
 }
 
diff --git a/src/actionGroups/menuGroup.vala b/src/actionGroups/menuGroup.vala
index 07a4bd1..247376d 100644
--- a/src/actionGroups/menuGroup.vala
+++ b/src/actionGroups/menuGroup.vala
@@ -30,10 +30,13 @@ public class MenuGroup : ActionGroup {
     /// the pies.conf file for this kind of ActionGroups.
     /////////////////////////////////////////////////////////////////////
     
-    public static void register(out string name, out string icon, out string settings_name) {
-        name = _("Main menu");
-        icon = "gnome-main-menu";
-        settings_name = "menu";
+    public static GroupRegistry.TypeDescription register() {
+        var description = new GroupRegistry.TypeDescription();
+        description.name = _("Group: Main menu");
+        description.icon = "gnome-main-menu";
+        description.description = _("Displays your main menu structure.");
+        description.id = "menu";
+        return description;
     }
     
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actionGroups/sessionGroup.vala b/src/actionGroups/sessionGroup.vala
index 0b3f249..26f8ebc 100644
--- a/src/actionGroups/sessionGroup.vala
+++ b/src/actionGroups/sessionGroup.vala
@@ -30,10 +30,13 @@ public class SessionGroup : ActionGroup {
     /// the pies.conf file for this kind of ActionGroups.
     /////////////////////////////////////////////////////////////////////
     
-    public static void register(out string name, out string icon, out string settings_name) {
-        name = _("Session Control");
-        icon = "gnome-logout";
-        settings_name = "session";
+    public static GroupRegistry.TypeDescription register() {
+        var description = new GroupRegistry.TypeDescription();
+        description.name = _("Group: Session Control");
+        description.icon = "gnome-logout";
+        description.description = _("Shows a Slice for Shutdown, Reboot, and Hibernate.");
+        description.id = "session";
+        return description;
     }
     
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actionGroups/windowListGroup.vala b/src/actionGroups/windowListGroup.vala
index b12f188..18bf55b 100644
--- a/src/actionGroups/windowListGroup.vala
+++ b/src/actionGroups/windowListGroup.vala
@@ -29,10 +29,13 @@ public class WindowListGroup : ActionGroup {
     /// the pies.conf file for this kind of ActionGroups.
     /////////////////////////////////////////////////////////////////////
     
-    public static void register(out string name, out string icon, out string settings_name) {
-        name = _("Window List");
-        icon = "window-manager";
-        settings_name = "window_list";
+    public static GroupRegistry.TypeDescription register() {
+        var description = new GroupRegistry.TypeDescription();
+        description.name = _("Group: Window List");
+        description.icon = "window-manager";
+        description.description = _("Shows a Slice for each of your opened Windows. Almost like Alt-Tab.");
+        description.id = "window_list";
+        return description;
     }
 
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actions/action.vala b/src/actions/action.vala
index ceed357..ff0e9cd 100644
--- a/src/actions/action.vala
+++ b/src/actions/action.vala
@@ -42,14 +42,14 @@ public abstract class Action : GLib.Object {
     /// The name of the Action.
     /////////////////////////////////////////////////////////////////////  
 
-    public virtual string name { get; protected set; }
+    public virtual string name { get; set; }
     
     /////////////////////////////////////////////////////////////////////
     /// The name of the icon of this Action. It should be in the users
     /// current icon theme.
     /////////////////////////////////////////////////////////////////////
     
-    public virtual string icon { get; protected set; }
+    public virtual string icon { get; set; }
     
     /////////////////////////////////////////////////////////////////////
     /// True, if this Action is the quickAction of the associated Pie.
@@ -57,14 +57,14 @@ public abstract class Action : GLib.Object {
     /// the center of a Pie.
     /////////////////////////////////////////////////////////////////////
     
-    public virtual bool is_quick_action { get; protected set; }
+    public virtual bool is_quickaction { get; set; }
 
     /////////////////////////////////////////////////////////////////////
     /// C'tor, initializes all members.
     /////////////////////////////////////////////////////////////////////
 
-    public Action(string name, string icon, bool is_quick_action) {
-        GLib.Object(name : name, icon : icon, is_quick_action : is_quick_action);
+    public Action(string name, string icon, bool is_quickaction) {
+        GLib.Object(name : name, icon : icon, is_quickaction : is_quickaction);
     }
 
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actions/actionRegistry.vala b/src/actions/actionRegistry.vala
index 091865f..135e90c 100644
--- a/src/actions/actionRegistry.vala
+++ b/src/actions/actionRegistry.vala
@@ -27,56 +27,68 @@ public class ActionRegistry : GLib.Object {
     /// A list containing all available Action types.
     /////////////////////////////////////////////////////////////////////
     
-    public static Gee.ArrayList<Type> types { get; private set; }
+    public static Gee.ArrayList<string> types { get; private set; }
     
     /////////////////////////////////////////////////////////////////////
-    /// Three maps associating a displayable name for each Action, 
+    /// A map associating a displayable name for each Action, 
     /// whether it has a custom icon and a name for the pies.conf
     /// file with it's type.
     /////////////////////////////////////////////////////////////////////
     
-    public static Gee.HashMap<Type, string> names { get; private set; }
-    public static Gee.HashMap<Type, bool> icon_name_editables { get; private set; }
-    public static Gee.HashMap<Type, string> settings_names { get; private set; }
+    public static Gee.HashMap<string, TypeDescription?> descriptions { get; private set; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// A helper class storing information on a Action type.
+    /////////////////////////////////////////////////////////////////////
+    
+    public class TypeDescription {
+        public string name { get; set; default=""; }
+        public string icon { get; set; default=""; }
+        public string description { get; set; default=""; }
+        public string id { get; set; default=""; }
+        public bool icon_name_editable { get; set; default=false; }
+    }
     
     /////////////////////////////////////////////////////////////////////
     /// Registers all Action types.
     /////////////////////////////////////////////////////////////////////
     
     public static void init() {
-        types = new Gee.ArrayList<Type>();
-    
-        names = new Gee.HashMap<Type, string>();
-        icon_name_editables = new Gee.HashMap<Type, bool>();
-        settings_names = new Gee.HashMap<Type, string>();
+        types = new Gee.ArrayList<string>();
+        descriptions = new Gee.HashMap<string, TypeDescription?>();
     
-        string name = "";
-        bool icon_name_editable = true;
-        string settings_name = "";
+        TypeDescription type_description;
         
-        AppAction.register(out name, out icon_name_editable, out settings_name);
-        types.add(typeof(AppAction));
-        names.set(typeof(AppAction), name);
-        icon_name_editables.set(typeof(AppAction), icon_name_editable);
-        settings_names.set(typeof(AppAction), settings_name);
+        types.add(typeof(AppAction).name());
+        type_description = AppAction.register();
+        descriptions.set(typeof(AppAction).name(), type_description);
         
-        KeyAction.register(out name, out icon_name_editable, out settings_name);
-        types.add(typeof(KeyAction));
-        names.set(typeof(KeyAction), name);
-        icon_name_editables.set(typeof(KeyAction), icon_name_editable);
-        settings_names.set(typeof(KeyAction), settings_name);
+        types.add(typeof(KeyAction).name());
+        type_description = KeyAction.register();
+        descriptions.set(typeof(KeyAction).name(), type_description);
         
-        PieAction.register(out name, out icon_name_editable, out settings_name);
-        types.add(typeof(PieAction));
-        names.set(typeof(PieAction), name);
-        icon_name_editables.set(typeof(PieAction), icon_name_editable);
-        settings_names.set(typeof(PieAction), settings_name);
+        types.add(typeof(PieAction).name());
+        type_description = PieAction.register();
+        descriptions.set(typeof(PieAction).name(), type_description);
+        
+        types.add(typeof(UriAction).name());
+        type_description = UriAction.register();
+        descriptions.set(typeof(UriAction).name(), type_description);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Creates a new Action from the given type name.
+    /////////////////////////////////////////////////////////////////////
+    
+    public static Action? create_action(string type_id, string name, string icon, string command, bool quickaction) {
+        switch (type_id) {
+            case "app": return new AppAction(name, icon, command, quickaction);
+            case "key": return new KeyAction(name, icon, command, quickaction);
+            case "uri": return new UriAction(name, icon, command, quickaction);
+            case "pie": return new PieAction(command, quickaction);
+        }
         
-        UriAction.register(out name, out icon_name_editable, out settings_name);
-        types.add(typeof(UriAction));
-        names.set(typeof(UriAction), name);
-        icon_name_editables.set(typeof(UriAction), icon_name_editable);
-        settings_names.set(typeof(UriAction), settings_name);
+        return null;
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -109,10 +121,12 @@ public class ActionRegistry : GLib.Object {
                 
             case "http": case "https":
                 final_icon = "www";
+                final_name = get_domain_name(uri);
                 break;
                 
             case "ftp": case "sftp":
                 final_icon = "folder-remote";
+                final_name = get_domain_name(uri);
                 break;
                 
             default:
@@ -174,6 +188,12 @@ public class ActionRegistry : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public static Action? new_for_desktop_file(string file_name) {
+        // check whether its a desktop file to open one of Gnome-Pie's pies
+        if (file_name.has_prefix(Paths.launchers)) {
+            string id = file_name.substring((long)file_name.length - 11, 3);
+            return new PieAction(id);
+        }
+        
         var info = new DesktopAppInfo.from_filename(file_name);
         return new_for_app_info(info);
     }
@@ -192,9 +212,23 @@ public class ActionRegistry : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public static Action? default_for_uri(string uri) {
-        var info = AppInfo. get_default_for_uri_scheme(uri);
+        var info = AppInfo.get_default_for_uri_scheme(uri);
         return new_for_app_info(info);
     }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Returns for example www.google.com when http://www.google.de/?q=h
+    /// is given.
+    /////////////////////////////////////////////////////////////////////
+    
+    private static string get_domain_name(string url) {
+        int domain_end = url.index_of_char('/', 7);
+        int domain_begin = url.index_of_char('/', 0) + 2;
+        
+        if (domain_begin < domain_end) return url.substring(domain_begin, domain_end-domain_begin);
+        
+        return url;
+    }
 }
 
 }
diff --git a/src/actions/appAction.vala b/src/actions/appAction.vala
index d8363e4..2371f7c 100644
--- a/src/actions/appAction.vala
+++ b/src/actions/appAction.vala
@@ -29,10 +29,14 @@ public class AppAction : Action {
     /// used in the pies.conf file for this kind of Actions.
     /////////////////////////////////////////////////////////////////////
 
-    public static void register(out string name, out bool icon_name_editable, out string settings_name) {
-        name = _("Launch application");
-        icon_name_editable = true;
-        settings_name = "app";
+    public static ActionRegistry.TypeDescription register() {
+        var description = new ActionRegistry.TypeDescription();
+        description.name = _("Launch application");
+        description.icon = "application-x-executable";
+        description.description = _("Executes the given command.");
+        description.icon_name_editable = true;
+        description.id = "app";
+        return description;
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -51,8 +55,8 @@ public class AppAction : Action {
     /// C'tor, initializes all members.
     /////////////////////////////////////////////////////////////////////
 
-    public AppAction(string name, string icon, string command, bool is_quick_action = false) {
-        GLib.Object(name : name, icon : icon, real_command : command, is_quick_action : is_quick_action);
+    public AppAction(string name, string icon, string command, bool is_quickaction = false) {
+        GLib.Object(name : name, icon : icon, real_command : command, is_quickaction : is_quickaction);
     }
 
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actions/keyAction.vala b/src/actions/keyAction.vala
index ddeebb5..3816686 100644
--- a/src/actions/keyAction.vala
+++ b/src/actions/keyAction.vala
@@ -29,10 +29,14 @@ public class KeyAction : Action {
     /// used in the pies.conf file for this kind of Actions.
     /////////////////////////////////////////////////////////////////////
 
-    public static void register(out string name, out bool icon_name_editable, out string settings_name) {
-        name = _("Press hotkey");
-        icon_name_editable = true;
-        settings_name = "key";
+    public static ActionRegistry.TypeDescription register() {
+        var description = new ActionRegistry.TypeDescription();
+        description.name = _("Press hotkey");
+        description.icon = "preferences-desktop-keyboard-shortcuts";
+        description.description = _("Simulates the activation of a hotkey.");
+        description.icon_name_editable = true;
+        description.id = "key";
+        return description;
     }   
     
     /////////////////////////////////////////////////////////////////////
@@ -57,12 +61,12 @@ public class KeyAction : Action {
     /// C'tor, initializes all members.
     /////////////////////////////////////////////////////////////////////
 
-    public KeyAction(string name, string icon, string command, bool is_quick_action = false) {
-        GLib.Object(name : name, icon : icon, real_command : command, is_quick_action : is_quick_action);
+    public KeyAction(string name, string icon, string command, bool is_quickaction = false) {
+        GLib.Object(name : name, icon : icon, real_command : command, is_quickaction : is_quickaction);
     }
     
     construct {
-        this.key = new Key(real_command);
+        this.key = new Key.from_string(real_command);
     }
     
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actions/pieAction.vala b/src/actions/pieAction.vala
index 53ea919..5b2c81d 100644
--- a/src/actions/pieAction.vala
+++ b/src/actions/pieAction.vala
@@ -29,10 +29,14 @@ public class PieAction : Action {
     /// used in the pies.conf file for this kind of Actions.
     /////////////////////////////////////////////////////////////////////
 
-    public static void register(out string name, out bool icon_name_editable, out string settings_name) {
-        name = _("Open Pie");
-        icon_name_editable = false;
-        settings_name = "pie";
+    public static ActionRegistry.TypeDescription register() {
+        var description = new ActionRegistry.TypeDescription();
+        description.name = _("Open Pie");
+        description.icon = "gnome-pie";
+        description.description = _("Opens another Pie of Gnome-Pie. You may create sub menus this way.");
+        description.icon_name_editable = false;
+        description.id = "pie";
+        return description;
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -79,8 +83,8 @@ public class PieAction : Action {
     /// C'tor, initializes all members.
     /////////////////////////////////////////////////////////////////////
 
-    public PieAction(string id, bool is_quick_action = false) {
-        GLib.Object(name : "", icon : "", real_command : id, is_quick_action : is_quick_action);
+    public PieAction(string id, bool is_quickaction = false) {
+        GLib.Object(name : "", icon : "", real_command : id, is_quickaction : is_quickaction);
     }
     
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actions/sigAction.vala b/src/actions/sigAction.vala
index cec9836..1edbc08 100644
--- a/src/actions/sigAction.vala
+++ b/src/actions/sigAction.vala
@@ -47,8 +47,8 @@ public class SigAction : Action {
     /// C'tor, initializes all members.
     /////////////////////////////////////////////////////////////////////
 
-    public SigAction(string name, string icon, string command, bool is_quick_action = false) {
-        GLib.Object(name : name, icon : icon, real_command : command, is_quick_action : is_quick_action);
+    public SigAction(string name, string icon, string command, bool is_quickaction = false) {
+        GLib.Object(name : name, icon : icon, real_command : command, is_quickaction : is_quickaction);
     }
 
     /////////////////////////////////////////////////////////////////////
diff --git a/src/actions/uriAction.vala b/src/actions/uriAction.vala
index 25d5c75..f407f6c 100644
--- a/src/actions/uriAction.vala
+++ b/src/actions/uriAction.vala
@@ -29,10 +29,14 @@ public class UriAction : Action {
     /// used in the pies.conf file for this kind of Actions.
     /////////////////////////////////////////////////////////////////////
     
-    public static void register(out string name, out bool icon_name_editable, out string settings_name) {
-        name = _("Open URI");
-        icon_name_editable = true;
-        settings_name = "uri";
+    public static ActionRegistry.TypeDescription register() {
+        var description = new ActionRegistry.TypeDescription();
+        description.name = _("Open URI");
+        description.icon = "web-browser";
+        description.description = _("Opens a given location. You may use URL's or files paths.");
+        description.icon_name_editable = true;
+        description.id = "uri";
+        return description;
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -51,8 +55,10 @@ public class UriAction : Action {
     /// C'tor, initializes all members.
     /////////////////////////////////////////////////////////////////////
 
-    public UriAction(string name, string icon, string command, bool is_quick_action = false) {
-        GLib.Object(name : name, icon : icon, real_command : command, is_quick_action : is_quick_action);
+    public UriAction(string name, string icon, string command, bool is_quickaction = false) {
+        GLib.Object(name : name, icon : icon, 
+                    real_command : command.has_prefix("www") ? "http://" + command : command, 
+                    is_quickaction : is_quickaction);
     }
 
     /////////////////////////////////////////////////////////////////////
diff --git a/src/deamon.vala b/src/deamon.vala
index 0cdb4c2..cec9539 100644
--- a/src/deamon.vala
+++ b/src/deamon.vala
@@ -15,11 +15,6 @@ You should have received a copy of the GNU General Public License along with
 this program.  If not, see <http://www.gnu.org/licenses/>. 
 */
 
-/////////////////////////////////////////////////////////////////////
-/// TODO-List (need comments):
-/// PieList
-/////////////////////////////////////////////////////////////////////
-
 namespace GnomePie {
 
 /////////////////////////////////////////////////////////////////////////    
@@ -36,6 +31,7 @@ public class Deamon : GLib.Object {
 
     public static int main(string[] args) {
         Logger.init();
+        Gdk.threads_init();
         Gtk.init(ref args);
         Paths.init();
 
@@ -100,7 +96,11 @@ public class Deamon : GLib.Object {
         // create unique application
         var app = new Unique.App("org.gnome.gnomepie", null);
 
-        if (app.is_running) {
+        #if HAVE_GTK_3
+            if (app.is_running()) {
+        #else
+            if (app.is_running) {
+        #endif
             // inform the running instance of the pie to be opened
             if (open_pie != null) {
             	message("Gnome-Pie is already running. Sending request to open pie " + open_pie + ".");
@@ -120,27 +120,27 @@ public class Deamon : GLib.Object {
             if (cmd == Unique.Command.ACTIVATE) {
                 var pie = data.get_text();
                 
-                if (pie != "") PieManager.open_pie(pie);
-                else           this.indicator.show_preferences();
+                if (pie != null && pie != "") PieManager.open_pie(pie);
+                else                          this.indicator.show_preferences();
 
                 return Unique.Response.OK;
             }
 
             return Unique.Response.PASSTHROUGH;
         });
-    
+        
+        // init locale support
+        Intl.bindtextdomain ("gnomepie", Paths.locales);
+        Intl.textdomain ("gnomepie");
+        
         // init toolkits and static stuff
-        Gdk.threads_init();
         ActionRegistry.init();
         GroupRegistry.init();
+        
         PieManager.init();
         Icon.init();
         ThemedIcon.init();
         RenderedText.init();
-    
-        // init locale support
-        Intl.bindtextdomain ("gnomepie", Paths.locales);
-        Intl.textdomain ("gnomepie");
         
         // launch the indicator
         this.indicator = new Indicator();
diff --git a/src/gui/about.vala b/src/gui/about.vala
deleted file mode 100644
index ce4256e..0000000
--- a/src/gui/about.vala
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 
-Copyright (c) 2011 by Simon Schneegans
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program 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 General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program.  If not, see <http://www.gnu.org/licenses/>. 
-*/
-
-namespace GnomePie {
-
-/////////////////////////////////////////////////////////////////////////    
-/// A simple about Dialog.
-/////////////////////////////////////////////////////////////////////////
-
-public class GnomePieAboutDialog: Gtk.AboutDialog {
-
-    public GnomePieAboutDialog () {
-    	string[] devs = {
-			"Simon Schneegans <code@simonschneegans.de>", 
-            "Francesco Piccinno <stack.box@gmail.com>"
-        };
-        string[] artists = {
-			"Simon Schneegans <code@simonschneegans.de>"
-        };
-    	string[] translators = {
-    		"DE\t\t Simon Schneegans <code@simonschneegans.de>",
-    		"IT\t\t Riccardo Traverso <gr3yfox.fw@gmail.com>",
-    		"PT-BR\t Magnun Leno <magnun@codecommunity.org>",
-    		"EN\t\t Simon Schneegans <code@simonschneegans.de>",
-    		"KO\t\t Kim Boram <Boramism@gmail.com>"
-    	};
-    	
-    	// sort translators
-    	GLib.List<string> translator_list = new GLib.List<string>();
-    	foreach (var translator in translators)
-    		translator_list.append(translator);
-    		
-    	translator_list.sort((a, b) => {
-    		return a.ascii_casecmp(b);
-    	});
-    	
-    	string translator_string = "";
-    	foreach (var translator in translator_list)
-	   		translator_string += translator + "\n";
-        
-        GLib.Object (
-            artists : artists,
-            authors : devs,
-            translator_credits : translator_string,
-            copyright : "Copyright (C) 2011 Simon Schneegans <code@simonschneegans.de>",
-            program_name: "Gnome-Pie",
-            logo_icon_name: "gnome-pie",
-            website: "http://www.simonschneegans.de/?page_id=12",
-            website_label: "www.gnome-pie.simonschneegans.de",
-            version: "0.3.1"
-        );
-    }
-}
-
-}
diff --git a/src/gui/aboutWindow.vala b/src/gui/aboutWindow.vala
new file mode 100644
index 0000000..ccd956a
--- /dev/null
+++ b/src/gui/aboutWindow.vala
@@ -0,0 +1,76 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A simple about dialog.
+/////////////////////////////////////////////////////////////////////////
+
+public class AboutWindow: Gtk.AboutDialog {
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, creates a new about dialog. The entries are sorted alpha-
+    /// betically.
+    /////////////////////////////////////////////////////////////////////
+    
+    public AboutWindow () {
+    	string[] devs = {
+			"Simon Schneegans <code@simonschneegans.de>", 
+            "Francesco Piccinno <stack.box@gmail.com>"
+        };
+        string[] artists = {
+			"Simon Schneegans <code@simonschneegans.de>"
+        };
+    	string[] translators = {
+    		"Simon Schneegans <code@simonschneegans.de> (DE, EN)",
+    		"Riccardo Traverso <gr3yfox.fw@gmail.com> (IT)",
+    		"Magnun Leno <magnun@codecommunity.org> (PT-BR)",
+    		"Kim Boram <Boramism@gmail.com> (KO)",
+            "Eduardo Anabalon <lalo1412@gmail.com> (ES)",
+            "Gregoire Bellon-Gervais <greggbg@gmail.com> (FR)",
+            "Eugene Roskin <pams@imail.ru> (RU)"
+    	};
+    	
+    	// sort translators
+    	GLib.List<string> translator_list = new GLib.List<string>();
+    	foreach (var translator in translators)
+    		translator_list.append(translator);
+    		
+    	translator_list.sort((a, b) => {
+    		return a.ascii_casecmp(b);
+    	});
+    	
+    	string translator_string = "";
+    	foreach (var translator in translator_list)
+	   		translator_string += translator + "\n";
+        
+        GLib.Object (
+            artists : artists,
+            authors : devs,
+            translator_credits : translator_string,
+            copyright : "Copyright (C) 2011-2012 Simon Schneegans <code@simonschneegans.de>",
+            program_name: "Gnome-Pie",
+            logo_icon_name: "gnome-pie",
+            website: "http://www.simonschneegans.de/?page_id=12",
+            website_label: "www.gnome-pie.simonschneegans.de",
+            version: "0.4.0"
+        );
+    }
+}
+
+}
diff --git a/src/gui/cellRendererIcon.vala b/src/gui/cellRendererIcon.vala
deleted file mode 100644
index 959a0b7..0000000
--- a/src/gui/cellRendererIcon.vala
+++ /dev/null
@@ -1,132 +0,0 @@
-/* 
-Copyright (c) 2011 by Simon Schneegans
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program 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 General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program.  If not, see <http://www.gnu.org/licenses/>. 
-*/
-
-namespace GnomePie {
-
-/////////////////////////////////////////////////////////////////////////    
-/// A cellrenderer which displays an Icon. When clicked onto, a window
-/// opens for selecting another icon. This needs to be a subclass of
-/// Gtk.CellRendererText because Gtk.CellRendererPixbuf can't receive
-/// click events. Internally it stores a Gtk.CellRendererPixbuf
-/// which renders and stuff.
-/////////////////////////////////////////////////////////////////////////
-
-public class CellRendererIcon : Gtk.CellRendererText {
-    
-    /////////////////////////////////////////////////////////////////////
-    /// This signal is emitted when the user selects another icon.
-    /////////////////////////////////////////////////////////////////////
-    
-    public signal void on_select(string path, string icon);
-    
-    /////////////////////////////////////////////////////////////////////
-    /// The IconSelectWindow which is shown on click.
-    /////////////////////////////////////////////////////////////////////
-
-    private IconSelectWindow select_window = null;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// The internal Renderer used for drawing.
-    /////////////////////////////////////////////////////////////////////
-    
-    private Gtk.CellRendererPixbuf renderer = null;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// A helper variable, needed to emit the current path.
-    /////////////////////////////////////////////////////////////////////
-    
-    private string current_path = "";
-    
-    public string icon_name { get; set; }
-
-    /////////////////////////////////////////////////////////////////////
-    /// Forward some parts of the CellRendererPixbuf's interface.
-    /////////////////////////////////////////////////////////////////////
-    
-    public bool follow_state {
-        get { return renderer.follow_state; }
-        set { renderer.follow_state = value; }
-    }
-    
-    public bool icon_sensitive {
-        get { return renderer.sensitive; }
-        set { renderer.sensitive = value; }
-    }
-    
-    public Gdk.Pixbuf pixbuf {
-        owned get { return renderer.pixbuf; }
-        set { renderer.pixbuf = value; }
-    }
-
-    /////////////////////////////////////////////////////////////////////
-    /// C'tor, creates a new CellRendererIcon.
-    /////////////////////////////////////////////////////////////////////
-    
-    public CellRendererIcon() {
-        this.select_window = new IconSelectWindow();  
-        this.renderer = new Gtk.CellRendererPixbuf();
-    
-        this.select_window.on_select.connect((icon) => {
-            this.on_select(current_path, icon);
-        });
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Forward some parts of the CellRendererPixbuf's interface.
-    /////////////////////////////////////////////////////////////////////
-    
-    public override void get_size (Gtk.Widget widget, Gdk.Rectangle? cell_area,
-                               out int x_offset, out int y_offset,
-                               out int width, out int height) {
-
-        this.renderer.get_size(widget, cell_area, out x_offset, out y_offset, out width, out height);
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Forward some parts of the CellRendererPixbuf's interface.
-    /////////////////////////////////////////////////////////////////////
-    
-    public override void render (Gdk.Window window, Gtk.Widget widget,
-                             Gdk.Rectangle bg_area,
-                             Gdk.Rectangle cell_area,
-                             Gdk.Rectangle expose_area,
-                             Gtk.CellRendererState flags) {
-                             
-        this.renderer.render(window, widget, bg_area, cell_area, expose_area, flags);
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Open the IconSelectWindow on click.
-    /////////////////////////////////////////////////////////////////////
-    
-    public override unowned Gtk.CellEditable start_editing(
-        Gdk.Event event, Gtk.Widget widget, string path, Gdk.Rectangle bg_area, 
-        Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
-        
-        this.select_window.set_transient_for((Gtk.Window)widget.get_toplevel());
-        this.select_window.set_modal(true);
-        
-        this.current_path = path;
-        this.select_window.show();
-        this.select_window.active_icon = this.icon_name;
-            
-        return this.renderer.start_editing(event, widget, path, bg_area, cell_area, flags);
-    }
-}
-
-}
-
diff --git a/src/gui/cellRendererTrigger.vala b/src/gui/cellRendererTrigger.vala
deleted file mode 100644
index a825c32..0000000
--- a/src/gui/cellRendererTrigger.vala
+++ /dev/null
@@ -1,84 +0,0 @@
-/* 
-Copyright (c) 2011 by Simon Schneegans
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program 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 General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program.  If not, see <http://www.gnu.org/licenses/>. 
-*/
-
-namespace GnomePie {
-
-/////////////////////////////////////////////////////////////////////////    
-/// A CellRenderer which opens a TriggerSelectWindow.
-/////////////////////////////////////////////////////////////////////////
-
-public class CellRendererTrigger : Gtk.CellRendererText {
-    
-    /////////////////////////////////////////////////////////////////////
-    /// This signal is emitted when the user selects another trigger.
-    /////////////////////////////////////////////////////////////////////
-    
-    public signal void on_select(string path, Trigger trigger);
-    
-    /////////////////////////////////////////////////////////////////////
-    /// The trigger which can be set with this window.
-    /////////////////////////////////////////////////////////////////////
-    
-    public string trigger { get; set; }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// The IconSelectWindow which is shown on click.
-    /////////////////////////////////////////////////////////////////////
-
-    private TriggerSelectWindow select_window = null;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// A helper variable, needed to emit the current path.
-    /////////////////////////////////////////////////////////////////////
-    
-    private string current_path = "";
-    
-    /////////////////////////////////////////////////////////////////////
-    /// C'tor, creates a new CellRendererIcon.
-    /////////////////////////////////////////////////////////////////////
-    
-    public CellRendererTrigger() {
-        this.select_window = new TriggerSelectWindow();  
-    
-        this.select_window.on_select.connect((trigger) => {
-            this.trigger = trigger.name;
-            this.on_select(current_path, trigger);
-        });
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Open the TriggerSelectWindow on click.
-    /////////////////////////////////////////////////////////////////////
-    
-    public override unowned Gtk.CellEditable start_editing(
-        Gdk.Event event, Gtk.Widget widget, string path, Gdk.Rectangle bg_area, 
-        Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
-        
-        this.current_path = path;
-        
-        this.select_window.set_transient_for((Gtk.Window)widget.get_toplevel());
-        this.select_window.set_modal(true);
-        this.select_window.set_trigger(new Trigger.from_string(this.trigger));
-                  
-        this.select_window.show();
-            
-        return base.start_editing(event, widget, path, bg_area, cell_area, flags);
-    }
-}
-
-}
-
diff --git a/src/gui/iconSelectWindow.vala b/src/gui/iconSelectWindow.vala
index 01a4a40..d66c654 100644
--- a/src/gui/iconSelectWindow.vala
+++ b/src/gui/iconSelectWindow.vala
@@ -23,45 +23,19 @@ namespace GnomePie {
 /// happens in an extra thread and a spinner is displayed while loading.
 /////////////////////////////////////////////////////////////////////////
 
-public class IconSelectWindow : Gtk.Dialog {
-
+public class IconSelectWindow : GLib.Object {
+   
     /////////////////////////////////////////////////////////////////////
-    /// The currently selected icon. If set, this icon gets focused.
+    /// This signal gets emitted when the user selects a new icon.
     /////////////////////////////////////////////////////////////////////
     
-    private string _active_icon = "application-default-icon";
-    
-    public string active_icon {
-        get {
-            return _active_icon;
-        }
-        set {
-            if (value.contains("/")) {
-                this.file_chooser.set_filename(value);
-                this.tabs.set_current_page(1);
-            } else {
-                this.icon_list_filtered.foreach((model, path, iter) => {
-                    string name = "";
-                    model.get(iter, 0, out name);
-                    
-                    if (name == value) {
-                        this.icon_view.select_path(path);
-                        this.icon_view.scroll_to_path(path, true, 0.5f, 0.0f);
-                        this.icon_view.set_cursor(path, null, false);
-                    }
-                    return (name == value);
-                });
-                
-                this.tabs.set_current_page(0);
-            }
-        }
-    }
+    public signal void on_ok(string icon_name);
     
     /////////////////////////////////////////////////////////////////////
-    /// This signal gets emitted when the user selects a new icon.
+    /// Stores the currently selected icon.
     /////////////////////////////////////////////////////////////////////
     
-    public signal void on_select(string icon_name);
+    private string active_icon = "";
 
     /////////////////////////////////////////////////////////////////////
     /// The ListStore storing all theme-icons.
@@ -120,6 +94,12 @@ public class IconSelectWindow : Gtk.Dialog {
     
     private Gtk.Notebook tabs = null;
     
+    /////////////////////////////////////////////////////////////////////
+    /// The main window.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gtk.Window window = null;
+    
     /////////////////////////////////////////////////////////////////////
     /// A little structure containing data for one icon in the icon_view.
     /////////////////////////////////////////////////////////////////////
@@ -156,217 +136,221 @@ public class IconSelectWindow : Gtk.Dialog {
     /// C'tor, creates a new IconSelectWindow.
     /////////////////////////////////////////////////////////////////////
     
-    public IconSelectWindow() {
-        this.title = _("Choose an Icon");
-        this.set_size_request(520, 520);
-        this.delete_event.connect(hide_on_delete);
-        this.load_queue = new GLib.AsyncQueue<ListEntry?>();
+    public IconSelectWindow(Gtk.Window parent) {
+        try {
+            this.load_queue = new GLib.AsyncQueue<ListEntry?>();
             
-        if (this.icon_list == null) {
-            this.icon_list = new Gtk.ListStore(3, typeof(string),      // icon name
-                                                  typeof(IconContext), // icon type
-                                                  typeof(Gdk.Pixbuf)); // the icon itself
-                                                  
-            // disable sorting until all icons are loaded
-            // else loading becomes horribly slow                                    
-            this.icon_list.set_default_sort_func(() => {return 0;});
+            if (this.icon_list == null) {
+                this.icon_list = new Gtk.ListStore(3, typeof(string), // icon name
+                                                      typeof(IconContext), // icon type
+                                                      typeof(Gdk.Pixbuf)); // the icon itself
+                                                      
+                // disable sorting until all icons are loaded
+                // else loading becomes horribly slow
+                this.icon_list.set_default_sort_func(() => {return 0;});
 
-            // reload if icon theme changes
-            Gtk.IconTheme.get_default().changed.connect(() => {
-                if (this.visible) load_icons();
-                else              need_reload = true;
-            });
-        } 
-        
-        // make the icon_view filterable
-        this.icon_list_filtered = new Gtk.TreeModelFilter(this.icon_list, null);
-
-        var container = new Gtk.VBox(false, 12);
-            container.set_border_width(12);
+                // reload if icon theme changes
+                Gtk.IconTheme.get_default().changed.connect(() => {
+                    if (this.window.visible) load_icons();
+                    else need_reload = true;
+                });
+            }
+            
+            // make the icon_view filterable
+            this.icon_list_filtered = new Gtk.TreeModelFilter(this.icon_list, null);
+                
+            Gtk.Builder builder = new Gtk.Builder();
 
-            // tab container
-            this.tabs = new Gtk.Notebook();
+            builder.add_from_file (Paths.ui_files + "/icon_select.ui");
 
-                // icon theme tab
-                var theme_tab = new Gtk.VBox(false, 12);
-                    theme_tab.set_border_width(12);
+            this.window = builder.get_object("window") as Gtk.Window;
+            this.window.set_transient_for(parent);
+            this.window.set_modal(true);
+            
+            this.tabs = builder.get_object("tabs") as Gtk.Notebook;
+            
+            this.spinner = builder.get_object("spinner") as Gtk.Spinner;
+            this.spinner.start();
             
-                    // type chooser combo-box
-                    var context_combo = new Gtk.ComboBox.text();
-                        context_combo.append_text(_("All icons"));
-                        context_combo.append_text(_("Applications"));
-                        context_combo.append_text(_("Actions"));
-                        context_combo.append_text(_("Places"));
-                        context_combo.append_text(_("File types"));
-                        context_combo.append_text(_("Emotes"));
-                        context_combo.append_text(_("Miscellaneous"));
+            (builder.get_object("ok-button") as Gtk.Button).clicked.connect(on_ok_button_clicked);
+            (builder.get_object("cancel-button") as Gtk.Button).clicked.connect(on_cancel_button_clicked);
+            
+            var combo_box = builder.get_object("combo-box") as Gtk.VBox;
+            
+            // context combo
+            #if HAVE_GTK_3
+                var context_combo = new Gtk.ComboBoxText();
+            #else
+                var context_combo = new Gtk.ComboBox.text();
+            #endif
+                context_combo.append_text(_("All icons"));
+                context_combo.append_text(_("Applications"));
+                context_combo.append_text(_("Actions"));
+                context_combo.append_text(_("Places"));
+                context_combo.append_text(_("File types"));
+                context_combo.append_text(_("Emotes"));
+                context_combo.append_text(_("Miscellaneous"));
 
-                        context_combo.set_active(0);
-                        
-                        context_combo.changed.connect(() => {
-                            this.icon_list_filtered.refilter();
-                        });
-                        
-                        theme_tab.pack_start(context_combo, false, false);
+                context_combo.set_active(0);
+                
+                context_combo.changed.connect(() => {
+                    this.icon_list_filtered.refilter();
+                });
+                
+            combo_box.pack_start(context_combo, false, false);
+                
+            // string filter entry
+            var filter = builder.get_object("filter-entry") as Gtk.Entry;
+                
+                // only display items which have the selected type
+                // and whose name contains the text entered in the entry
+                this.icon_list_filtered.set_visible_func((model, iter) => {
+                    string name = "";
+                    IconContext context = IconContext.ALL;
+                    model.get(iter, 0, out name);
+                    model.get(iter, 1, out context);
                     
-                    // string filter entry
-                    var filter = new Gtk.Entry();
-                        filter.primary_icon_stock = Gtk.Stock.FIND;
-                        filter.primary_icon_activatable = false;
-                        filter.secondary_icon_stock = Gtk.Stock.CLEAR;
-                        theme_tab.pack_start(filter, false, false);
-                        
-                        // only display items which have the selected type
-                        // and whose name contains the text entered in the entry
-                        this.icon_list_filtered.set_visible_func((model, iter) => {
-                            string name = "";
-                            IconContext context = IconContext.ALL;
-                            model.get(iter, 0, out name);
-                            model.get(iter, 1, out context);
-                            
-                            if (name == null) return false;
-                            
-                            return (context_combo.get_active() == context || 
-                                    context_combo.get_active() == IconContext.ALL) && 
-                                    name.down().contains(filter.text.down());
-                        });
-                        
-                        // clear when the users clicks on the "clear" icon
-                        filter.icon_release.connect((pos, event) => {
-                            if (pos == Gtk.EntryIconPosition.SECONDARY)
-                                filter.text = "";
-                        });
-                        
-                        // refilter on input
-                        filter.notify["text"].connect(() => {
-                            this.icon_list_filtered.refilter();
-                        });
+                    if (name == null) return false;
                     
-                    // container for the icon_view
-                    var scroll = new Gtk.ScrolledWindow (null, null);
-                        scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
-                        scroll.set_shadow_type (Gtk.ShadowType.IN);
+                    return (context_combo.get_active() == context ||
+                            context_combo.get_active() == IconContext.ALL) &&
+                            name.down().contains(filter.text.down());
+                });
+                
+                // clear when the users clicks on the "clear" icon
+                filter.icon_release.connect((pos, event) => {
+                    if (pos == Gtk.EntryIconPosition.SECONDARY)
+                        filter.text = "";
+                });
+                
+                // refilter on input
+                filter.notify["text"].connect(() => {
+                    this.icon_list_filtered.refilter();
+                });
+            
+            // container for the icon_view
+            var scroll = builder.get_object("icon-scrolledwindow") as Gtk.ScrolledWindow;
 
-                        // displays the filtered icons
-                        this.icon_view = new Gtk.IconView.with_model(this.icon_list_filtered);
-                            this.icon_view.item_width = 32;
-                            this.icon_view.item_padding = 3;
-                            this.icon_view.pixbuf_column = 2;
-                            this.icon_view.tooltip_column = 0;
-                            
-                            // set _active_icon if selection changes
-                            this.icon_view.selection_changed.connect(() => {
-                                foreach (var path in this.icon_view.get_selected_items()) {
-                                    Gtk.TreeIter iter;
-                                    this.icon_list_filtered.get_iter(out iter, path);
-                                    this.icon_list_filtered.get(iter, 0, out this._active_icon);
-                                }
-                            });
-                            
-                            // hide this window when the user activates an icon
-                            this.icon_view.item_activated.connect((path) => {
-                                Gtk.TreeIter iter;
-                                this.icon_list_filtered.get_iter(out iter, path);
-                                this.icon_list_filtered.get(iter, 0, out this._active_icon);
-                                this.on_select(this._active_icon);
-                                this.hide();
-                            });
+                // displays the filtered icons
+                this.icon_view = new Gtk.IconView.with_model(this.icon_list_filtered);
+                    this.icon_view.item_width = 32;
+                    this.icon_view.item_padding = 3;
+                    this.icon_view.pixbuf_column = 2;
+                    this.icon_view.tooltip_column = 0;
                     
-                        scroll.add(this.icon_view);
+                    // set active_icon if selection changes
+                    this.icon_view.selection_changed.connect(() => {
+                        foreach (var path in this.icon_view.get_selected_items()) {
+                            Gtk.TreeIter iter;
+                            this.icon_list_filtered.get_iter(out iter, path);
+                            this.icon_list_filtered.get(iter, 0, out this.active_icon);
+                        }
+                    });
                     
-                        theme_tab.pack_start(scroll, true, true);
-                        
-                    tabs.append_page(theme_tab, new Gtk.Label(_("Icon Theme")));
+                    // hide this window when the user activates an icon
+                    this.icon_view.item_activated.connect((path) => {
+                        Gtk.TreeIter iter;
+                        this.icon_list_filtered.get_iter(out iter, path);
+                        this.icon_list_filtered.get(iter, 0, out this.active_icon);
+                        this.on_ok(this.active_icon);
+                        this.window.hide();
+                    });
+            
+                scroll.add(this.icon_view);
                 
-                // tab containing the possibility to choose a custom icon
-                var custom_tab = new Gtk.VBox(false, 6);
-                    custom_tab.border_width = 12;
+            // file chooser widget
+            this.file_chooser = builder.get_object("filechooser") as Gtk.FileChooserWidget;
+                var file_filter = new Gtk.FileFilter();
+                    file_filter.add_pixbuf_formats();
                     
-                    // file chooser widget
-                    this.file_chooser = new Gtk.FileChooserWidget(Gtk.FileChooserAction.OPEN);
-                        var file_filter = new Gtk.FileFilter();
-                        file_filter.add_pixbuf_formats();
+                    #if HAVE_GTK_3
+                        file_filter.set_filter_name(_("All supported image formats"));
+                    #else
                         file_filter.set_name(_("All supported image formats"));
-                        file_chooser.add_filter(file_filter);
-                        
-                        // set _active_icon if the user selected a file
-                        file_chooser.selection_changed.connect(() => {
-                            if (file_chooser.get_filename() != null && 
-                                GLib.FileUtils.test(file_chooser.get_filename(), 
-                                                    GLib.FileTest.IS_REGULAR))
-                                
-                                this._active_icon = file_chooser.get_filename();
-                        });
-                        
-                        // hide this window when the user activates a file
-                        file_chooser.file_activated.connect(() => {
-                            this._active_icon = file_chooser.get_filename();
-                            this.on_select(this._active_icon);
-                            this.hide();
-                        });
-                    
-                    
-                    custom_tab.pack_start(file_chooser, true, true);
-                    
-                tabs.append_page(custom_tab, new Gtk.Label(_("Custom Icon")));
-                    
-            container.pack_start(tabs, true, true);
-
-            // button box --- this dialog has a custom button box at the bottom because it
-            // should have a spinner there. Sadly that's impossible with the "normal"
-            // action_area of Gtk.Dialog's 
-            var bottom_box = new Gtk.HBox(false, 0);
-            
-                var bbox = new Gtk.HButtonBox();
-                    bbox.set_spacing(6);
-                    bbox.set_layout(Gtk.ButtonBoxStyle.END);
-                    
-                    var cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL);
-                        cancel_button.clicked.connect(() => { 
-                            this.hide();
-                        });
-                        bbox.pack_start(cancel_button);
-                        
-                    var ok_button = new Gtk.Button.from_stock(Gtk.Stock.OK);
-                        ok_button.clicked.connect(() => { 
-                            this.on_select(this._active_icon);
-                            this.hide();
-                        });
-                        bbox.pack_start(ok_button);
-                        
-                    bottom_box.pack_end(bbox, false);
+                    #endif
                     
-                    this.spinner = new Gtk.Spinner();
-                        this.spinner.set_size_request(16, 16);
-                        this.spinner.start();
+                    file_chooser.add_filter(file_filter);
+                
+                // set active_icon if the user selected a file
+                file_chooser.selection_changed.connect(() => {
+                    if (file_chooser.get_filename() != null &&
+                        GLib.FileUtils.test(file_chooser.get_filename(),
+                                            GLib.FileTest.IS_REGULAR))
                         
-                        bottom_box.pack_start(this.spinner, false, false);
+                        this.active_icon = file_chooser.get_filename();
+                });
+                
+                // hide this window when the user activates a file
+                file_chooser.file_activated.connect(() => {
+                    this.active_icon = file_chooser.get_filename();
+                    this.on_ok(this.active_icon);
+                    this.window.hide();
+                });
             
-            container.pack_start(bottom_box, false, false);
-          
-        this.vbox.pack_start(container, true, true);
-
-        this.vbox.show_all();
-
-        this.set_focus(this.icon_view);
+            this.window.set_focus(this.icon_view);
+            this.window.delete_event.connect(this.window.hide_on_delete);
+            
+        } catch (GLib.Error e) {
+            error("Could not load UI: %s\n", e.message);
+        }
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Hide the "normal" action_area when this window is shown. Reload
-    /// all icons if necessary.
+    /// Displays the window. The icons are reloaded if neccessary.
     /////////////////////////////////////////////////////////////////////
-    
-    public override void show() {
-        base.show();
-        
-        // hide the "normal" action_area --- this Dialog has a custom set of
-        // buttons containg the spinner
-        this.action_area.hide();
+
+    public void show() {
+        this.window.show_all();
+        this.spinner.hide();
         
         if (this.need_reload) {
             this.need_reload = false;
             this.load_icons();
         }
+    } 
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes the window select the icon of the given Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_pie(string id) {
+        string icon = PieManager.all_pies[id].icon;
+    
+        if (icon.contains("/")) {
+            this.file_chooser.set_filename(icon);
+            this.tabs.set_current_page(1);
+        } else {
+            this.icon_list_filtered.foreach((model, path, iter) => {
+                string name = "";
+                model.get(iter, 0, out name);
+                
+                if (name == icon) {
+                    this.icon_view.select_path(path);
+                    this.icon_view.scroll_to_path(path, true, 0.5f, 0.0f);
+                    this.icon_view.set_cursor(path, null, false);
+                }
+                return (name == icon);
+            });
+            
+            this.tabs.set_current_page(0);
+        }
+    } 
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user clicks the ok button.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_ok_button_clicked() {
+        this.on_ok(this.active_icon);
+        this.window.hide();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user clicks the cancel button.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_cancel_button_clicked() {
+        this.window.hide();
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -400,13 +384,13 @@ public class IconSelectWindow : Gtk.Dialog {
                     var new_entry = this.load_queue.pop();
                     Gtk.TreeIter current;
                     this.icon_list.append(out current);
-                    this.icon_list.set(current, 0, new_entry.name, 
+                    this.icon_list.set(current, 0, new_entry.name,
                                                 1, new_entry.context,
                                                 2, new_entry.pixbuf);
                 }
                 
                 // enable sorting of the icon_view if loading finished
-                if (!this.loading) this.icon_list.set_sort_column_id(0, Gtk.SortType.ASCENDING);  
+                if (!this.loading) this.icon_list.set_sort_column_id(0, Gtk.SortType.ASCENDING);
 
                 return loading;
             });
@@ -439,12 +423,12 @@ public class IconSelectWindow : Gtk.Dialog {
                         default: break;
                     }
                     
-                    try {      
+                    try {
                         // create a new entry for the queue
                         var new_entry = new ListEntry();
                         new_entry.name = icon;
                         new_entry.context = icon_context;
-                        new_entry.pixbuf = icon_theme.load_icon(icon, 32, 0); 
+                        new_entry.pixbuf = icon_theme.load_icon(icon, 32, 0);
                         
                         // some icons have only weird sizes... do not include them
                         if (new_entry.pixbuf.width == 32)
@@ -462,7 +446,7 @@ public class IconSelectWindow : Gtk.Dialog {
         
         // hide the spinner
         if (spinner != null)
-            spinner.visible = this.loading;
+            spinner.visible = false;
 
         return null;
     }
diff --git a/src/gui/indicator.vala b/src/gui/indicator.vala
index 8033cb7..dea4d3c 100644
--- a/src/gui/indicator.vala
+++ b/src/gui/indicator.vala
@@ -38,7 +38,7 @@ public class Indicator : GLib.Object {
     /// The Preferences Menu of Gnome-Pie.
     /////////////////////////////////////////////////////////////////////
 
-    private Preferences prefs { private get; private set; }
+    private PreferencesWindow prefs { private get; private set; }
 
     /////////////////////////////////////////////////////////////////////
     /// Returns true, when the indicator is currently visible.
@@ -73,7 +73,7 @@ public class Indicator : GLib.Object {
             string icon = "indicator-applet";
             try {
                 path = GLib.Path.get_dirname(GLib.FileUtils.read_link("/proc/self/exe"))+"/resources";
-                icon = "gnome-pie-indicator";
+                icon = "gnome-pie";
             } catch (GLib.FileError e) {
                 warning("Failed to get path of executable!");
             }
@@ -86,23 +86,23 @@ public class Indicator : GLib.Object {
             try {
                 var file = GLib.File.new_for_path(GLib.Path.build_filename(
                     GLib.Path.get_dirname(GLib.FileUtils.read_link("/proc/self/exe"))+"/resources",
-                    "gnome-pie-indicator.svg"
+                    "gnome-pie.svg"
                 ));
 
                 if (!file.query_exists())
-                  this.indicator.set_from_icon_name("gnome-pie-indicator");
+                  this.indicator.set_from_icon_name("gnome-pie");
                 else
                   this.indicator.set_from_file(file.get_path());
             } catch (GLib.FileError e) {
                 warning("Failed to get path of executable!");
-                this.indicator.set_from_icon_name("gnome-pie-indicator");
+                this.indicator.set_from_icon_name("gnome-pie");
             }
 
             this.menu = new Gtk.Menu();
             var menu = this.menu;
         #endif
 
-        this.prefs = new Preferences();
+        this.prefs = new PreferencesWindow();
 
         // preferences item
         var item = new Gtk.ImageMenuItem.from_stock (Gtk.Stock.PREFERENCES, null);
@@ -117,7 +117,7 @@ public class Indicator : GLib.Object {
         item = new Gtk.ImageMenuItem.from_stock (Gtk.Stock.ABOUT, null);
         item.show();
         item.activate.connect(() => {
-            var about = new GnomePieAboutDialog();
+            var about = new AboutWindow();
             about.run();
             about.destroy();
         });
diff --git a/src/gui/newSliceWindow.vala b/src/gui/newSliceWindow.vala
new file mode 100644
index 0000000..4e38376
--- /dev/null
+++ b/src/gui/newSliceWindow.vala
@@ -0,0 +1,394 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A window which allows selection of a new Slice which is about to be
+/// added to a Pie. It can be also used to edit an existing Slice
+/////////////////////////////////////////////////////////////////////////
+
+public class NewSliceWindow : GLib.Object {
+
+    /////////////////////////////////////////////////////////////////////
+    /// This signal gets emitted when the user confirms his selection.
+    /////////////////////////////////////////////////////////////////////
+
+    public signal void on_select(ActionGroup action, bool as_new_slice, int at_position); 
+
+    /////////////////////////////////////////////////////////////////////
+    /// The contained list of slice types. It contains both: Groups and
+    /// single actions.
+    /////////////////////////////////////////////////////////////////////
+
+    private SliceTypeList slice_type_list = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The IconSelectWindow used for icon selection for a Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    private IconSelectWindow? icon_window = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some widgets of this window. Loaded by a ui-builder and stored
+    /// for later access.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gtk.Dialog window = null;
+    private Gtk.HBox name_box = null;
+    private Gtk.HBox command_box = null;
+    private Gtk.Button icon_button = null;
+    private Gtk.VBox no_options_box = null;
+    private Gtk.HBox pie_box = null;
+    private Gtk.HBox hotkey_box = null;
+    private Gtk.HBox uri_box = null;
+    private Gtk.HBox quickaction_box = null;
+    private Gtk.Image icon = null;
+    private Gtk.Entry name_entry = null;
+    private Gtk.Entry command_entry = null;
+    private Gtk.Entry uri_entry = null;
+    private Gtk.CheckButton quickaction_checkbutton = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Two custom widgets. For Pie and hotkey selection respectively.
+    /////////////////////////////////////////////////////////////////////
+    
+    private PieComboList pie_select = null;
+    private TriggerSelectButton key_select = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// These members store information on the currently selected Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    private string current_type = "";
+    private string current_icon = "";
+    private string current_id = "";
+    private string current_custom_icon = "";
+    private string current_hotkey = "";
+    private string current_pie_to_open = "";
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The position of the edited Slice in its parent Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    private int slice_position = 0;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// True, if the Slice i going to be added as a new Slice. Else it
+    /// will edit the Slice at slice_position in its parent Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool add_as_new_slice = true;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor creates a new window.
+    /////////////////////////////////////////////////////////////////////
+    
+    public NewSliceWindow() {
+        try {
+        
+            Gtk.Builder builder = new Gtk.Builder();
+
+            builder.add_from_file (Paths.ui_files + "/slice_select.ui");
+            
+            this.slice_type_list = new SliceTypeList();
+            this.slice_type_list.on_select.connect((type, icon) => {
+                
+                this.name_box.hide();
+                this.command_box.hide();
+                this.icon_button.sensitive = false;
+                this.no_options_box.hide();
+                this.pie_box.hide();
+                this.hotkey_box.hide();
+                this.uri_box.hide();
+                this.quickaction_box.hide();
+                
+                this.current_type = type;
+                
+                switch (type) {
+                    case "bookmarks": case "clipboard": case "devices":
+                    case "menu": case "session": case "window_list":
+                        this.no_options_box.show();
+                        this.set_icon(icon);
+                        break;
+                    case "app":
+                        this.name_box.show();
+                        this.command_box.show();
+                        this.quickaction_box.show();
+                        this.icon_button.sensitive = true;
+                        if (this.current_custom_icon == "") this.set_icon(icon);
+                        else                                this.set_icon(this.current_custom_icon);
+                        break;
+                    case "key":
+                        this.name_box.show();
+                        this.hotkey_box.show();
+                        this.quickaction_box.show();
+                        this.icon_button.sensitive = true;
+                        if (this.current_custom_icon == "") this.set_icon(icon);
+                        else                                this.set_icon(this.current_custom_icon);
+                        break;
+                    case "pie":
+                        this.pie_box.show();
+                        this.quickaction_box.show();
+                        this.set_icon(PieManager.all_pies[this.pie_select.current_id].icon);
+                        break;
+                    case "uri":
+                        this.name_box.show();
+                        this.uri_box.show();
+                        this.quickaction_box.show();
+                        this.icon_button.sensitive = true;
+                        if (this.current_custom_icon == "") this.set_icon(icon);
+                        else                                this.set_icon(this.current_custom_icon);
+                        break;
+                }
+            });
+            
+            this.name_box = builder.get_object("name-box") as Gtk.HBox;
+            this.command_box = builder.get_object("command-box") as Gtk.HBox;
+            this.icon_button = builder.get_object("icon-button") as Gtk.Button;
+            this.no_options_box = builder.get_object("no-options-box") as Gtk.VBox;
+            this.pie_box = builder.get_object("pie-box") as Gtk.HBox;
+            this.pie_select = new PieComboList();
+            this.pie_select.on_select.connect((id) => {
+                this.current_pie_to_open = id;
+                this.set_icon(PieManager.all_pies[id].icon);
+            });
+            
+            this.pie_box.pack_start(this.pie_select, true, true);
+                
+            this.hotkey_box = builder.get_object("hotkey-box") as Gtk.HBox;
+            this.key_select = new TriggerSelectButton(false);
+            this.hotkey_box.pack_start(this.key_select, false, true);
+            this.key_select.on_select.connect((trigger) => {
+                this.current_hotkey = trigger.name;
+            });
+            
+            this.uri_box = builder.get_object("uri-box") as Gtk.HBox;
+            
+            this.name_entry = builder.get_object("name-entry") as Gtk.Entry;
+            this.uri_entry = builder.get_object("uri-entry") as Gtk.Entry;
+            this.command_entry = builder.get_object("command-entry") as Gtk.Entry;
+            this.quickaction_checkbutton = builder.get_object("quick-action-checkbutton") as Gtk.CheckButton;
+            
+            this.quickaction_box = builder.get_object("quickaction-box") as Gtk.HBox;
+            this.icon = builder.get_object("icon") as Gtk.Image;            
+            
+            this.icon_button.clicked.connect(on_icon_button_clicked);
+            
+            var scroll_area = builder.get_object("slice-scrolledwindow") as Gtk.ScrolledWindow;
+                scroll_area.add(this.slice_type_list);
+
+            this.window = builder.get_object("window") as Gtk.Dialog;
+            
+            (builder.get_object("ok-button") as Gtk.Button).clicked.connect(on_ok_button_clicked);
+            (builder.get_object("cancel-button") as Gtk.Button).clicked.connect(on_cancel_button_clicked);
+            
+            this.window.delete_event.connect(this.window.hide_on_delete);
+                
+        } catch (GLib.Error e) {
+            error("Could not load UI: %s\n", e.message);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Sets the parent window, in order to make this window stay in
+    /// front.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_parent(Gtk.Window parent) {
+        this.window.set_transient_for(parent);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Sows the window on the screen.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void show() {
+        this.slice_type_list.select_first();
+        this.pie_select.select_first();
+        this.key_select.set_trigger(new Trigger());
+        this.window.show_all();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Reloads the window.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void reload() {
+        this.pie_select.reload();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes all widgets display stuff according to the given action.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_action(ActionGroup group, int position) {
+        this.set_default(group.parent_id, position);
+        
+        this.add_as_new_slice = false;
+        string type = "";
+        
+        if (group.get_type().depth() == 2) {
+            var action = group.actions[0];
+            type = ActionRegistry.descriptions[action.get_type().name()].id;
+            this.select_type(type);
+            
+            this.set_icon(action.icon);
+            this.quickaction_checkbutton.active = action.is_quickaction;
+            this.name_entry.text = action.name;
+            
+            switch (type) {
+                case "app":
+                    this.current_custom_icon = action.icon;
+                    this.command_entry.text = action.real_command;
+                    break;
+                case "key":
+                    this.current_custom_icon = action.icon;
+                    this.key_select.set_trigger(new Trigger.from_string(action.real_command));
+                    break;
+                case "pie":
+                    this.pie_select.select(action.real_command);
+                    break;
+                case "uri":
+                    this.current_custom_icon = action.icon;
+                    this.uri_entry.text = action.real_command;
+                    break;
+            }
+            
+        } else {
+            type = GroupRegistry.descriptions[group.get_type().name()].id;
+            this.select_type(type);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Selects a default action.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_default(string pie_id, int position) {
+        this.slice_position = position;
+        this.add_as_new_slice = true;
+        this.current_custom_icon = "";
+        this.select_type("app");
+        this.current_id = pie_id;
+        this.key_select.set_trigger(new Trigger());
+        this.pie_select.select_first();
+        this.name_entry.text = _("Rename me!");
+        this.command_entry.text = "";
+        this.uri_entry.text = "";
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Selects a specific action type.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void select_type(string type) {
+        this.current_type = type;
+        this.slice_type_list.select(type);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called, when the user presses the ok button.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_ok_button_clicked() {
+        this.window.hide();
+        
+        ActionGroup group = null;
+        
+        switch (this.current_type) {
+            case "bookmarks":   group = new BookmarkGroup(this.current_id);      break;
+            case "clipboard":   group = new ClipboardGroup(this.current_id);     break;
+            case "devices":     group = new DevicesGroup(this.current_id);       break;
+            case "menu":        group = new MenuGroup(this.current_id);          break;
+            case "session":     group = new SessionGroup(this.current_id);       break;
+            case "window_list": group = new WindowListGroup(this.current_id);    break;
+
+            case "app":
+                group = new ActionGroup(this.current_id);
+                group.add_action(new AppAction(this.name_entry.text, this.current_icon, 
+                                               this.command_entry.text, 
+                                               this.quickaction_checkbutton.active));
+                break;
+            case "key":
+                group = new ActionGroup(this.current_id);
+                group.add_action(new KeyAction(this.name_entry.text, this.current_icon, 
+                                               this.current_hotkey, 
+                                               this.quickaction_checkbutton.active));
+                break;
+            case "pie":
+                group = new ActionGroup(this.current_id);
+                group.add_action(new PieAction(this.current_pie_to_open, 
+                                               this.quickaction_checkbutton.active));
+                break;
+            case "uri":
+                group = new ActionGroup(this.current_id);
+                group.add_action(new UriAction(this.name_entry.text, this.current_icon, 
+                                               this.uri_entry.text, 
+                                               this.quickaction_checkbutton.active));
+                break;
+        }
+        
+        this.on_select(group, this.add_as_new_slice, this.slice_position);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user presses the cancel button.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_cancel_button_clicked() {
+        this.window.hide();
+    }   
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user presses the icon select button.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_icon_button_clicked(Gtk.Button button) {
+        if (icon_window == null) {
+            icon_window = new IconSelectWindow(this.window);
+            icon_window.on_ok.connect((icon) => {
+                this.current_custom_icon = icon;
+                this.set_icon(icon);
+            });
+        }
+        
+        icon_window.show();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Helper method which sets the icon of the icon select button.
+    /// It assures that both can be displayed: A customly chosen image
+    /// from or an icon from the current theme.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void set_icon(string icon) {
+        if (icon.contains("/"))
+            try {
+                this.icon.pixbuf = new Gdk.Pixbuf.from_file_at_scale(icon, this.icon.get_pixel_size(), 
+                                                                     this.icon.get_pixel_size(), true);
+            } catch (GLib.Error error) {
+                warning(error.message);
+            }
+        else
+            this.icon.icon_name = icon;
+            
+        this.current_icon = icon;
+    } 
+}
+
+}
diff --git a/src/gui/pieComboList.vala b/src/gui/pieComboList.vala
new file mode 100644
index 0000000..3b54944
--- /dev/null
+++ b/src/gui/pieComboList.vala
@@ -0,0 +1,155 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A drop-down list, containing one entry for each existing Pie.
+/////////////////////////////////////////////////////////////////////////
+
+class PieComboList : Gtk.ComboBox {
+
+    /////////////////////////////////////////////////////////////////////
+    /// This signal gets emitted when the user selects a new Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    public signal void on_select(string id);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The currently selected row.
+    /////////////////////////////////////////////////////////////////////
+    
+    public string current_id { get; private set; default=""; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Stores the data internally.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gtk.ListStore data;
+    private enum DataPos {ICON, NAME, ID}
+
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, constructs the Widget.
+    /////////////////////////////////////////////////////////////////////
+
+    public PieComboList() {
+        GLib.Object();
+        
+        this.data = new Gtk.ListStore(3, typeof(Gdk.Pixbuf),   
+                                         typeof(string),
+                                         typeof(string));
+                                         
+        this.data.set_sort_column_id(1, Gtk.SortType.ASCENDING);
+        
+        base.set_model(this.data);
+        
+        var icon_render = new Gtk.CellRendererPixbuf();
+            icon_render.xpad = 4;
+            this.pack_start(icon_render, false);
+    
+        var name_render = new Gtk.CellRendererText();
+            this.pack_start(name_render, true);
+        
+        this.add_attribute(icon_render, "pixbuf", DataPos.ICON);
+        this.add_attribute(name_render, "markup", DataPos.NAME);
+        
+        this.changed.connect(() => {
+            Gtk.TreeIter active;
+            if (this.get_active_iter(out active)) {
+                string id = "";
+                this.data.get(active, DataPos.ID, out id);
+                this.on_select(id);
+                this.current_id = id;
+            }
+        });
+        
+        reload();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Loads all existing Pies to the list.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void reload() {
+        Gtk.TreeIter active;
+        string id = "";
+        if (this.get_active_iter(out active))
+            this.data.get(active, DataPos.ID, out id);
+    
+        data.clear();
+        foreach (var pie in PieManager.all_pies.entries) {
+            this.load_pie(pie.value);
+        }
+        
+        select_first();
+        select(id);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Selects the first Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void select_first() {
+        Gtk.TreeIter active;
+        
+        if(this.data.get_iter_first(out active) ) {
+            this.set_active_iter(active);
+            string id = "";
+            this.data.get(active, DataPos.ID, out id);
+            this.on_select(id);
+            this.current_id = id;
+        } else {
+            this.on_select("");
+            this.current_id = "";
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Selects the Pie with the given ID.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void select(string id) {
+        this.data.foreach((model, path, iter) => {
+            string pie_id;
+            this.data.get(iter, DataPos.ID, out pie_id);
+            
+            if (id == pie_id) {
+                this.set_active_iter(iter);
+                return true;
+            }
+            
+            return false;
+        });
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Loads one given pie to the list.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void load_pie(Pie pie) {
+        if (pie.id.length == 3) {
+            Gtk.TreeIter last;
+            this.data.append(out last);
+            var icon = new Icon(pie.icon, 24);
+            this.data.set(last, DataPos.ICON, icon.to_pixbuf(), 
+                                DataPos.NAME, pie.name,
+                                DataPos.ID, pie.id); 
+        }
+    }
+}
+
+}
diff --git a/src/gui/pieList.vala b/src/gui/pieList.vala
index 46970d5..bfcb832 100644
--- a/src/gui/pieList.vala
+++ b/src/gui/pieList.vala
@@ -17,1029 +17,226 @@ this program.  If not, see <http://www.gnu.org/licenses/>.
 
 namespace GnomePie {
 
-// A very complex Widget. This is by far the most ugly file of this project
-// but well, this list *is* complex... sorry ;)
+/////////////////////////////////////////////////////////////////////////    
+/// A list, containing one entry for each existing Pie.
+/////////////////////////////////////////////////////////////////////////
 
 class PieList : Gtk.TreeView {
 
-    private Gtk.ListStore groups;
-    private Gtk.ListStore pies;
-    private Gtk.ListStore actions;
-    private Gtk.TreeStore data;
+    /////////////////////////////////////////////////////////////////////
+    /// This signal gets emitted when the user selects a new Pie.
+    /////////////////////////////////////////////////////////////////////
     
-    private const int small_icon = 24;
-    private const int large_icon = 36;
+    public signal void on_select(string id);
     
-    // data positions in the data ListStore
-    private enum DataPos {IS_QUICKACTION, ICON, NAME, TYPE_ID, ACTION_TYPE,
-                          ICON_PIXBUF, FONT_WEIGHT, ICON_NAME_EDITABLE, QUICKACTION_VISIBLE, QUICKACTION_ACTIVATABLE,
-                          TYPE_VISIBLE, GROUP_VISIBLE, APP_VISIBLE, KEY_VISIBLE, PIE_VISIBLE,
-                          URI_VISIBLE, TRIGGER_VISIBLE, DISPLAY_COMMAND_GROUP, DISPLAY_COMMAND_APP, 
-                          DISPLAY_COMMAND_KEY, DISPLAY_COMMAND_PIE, DISPLAY_COMMAND_URI,
-                          REAL_COMMAND_GROUP, REAL_COMMAND_PIE, REAL_COMMAND_KEY}
+    /////////////////////////////////////////////////////////////////////
+    /// Stores the data internally.
+    /////////////////////////////////////////////////////////////////////
     
-    // data positions in the actions ListStore
-    private enum ActionPos {NAME, TYPE, CAN_QUICKACTION, ICON_NAME_EDITABLE}
+    private Gtk.ListStore data;
+    private enum DataPos {ICON, ICON_NAME, NAME, ID}
     
-    // data positions in the pies ListStore
-    private enum PiePos {NAME, ID}
+    /////////////////////////////////////////////////////////////////////
+    /// Stores where a drag startet.
+    /////////////////////////////////////////////////////////////////////
     
-    // data positions in the groups ListStore
-    private enum GroupPos {NAME, TYPE, ICON}
+    private Gtk.TreeIter? drag_start = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Rembers the time when a last drag move event was reported. Used
+    /// to avoid frequent changes of selected Pie when a Pie is dragged
+    /// over this widget.
+    /////////////////////////////////////////////////////////////////////
+
+    private uint last_hover = 0;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, constructs the Widget.
+    /////////////////////////////////////////////////////////////////////
 
     public PieList() {
         GLib.Object();
         
-        Gtk.TreeIter last;
-        
-        // group choices
-        this.groups = new Gtk.ListStore(3, typeof(string),     // group name
-                                           typeof(string),     // group type
-                                           typeof(string));    // group icon
-        
-        // add all registered group types
-        foreach (var type in GroupRegistry.types) {
-            this.groups.append(out last); 
-            this.groups.set(last, GroupPos.NAME, GroupRegistry.names[type], 
-                                  GroupPos.TYPE, type.name(), 
-                                  GroupPos.ICON, GroupRegistry.icons[type]); 
-        }
-         
-        // pie choices
-        this.pies = new Gtk.ListStore(2,  typeof(string),      // pie name 
-                                          typeof(string));     // pie id
-        
-        // action type choices                                                              
-        this.actions = new Gtk.ListStore(4, typeof(string),    // type name
-                                            typeof(string),    // action type 
-                                            typeof(bool),      // can be quickaction
-                                            typeof(bool));     // icon/name editable   
-        
-        // add all registered action types
-        foreach (var type in ActionRegistry.types) {
-            this.actions.append(out last); 
-            this.actions.set(last, ActionPos.NAME, ActionRegistry.names[type], 
-                                   ActionPos.TYPE, type.name(), 
-                        ActionPos.CAN_QUICKACTION, true, 
-                     ActionPos.ICON_NAME_EDITABLE, ActionRegistry.icon_name_editables[type]); 
-        }
-        // and one type for groups
-        this.actions.append(out last); 
-        this.actions.set(last, ActionPos.NAME, _("Slice group"), 
-                               ActionPos.TYPE, typeof(ActionGroup).name(), 
-                    ActionPos.CAN_QUICKACTION, false, 
-                 ActionPos.ICON_NAME_EDITABLE, false); 
+        this.data = new Gtk.ListStore(4, typeof(Gdk.Pixbuf),   
+                                         typeof(string),
+                                         typeof(string),
+                                         typeof(string));
+                                         
+        this.data.set_sort_column_id(DataPos.NAME, Gtk.SortType.ASCENDING);
         
-        // main data model
-        this.data = new Gtk.TreeStore(25, typeof(bool),       // is quickaction
-                                          typeof(string),     // icon
-                                          typeof(string),     // name   
-                                          typeof(string),     // slice: type label, pie: "ID: %id"
-                                          typeof(string),     // typeof(action), typeof(ActionGroup).name() if group action, pie_id if Pie 
-                                          
-                                          typeof(Gdk.Pixbuf), // icon pixbuf
-                                          typeof(int),        // font weight
-                                          
-                                          typeof(bool),       // icon/name editable
-                                          
-                                          typeof(bool),       // quickaction visible
-                                          typeof(bool),       // quickaction activatable
-                                          typeof(bool),       // type visible
-                                          typeof(bool),       // group renderer visible
-                                          typeof(bool),       // app renderer visible
-                                          typeof(bool),       // key renderer visible
-                                          typeof(bool),       // pie renderer visible
-                                          typeof(bool),       // uri renderer visible
-                                          typeof(bool),       // trigger renderer visible
-                                          
-                                          typeof(string),     // display command group
-                                          typeof(string),     // display command app
-                                          typeof(string),     // display command key
-                                          typeof(string),     // display command pie
-                                          typeof(string),     // display command uri
-                                          
-                                          typeof(string),     // real command group
-                                          typeof(string),     // real command pie
-                                          typeof(string));    // real command key
-                                          
-            
         this.set_model(this.data);
+        this.set_headers_visible(false);
         this.set_grid_lines(Gtk.TreeViewGridLines.NONE);
-        this.set_enable_tree_lines(false);
-        this.set_reorderable(false);
-        this.set_level_indentation(-10);
+        this.width_request = 170;
+        this.set_enable_search(false);
         
-        // create the gui
-        // icon column
-        var icon_column = new Gtk.TreeViewColumn();
-            icon_column.title = _("Icon");
-            icon_column.expand = false;
-            
-            // quickaction checkbox
-            var check_render = new Gtk.CellRendererToggle();
-                check_render.activatable = true;
-                check_render.radio = true;
-                check_render.width = 15;
-
-                check_render.toggled.connect((path) => {
-                    Gtk.TreeIter toggled;
-                    this.data.get_iter_from_string(out toggled, path);
-                    
-                    bool current = false;
-                    this.data.get(toggled, DataPos.IS_QUICKACTION, out current);
-                    
-                    // set all others off
-                    Gtk.TreeIter parent;
-                    this.data.iter_parent(out parent, toggled);
-                    string parent_pos = this.data.get_string_from_iter(parent);
-                    int child_count = this.data.iter_n_children(parent);
-                    
-                    for (int i=0; i<child_count; ++i) {
-                        Gtk.TreeIter child;
-                        this.data.get_iter_from_string(out child, "%s:%d".printf(parent_pos, i));
-                        this.data.set(child, DataPos.IS_QUICKACTION, false);
-                    }
-                    
-                    // toggle selected
-                    this.data.set(toggled, DataPos.IS_QUICKACTION, !current);
-                    
-                    this.update_pie(toggled);
-                });
-                
-                icon_column.pack_start(check_render, false);
-                icon_column.add_attribute(check_render, "activatable", DataPos.QUICKACTION_ACTIVATABLE);
-                icon_column.add_attribute(check_render, "sensitive", DataPos.QUICKACTION_ACTIVATABLE);
-                icon_column.add_attribute(check_render, "visible", DataPos.QUICKACTION_VISIBLE);
-                icon_column.add_attribute(check_render, "active", DataPos.IS_QUICKACTION);
-                
+        this.set_events(Gdk.EventMask.POINTER_MOTION_MASK);
         
-            // icon 
-            var icon_render = new GnomePie.CellRendererIcon();
-                icon_render.editable = true;
-
-                icon_render.on_select.connect((path, icon_name) => {
-                    Gtk.TreeIter iter;
-                    this.data.get_iter_from_string(out iter, path);
-                    int icon_size =  this.data.iter_depth(iter) == 0 ? this.large_icon : this.small_icon;
-                    
-                    this.data.set(iter, DataPos.ICON, icon_name);
-                    this.data.set(iter, DataPos.ICON_PIXBUF, this.load_icon(icon_name, icon_size));
-                    
-                    this.update_pie(iter);
-                    this.update_linked();
-                });
-                
-                icon_column.pack_start(icon_render, false);
-                icon_column.add_attribute(icon_render, "icon_name", DataPos.ICON);
-                icon_column.add_attribute(icon_render, "pixbuf", DataPos.ICON_PIXBUF);
-                icon_column.add_attribute(icon_render, "editable", DataPos.ICON_NAME_EDITABLE);
-                icon_column.add_attribute(icon_render, "icon_sensitive", DataPos.ICON_NAME_EDITABLE);
-                  
-        // command column    
-        var command_column = new Gtk.TreeViewColumn();
-            command_column.title = _("Command");
-            command_column.resizable = true;
-            command_column.expand = true;
-            
-            // trigger 
-            var command_renderer_trigger = new CellRendererTrigger();
-                command_renderer_trigger.editable = true;
-                command_renderer_trigger.ellipsize = Pango.EllipsizeMode.END;
-
-                command_renderer_trigger.on_select.connect((path, trigger) => {                 
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    this.data.set(data_iter, DataPos.DISPLAY_COMMAND_KEY, trigger.label_with_specials);
-                    this.data.set(data_iter, DataPos.REAL_COMMAND_KEY, trigger.name);
-                    
-                    this.update_pie(data_iter);
-                });
-                
-                command_column.pack_end(command_renderer_trigger, true);
-                command_column.add_attribute(command_renderer_trigger, "weight", DataPos.FONT_WEIGHT);
-                command_column.add_attribute(command_renderer_trigger, "markup", DataPos.DISPLAY_COMMAND_KEY);
-                command_column.add_attribute(command_renderer_trigger, "visible", DataPos.TRIGGER_VISIBLE);
-                command_column.add_attribute(command_renderer_trigger, "trigger", DataPos.REAL_COMMAND_KEY);
-            
-            // slice group 
-            var command_renderer_group = new Gtk.CellRendererCombo();
-                command_renderer_group.editable = true;
-                command_renderer_group.has_entry = false;
-                command_renderer_group.text_column = 0;
-                command_renderer_group.ellipsize = Pango.EllipsizeMode.END;
-                command_renderer_group.model = this.groups;
-
-                command_renderer_group.changed.connect((path, iter) => {
-                    string display_name;
-                    string type;
-                    string icon;
-                    
-                    this.groups.get(iter, GroupPos.NAME, out display_name);
-                    this.groups.get(iter, GroupPos.TYPE, out type);
-                    this.groups.get(iter, GroupPos.ICON, out icon);
-                                     
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    this.data.set(data_iter, DataPos.DISPLAY_COMMAND_GROUP, display_name);
-                    this.data.set(data_iter, DataPos.REAL_COMMAND_GROUP, type);
-                    this.data.set(data_iter, DataPos.NAME, display_name);
-                    this.data.set(data_iter, DataPos.ICON, icon);
-                    
-                    this.update_pie(data_iter);
-                });
-                
-                command_column.pack_end(command_renderer_group, true);
-                command_column.add_attribute(command_renderer_group, "weight", DataPos.FONT_WEIGHT);
-                command_column.add_attribute(command_renderer_group, "text", DataPos.DISPLAY_COMMAND_GROUP);
-                command_column.add_attribute(command_renderer_group, "visible", DataPos.GROUP_VISIBLE);
-                
-                
-            // app action 
-            var command_renderer_app = new Gtk.CellRendererText();
-                command_renderer_app.editable = true;
-                command_renderer_app.ellipsize = Pango.EllipsizeMode.END;
-
-                command_renderer_app.edited.connect((path, command) => {                 
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    this.data.set(data_iter, DataPos.DISPLAY_COMMAND_APP, command);
-                    
-                    this.update_pie(data_iter);
-                });
-                
-                command_column.pack_end(command_renderer_app, true);
-                command_column.add_attribute(command_renderer_app, "weight", DataPos.FONT_WEIGHT);
-                command_column.add_attribute(command_renderer_app, "text", DataPos.DISPLAY_COMMAND_APP);
-                command_column.add_attribute(command_renderer_app, "visible", DataPos.APP_VISIBLE);
-                
-                
-            // key action 
-            var command_renderer_key = new Gtk.CellRendererAccel();
-                command_renderer_key.editable = true;
-                command_renderer_key.ellipsize = Pango.EllipsizeMode.END;
-
-                command_renderer_key.accel_edited.connect((path, key, mods) => {                 
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    string label = Gtk.accelerator_get_label(key, mods);
-                    string accelerator = Gtk.accelerator_name(key, mods);
-                    
-                    this.data.set(data_iter, DataPos.DISPLAY_COMMAND_KEY, label);
-                    this.data.set(data_iter, DataPos.REAL_COMMAND_KEY, accelerator);
-                    
-                    this.update_pie(data_iter);
-                });
-                
-                command_renderer_key.accel_cleared.connect((path) => {                 
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    this.data.set(data_iter, DataPos.DISPLAY_COMMAND_KEY, _("Not bound"));
-                    this.data.set(data_iter, DataPos.REAL_COMMAND_KEY, "");
-                    
-                    this.update_pie(data_iter);
-                });
-                
-                command_column.pack_end(command_renderer_key, true);
-                command_column.add_attribute(command_renderer_key, "weight", DataPos.FONT_WEIGHT);
-                command_column.add_attribute(command_renderer_key, "text", DataPos.DISPLAY_COMMAND_KEY);
-                command_column.add_attribute(command_renderer_key, "visible", DataPos.KEY_VISIBLE);
-                
-                
-            // pie action 
-            var command_renderer_pie = new Gtk.CellRendererCombo();
-                command_renderer_pie.editable = true;
-                command_renderer_pie.has_entry = false;
-                command_renderer_pie.text_column = 0;
-                command_renderer_pie.ellipsize = Pango.EllipsizeMode.END;
-                command_renderer_pie.model = this.pies;
-
-                command_renderer_pie.changed.connect((path, iter) => {
-                    string name;
-                    string id;
-                    
-                    this.pies.get(iter, PiePos.NAME, out name);
-                    this.pies.get(iter, PiePos.ID, out id);
-                                     
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    this.data.set(data_iter, DataPos.DISPLAY_COMMAND_PIE, name);
-                    this.data.set(data_iter, DataPos.REAL_COMMAND_PIE, id);
-                    
-                    this.update_pie(data_iter);
-                    this.update_linked();
-                });
-                
-                command_column.pack_end(command_renderer_pie, true);
-                command_column.add_attribute(command_renderer_pie, "weight", DataPos.FONT_WEIGHT);
-                command_column.add_attribute(command_renderer_pie, "text", DataPos.DISPLAY_COMMAND_PIE);
-                command_column.add_attribute(command_renderer_pie, "visible", DataPos.PIE_VISIBLE);
-                
-                
-            // uri action 
-            var command_renderer_uri = new Gtk.CellRendererText();
-                command_renderer_uri.editable = true;
-                command_renderer_uri.ellipsize = Pango.EllipsizeMode.END;
-
-                command_renderer_uri.edited.connect((path, uri) => {                 
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    this.data.set(data_iter, DataPos.DISPLAY_COMMAND_URI, uri);
-                    
-                    this.update_pie(data_iter);
-                });
-                
-                command_column.pack_end(command_renderer_uri, true);
-                command_column.add_attribute(command_renderer_uri, "weight", DataPos.FONT_WEIGHT);
-                command_column.add_attribute(command_renderer_uri, "text", DataPos.DISPLAY_COMMAND_URI);
-                command_column.add_attribute(command_renderer_uri, "visible", DataPos.URI_VISIBLE);
-                
-        
-        // type column   
-        var type_column = new Gtk.TreeViewColumn();
-            type_column.title = _("Pie-ID / Action type");
-            type_column.resizable = true;
-            type_column.expand = false;
-                
-            var type_render = new Gtk.CellRendererCombo();
-                type_render.editable = true;
-                type_render.has_entry = false;
-                type_render.model = actions;
-                type_render.text_column = 0;
-                type_render.ellipsize = Pango.EllipsizeMode.END;
-
-                // change command_render's visibility accordingly
-                type_render.changed.connect((path, iter) => {
-                    string text = "";
-                    string type;
-                    bool can_quickaction;
-                    bool icon_name_editable;
-                    
-                    this.actions.get(iter, ActionPos.NAME, out text);
-                    this.actions.get(iter, ActionPos.TYPE, out type);
-                    this.actions.get(iter, ActionPos.CAN_QUICKACTION, out can_quickaction);
-                    this.actions.get(iter, ActionPos.ICON_NAME_EDITABLE, out icon_name_editable);
-                
-                    Gtk.TreeIter data_iter;
-                    this.data.get_iter_from_string(out data_iter, path);
-                    
-                    this.data.set(data_iter, DataPos.TYPE_ID, text);
-                    this.data.set(data_iter, DataPos.ACTION_TYPE, type);
-                    this.data.set(data_iter, DataPos.QUICKACTION_ACTIVATABLE, can_quickaction);
-                    this.data.set(data_iter, DataPos.ICON_NAME_EDITABLE, icon_name_editable);
-                    
-                    // set all command renderes invisible
-                    this.data.set(data_iter, DataPos.GROUP_VISIBLE, false);
-                    this.data.set(data_iter, DataPos.APP_VISIBLE, false);
-                    this.data.set(data_iter, DataPos.KEY_VISIBLE, false);
-                    this.data.set(data_iter, DataPos.PIE_VISIBLE, false);
-                    this.data.set(data_iter, DataPos.URI_VISIBLE, false);
-                    
-                    // set one visible
-                    int type_id = 0;
-                    if(type == typeof(AppAction).name()) type_id = 1; 
-                    else if(type == typeof(KeyAction).name()) type_id = 2; 
-                    else if(type == typeof(PieAction).name()) type_id = 3; 
-                    else if(type == typeof(UriAction).name()) type_id = 4; 
-                    else type_id = 0;
-                    
-                    this.data.set(data_iter, DataPos.GROUP_VISIBLE + type_id, true);
-                    
-                    this.update_linked();
-                    this.update_pie(data_iter);
-                    
-                    //this.set_cursor(new Gtk.TreePath.from_string(path), command_column, true);
-                });
-                
-                type_column.pack_start(type_render, true);
-                type_column.add_attribute(type_render, "sensitive", DataPos.TYPE_VISIBLE);
-                type_column.add_attribute(type_render, "editable", DataPos.TYPE_VISIBLE);
-                type_column.add_attribute(type_render, "text", DataPos.TYPE_ID);
-        
-        // name column    
-        var name_column = new Gtk.TreeViewColumn();
-            name_column.title = _("Name");
-            name_column.expand = true;
-            name_column.resizable = true;
+        var main_column = new Gtk.TreeViewColumn();
+            var icon_render = new Gtk.CellRendererPixbuf();
+                icon_render.xpad = 4;
+                icon_render.ypad = 4;
+                main_column.pack_start(icon_render, false);
         
             var name_render = new Gtk.CellRendererText();
-                name_render.editable = true;
                 name_render.ellipsize = Pango.EllipsizeMode.END;
-
-                name_render.edited.connect((path, text) => {                        
-                    Gtk.TreeIter iter;
-                    this.data.get_iter_from_string(out iter, path);
-                    
-                    this.data.set(iter, DataPos.NAME, text);
-                    
-                    // try to change icon to a fitting one
-                    string icon;
-                    this.data.get(iter, DataPos.ICON, out icon);
-                    if (icon == "application-default-icon" && Gtk.IconTheme.get_default().has_icon(text.down())) {
-                        this.data.set(iter, DataPos.ICON, text.down());
-                    }
-                    
-                    this.update_pie(iter);
-                    this.update_linked();
-                    
-                    //this.set_cursor(new Gtk.TreePath.from_string(path), type_column, true);
-                });
-                
-                name_column.pack_start(name_render, true);
-                name_column.add_attribute(name_render, "weight", DataPos.FONT_WEIGHT);
-                name_column.add_attribute(name_render, "text", DataPos.NAME);
-                name_column.add_attribute(name_render, "sensitive", DataPos.ICON_NAME_EDITABLE);
-                name_column.add_attribute(name_render, "editable", DataPos.ICON_NAME_EDITABLE);
-        
-        this.append_column(icon_column);
-        this.append_column(name_column);
-        this.append_column(type_column);
-        this.append_column(command_column);
+                name_render.ellipsize_set = true;
+                main_column.pack_start(name_render, true);
         
-        this.realize.connect(this.load);
-        
-        // context menu
-        var menu = new Gtk.Menu();
-
-        var item = new Gtk.ImageMenuItem.with_label(_("Add new Pie"));
-        item.set_image(new Gtk.Image.from_stock(Gtk.Stock.ADD, Gtk.IconSize.MENU));
-        item.activate.connect(this.add_empty_pie);
-        menu.append(item);
-
-        item = new Gtk.ImageMenuItem.with_label(_("Add new Slice"));
-        item.set_image(new Gtk.Image.from_stock(Gtk.Stock.ADD, Gtk.IconSize.MENU));
-        item.activate.connect(this.add_empty_slice);
-        menu.append(item);
-        
-        var sepa = new Gtk.SeparatorMenuItem();
-        menu.append(sepa);
-
-        item = new Gtk.ImageMenuItem.with_label(_("Delete"));
-        item.set_image(new Gtk.Image.from_stock(Gtk.Stock.DELETE, Gtk.IconSize.MENU));
-        item.activate.connect(this.delete_selection);
-        menu.append(item);
+        base.append_column(main_column);
         
-        menu.show_all();
-        
-        this.button_press_event.connect((event) => {
-            if (event.type == Gdk.EventType.BUTTON_PRESS && event.button == 3) {
-                menu.popup(null, null, null, event.button, event.time);
-            }
-            return false;
-        });
+        main_column.add_attribute(icon_render, "pixbuf", DataPos.ICON);
+        main_column.add_attribute(name_render, "markup", DataPos.NAME);
         
         // setup drag'n'drop
         Gtk.TargetEntry uri_source = {"text/uri-list", 0, 0};
         Gtk.TargetEntry[] entries = { uri_source };
-        
-        this.drag_data_received.connect(this.on_dnd_received);
-        this.drag_data_get.connect(this.on_dnd_source);
+        this.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, entries, Gdk.DragAction.LINK);
         this.enable_model_drag_dest(entries, Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK);
+        this.drag_data_get.connect(this.on_dnd_source);
+        this.drag_begin.connect_after(this.on_start_drag);
+        this.drag_motion.connect(this.on_drag_move);
+        this.drag_leave.connect(() => {
+            this.last_hover = 0;
+        });
         
         this.get_selection().changed.connect(() => {
-            Gtk.TreeIter selected;
-            if (this.get_selection().get_selected(null, out selected)) {
-                if (this.data.iter_depth(selected) == 0) {
-                     this.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, entries, Gdk.DragAction.LINK);   
-                } else {
-                    this.unset_rows_drag_source();
-                }
+            Gtk.TreeIter active;
+            if (this.get_selection().get_selected(null, out active)) {
+                string id = "";
+                this.data.get(active, DataPos.ID, out id);
+                this.on_select(id);
             }
         });
         
-        this.drag_begin.connect(() => {
-            this.unset_rows_drag_dest();
-        });
-        
-        this.drag_end.connect(() => {
-            this.enable_model_drag_dest(entries, Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK);
-        });
+        reload_all();
     }
     
-    // moves the selected slice up
-    public void selection_up() {
-        Gtk.TreeIter selected;
-        if (this.get_selection().get_selected(null, out selected)) {
-            Gtk.TreePath path = this.data.get_path(selected);
-            Gtk.TreeIter? before = null;;
-            if (path.prev() && this.data.get_iter(out before, path)) {
-                this.data.swap(selected, before);
-                this.get_selection().changed();
-                this.update_pie(selected);
-            }
-        }
-    }
+    /////////////////////////////////////////////////////////////////////
+    /// Loads all existing Pies to the list.
+    /////////////////////////////////////////////////////////////////////
     
-    // moves the selected slice down
-    public void selection_down() {
-        Gtk.TreeIter selected;
-        if (this.get_selection().get_selected(null, out selected)) {
-            Gtk.TreePath path = this.data.get_path(selected);
-            Gtk.TreeIter? after = null;
-            path.next();
-            if (this.data.get_iter(out after, path)) {
-                this.data.swap(selected, after);
-                this.get_selection().changed();
-                this.update_pie(selected);
-            }
-        }
-    }
+    public void reload_all() {
+        Gtk.TreeIter active;
+        string id = "";
+        if (this.get_selection().get_selected(null, out active))
+            this.data.get(active, DataPos.ID, out id);
     
-    // updates the entire list, checking for changed cross-references via PieActions
-    // updates their names and icons if needed
-    private void update_linked() {
-        this.data.foreach((model, path, iter) => {
-            string action_type;
-            this.data.get(iter, DataPos.ACTION_TYPE, out action_type);
-            
-            if (action_type == typeof(PieAction).name()) {
-                string command;
-                this.data.get(iter, DataPos.REAL_COMMAND_PIE, out command);
-                
-                var referee = PieManager.all_pies[command];
-                
-                if (referee != null) {
-                    this.data.set(iter, DataPos.ICON, referee.icon);
-                    this.data.set(iter, DataPos.NAME, referee.name);
-                    this.data.set(iter, DataPos.ICON_PIXBUF, this.load_icon(referee.icon, this.small_icon));
-                    this.data.set(iter, DataPos.DISPLAY_COMMAND_PIE, referee.name);
-                } else {
-                    // referenced Pie does not exist anymore or no is selected;
-                    // select the first one...
-                    Gtk.TreeIter first_pie;
-                    this.pies.get_iter_first(out first_pie);
-                    
-                    string name;
-                    string id;
-                    
-                    this.pies.get(first_pie, PiePos.NAME, out name);
-                    this.pies.get(first_pie, PiePos.ID, out id);
-                    
-                    this.data.set(iter, DataPos.DISPLAY_COMMAND_PIE, name);
-                    this.data.set(iter, DataPos.REAL_COMMAND_PIE, id);
-                    
-                    update_linked();
-                }
-            } else if (action_type == typeof(ActionGroup).name()) {
-                string command;
-                this.data.get(iter, DataPos.REAL_COMMAND_GROUP, out command);
-                               
-                if (command == "") {
-                    // no group is selected, select the first one...
-                    Gtk.TreeIter first_group;
-                    this.groups.get_iter_first(out first_group);
-                    
-                    string name;
-                    string type;
-                    string icon;
-                    
-                    this.groups.get(first_group, GroupPos.NAME, out name);
-                    this.groups.get(first_group, GroupPos.TYPE, out type);
-                    this.groups.get(first_group, GroupPos.ICON, out icon);
-                    
-                    this.data.set(iter, DataPos.DISPLAY_COMMAND_GROUP, name);
-                    this.data.set(iter, DataPos.NAME, name);
-                    this.data.set(iter, DataPos.REAL_COMMAND_GROUP, type);
-                    this.data.set(iter, DataPos.ICON, icon);
-                }
-            }
-            
-            return false;
-        });
+        data.clear();
+        foreach (var pie in PieManager.all_pies.entries) {
+            this.load_pie(pie.value);
+        }
+        
+        select(id);
     }
     
-    // adds a new, empty pie to the list
-    private void add_empty_pie() {
-        var new_one = PieManager.create_persistent_pie(_("New Pie"), "application-default-icon", null);
-        
-        Gtk.TreeIter last;
-        this.pies.append(out last); this.pies.set(last, 0, new_one.name, 1, new_one.id); 
+    /////////////////////////////////////////////////////////////////////
+    /// Selects the first Pie.
+    /////////////////////////////////////////////////////////////////////
     
-        Gtk.TreeIter parent;
-        this.data.append(out parent, null);
-        this.data.set(parent, DataPos.IS_QUICKACTION, false,
-                                        DataPos.ICON, new_one.icon,
-                                        DataPos.NAME, new_one.name,
-                                     DataPos.TYPE_ID, "ID: " + new_one.id,
-                                 DataPos.ACTION_TYPE, new_one.id,
-                                 DataPos.ICON_PIXBUF, this.load_icon(new_one.icon, this.large_icon),
-                                 DataPos.FONT_WEIGHT, 800,
-                          DataPos.ICON_NAME_EDITABLE, true,
-                         DataPos.QUICKACTION_VISIBLE, false,
-                     DataPos.QUICKACTION_ACTIVATABLE, false,
-                                DataPos.TYPE_VISIBLE, false,
-                               DataPos.GROUP_VISIBLE, false,
-                                 DataPos.APP_VISIBLE, false,
-                                 DataPos.KEY_VISIBLE, false,
-                                 DataPos.PIE_VISIBLE, false,
-                                 DataPos.URI_VISIBLE, false,
-                             DataPos.TRIGGER_VISIBLE, true,
-                       DataPos.DISPLAY_COMMAND_GROUP, "",
-                         DataPos.DISPLAY_COMMAND_APP, "",
-                         DataPos.DISPLAY_COMMAND_KEY, PieManager.get_accelerator_label_of(new_one.id),
-                         DataPos.DISPLAY_COMMAND_PIE, "",
-                         DataPos.DISPLAY_COMMAND_URI, "",
-                          DataPos.REAL_COMMAND_GROUP, "",
-                            DataPos.REAL_COMMAND_PIE, "",
-                            DataPos.REAL_COMMAND_KEY, PieManager.get_accelerator_of(new_one.id));
-                          
+    public void select_first() {
+        Gtk.TreeIter active;
         
-        this.get_selection().select_iter(parent);
-        this.scroll_to_cell(this.data.get_path(parent), null, true, 0.5f, 0.0f);
-    }
-    
-    // adds a new empty slice to the list
-    private void add_empty_slice() {
-        Gtk.TreeIter selected;
-        if (this.get_selection().get_selected(null, out selected)) {
-            var path = this.data.get_path(selected);
-            if (path != null) {
-                if (path.get_depth() == 2)
-                    this.data.iter_parent(out selected, selected);
-                
-                this.load_action(selected, new AppAction(_("New Action"), "application-default-icon", ""));
-                
-                Gtk.TreeIter new_one;
-                this.data.iter_nth_child(out new_one, selected, this.data.iter_n_children(selected)-1);
-                this.expand_to_path(this.data.get_path(new_one));
-                this.get_selection().select_iter(new_one);
-                this.scroll_to_cell(this.data.get_path(new_one), null, true, 0.5f, 0.0f);
-                
-                this.update_pie(selected);
-            } 
+        if(this.data.get_iter_first(out active) ) {
+            this.get_selection().select_iter(active);
+            string id = "";
+            this.data.get(active, DataPos.ID, out id);
+            this.on_select(id);
         } else {
-            var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, 
-                                                     Gtk.MessageType.INFO, 
-                                                     Gtk.ButtonsType.CLOSE, 
-                                                     _("You have to select a Pie to add a Slice to!"));
-            dialog.run();
-            dialog.destroy();
+            this.on_select("");
         }
     }
     
-    // writes the contents of action to the position pointed by slice
-    private void write_action(Action action, Gtk.TreeIter slice) {
-        this.data.set(slice, DataPos.IS_QUICKACTION, action.is_quick_action,
-                                       DataPos.ICON, action.icon,
-                                       DataPos.NAME, action.name,
-                                    DataPos.TYPE_ID, ActionRegistry.names[action.get_type()],
-                                DataPos.ACTION_TYPE, action.get_type().name(),
-                                DataPos.ICON_PIXBUF, this.load_icon(action.icon, this.small_icon),
-                                DataPos.FONT_WEIGHT, 400,
-                         DataPos.ICON_NAME_EDITABLE, !(action is PieAction),
-                        DataPos.QUICKACTION_VISIBLE, true,
-                    DataPos.QUICKACTION_ACTIVATABLE, true,
-                               DataPos.TYPE_VISIBLE, true,
-                              DataPos.GROUP_VISIBLE, false,
-                            DataPos.TRIGGER_VISIBLE, false,
-                                DataPos.APP_VISIBLE, action is AppAction,
-                                DataPos.KEY_VISIBLE, action is KeyAction,
-                                DataPos.PIE_VISIBLE, action is PieAction,
-                                DataPos.URI_VISIBLE, action is UriAction,
-                      DataPos.DISPLAY_COMMAND_GROUP, "",
-                        DataPos.DISPLAY_COMMAND_APP, (action is AppAction) ? action.display_command : "",
-                        DataPos.DISPLAY_COMMAND_KEY, (action is KeyAction) ? action.display_command : _("Not bound"),
-                        DataPos.DISPLAY_COMMAND_PIE, (action is PieAction) ? action.display_command : "",
-                        DataPos.DISPLAY_COMMAND_URI, (action is UriAction) ? action.display_command : "",
-                         DataPos.REAL_COMMAND_GROUP, "",
-                           DataPos.REAL_COMMAND_PIE, (action is PieAction) ? action.real_command : "",
-                           DataPos.REAL_COMMAND_KEY, (action is KeyAction) ? action.real_command : "");
-    }
+    /////////////////////////////////////////////////////////////////////
+    /// Selects the Pie with the given ID.
+    /////////////////////////////////////////////////////////////////////
     
-    // deletes the currently selected pie or slice
-    private void delete_selection() {
-        Gtk.TreeIter selected;
-        if (this.get_selection().get_selected(null, out selected)) {
-            var path = this.data.get_path(selected);
-            if (path != null) {
-                if (path.get_depth() == 1)
-                    this.delete_pie(selected);
-                else
-                    this.delete_slice(selected);
-            } 
-        } else {
-            var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, 
-                                                     Gtk.MessageType.INFO, 
-                                                     Gtk.ButtonsType.CLOSE, 
-                                                     _("You have to select a Pie or a Slice to delete!"));
-            dialog.run();
-            dialog.destroy();
-        }
-    }
-
-    // deletes the given pie
-    private void delete_pie(Gtk.TreeIter pie) {
-        var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, 
-                                                 Gtk.MessageType.QUESTION, 
-                                                 Gtk.ButtonsType.YES_NO, 
-                                                 _("Do you really want to delete the selected Pie with all contained Slices?"));
-                                                 
-        dialog.response.connect((response) => {
-            if (response == Gtk.ResponseType.YES) {
-                string id;
-                this.data.get(pie, DataPos.ACTION_TYPE, out id);
-                this.data.remove(pie);
-                PieManager.remove_pie(id);
-                
-                this.pies.foreach((model, path, iter) => {
-                    string pies_id;
-                    this.pies.get(iter, PiePos.ID, out pies_id);
-                    
-                    if (id == pies_id) {
-                        this.pies.remove(iter);
-                        return true;
-                    }
-                    
-                    return false;
-                });
-                
-                this.update_linked();
-            }
-        });
-        
-        dialog.run();
-        dialog.destroy();
-    }
-
-    // deletes the given slice
-    private void delete_slice(Gtk.TreeIter slice) {
-        var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, 
-                                                 Gtk.MessageType.QUESTION, 
-                                                 Gtk.ButtonsType.YES_NO, 
-                                                 _("Do you really want to delete the selected Slice?"));
-                                                 
-        dialog.response.connect((response) => {
-            if (response == Gtk.ResponseType.YES) {
-                Gtk.TreeIter parent;
-                this.data.iter_parent(out parent, slice);
-                this.data.remove(slice);
-                this.update_pie(parent);
+    public void select(string id) {
+        this.data.foreach((model, path, iter) => {
+            string pie_id;
+            this.data.get(iter, DataPos.ID, out pie_id);
+            
+            if (id == pie_id) {
+                this.get_selection().select_iter(iter);
+                return true;
             }
+            
+            return false;
         });
-        
-        dialog.run();
-        dialog.destroy();
     }
     
-    // loads all pies to the list
-    private void load() {
-        foreach (var pie in PieManager.all_pies.entries) {
-            this.load_pie(pie.value);
-        }
-    }
+    /////////////////////////////////////////////////////////////////////
+    /// Loads one given pie to the list.
+    /////////////////////////////////////////////////////////////////////
     
-    // loads one given pie to the list
     private void load_pie(Pie pie) {
         if (pie.id.length == 3) {
-        
             Gtk.TreeIter last;
-            this.pies.append(out last); this.pies.set(last, PiePos.NAME, pie.name, 
-                                                              PiePos.ID, pie.id); 
-        
-            Gtk.TreeIter parent;
-            this.data.append(out parent, null);
-            this.data.set(parent, DataPos.IS_QUICKACTION, false,
-                                            DataPos.ICON, pie.icon,
-                                            DataPos.NAME, pie.name,
-                                         DataPos.TYPE_ID, "ID: " + pie.id,
-                                     DataPos.ACTION_TYPE, pie.id,
-                                     DataPos.ICON_PIXBUF, this.load_icon(pie.icon, this.large_icon),
-                                     DataPos.FONT_WEIGHT, 800,
-                              DataPos.ICON_NAME_EDITABLE, true,
-                             DataPos.QUICKACTION_VISIBLE, false,
-                         DataPos.QUICKACTION_ACTIVATABLE, false,
-                                    DataPos.TYPE_VISIBLE, false,
-                                   DataPos.GROUP_VISIBLE, false,
-                                     DataPos.APP_VISIBLE, false,
-                                     DataPos.KEY_VISIBLE, false,
-                                     DataPos.PIE_VISIBLE, false,
-                                     DataPos.URI_VISIBLE, false,
-                                 DataPos.TRIGGER_VISIBLE, true,
-                           DataPos.DISPLAY_COMMAND_GROUP, "",
-                             DataPos.DISPLAY_COMMAND_APP, "",
-                             DataPos.DISPLAY_COMMAND_KEY, PieManager.get_accelerator_label_of(pie.id),
-                             DataPos.DISPLAY_COMMAND_PIE, "",
-                             DataPos.DISPLAY_COMMAND_URI, "",
-                              DataPos.REAL_COMMAND_GROUP, "",
-                                DataPos.REAL_COMMAND_PIE, "",
-                                DataPos.REAL_COMMAND_KEY, PieManager.get_accelerator_of(pie.id));
-                             
-            foreach (var group in pie.action_groups) {
-                this.load_group(parent, group);
-            }
+            this.data.append(out last);
+            var icon = new Icon(pie.icon, 24);
+            this.data.set(last, DataPos.ICON, icon.to_pixbuf(), 
+                                DataPos.ICON_NAME, pie.icon,
+                                DataPos.NAME, pie.name,
+                                DataPos.ID, pie.id); 
         }
     }
     
-    // loads a given group
-    private void load_group(Gtk.TreeIter parent, ActionGroup group) {
-        if (group.get_type() == typeof(ActionGroup)) {
-            foreach (var action in group.actions) {
-                this.load_action(parent, action);
-            }
-        } else {
-            Gtk.TreeIter child;
-            this.data.append(out child, parent);
-            this.data.set(child, DataPos.IS_QUICKACTION, false,
-                                           DataPos.ICON, GroupRegistry.icons[group.get_type()],
-                                           DataPos.NAME, GroupRegistry.names[group.get_type()],
-                                        DataPos.TYPE_ID, _("Slice group"),
-                                    DataPos.ACTION_TYPE, typeof(ActionGroup).name(),
-                                    DataPos.ICON_PIXBUF, this.load_icon(GroupRegistry.icons[group.get_type()], this.small_icon),
-                                    DataPos.FONT_WEIGHT, 400,
-                             DataPos.ICON_NAME_EDITABLE, false,
-                            DataPos.QUICKACTION_VISIBLE, true,
-                        DataPos.QUICKACTION_ACTIVATABLE, false,
-                                   DataPos.TYPE_VISIBLE, true,
-                                  DataPos.GROUP_VISIBLE, true,
-                                    DataPos.APP_VISIBLE, false,
-                                    DataPos.KEY_VISIBLE, false,
-                                    DataPos.PIE_VISIBLE, false,
-                                    DataPos.URI_VISIBLE, false,
-                                DataPos.TRIGGER_VISIBLE, false,
-                          DataPos.DISPLAY_COMMAND_GROUP, GroupRegistry.names[group.get_type()],
-                            DataPos.DISPLAY_COMMAND_APP, "",
-                            DataPos.DISPLAY_COMMAND_KEY, _("Not bound"),
-                            DataPos.DISPLAY_COMMAND_PIE, "",
-                            DataPos.DISPLAY_COMMAND_URI, "",
-                             DataPos.REAL_COMMAND_GROUP, group.get_type().name(),
-                               DataPos.REAL_COMMAND_PIE, "",
-                               DataPos.REAL_COMMAND_KEY, "");
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a drag which started on this Widget was successfull.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_dnd_source(Gdk.DragContext context, Gtk.SelectionData selection_data, uint info, uint time_) {
+        if (this.drag_start != null) {
+            string id = "";
+            this.data.get(this.drag_start, DataPos.ID, out id);
+            selection_data.set_uris({"file://" + Paths.launchers + "/" + id + ".desktop"});
         }
     }
     
-    // loads a given slice
-    private void load_action(Gtk.TreeIter parent, Action action) {
-        Gtk.TreeIter child;
-        this.data.append(out child, parent);
-        this.write_action(action, child);
-    }
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a drag operation is started on this Widget.
+    /////////////////////////////////////////////////////////////////////
     
-    // applies all changes done to the given pie
-    private void update_pie(Gtk.TreeIter slice_or_pie) {
-        // get pie iter
-        var path = this.data.get_path(slice_or_pie);
-        if (path != null) {
-            var pie = slice_or_pie;
-            if (path.get_depth() == 2)
-                this.data.iter_parent(out pie, slice_or_pie);
+    private void on_start_drag(Gdk.DragContext ctx) {
+        if (this.get_selection().get_selected(null, out this.drag_start)) {
+            string icon_name = "";
+            this.data.get(this.drag_start, DataPos.ICON_NAME, out icon_name);
             
-            // get information on pie
-            string id;
-            string icon;
-            string name;
-            string hotkey;
-            
-            this.data.get(pie, DataPos.ICON, out icon);
-            this.data.get(pie, DataPos.NAME, out name);
-            this.data.get(pie, DataPos.ACTION_TYPE, out id);
-            this.data.get(pie, DataPos.REAL_COMMAND_KEY, out hotkey);
-            
-            // remove pie
-            PieManager.remove_pie(id);
-             
-            this.pies.foreach((model, path, iter) => {
-                string pies_id;
-                this.pies.get(iter, PiePos.ID, out pies_id);
-                
-                if (id == pies_id) {
-                    this.pies.set(iter, PiePos.NAME, name);
-                    return true;
-                }
-                
-                return false;
-            });
-                
-            // create new pie
-            var new_pie = PieManager.create_persistent_pie(name, icon, new Trigger.from_string(hotkey), id);
-            
-            // add actions accordingly
-            if (this.data.iter_has_child(pie)) {
-                Gtk.TreeIter child;
-                this.data.iter_children(out child, pie);
-                
-                do {
-                    // get slice information
-                    string slice_type;
-                    string slice_icon;
-                    string slice_name;
-                    bool is_quick_action;
-                    
-                    this.data.get(child, DataPos.ICON, out slice_icon);
-                    this.data.get(child, DataPos.NAME, out slice_name);
-                    this.data.get(child, DataPos.ACTION_TYPE, out slice_type);
-                    this.data.get(child, DataPos.IS_QUICKACTION, out is_quick_action);
-                    
-                    if (slice_type == typeof(AppAction).name()) {
-                        string slice_command;
-                        this.data.get(child, DataPos.DISPLAY_COMMAND_APP, out slice_command);
-                        var group = new ActionGroup(new_pie.id);
-                        group.add_action(new AppAction(slice_name, slice_icon, slice_command, is_quick_action));
-                        new_pie.add_group(group);
-                    } else if (slice_type == typeof(KeyAction).name()) {
-                        string slice_command;
-                        this.data.get(child, DataPos.REAL_COMMAND_KEY, out slice_command);
-                        var group = new ActionGroup(new_pie.id);
-                        group.add_action(new KeyAction(slice_name, slice_icon, slice_command, is_quick_action));
-                        new_pie.add_group(group);
-                    } else if (slice_type == typeof(PieAction).name()) {
-                        string slice_command;
-                        this.data.get(child, DataPos.REAL_COMMAND_PIE, out slice_command);
-                        var group = new ActionGroup(new_pie.id);
-                        group.add_action(new PieAction(slice_command, is_quick_action));
-                        new_pie.add_group(group);
-                    } else if (slice_type == typeof(UriAction).name()) {
-                        string slice_command;
-                        this.data.get(child, DataPos.DISPLAY_COMMAND_URI, out slice_command);
-                        var group = new ActionGroup(new_pie.id);
-                        group.add_action(new UriAction(slice_name, slice_icon, slice_command, is_quick_action));
-                        new_pie.add_group(group);
-                    } else if (slice_type == typeof(ActionGroup).name()) {
-                        string slice_command;
-                        this.data.get(child, DataPos.REAL_COMMAND_GROUP, out slice_command);
-                        
-                        var group = GLib.Object.new(GLib.Type.from_name(slice_command), "parent_id", new_pie.id);
-                        new_pie.add_group(group as ActionGroup);
-                    } 
-                    
-                } while (this.data.iter_next(ref child));
-            }
-        }         
+            var icon = new Icon(icon_name, 48);
+            var pixbuf = icon.to_pixbuf();
+            Gtk.drag_set_icon_pixbuf(ctx, pixbuf, icon.size()/2, icon.size()/2);
+        }
     }
     
-    // creates new action when the list receives a drag'n'drop event
-    private void on_dnd_received(Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint info, uint time_) {
-        string[] uris = selection_data.get_uris();
-        
+    /////////////////////////////////////////////////////////////////////
+    /// Called when something is dragged over this Widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool on_drag_move(Gdk.DragContext context, int x, int y, uint time) {
+    
+        Gtk.TreeViewDropPosition position;
         Gtk.TreePath path;
-        Gtk.TreeViewDropPosition pos;
         
-        // check for valid position
-        if (!this.get_dest_row_at_pos(x, y, out path, out pos)
-            || (path.to_string() == "0" && pos == Gtk.TreeViewDropPosition.BEFORE)) {
-            
-            warning("Failed to insert Slice: Invalid location!");
-            return;
-        }
-        
-        // get position to insert (when child: after, when parent: as first child)
-        Gtk.TreeIter parent;
-        int insert_pos = 0;
-        if (path.get_depth() == 1) {
-            if (pos == Gtk.TreeViewDropPosition.BEFORE) {
-                path.prev();
-                this.data.get_iter(out parent, path);
-                insert_pos = this.data.iter_n_children(parent);
-            } else {
-                this.data.get_iter(out parent, path);
-            }
-        } else {
-            if (pos == Gtk.TreeViewDropPosition.BEFORE) {
-                insert_pos = path.get_indices()[1];
-            } else {
-                insert_pos = path.get_indices()[1]+1;
-            }
-            
-            path.up();
-            this.data.get_iter(out parent, path);
-        }
+        if (!this.get_dest_row_at_pos(x, y, out path, out position))
+            return false;
         
-        foreach (var uri in uris) {
-            Gtk.TreeIter new_child;
-            this.data.insert(out new_child, parent, insert_pos);
-            this.write_action(ActionRegistry.new_for_uri(uri), new_child);
-        }
+        if (position == Gtk.TreeViewDropPosition.BEFORE)
+            this.set_drag_dest_row(path, Gtk.TreeViewDropPosition.INTO_OR_BEFORE);
+        else if (position == Gtk.TreeViewDropPosition.AFTER)
+            this.set_drag_dest_row(path, Gtk.TreeViewDropPosition.INTO_OR_AFTER);
+
+        Gdk.drag_status(context, context.get_suggested_action(), time);
         
-        this.update_pie(parent);
-    }
-    
-    private void on_dnd_source(Gdk.DragContext context, Gtk.SelectionData selection_data, uint info, uint time_) {
-        Gtk.TreeIter selected;
-        if (this.get_selection().get_selected(null, out selected)) {
-            string id = "";
-            this.data.get(selected, DataPos.ACTION_TYPE, out id);
-            selection_data.set_uris({"file://" + Paths.launchers + "/" + id + ".desktop"});
-        }
-    }
-    
-    private Gdk.Pixbuf load_icon(string name, int size) {
-        Gdk.Pixbuf pixbuf = null;
+        // avoid too frequent selection...
+        this.last_hover = time;
         
-        try {
-            if (name.contains("/"))
-                pixbuf = new Gdk.Pixbuf.from_file_at_size(name, size, size);
-            else
-                pixbuf = new Gdk.Pixbuf.from_file_at_size(Icon.get_icon_file(name, size), size, size);
-        } catch (GLib.Error e) {
-            warning(e.message);
-        }
+        GLib.Timeout.add(150, () => {
+            if (this.last_hover == time)
+                this.get_selection().select_path(path); 
+            return false;
+        });
         
-        return pixbuf;
+        return true;
     }
 }
 
diff --git a/src/gui/piePreview.vala b/src/gui/piePreview.vala
new file mode 100644
index 0000000..5745fcb
--- /dev/null
+++ b/src/gui/piePreview.vala
@@ -0,0 +1,369 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A custom widget displaying the preview of a Pie. It can be used to
+/// configure the displayed Pie in various aspects.
+/////////////////////////////////////////////////////////////////////////
+
+class PiePreview : Gtk.DrawingArea {
+
+    /////////////////////////////////////////////////////////////////////
+    /// These get called when the last Slice is removed and when the
+    /// first Slice is added respectively.
+    /////////////////////////////////////////////////////////////////////
+
+    public signal void on_last_slice_removed();
+    public signal void on_first_slice_added();
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The internally used renderer to draw the Pie.
+    /////////////////////////////////////////////////////////////////////
+
+    private PiePreviewRenderer renderer = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The window which pops up, when a Slice is added or edited.
+    /////////////////////////////////////////////////////////////////////
+    
+    private NewSliceWindow? new_slice_window = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// A timer used for calculating the frame time.
+    /////////////////////////////////////////////////////////////////////
+    
+    private GLib.Timer timer;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// True, when it is possible to drag a slice from this widget.
+    /// False, when the user currently hovers over the add sign.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool drag_enabled = false;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The ID of the currently displayed Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    private string current_id = "";
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The position from where a Slice-drag started.
+    /////////////////////////////////////////////////////////////////////
+    
+    private int drag_start_index = -1;
+
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, creates the widget.
+    /////////////////////////////////////////////////////////////////////
+
+    public PiePreview() {
+        this.renderer = new PiePreviewRenderer();
+    
+        #if HAVE_GTK_3
+            this.draw.connect(this.on_draw);
+        #else
+            this.expose_event.connect(this.on_draw);
+        #endif
+    
+        this.timer = new GLib.Timer();
+        this.set_events(Gdk.EventMask.POINTER_MOTION_MASK 
+                      | Gdk.EventMask.LEAVE_NOTIFY_MASK
+                      | Gdk.EventMask.ENTER_NOTIFY_MASK);
+        
+        // setup drag and drop
+        this.enable_drag_source();
+        
+        Gtk.TargetEntry uri_dest = {"text/uri-list", 0, 0};
+        Gtk.TargetEntry slice_dest = {"text/plain", Gtk.TargetFlags.SAME_WIDGET, 0};
+        Gtk.TargetEntry[] destinations = { uri_dest, slice_dest };
+        Gtk.drag_dest_set(this, Gtk.DestDefaults.ALL, destinations, Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK);
+        
+        this.drag_begin.connect(this.on_start_drag);
+        this.drag_end.connect(this.on_end_drag);
+        this.drag_data_received.connect(this.on_dnd_received);
+        
+        // connect mouse events
+        this.drag_motion.connect(this.on_drag_move);
+        this.leave_notify_event.connect(this.on_mouse_leave);
+        this.enter_notify_event.connect(this.on_mouse_enter);  
+        this.motion_notify_event.connect_after(this.on_mouse_move);
+        this.button_release_event.connect_after(this.on_button_release);
+        this.button_press_event.connect_after(this.on_button_press);
+        
+        this.new_slice_window = new NewSliceWindow();
+        this.new_slice_window.on_select.connect((new_action, as_new_slice, at_position) => {
+            var pie = PieManager.all_pies[this.current_id];
+            
+            if (new_action.has_quickaction())
+                renderer.disable_quickactions();
+            
+            if (as_new_slice) {
+                pie.add_group(new_action, at_position+1);
+                this.renderer.add_group(new_action, at_position+1);
+                
+                if (this.renderer.slice_count() == 1)
+                    this.on_first_slice_added();
+            } else {
+                pie.update_group(new_action, at_position);
+                this.renderer.update_group(new_action, at_position);
+            }
+        });
+        
+        this.renderer.on_edit_slice.connect((pos) => {
+            this.new_slice_window.reload();
+            
+            this.new_slice_window.set_parent(this.get_toplevel() as Gtk.Window);
+            this.new_slice_window.show();
+            
+            var pie = PieManager.all_pies[this.current_id];
+            this.new_slice_window.set_action(pie.action_groups[pos], pos);
+        });
+        
+        this.renderer.on_add_slice.connect((pos) => {
+            this.new_slice_window.reload();
+            
+            this.new_slice_window.set_parent(this.get_toplevel() as Gtk.Window);
+            this.new_slice_window.show();
+            
+            this.new_slice_window.set_default(this.current_id, pos);
+        });
+        
+        this.renderer.on_remove_slice.connect((pos) => {
+            
+            var dialog = new Gtk.MessageDialog(this.get_toplevel() as Gtk.Window, Gtk.DialogFlags.MODAL,
+                         Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO,
+                         _("Do you really want to delete this Slice?"));
+                                                     
+            dialog.response.connect((response) => {
+                if (response == Gtk.ResponseType.YES) {
+                    var pie = PieManager.all_pies[this.current_id];
+            
+                    pie.remove_group(pos);
+                    this.renderer.remove_group(pos);
+                    
+                    if (this.renderer.slice_count() == 0)
+                        this.on_last_slice_removed();
+                }
+            });
+            
+            dialog.run();
+            dialog.destroy();
+        });
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Sets the currently displayed Pie to the Pie with the given ID.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_pie(string id) {
+        this.current_id = id;
+        this.modify_bg(Gtk.StateType.NORMAL, Gtk.rc_get_style(this).light[0]);
+        this.renderer.load_pie(PieManager.all_pies[id]);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Begins the draw loop. It automatically ends, when the containing
+    /// window becomes invisible.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void draw_loop() {
+        this.timer.start();
+        this.queue_draw();
+        
+        GLib.Timeout.add((uint)(1000.0/Config.global.refresh_rate), () => {
+            this.queue_draw();
+            return this.get_toplevel().visible;
+        });
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    /// Called every frame.
+    /////////////////////////////////////////////////////////////////////
+    
+    #if HAVE_GTK_3
+         private bool on_draw(Cairo.Context ctx) { 
+    #else
+         private bool on_draw(Gtk.Widget da, Gdk.EventExpose event) { 
+            var ctx = Gdk.cairo_create(this.get_window());
+    #endif
+        // store the frame time
+        double frame_time = this.timer.elapsed();
+        this.timer.reset();
+        
+        Gtk.Allocation allocation;
+        this.get_allocation(out allocation);
+        ctx.translate((int)(allocation.width*0.5), (int)(allocation.height*0.5));
+        
+        this.renderer.draw(frame_time, ctx);
+        
+        return true;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse leaves the area of this widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool on_mouse_leave(Gdk.EventCrossing event) {
+        this.renderer.on_mouse_leave();
+        return true;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse enters the area of this widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool on_mouse_enter(Gdk.EventCrossing event) {
+        this.renderer.on_mouse_enter();
+        return true;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse moves in the area of this widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool on_mouse_move(Gdk.EventMotion event) {
+        this.renderer.set_dnd_mode(false);
+        Gtk.Allocation allocation;
+        this.get_allocation(out allocation);
+        this.renderer.on_mouse_move(event.x-allocation.width*0.5, event.y-allocation.height*0.5);
+        
+        if (this.renderer.get_active_slice() < 0) this.disable_drag_source();
+        else                                      this.enable_drag_source();
+        
+        return true;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a mouse button is pressed.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool on_button_press() {
+        this.renderer.on_button_press();
+        return true;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a mouse button is released.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool on_button_release() {
+        if (!this.renderer.drag_n_drop_mode) 
+            this.renderer.on_button_release();
+        return true;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse is moved over this widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool on_drag_move(Gdk.DragContext ctx, int x, int y, uint time) {
+        this.renderer.set_dnd_mode(true);
+        Gtk.Allocation allocation;
+        this.get_allocation(out allocation);
+        this.renderer.on_mouse_move(x-allocation.width*0.5, y-allocation.height*0.5);
+        return true;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user tries to drag something from this widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_start_drag(Gdk.DragContext ctx) {
+        this.drag_start_index = this.renderer.get_active_slice();
+        var icon = this.renderer.get_active_icon();
+        var pixbuf = icon.to_pixbuf();
+
+        this.renderer.hide_group(this.drag_start_index);
+        Gtk.drag_set_icon_pixbuf(ctx, pixbuf, icon.size()/2, icon.size()/2);
+        
+        this.renderer.set_dnd_mode(true);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user finishes a drag operation on this widget.
+    /// Only used for Slice-movement.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_end_drag(Gdk.DragContext context) {
+        
+        if (context.list_targets() != null) {
+        
+            int target_index = this.renderer.get_active_slice();
+            this.renderer.set_dnd_mode(false);
+
+            context.list_targets().foreach((target) => {
+                Gdk.Atom target_type = (Gdk.Atom)target;
+                if (target_type.name() == "text/plain") {
+                    var pie = PieManager.all_pies[this.current_id];
+                    pie.move_group(this.drag_start_index, target_index);
+                    this.renderer.show_hidden_group_at(target_index);
+                }
+            });
+        }  
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user finishes a drag operation on this widget.
+    /// Only used for external drags.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_dnd_received(Gdk.DragContext context, int x, int y, 
+                                 Gtk.SelectionData selection_data, uint info, uint time_) {
+                                 
+        var pie = PieManager.all_pies[this.current_id];
+        int position = this.renderer.get_active_slice();
+        this.renderer.set_dnd_mode(false);
+        
+        foreach (var uri in selection_data.get_uris()) {
+            pie.add_action(ActionRegistry.new_for_uri(uri), position);
+            this.renderer.add_group(pie.action_groups[position], position);
+            
+            if (this.renderer.slices.size == 1)
+                this.on_first_slice_added();
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Enables this widget to be a source for drag operations.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void enable_drag_source() {
+        if (!this.drag_enabled) {
+            this.drag_enabled = true;
+            Gtk.TargetEntry slice_source = {"text/plain", Gtk.TargetFlags.SAME_WIDGET | Gtk.TargetFlags.SAME_APP, 0};
+            Gtk.TargetEntry[] sources = { slice_source };
+            Gtk.drag_source_set(this, Gdk.ModifierType.BUTTON1_MASK, sources, Gdk.DragAction.MOVE);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Disables this widget to be a source for drag operations.
+    /////////////////////////////////////////////////////////////////////   
+       
+    private void disable_drag_source() {
+        if (this.drag_enabled) {
+            this.drag_enabled = false;
+            Gtk.drag_source_unset(this);
+        }
+    }
+   
+}
+
+}
diff --git a/src/gui/piePreviewAddSign.vala b/src/gui/piePreviewAddSign.vala
new file mode 100644
index 0000000..ee8c14b
--- /dev/null
+++ b/src/gui/piePreviewAddSign.vala
@@ -0,0 +1,220 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using GLib.Math;
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A liitle plus-sign displayed on the preview widget to indicate where
+/// the user may add a new Slice.
+/////////////////////////////////////////////////////////////////////////
+
+public class PiePreviewAddSign : GLib.Object {
+
+    /////////////////////////////////////////////////////////////////////
+    /// Gets emitted, when the users clicks on this object.
+    /////////////////////////////////////////////////////////////////////
+
+    public signal void on_clicked(int position);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The image used to display this oject.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Image icon { get; private set; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// True, when the add sign is currently visible.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool visible { get; private set; default=false; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The position of the sign in its parent Pie. May be 2.5 for
+    /// example.
+    /////////////////////////////////////////////////////////////////////
+    
+    private double position = 0;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The parent renderer.
+    /////////////////////////////////////////////////////////////////////
+
+    private unowned PiePreviewRenderer parent;  
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some values used for displaying this sign.
+    /////////////////////////////////////////////////////////////////////
+    
+    private double time = 0;
+    private double max_size = 0; 
+    private double angle = 0; 
+    private AnimatedValue size; 
+    private AnimatedValue alpha; 
+    private AnimatedValue activity; 
+    private AnimatedValue clicked; 
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, sets everything up.
+    /////////////////////////////////////////////////////////////////////
+
+    public PiePreviewAddSign(PiePreviewRenderer parent) {
+        this.parent = parent;
+        
+        this.size = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 0, 0, 0, 2.0);
+        this.alpha = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 0, 0, 0, 0.0);
+        this.activity = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, -3, -3, 0, 0.0);
+        this.clicked = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 1, 1, 0, 0.0);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Loads the desired icon for this sign.
+    /////////////////////////////////////////////////////////////////////
+
+    public void load() {
+        this.icon = new Icon("add", 36);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Updates the position where this object should be displayed.
+    /////////////////////////////////////////////////////////////////////
+
+    public void set_position(int position) {
+        double new_position = position;
+        
+        if (!this.parent.drag_n_drop_mode)
+            new_position += 0.5;
+
+        this.position = new_position;
+        this.angle = 2.0 * PI * new_position/parent.slice_count();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes this object visible.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void show() {
+        this.visible = true;
+        this.size.reset_target(this.max_size, 0.3); 
+        this.alpha.reset_target(1.0, 0.3);   
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes this object invisible.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void hide() {
+        this.visible = false;
+        this.size.reset_target(0.0, 0.3); 
+        this.alpha.reset_target(0.0, 0.3);     
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Updates the size of this object. All transitions will be smooth.
+    /////////////////////////////////////////////////////////////////////
+
+    public void set_size(double size) {
+        this.max_size = size;
+        this.size.reset_target(size, 0.5);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Draws the sign to the given context.
+    /////////////////////////////////////////////////////////////////////
+
+    public void draw(double frame_time, Cairo.Context ctx) {
+
+        this.time += frame_time;
+        
+        this.size.update(frame_time);
+        this.alpha.update(frame_time);
+        this.activity.update(frame_time);
+        this.clicked.update(frame_time);
+        
+        if (this.parent.slice_count() == 0) {
+            ctx.save();
+            
+            double scale = this.clicked.val 
+                         + GLib.Math.sin(this.time*10)*0.02*this.alpha.val
+                         + this.alpha.val*0.08 - 0.1;
+            ctx.scale(scale, scale);
+        
+            // paint the image
+            icon.paint_on(ctx);
+                
+            ctx.restore();
+            
+        } else if (this.alpha.val*this.activity.val > 0) {
+            ctx.save();
+            
+            // distance from the center
+            double radius = 120;
+            
+            // transform the context
+            ctx.translate(cos(this.angle)*radius, sin(this.angle)*radius);
+            double scale = this.size.val*this.clicked.val 
+                         + this.activity.val*0.07
+                         + GLib.Math.sin(this.time*10)*0.03*this.activity.val
+                         - 0.1;
+            ctx.scale(scale, scale);
+        
+            // paint the image
+            icon.paint_on(ctx, this.alpha.val*this.activity.val);
+                
+            ctx.restore();
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse moves to another position.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_mouse_move(double angle) {
+        double direction = 2.0 * PI * position/parent.slice_count();
+        double diff = fabs(angle-direction);
+        
+        if (diff > PI)
+	        diff = 2 * PI - diff;
+	    
+	    if (diff < 0.5*PI/parent.slice_count()) this.activity.reset_target(1.0, 1.0);
+        else                                    this.activity.reset_target(-3.0, 1.5);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a button of the mouse is pressed.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_button_press(double x, double y) {
+        if (this.activity.end == 1.0) {
+            this.clicked.reset_target(0.9, 0.1);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a button of the mouse is released.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_button_release(double x, double y) {
+        if (this.clicked.end == 0.9) {
+            this.clicked.reset_target(1.0, 0.1);
+            this.on_clicked((int)this.position);
+        }
+    }
+}
+
+}
diff --git a/src/gui/piePreviewCenter.vala b/src/gui/piePreviewCenter.vala
new file mode 100644
index 0000000..21bbd78
--- /dev/null
+++ b/src/gui/piePreviewCenter.vala
@@ -0,0 +1,108 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using GLib.Math;
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// 
+/////////////////////////////////////////////////////////////////////////
+
+public class PiePreviewCenter : GLib.Object {
+    
+    /////////////////////////////////////////////////////////////////////
+    /// THe Images displayed. When the displayed text changes the
+    /// currently displayed text becomes the old_text. So it's possible
+    /// to create a smooth transitions.
+    /////////////////////////////////////////////////////////////////////
+    
+    private RenderedText text = null;
+    private RenderedText old_text = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Stores the currently displayed text in order to avoid frequent
+    /// and useless updates.
+    /////////////////////////////////////////////////////////////////////
+    
+    private string current_text = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// An AnimatedValue for smooth transitions.
+    /////////////////////////////////////////////////////////////////////
+    
+    private AnimatedValue blend; 
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The parent renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    private unowned PiePreviewRenderer parent;  
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, sets everything up.
+    /////////////////////////////////////////////////////////////////////
+    
+    public PiePreviewCenter(PiePreviewRenderer parent) {
+        this.parent = parent;
+        this.blend = new AnimatedValue.linear(0, 0, 0);
+        
+        this.text = new RenderedText("", 1, 1, "", new Color(), 1.0);
+        this.old_text = text;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Updates the currently displayed text. It will be smoothly
+    /// blended and may contain pango markup. 
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_text(string text) {
+        if (text != this.current_text) {
+            
+            var style = new Gtk.Style();
+            
+            this.old_text = this.text;
+            this.text = new RenderedText.with_markup(text, 180, 180, style.font_desc.get_family()+" 10", 
+                                                     new Color.from_gdk(style.fg[0]), 1.0);
+            this.current_text = text;
+            
+            this.blend.reset_target(0.0, 0.0);
+            this.blend.reset_target(1.0, 0.1);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Draws the center to the given context.
+    /////////////////////////////////////////////////////////////////////
+
+    public void draw(double frame_time, Cairo.Context ctx) {
+
+        this.blend.update(frame_time);
+        
+        ctx.save();
+        
+        if (this.parent.slice_count() == 0) 
+            ctx.translate(0, 40);
+        
+        this.old_text.paint_on(ctx, 1-this.blend.val);
+        this.text.paint_on(ctx, this.blend.val);
+            
+        ctx.restore();
+    }
+}
+
+}
diff --git a/src/gui/piePreviewDeleteSign.vala b/src/gui/piePreviewDeleteSign.vala
new file mode 100644
index 0000000..2ff3321
--- /dev/null
+++ b/src/gui/piePreviewDeleteSign.vala
@@ -0,0 +1,195 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using GLib.Math;
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// The delete sign, displayed in the upper right corner of each
+/// Slice.
+/////////////////////////////////////////////////////////////////////////
+
+public class PiePreviewDeleteSign : GLib.Object {
+
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user clicked on this sign.
+    /////////////////////////////////////////////////////////////////////
+
+    public signal void on_clicked();
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The image used to display this oject.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Image icon { get; private set; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some constants determining the look and behaviour of this Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    private const int radius = 18;
+    private const double globale_scale = 0.8;
+    private const double click_cancel_treshold = 5;
+
+    /////////////////////////////////////////////////////////////////////
+    /// True, when the add sign is currently visible.
+    /////////////////////////////////////////////////////////////////////
+
+    private bool visible = false;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some AnimatedValues for smooth transitions.
+    /////////////////////////////////////////////////////////////////////
+    
+    private AnimatedValue size;
+    private AnimatedValue alpha; 
+    private AnimatedValue activity; 
+    private AnimatedValue clicked; 
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Storing the position where a mouse click was executed. Useful for
+    /// canceling the click when the mouse moves some pixels.
+    /////////////////////////////////////////////////////////////////////
+    
+    private double clicked_x = 0.0;
+    private double clicked_y = 0.0;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, sets everything up.
+    /////////////////////////////////////////////////////////////////////
+
+    public PiePreviewDeleteSign() {
+        this.size = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 0, 0, 0, 2.0);
+        this.alpha = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 0, 0, 0, 0.0);
+        this.activity = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, -3, -3, 0, 0.0);
+        this.clicked = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 1, 1, 0, 0.0);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Loads an Action. All members are initialized accordingly.
+    /////////////////////////////////////////////////////////////////////
+
+    public void load() {
+        this.icon = new Icon("stock_delete", radius*2);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes this object visible.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void show() {
+        if (!this.visible) {
+            this.visible = true;
+            this.alpha.reset_target(1.0, 0.3);   
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes this object invisible.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void hide() {
+        if (this.visible) {
+            this.visible = false;
+            this.alpha.reset_target(0.0, 0.3);     
+        }
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    /// Updates the size of this object. All transitions will be smooth.
+    /////////////////////////////////////////////////////////////////////
+
+    public void set_size(double size) {
+        this.size.reset_target(size, 0.2);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Draws the sign to the given context.
+    /////////////////////////////////////////////////////////////////////
+
+    public void draw(double frame_time, Cairo.Context ctx) {
+        this.size.update(frame_time);
+        this.alpha.update(frame_time);
+        this.activity.update(frame_time);
+        this.clicked.update(frame_time);
+        
+        if (this.alpha.val > 0) {
+            ctx.save();
+            
+            // transform the context
+            double scale = (this.size.val*this.clicked.val 
+                         + this.activity.val*0.2 - 0.2)*globale_scale;
+            ctx.scale(scale, scale);
+        
+            // paint the image
+            icon.paint_on(ctx, this.alpha.val);
+                
+            ctx.restore();
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse moves to another position.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool on_mouse_move(double x, double y) {
+        if (this.clicked.end == 0.9) {
+            double dist = GLib.Math.pow(x-this.clicked_x, 2) + GLib.Math.pow(y-this.clicked_y, 2);
+            if (dist > this.click_cancel_treshold*this.click_cancel_treshold)
+                this.clicked.reset_target(1.0, 0.1);
+        }
+    
+	    if (GLib.Math.fabs(x) <= radius*globale_scale && GLib.Math.fabs(y) <= radius*globale_scale) {
+	        this.activity.reset_target(1.0, 0.2);
+	        return true;
+        } 
+        
+        this.activity.reset_target(0.0, 0.2);
+        return false;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a button of the mouse is pressed.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool on_button_press(double x, double y) {
+        if (this.activity.end == 1.0) {
+            this.clicked.reset_target(0.9, 0.1);
+            this.clicked_x = x;
+            this.clicked_y = y;
+            return true;
+        }
+        return false;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a button of the mouse is released.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool on_button_release(double x, double y) {
+        if (this.clicked.end == 0.9) {
+            this.clicked.reset_target(1.0, 0.1);
+            this.on_clicked();
+            
+            return true;
+        }
+        return false;
+    }
+}
+
+}
diff --git a/src/gui/piePreviewRenderer.vala b/src/gui/piePreviewRenderer.vala
new file mode 100644
index 0000000..1cf83ff
--- /dev/null
+++ b/src/gui/piePreviewRenderer.vala
@@ -0,0 +1,436 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using GLib.Math;
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A complex class which is able to draw the preview of a Pie. It can
+/// manipulate the displayed Pie as well.
+/////////////////////////////////////////////////////////////////////////
+
+public class PiePreviewRenderer : GLib.Object {
+    
+    /////////////////////////////////////////////////////////////////////
+    /// These signals get emitted when a slice is added, removed or
+    /// manipulated.
+    /////////////////////////////////////////////////////////////////////
+    
+    public signal void on_add_slice(int position);
+    public signal void on_remove_slice(int position);
+    public signal void on_edit_slice(int position);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// True, when there is currently a drag going on.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool drag_n_drop_mode { get; private set; default=false; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// A list containing all SliceRenderers of this Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Gee.ArrayList<PiePreviewSliceRenderer?> slices;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// When a Slice is moved within a Pie it is temporarily removed.
+    /// If so, it is stored in this member.
+    /////////////////////////////////////////////////////////////////////
+    
+    public PiePreviewSliceRenderer hidden_group { get; private set; default=null; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The add sign which indicates that a new Slice could be added.
+    /////////////////////////////////////////////////////////////////////
+    
+    private PiePreviewAddSign add_sign = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The object which renders the name of the currently selected Slice
+    /// in the middle.
+    /////////////////////////////////////////////////////////////////////
+    
+    private PiePreviewCenter center_renderer = null;
+    private enum CenterDisplay { NONE, ACTIVE_SLICE, DROP, ADD, DELETE }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some members storing some inter-frame-information.
+    /////////////////////////////////////////////////////////////////////
+
+    private int active_slice = -1;
+    private double angle = 0.0;    
+    private double mouse_x = 0.0;
+    private double mouse_y = 0.0;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, initializes members.
+    /////////////////////////////////////////////////////////////////////
+    
+    public PiePreviewRenderer() {
+        this.slices = new Gee.ArrayList<PiePreviewSliceRenderer?>(); 
+        this.center_renderer = new PiePreviewCenter(this);
+        this.add_sign = new PiePreviewAddSign(this);
+        this.add_sign.load();
+        
+        this.add_sign.on_clicked.connect((pos) => {
+            this.on_add_slice(pos);
+        });
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Loads an Pie. All members are initialized accordingly.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void load_pie(Pie pie) {
+        this.slices.clear();
+    
+        foreach (var group in pie.action_groups) {
+            var renderer = new PiePreviewSliceRenderer(this);
+            renderer.load(group);
+            
+            this.add_slice_renderer(renderer);
+            this.connect_siganls(renderer);
+        }
+        
+        this.active_slice = -1;
+        this.update_sizes();
+        this.update_positions(false);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Enables or disables the drag n dropn mode.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_dnd_mode(bool dnd) {
+        if (this.drag_n_drop_mode != dnd) {
+            this.drag_n_drop_mode = dnd;
+            this.update_positions();
+            this.update_sizes();
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Returns the number of Slices.
+    /////////////////////////////////////////////////////////////////////
+    
+    public int slice_count() {
+        if (this.drag_n_drop_mode && !(this.slices.size == 0)) 
+            return slices.size+1;
+        
+        return slices.size;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Returns the index of the currently hovered Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    public int get_active_slice() {
+        if (this.slices.size == 0)
+            return 0;
+    
+        if (this.drag_n_drop_mode)
+            return (int)(this.angle/(2*PI)*this.slice_count() + 0.5) % this.slice_count();
+            
+        return this.active_slice;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Returns the Icon of the currently hovered Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Icon get_active_icon() {
+        if (this.active_slice >= 0 && this.active_slice < this.slices.size)
+            return this.slices[this.active_slice].icon;
+        else
+            return new Icon("", 24);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Draws the entire Pie to the given context.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void draw(double frame_time, Cairo.Context ctx) {
+        this.add_sign.draw(frame_time, ctx);
+        this.center_renderer.draw(frame_time, ctx);
+        
+        foreach (var slice in this.slices)
+            slice.draw(frame_time, ctx);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse leaves the drawing area of this renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_mouse_leave() {
+        this.add_sign.hide();
+        this.update_positions();
+        this.update_center(CenterDisplay.NONE);
+        
+        foreach (var slice in this.slices)
+            slice.on_mouse_leave();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse enters the drawing area of this renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_mouse_enter() {
+        this.add_sign.show();
+        this.update_positions();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse moves in the drawing area of this renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_mouse_move(double x, double y) {
+        this.mouse_x = x;
+        this.mouse_y = y;
+        
+        this.angle = acos(x/sqrt(x*x + y*y));
+        if (y < 0) this.angle = 2*PI - this.angle;
+    
+        if (!this.drag_n_drop_mode)
+            this.active_slice = -1;
+        
+        bool delete_hovered = false;
+        
+        for (int i=0; i<this.slices.size; ++i)
+            if (slices[i].on_mouse_move(this.angle, x, y) && !this.drag_n_drop_mode) {
+                this.active_slice = i;
+                delete_hovered = slices[i].delete_hovered;
+            }
+        
+        if (this.drag_n_drop_mode)      this.update_center(CenterDisplay.DROP);
+        else if (this.active_slice < 0) this.update_center(CenterDisplay.ADD);
+        else if (delete_hovered)        this.update_center(CenterDisplay.DELETE);
+        else                            this.update_center(CenterDisplay.ACTIVE_SLICE);
+            
+        this.add_sign.on_mouse_move(this.angle);
+        
+        this.update_positions();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a mouse button is pressed over this renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_button_press() {
+        for (int i=0; i<this.slices.size; ++i)
+            this.slices[i].on_button_press(this.mouse_x, this.mouse_y);
+        this.add_sign.on_button_press(this.mouse_x, this.mouse_y);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a mouse button is released over this renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_button_release() {
+        for (int i=0; i<this.slices.size; ++i)
+            this.slices[i].on_button_release(this.mouse_x, this.mouse_y);
+        this.add_sign.on_button_release(this.mouse_x, this.mouse_y);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Adds a new Slice to the renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void add_group(ActionGroup group, int at_position = -1) {
+        var renderer = new PiePreviewSliceRenderer(this);
+        renderer.load(group);
+        this.add_slice_renderer(renderer, at_position);
+        this.connect_siganls(renderer);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Removes a Slice from the renderer.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void remove_group(int index) {
+        if (this.slices.size > index) {
+            this.slices.remove_at(index);
+            this.update_positions();
+            this.update_sizes();
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Hides the Slice at the given position temporarily.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void hide_group(int index) {
+        if (this.slices.size > index) {
+            this.hidden_group = this.slices[index];
+            this.remove_group(index);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Re-shows a Slice which has been hidden before.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void show_hidden_group_at(int index) {
+        if (this.slices.size >= index && this.hidden_group != null) {
+            this.hidden_group.set_position(index, false);
+            this.add_slice_renderer(this.hidden_group, index);
+            this.hidden_group = null;
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Updates a Slice at the given position.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void update_group(ActionGroup group, int index) {
+        if (this.slices.size > index) {
+            var renderer = new PiePreviewSliceRenderer(this);
+            this.slices.set(index, renderer);
+            renderer.load(group);
+            
+            this.connect_siganls(renderer);
+            
+            this.update_positions(false);
+            this.update_sizes();
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Disables all quickactions of this pie preview.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void disable_quickactions() {
+        foreach (var slice in this.slices)
+            slice.disable_quickactions();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Helper method which adds a new Slice to the given position.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void add_slice_renderer(PiePreviewSliceRenderer renderer, int at_position = -1) {
+        if (at_position < 0 || at_position >= this.slices.size)
+            this.slices.add(renderer);
+        else
+            this.slices.insert(at_position, renderer);
+        
+        this.update_positions(false);
+        this.update_sizes();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Helper method which connects all neccessary signals of a newly
+    /// added Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void connect_siganls(PiePreviewSliceRenderer renderer) {
+        renderer.on_clicked.connect((pos) => {
+            this.on_edit_slice(pos);
+        });
+        
+        renderer.on_remove.connect((pos) => {
+            this.on_remove_slice(pos);
+        });
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Moves all slices to their positions. This may happen smoothly if
+    /// desired.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void update_positions(bool smoothly = true) {
+        if (this.slices.size > 0) {
+            if (this.add_sign.visible) {
+                int add_position = 0;
+                add_position = (int)(this.angle/(2*PI)*this.slice_count()) % this.slice_count();
+                this.add_sign.set_position(add_position);
+                
+                for (int i=0; i<this.slices.size; ++i) {
+                    this.slices[i].set_position(i, smoothly);
+                }
+            
+            } else if (this.drag_n_drop_mode) {
+                int add_position = 0;
+                add_position = (int)(this.angle/(2*PI)*this.slice_count() + 0.5) % this.slice_count();
+
+                for (int i=0; i<this.slices.size; ++i) {
+                    this.slices[i].set_position(i >= add_position ? i+1 : i, smoothly);
+                }
+                
+                this.update_center(CenterDisplay.DROP);
+                
+            } else {
+                for (int i=0; i<this.slices.size; ++i) {
+                    this.slices[i].set_position(i, smoothly);
+                }
+                
+                if (this.active_slice < 0)  this.update_center(CenterDisplay.NONE);
+                else                        this.update_center(CenterDisplay.ACTIVE_SLICE);
+            }
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Resizes all slices to their new sizes. This may happen smoothly 
+    /// if desired.
+    /////////////////////////////////////////////////////////////////////
+        
+    private void update_sizes() {
+        double size = 1.0;
+        if (this.slice_count() > 20)     size = 0.5;
+        else if (this.slice_count() > 8) size = 1.0 - (double)(this.slice_count() - 8)/24.0;
+        
+        this.add_sign.set_size(size);
+        
+        for (int i=0; i<this.slices.size; ++i) 
+            this.slices[i].set_size(size);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Displays a new text in the middle of the preview.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void update_center(CenterDisplay display) {
+        switch (display) {
+            case CenterDisplay.ACTIVE_SLICE:
+                if (this.active_slice >= 0 && this.active_slice < this.slices.size)
+                    this.center_renderer.set_text("<b>" + slices[this.active_slice].name + "</b>\n<small>" 
+                                            + _("Click to edit") + "\n" + _("Drag to move") + "</small>");
+                break;
+            case CenterDisplay.ADD:
+                this.center_renderer.set_text("<small>" + _("Click to add a new Slice") + "</small>");
+                break;
+            case CenterDisplay.DROP:
+                if (hidden_group == null)
+                    this.center_renderer.set_text("<small>" + _("Drop to add as new Slice") + "</small>");
+                else
+                    this.center_renderer.set_text("<b>" + this.hidden_group.name + "</b>\n<small>"
+                                            + _("Drop to move Slice") + "</small>");
+                break;
+            case CenterDisplay.DELETE:
+                if (this.active_slice >= 0 && this.active_slice < this.slices.size)
+                    this.center_renderer.set_text("<b>" + slices[this.active_slice].name + "</b>\n<small>" 
+                                            + _("Click to delete") + "\n" + _("Drag to move") + "</small>");
+                break;
+            default:
+                this.center_renderer.set_text("");
+                break;
+        }
+    }
+}
+
+}
diff --git a/src/gui/piePreviewSliceRenderer.vala b/src/gui/piePreviewSliceRenderer.vala
new file mode 100644
index 0000000..af39c1f
--- /dev/null
+++ b/src/gui/piePreviewSliceRenderer.vala
@@ -0,0 +1,276 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using GLib.Math;
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// Displays the preview of a Slice.
+/////////////////////////////////////////////////////////////////////////
+
+public class PiePreviewSliceRenderer : GLib.Object {
+
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user clicked on this Slice.
+    /////////////////////////////////////////////////////////////////////
+
+    public signal void on_clicked(int position);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user clicked on the delete sign.
+    /////////////////////////////////////////////////////////////////////
+    
+    public signal void on_remove(int position);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The image used to display this oject.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Icon icon { get; private set; }
+    public ActionGroup action_group { get; private set; }
+    public string name { get; private set; default=""; }
+    public bool delete_hovered { get; private set; default=false; }
+
+    /////////////////////////////////////////////////////////////////////
+    /// The parent renderer.
+    /////////////////////////////////////////////////////////////////////
+
+    private unowned PiePreviewRenderer parent;  
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The delete sign, displayed in the upper right corner of each
+    /// Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    private PiePreviewDeleteSign delete_sign = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some AnimatedValues for smooth transitions.
+    /////////////////////////////////////////////////////////////////////
+    
+    private AnimatedValue angle; 
+    private AnimatedValue size; 
+    private AnimatedValue activity; 
+    private AnimatedValue clicked; 
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some constants determining the look and behaviour of this Slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    private const double pie_radius = 126;
+    private const double radius = 24;
+    private const double delete_x = 13;
+    private const double delete_y = -13;
+    private const double click_cancel_treshold = 5;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Storing the position where a mouse click was executed. Useful for
+    /// canceling the click when the mouse moves some pixels.
+    /////////////////////////////////////////////////////////////////////
+    
+    private double clicked_x = 0.0;
+    private double clicked_y = 0.0;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The index of this slice in a pie. Clockwise assigned, starting
+    /// from the right-most slice.
+    /////////////////////////////////////////////////////////////////////
+    
+    private int position;
+
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, sets everything up.
+    /////////////////////////////////////////////////////////////////////
+
+    public PiePreviewSliceRenderer(PiePreviewRenderer parent) {
+        this.delete_sign = new PiePreviewDeleteSign();
+        this.delete_sign.load();
+        this.delete_sign.on_clicked.connect(() => {
+            this.on_remove(this.position);
+        });
+    
+        this.parent = parent;
+        this.angle = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 0, 0, 0, 0.5);
+        this.size = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 0, 0, 0, 1.0);
+        this.activity = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 0, 0, 0, 0.0);
+        this.clicked = new AnimatedValue.cubic(AnimatedValue.Direction.OUT, 1, 1, 0, 1.0);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Loads an Action. All members are initialized accordingly.
+    /////////////////////////////////////////////////////////////////////
+
+    public void load(ActionGroup group) {
+        this.action_group = group;
+        
+        // if it's a custom ActionGroup
+        if (group.get_type().depth() == 2 && group.actions.size > 0) {
+            this.icon = new Icon(group.actions[0].icon, (int)(radius*2));
+            this.name = group.actions[0].name;
+        } else {
+            this.icon = new Icon(GroupRegistry.descriptions[group.get_type().name()].icon, (int)(radius*2));
+            this.name = GroupRegistry.descriptions[group.get_type().name()].name;
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Updates the position where this object should be displayed.
+    /////////////////////////////////////////////////////////////////////
+
+    public void set_position(int position, bool smoothly = true) {
+        double direction = 2.0 * PI * position/parent.slice_count();
+        
+        if (direction != this.angle.end) {
+            this.position = position;
+            this.angle.reset_target(direction, smoothly ? 0.5 : 0.0);
+            
+            if (!smoothly)
+                this.angle.update(1.0);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Updates the size of this object. All transitions will be smooth.
+    /////////////////////////////////////////////////////////////////////
+
+    public void set_size(double size) {
+        this.size.reset_target(size, 0.5);
+        this.delete_sign.set_size(size);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Notifies that all quick actions should be disabled.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void disable_quickactions() {
+        this.action_group.disable_quickactions();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Draws the slice to the given context.
+    /////////////////////////////////////////////////////////////////////
+
+    public void draw(double frame_time, Cairo.Context ctx) {
+        this.size.update(frame_time);
+        this.angle.update(frame_time);
+        this.activity.update(frame_time);
+        this.clicked.update(frame_time);
+
+        ctx.save();
+        
+            // transform the context
+            ctx.translate(cos(this.angle.val)*pie_radius, sin(this.angle.val)*pie_radius);
+            
+            double scale = this.size.val*this.clicked.val 
+                         + this.activity.val*0.1 - 0.1;
+            ctx.save();     
+                        
+                ctx.scale(scale, scale);
+            
+                // paint the image
+                icon.paint_on(ctx);
+            
+            ctx.restore();
+            
+            ctx.translate(delete_x*this.size.val, delete_y*this.size.val);
+            this.delete_sign.draw(frame_time, ctx);
+            
+        ctx.restore();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse moves to another position.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool on_mouse_move(double angle, double x, double y) {
+        double direction = 2.0 * PI * position/parent.slice_count();
+        double diff = fabs(angle-direction);
+        
+        if (diff > PI)
+	        diff = 2 * PI - diff;
+	        
+	    bool active = diff < 0.5*PI/parent.slice_count();
+	    
+	    if (active) {
+	        this.activity.reset_target(1.0, 0.3);
+	        this.delete_sign.show();
+        } else {
+            this.activity.reset_target(0.0, 0.3);
+            this.delete_sign.hide();
+        }                                  
+        
+        if (this.clicked.end == 0.9) {
+            double dist = GLib.Math.pow(x-this.clicked_x, 2) + GLib.Math.pow(y-this.clicked_y, 2);
+            if (dist > this.click_cancel_treshold*this.click_cancel_treshold)
+                this.clicked.reset_target(1.0, 0.1);
+        }
+        
+        double own_x = cos(this.angle.val)*pie_radius;
+        double own_y = sin(this.angle.val)*pie_radius;
+        this.delete_hovered = this.delete_sign.on_mouse_move(x - own_x - delete_x*this.size.val, 
+                                                             y - own_y - delete_y*this.size.val);
+                                       
+        return active;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the mouse leaves the area of this widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_mouse_leave() {
+        this.activity.reset_target(0.0, 0.3);
+        this.delete_sign.hide();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a button of the mouse is pressed.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_button_press(double x, double y) {
+        bool delete_pressed = false;
+        if (this.activity.end == 1.0) {
+            double own_x = cos(this.angle.val)*pie_radius;
+            double own_y = sin(this.angle.val)*pie_radius;
+            delete_pressed = this.delete_sign.on_button_press(x - own_x - delete_x*this.size.val, 
+                                                              y - own_y - delete_y*this.size.val);
+        }
+    
+        if (!delete_pressed && this.activity.end == 1.0) {
+            this.clicked.reset_target(0.9, 0.1);
+            this.clicked_x = x;
+            this.clicked_y = y;
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a button of the mouse is released.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void on_button_release(double x, double y) {
+        bool deleted = false;
+        if (this.activity.end == 1.0)
+            deleted = this.delete_sign.on_button_release(x, y);
+        
+        if (!deleted && this.clicked.end == 0.9) {
+            this.clicked.reset_target(1.0, 0.1);
+            this.on_clicked(this.position);
+        }
+    }
+}
+
+}
diff --git a/src/gui/preferences.vala b/src/gui/preferences.vala
deleted file mode 100644
index 9444fac..0000000
--- a/src/gui/preferences.vala
+++ /dev/null
@@ -1,325 +0,0 @@
-/* 
-Copyright (c) 2011 by Simon Schneegans
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program 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 General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program.  If not, see <http://www.gnu.org/licenses/>. 
-*/
-
-namespace GnomePie {
-
-/////////////////////////////////////////////////////////////////////////    
-/// The Gtk settings menu of Gnome-Pie.
-/////////////////////////////////////////////////////////////////////////
-
-public class Preferences : Gtk.Window {
-    
-    /////////////////////////////////////////////////////////////////////
-    /// C'tor, constructs the whole dialog. Many thanks to the
-    /// synapse-project, since some of this code is taken from there! 
-    /////////////////////////////////////////////////////////////////////
-    
-    public Preferences() {
-        this.title = _("Gnome-Pie - Settings");
-        this.set_position(Gtk.WindowPosition.CENTER);
-        this.set_size_request(550, 550);
-        this.resizable = false;
-        this.icon_name = "gnome-pie";
-        this.delete_event.connect(hide_on_delete);
-        
-        // main container
-        var main_vbox = new Gtk.VBox(false, 12);
-            main_vbox.border_width = 12;
-            add(main_vbox);
-
-            // tab container
-            var tabs = new Gtk.Notebook();
-            
-                // general tab
-                var general_tab = new Gtk.VBox(false, 6);
-                    general_tab.border_width = 12;
-                    
-                    // behavior frame
-                    var behavior_frame = new Gtk.Frame(null);
-                        behavior_frame.set_shadow_type(Gtk.ShadowType.NONE);
-                        var behavior_frame_label = new Gtk.Label(null);
-                        behavior_frame_label.set_markup(Markup.printf_escaped ("<b>%s</b>", _("Behavior")));
-                        behavior_frame.set_label_widget(behavior_frame_label);
-
-                        var behavior_vbox = new Gtk.VBox (false, 6);
-                        var align = new Gtk.Alignment (0.5f, 0.5f, 1.0f, 1.0f);
-                        align.set_padding (6, 12, 12, 12);
-                        align.add (behavior_vbox);
-                        behavior_frame.add (align);
-
-                        // Autostart checkbox
-                        var autostart = new Gtk.CheckButton.with_label (_("Startup on Login"));
-                            autostart.tooltip_text = _("If checked, Gnome-Pie will start when you log in.");
-                            autostart.active = Config.global.auto_start;
-                            autostart.toggled.connect(autostart_toggled);
-                            behavior_vbox.pack_start(autostart, false);
-
-                        // Indicator icon 
-                        var indicator = new Gtk.CheckButton.with_label (_("Show Indicator"));
-                            indicator.tooltip_text = _("If checked, an indicator for easy access of the settings menu is shown in your panel.");
-                            indicator.active = Config.global.show_indicator;
-                            indicator.toggled.connect(indicator_toggled);
-                            behavior_vbox.pack_start(indicator, false);
-                            
-                        // Open Pies at Mouse
-                        var open_at_mouse = new Gtk.CheckButton.with_label (_("Open Pies at Mouse"));
-                            open_at_mouse.tooltip_text = _("If checked, pies will open at your pointer. Otherwise they'll pop up in the middle of the screen.");
-                            open_at_mouse.active = Config.global.open_at_mouse;
-                            open_at_mouse.toggled.connect(open_at_mouse_toggled);
-                            behavior_vbox.pack_start(open_at_mouse, false);
-                            
-                        // Slider
-                        var slider_hbox = new Gtk.HBox (false, 6);
-                            behavior_vbox.pack_start(slider_hbox);
-                            
-                            var scale_label = new Gtk.Label(_("Global Scale"));
-                                slider_hbox.pack_start(scale_label, false, false);
-                            
-                            var scale_slider = new Gtk.HScale.with_range(0.5, 2.0, 0.05);
-                                scale_slider.set_value(Config.global.global_scale);
-                                scale_slider.value_pos = Gtk.PositionType.RIGHT;
-                                
-                                bool changing = false;
-                                bool changed_again = false;
-
-                                scale_slider.value_changed.connect(() => {
-                                    if (!changing) {
-                                        changing = true;
-                                        Timeout.add(300, () => {
-                                            if (changed_again) {
-                                                changed_again = false;
-                                                return true;
-                                            }
-
-                                            Config.global.global_scale = scale_slider.get_value();
-                                            Config.global.load_themes(Config.global.theme.name);
-                                            changing = false;
-                                            return false;
-                                        });
-                                    } else {
-                                        changed_again = true;
-                                    }
-                                });
-                                
-                                slider_hbox.pack_end(scale_slider, true, true);
-
-                    general_tab.pack_start (behavior_frame, false);
-                    
-                    // theme frame
-                    var theme_frame = new Gtk.Frame(null);
-                        theme_frame.set_shadow_type(Gtk.ShadowType.NONE);
-                        var theme_frame_label = new Gtk.Label(null);
-                        theme_frame_label.set_markup(Markup.printf_escaped("<b>%s</b>", _("Themes")));
-                        theme_frame.set_label_widget(theme_frame_label);
-                        
-                        // scrollable frame
-                        var scroll = new Gtk.ScrolledWindow (null, null);
-                            align = new Gtk.Alignment(0.5f, 0.5f, 1.0f, 1.0f);
-                            align.set_padding(6, 12, 12, 12);
-                            align.add(scroll);
-                            theme_frame.add(align);
-
-                            scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
-                            scroll.set_shadow_type (Gtk.ShadowType.IN);
-                            
-                            // themes list
-                            var theme_list = new ThemeList();
-                                scroll.add(theme_list);
-
-                general_tab.pack_start (theme_frame, true, true);
-                tabs.append_page(general_tab, new Gtk.Label(_("General")));
-                
-                // pies tab
-                var pies_tab = new Gtk.VBox(false, 6);
-                    pies_tab.border_width = 12;
-                    tabs.append_page(pies_tab, new Gtk.Label(_("Pies")));
-                        
-                    // scrollable frame
-                    scroll = new Gtk.ScrolledWindow (null, null);
-                        align = new Gtk.Alignment(0.5f, 0.5f, 1.0f, 1.0f);
-                        align.add(scroll);
-                        pies_tab.add(align);
-
-                        scroll.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
-                        scroll.set_shadow_type (Gtk.ShadowType.IN);
-                        
-                        // pies list
-                        var pie_list = new PieList();
-                            scroll.add(pie_list);
-                        
-                    // bottom box
-                    var info_box = new Gtk.HBox (false, 6);
-                    
-                        // info image
-                        var info_image = new Gtk.Image.from_stock (Gtk.Stock.INFO, Gtk.IconSize.MENU);
-                            info_box.pack_start (info_image, false);
-
-                        // info label
-                        var info_label = new TipViewer({
-                                _("You can right-click in the list for adding or removing entries."),
-                                _("You can reset Gnome-Pie to its default options with the terminal command \"gnome-pie --reset\"."),
-                                _("The radiobutton at the beginning of each slice-line indicates the QuickAction of the pie."),
-                                _("Pies can be opened with the terminal command \"gnome-pie --open=ID\"."),
-                                _("Feel free to visit Gnome-Pie's homepage at %s!").printf("<a href='http://gnome-pie.simonschneegans.de'>gnome-pie.simonschneegans.de</a>"),
-                                _("You can drag'n'drop applications from your main menu to the list above."),
-                                _("If you want to give some feedback, please write an e-mail to %s!").printf("<a href='mailto:code@simonschneegans.de'>code@simonschneegans.de</a>"),
-                                _("You may drag'n'drop URLs and bookmarks from your internet browser to the list above."),
-                                _("Bugs can be reported at %s!").printf("<a href='https://github.com/Simmesimme/Gnome-Pie'>Github</a>"),
-                                _("It's possible to drag'n'drop files and folders from your file browser to the list above."),
-                                _("It's recommended to keep your Pies small (at most 6-8 Slices). Else they will become hard to navigate."),
-                                _("In order to create a launcher for a Pie, drag the Pie from the list to your desktop!")
-                            });
-                            this.show.connect(info_label.start_slide_show);
-                            this.hide.connect(info_label.stop_slide_show);
-                            
-                            info_box.pack_start (info_label);
-                        
-                        // down Button
-                        var down_button = new Gtk.Button();
-                            down_button.tooltip_text = _("Moves the selected Slice down");
-                            down_button.sensitive = false;
-                            var down_image = new Gtk.Image.from_stock (Gtk.Stock.GO_DOWN, Gtk.IconSize.LARGE_TOOLBAR);
-                            down_button.add(down_image);
-                            down_button.clicked.connect (() => {
-                                pie_list.selection_down();
-                            });
-
-                            info_box.pack_end(down_button, false, false);
-                        
-                        // up Button
-                        var up_button = new Gtk.Button();
-                            up_button.tooltip_text = _("Moves the selected Slice up");
-                            up_button.sensitive = false;
-                            var up_image = new Gtk.Image.from_stock (Gtk.Stock.GO_UP, Gtk.IconSize.LARGE_TOOLBAR);
-                            up_button.add(up_image);
-                            up_button.clicked.connect (() => {
-                                pie_list.selection_up();
-                            });
-                            
-                            info_box.pack_end(up_button, false, false);
-                            
-                        pie_list.get_selection().changed.connect(() => {
-                            Gtk.TreeIter selected;
-                            if (pie_list.get_selection().get_selected(null, out selected)) {
-                                Gtk.TreePath path = pie_list.model.get_path(selected);
-                                if (path.get_depth() == 1) {
-                                    up_button.sensitive = false;
-                                    down_button.sensitive = false;
-                                } else {
-                                    up_button.sensitive = true;
-                                    down_button.sensitive = true;
-                                    
-                                    int child_pos = path.get_indices()[1];
-
-                                    if (child_pos == 0)
-                                        up_button.sensitive = false;
-                                    
-                                    path.up();
-                                    Gtk.TreeIter parent_iter;
-                                    pie_list.model.get_iter(out parent_iter, path);
-                                    if (child_pos == pie_list.model.iter_n_children(parent_iter)-1)
-                                        down_button.sensitive = false;
-                                    
-                                }
-                            }
-                        });
-                        
-                        pies_tab.pack_start (info_box, false);
-                
-                main_vbox.pack_start(tabs);
-
-            // close button 
-            var bbox = new Gtk.HButtonBox ();
-                bbox.set_layout (Gtk.ButtonBoxStyle.END);
-                var close_button = new Gtk.Button.from_stock(Gtk.Stock.CLOSE);
-                close_button.clicked.connect (() => { 
-                    hide();
-                });
-                bbox.pack_start (close_button);
-
-                main_vbox.pack_start(bbox, false);
-                
-            main_vbox.show_all();
-            
-        this.hide.connect(() => {
-            // save settings on close
-            Config.global.save();
-            Pies.save();
-        });
-    }
-
-    /////////////////////////////////////////////////////////////////////
-    /// Creates or deletes the autostart file. This code is inspired
-    /// by project synapse as well.
-    /////////////////////////////////////////////////////////////////////
-    
-    private void autostart_toggled(Gtk.ToggleButton check_box) {
-        bool active = check_box.active;
-        if (!active && FileUtils.test(Paths.autostart, FileTest.EXISTS)) {
-            // delete the autostart file
-            FileUtils.remove (Paths.autostart);
-        }
-        else if (active && !FileUtils.test(Paths.autostart, FileTest.EXISTS)) {
-            string autostart_entry = 
-                "#!/usr/bin/env xdg-open\n" + 
-                "[Desktop Entry]\n" +
-                "Name=Gnome-Pie\n" +
-                "Exec=gnome-pie\n" +
-                "Encoding=UTF-8\n" +
-                "Type=Application\n" +
-                "X-GNOME-Autostart-enabled=true\n" +
-                "Icon=gnome-pie\n";
-
-            // create the autostart file
-            string autostart_dir = GLib.Path.get_dirname(Paths.autostart);
-            if (!FileUtils.test(autostart_dir, FileTest.EXISTS | FileTest.IS_DIR)) {
-                DirUtils.create_with_parents(autostart_dir, 0755);
-            }
-            
-            try {
-                FileUtils.set_contents(Paths.autostart, autostart_entry);
-                FileUtils.chmod(Paths.autostart, 0755);
-            } catch (Error e) {
-                var d = new Gtk.MessageDialog (this, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,
-                                           "%s", e.message);
-                d.run ();
-                d.destroy ();
-            }
-        }
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Shows or hides the indicator.
-    /////////////////////////////////////////////////////////////////////
-    
-    private void indicator_toggled(Gtk.ToggleButton check_box) {
-        var check = check_box as Gtk.CheckButton;
-        Config.global.show_indicator = check.active;
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Toggles whether the Pies are shown at the mouse or in the middle
-    /// of the screen.
-    /////////////////////////////////////////////////////////////////////
-    
-    private void open_at_mouse_toggled(Gtk.ToggleButton check_box) {
-        var check = check_box as Gtk.CheckButton;
-        Config.global.open_at_mouse = check.active;
-    }
-}
-
-}
diff --git a/src/gui/preferencesWindow.vala b/src/gui/preferencesWindow.vala
new file mode 100644
index 0000000..022e44b
--- /dev/null
+++ b/src/gui/preferencesWindow.vala
@@ -0,0 +1,311 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// The settings menu of Gnome-Pie.
+/////////////////////////////////////////////////////////////////////////
+
+public class PreferencesWindow : GLib.Object {
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The ID of the currently selected Pie.
+    /////////////////////////////////////////////////////////////////////
+    
+    private string selected_id = "";
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some Gtk widgets used by this window.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gtk.Window? window = null;
+    private Gtk.Label? id_label = null;
+    private Gtk.Label? name_label = null;
+    private Gtk.Label? hotkey_label = null;
+    private Gtk.Label? no_pie_label = null;
+    private Gtk.Label? no_slice_label = null;
+    private Gtk.VBox? preview_box = null;
+    private Gtk.Image? icon = null;
+    private Gtk.EventBox? preview_background = null;
+    private Gtk.Button? icon_button = null;
+    private Gtk.Button? name_button = null;
+    private Gtk.Button? hotkey_button = null;
+    private Gtk.ToolButton? remove_pie_button = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some custom widgets and dialogs used by this window.
+    /////////////////////////////////////////////////////////////////////
+    
+    private PiePreview? preview = null;
+    private PieList? pie_list = null;
+    private SettingsWindow? settings_window = null;
+    private TriggerSelectWindow? trigger_window = null;
+    private IconSelectWindow? icon_window = null;
+    private RenameWindow? rename_window = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, creates the window.
+    /////////////////////////////////////////////////////////////////////
+    
+    public PreferencesWindow() {
+        try {
+            var builder = new Gtk.Builder();
+
+            builder.add_from_file (Paths.ui_files + "/preferences.ui");
+
+            this.window = builder.get_object("window") as Gtk.Window;
+            
+            this.window.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK |
+                        Gdk.EventMask.KEY_RELEASE_MASK |
+                        Gdk.EventMask.KEY_PRESS_MASK |
+                        Gdk.EventMask.POINTER_MOTION_MASK);
+            
+            #if HAVE_GTK_3
+                var toolbar = builder.get_object ("toolbar") as Gtk.Widget;
+                toolbar.get_style_context().add_class("primary-toolbar");
+                
+                var inline_toolbar = builder.get_object ("pies-toolbar") as Gtk.Widget;
+                inline_toolbar.get_style_context().add_class("inline-toolbar");
+            #endif
+            
+            this.pie_list = new PieList();
+            this.pie_list.on_select.connect(this.on_pie_select);
+            
+            var scroll_area = builder.get_object("pies-scrolledwindow") as Gtk.ScrolledWindow;
+            scroll_area.add(this.pie_list);
+            
+            this.preview = new PiePreview();
+            this.preview.on_first_slice_added.connect(() => {
+                this.no_slice_label.hide();
+            });
+            
+            this.preview.on_last_slice_removed.connect(() => {
+                this.no_slice_label.show();
+            });
+            
+            preview_box = builder.get_object("preview-box") as Gtk.VBox;
+            this.preview_box.pack_start(preview, true, true);
+            
+            this.id_label = builder.get_object("id-label") as Gtk.Label;
+            this.name_label = builder.get_object("pie-name-label") as Gtk.Label;
+            this.hotkey_label = builder.get_object("hotkey-label") as Gtk.Label;
+            this.no_pie_label = builder.get_object("no-pie-label") as Gtk.Label;
+            this.no_slice_label = builder.get_object("no-slice-label") as Gtk.Label;
+            this.icon = builder.get_object("icon") as Gtk.Image;
+            this.preview_background = builder.get_object("preview-background") as Gtk.EventBox;
+                    
+            (builder.get_object("settings-button") as Gtk.ToolButton).clicked.connect(on_settings_button_clicked);
+            
+            this.hotkey_button = builder.get_object("key-button") as Gtk.Button;
+            this.hotkey_button.clicked.connect(on_key_button_clicked);
+            
+            this.icon_button = builder.get_object("icon-button") as Gtk.Button;
+            this.icon_button.clicked.connect(on_icon_button_clicked);
+            
+            this.name_button = builder.get_object("rename-button") as Gtk.Button;
+            this.name_button.clicked.connect(on_rename_button_clicked);
+            
+            this.remove_pie_button = builder.get_object("remove-pie-button") as Gtk.ToolButton;
+            this.remove_pie_button.clicked.connect(on_remove_pie_button_clicked);
+            
+            (builder.get_object("add-pie-button") as Gtk.ToolButton).clicked.connect(on_add_pie_button_clicked);
+            
+            this.window.hide.connect(() => {
+                // save settings on close
+                Config.global.save();
+                Pies.save();
+            });
+            
+            this.window.delete_event.connect(this.window.hide_on_delete);
+                
+        } catch (GLib.Error e) {
+            error("Could not load UI: %s\n", e.message);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Shows the window.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void show() {
+        this.preview.draw_loop();
+        this.window.show_all();
+        this.pie_list.select_first();
+        this.preview_background.modify_bg(Gtk.StateType.NORMAL, Gtk.rc_get_style(this.window).light[0]);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when a new Pie is selected in the PieList.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_pie_select(string id) {
+        selected_id = id;
+        
+        this.no_slice_label.hide();
+        this.no_pie_label.hide();
+        this.preview_box.hide();
+        
+        this.name_button.sensitive = false;
+        this.hotkey_button.sensitive = false;
+        this.icon_button.sensitive = false;
+        this.remove_pie_button.sensitive = false;
+        
+        if (id == "") {
+            this.id_label.label = "";
+            this.name_label.label = _("No Pie selected.");
+            this.hotkey_label.set_markup("");
+            this.icon.icon_name = "application-default-icon";
+
+            this.no_pie_label.show();
+        } else {
+            var pie = PieManager.all_pies[selected_id];
+            this.id_label.label = ("ID: %s").printf(pie.id);
+            this.name_label.label = PieManager.get_name_of(pie.id);
+            this.hotkey_label.set_markup(PieManager.get_accelerator_label_of(pie.id));
+            
+            if (pie.icon.contains("/"))
+                try {
+                    this.icon.pixbuf = new Gdk.Pixbuf.from_file_at_scale(pie.icon, 
+                                                                         this.icon.get_pixel_size(), 
+                                                                         this.icon.get_pixel_size(), 
+                                                                         true);
+                } catch (GLib.Error error) {
+                    warning(error.message);
+                }
+            else
+                this.icon.icon_name = pie.icon;
+            
+            this.preview.set_pie(id);
+            this.preview_box.show();
+            
+            if (pie.action_groups.size == 0) {
+                this.no_slice_label.show();
+            }
+            
+            this.name_button.sensitive = true;
+            this.hotkey_button.sensitive = true;
+            this.icon_button.sensitive = true;
+            this.remove_pie_button.sensitive = true;
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the add Pie button is clicked.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_add_pie_button_clicked(Gtk.ToolButton button) {
+        var new_pie = PieManager.create_persistent_pie(_("New Pie"), "application-default-icon", null);
+        this.pie_list.reload_all();
+        this.pie_list.select(new_pie.id);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the remove Pie button is clicked.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_remove_pie_button_clicked(Gtk.ToolButton button) {
+        if (this.selected_id != "") {
+            var dialog = new Gtk.MessageDialog((Gtk.Window)this.window.get_toplevel(), Gtk.DialogFlags.MODAL,
+                         Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO,
+                         _("Do you really want to delete the selected Pie with all contained Slices?"));
+                                                     
+            dialog.response.connect((response) => {
+                if (response == Gtk.ResponseType.YES) {
+                    PieManager.remove_pie(selected_id);
+                    this.pie_list.reload_all();
+                    this.pie_list.select_first();
+                }
+            });
+            
+            dialog.run();
+            dialog.destroy();
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when rename Pie button is clicked.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_rename_button_clicked(Gtk.Button button) {
+        if (this.rename_window == null) {
+            this.rename_window = new RenameWindow();
+            this.rename_window.set_parent(window);
+            this.rename_window.on_ok.connect((name) => {
+                var pie = PieManager.all_pies[selected_id];
+                pie.name = name;
+                PieManager.create_launcher(pie.id);
+                this.name_label.label = name;
+                this.pie_list.reload_all();
+            });
+        }
+        
+        this.rename_window.set_pie(selected_id);
+        this.rename_window.show();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the hotkey button is clicked.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_key_button_clicked(Gtk.Button button) {
+        if (this.trigger_window == null) {
+            this.trigger_window = new TriggerSelectWindow();
+            this.trigger_window.set_parent(window);
+            this.trigger_window.on_ok.connect((trigger) => {
+                PieManager.bind_trigger(trigger, selected_id);
+                this.hotkey_label.set_markup(trigger.label_with_specials);
+            });
+        }
+        
+        this.trigger_window.set_pie(selected_id);
+        this.trigger_window.show();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the general settings button is clicked.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_settings_button_clicked(Gtk.ToolButton button) {
+        if (this.settings_window == null) {
+            this.settings_window = new SettingsWindow();
+            this.settings_window.set_parent(this.window.get_toplevel() as Gtk.Window);
+        }
+        
+        this.settings_window.show();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the icon button is clicked.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_icon_button_clicked(Gtk.Button button) {
+        if (this.icon_window == null) {
+            this.icon_window = new IconSelectWindow(this.window);
+            this.icon_window.on_ok.connect((icon) => {
+                var pie = PieManager.all_pies[selected_id];
+                pie.icon = icon;
+                PieManager.create_launcher(pie.id);
+                this.pie_list.reload_all();
+            });
+        }
+        
+        this.icon_window.show();
+    }
+}
+
+}
diff --git a/src/gui/renameWindow.vala b/src/gui/renameWindow.vala
new file mode 100644
index 0000000..389b460
--- /dev/null
+++ b/src/gui/renameWindow.vala
@@ -0,0 +1,109 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A window which allows selection of a new name for a Pie.
+/////////////////////////////////////////////////////////////////////////
+
+public class RenameWindow : GLib.Object {
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Gets emitted when the user selects a new name.
+    /////////////////////////////////////////////////////////////////////
+    
+    public signal void on_ok(string new_name);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some Widgets used by this dialog.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gtk.Dialog window = null;
+    private Gtk.Entry entry = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, constructs the Widget.
+    /////////////////////////////////////////////////////////////////////
+    
+    public RenameWindow() {
+        try {
+        
+            Gtk.Builder builder = new Gtk.Builder();
+
+            builder.add_from_file (Paths.ui_files + "/rename_pie.ui");
+
+            window = builder.get_object("window") as Gtk.Dialog;
+            entry = builder.get_object("name-entry") as Gtk.Entry;
+            
+            entry.activate.connect(this.on_ok_button_clicked);
+            
+            (builder.get_object("ok-button") as Gtk.Button).clicked.connect(on_ok_button_clicked);
+            (builder.get_object("cancel-button") as Gtk.Button).clicked.connect(on_cancel_button_clicked);
+            
+            this.window.delete_event.connect(this.window.hide_on_delete);
+                
+        } catch (GLib.Error e) {
+            error("Could not load UI: %s\n", e.message);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Sets the parent window, in order to make this window stay in
+    /// front.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_parent(Gtk.Window parent) {
+        this.window.set_transient_for(parent);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Displays the window on the screen.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void show() {
+        this.window.show_all();
+        this.entry.is_focus = true;
+    }  
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Make the text entry display the name of the Pie with given ID.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_pie(string id) {
+        entry.text = PieManager.get_name_of(id);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the ok button is pressed.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_ok_button_clicked() {
+        this.on_ok(entry.text);
+        this.window.hide();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the cancel button is pressed.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_cancel_button_clicked() {
+        this.window.hide();
+    }
+}
+
+}
diff --git a/src/gui/settingsWindow.vala b/src/gui/settingsWindow.vala
new file mode 100644
index 0000000..1eaa0b4
--- /dev/null
+++ b/src/gui/settingsWindow.vala
@@ -0,0 +1,174 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// The settings menu of Gnome-Pie, with options for theme switching and
+/// some general options.
+/////////////////////////////////////////////////////////////////////////
+
+public class SettingsWindow : GLib.Object {
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Some widgets.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gtk.Dialog? window = null;
+    private ThemeList? theme_list = null;
+    private Gtk.ToggleButton? indicator = null;
+    private Gtk.ToggleButton? autostart = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor creates, the dialog.
+    /////////////////////////////////////////////////////////////////////
+    
+    public SettingsWindow() {
+        try {
+        
+            Gtk.Builder builder = new Gtk.Builder();
+
+            builder.add_from_file (Paths.ui_files + "/settings.ui");
+
+            this.window = builder.get_object("window") as Gtk.Dialog;
+            
+            this.theme_list = new ThemeList();
+            
+            var scroll_area = builder.get_object("theme-scrolledwindow") as Gtk.ScrolledWindow;
+                scroll_area.add(this.theme_list);
+                
+            (builder.get_object("close-button") as Gtk.Button).clicked.connect(on_close_button_clicked);
+            
+            this.autostart = (builder.get_object("autostart-checkbox") as Gtk.ToggleButton);
+            this.autostart.toggled.connect(on_autostart_toggled);
+            
+            this.indicator = (builder.get_object("indicator-checkbox") as Gtk.ToggleButton);
+            this.indicator.toggled.connect(on_indicator_toggled);
+            
+            var scale_slider = (builder.get_object("scale-hscale") as Gtk.HScale);
+                scale_slider.set_range(0.5, 2.0);
+                scale_slider.set_increments(0.05, 0.25);
+                scale_slider.set_value(Config.global.global_scale);
+                
+                bool changing = false;
+                bool changed_again = false;
+
+                scale_slider.value_changed.connect(() => {
+                    if (!changing) {
+                        changing = true;
+                        Timeout.add(300, () => {
+                            if (changed_again) {
+                                changed_again = false;
+                                return true;
+                            }
+
+                            Config.global.global_scale = scale_slider.get_value();
+                            Config.global.load_themes(Config.global.theme.name);
+                            changing = false;
+                            return false;
+                        });
+                    } else {
+                        changed_again = true;
+                    }
+                });
+                
+            this.window.delete_event.connect(this.window.hide_on_delete);
+                
+        } catch (GLib.Error e) {
+            error("Could not load UI: %s\n", e.message);
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Sets the parent window, in order to make this window stay in
+    /// front.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_parent(Gtk.Window parent) {
+        this.window.set_transient_for(parent);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Displays the window on the screen.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void show() {
+        this.indicator.active = Config.global.show_indicator;
+        this.autostart.active = Config.global.auto_start;
+    
+        this.window.show_all(); 
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the close button is clicked.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_close_button_clicked() {
+        this.window.hide();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Creates or deletes the autostart file. This code is inspired
+    /// by project synapse as well.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_autostart_toggled(Gtk.ToggleButton check_box) {
+        bool active = check_box.active;
+        if (!active && FileUtils.test(Paths.autostart, FileTest.EXISTS)) {
+            // delete the autostart file
+            FileUtils.remove (Paths.autostart);
+        }
+        else if (active && !FileUtils.test(Paths.autostart, FileTest.EXISTS)) {
+            string autostart_entry = 
+                "#!/usr/bin/env xdg-open\n" + 
+                "[Desktop Entry]\n" +
+                "Name=Gnome-Pie\n" +
+                "Exec=gnome-pie\n" +
+                "Encoding=UTF-8\n" +
+                "Type=Application\n" +
+                "X-GNOME-Autostart-enabled=true\n" +
+                "Icon=gnome-pie\n";
+
+            // create the autostart file
+            string autostart_dir = GLib.Path.get_dirname(Paths.autostart);
+            if (!FileUtils.test(autostart_dir, FileTest.EXISTS | FileTest.IS_DIR)) {
+                DirUtils.create_with_parents(autostart_dir, 0755);
+            }
+            
+            try {
+                FileUtils.set_contents(Paths.autostart, autostart_entry);
+                FileUtils.chmod(Paths.autostart, 0755);
+            } catch (Error e) {
+                var d = new Gtk.MessageDialog (this.window, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,
+                                           "%s", e.message);
+                d.run ();
+                d.destroy ();
+            }
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Shows or hides the indicator.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void on_indicator_toggled(Gtk.ToggleButton check_box) {
+        var check = check_box as Gtk.CheckButton;
+        Config.global.show_indicator = check.active;
+    }
+}
+
+}
diff --git a/src/gui/sliceTypeList.vala b/src/gui/sliceTypeList.vala
new file mode 100644
index 0000000..541658e
--- /dev/null
+++ b/src/gui/sliceTypeList.vala
@@ -0,0 +1,172 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// A list displaying all available Action types and ActionGroup types.
+/////////////////////////////////////////////////////////////////////////
+
+class SliceTypeList : Gtk.TreeView {
+
+    /////////////////////////////////////////////////////////////////////
+    /// This signal gets emitted when the user selects a new Type.
+    /////////////////////////////////////////////////////////////////////
+    
+    public signal void on_select(string id, string icon_name);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The listore which staroes all types internally.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gtk.ListStore data;
+    private enum DataPos {ICON, ICON_NAME, NAME, ID}
+
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, constructs the Widget.
+    /////////////////////////////////////////////////////////////////////
+
+    public SliceTypeList() {
+        GLib.Object();
+        
+        this.data = new Gtk.ListStore(4, typeof(Gdk.Pixbuf),   
+                                         typeof(string),
+                                         typeof(string),
+                                         typeof(string));
+                                         
+        this.data.set_sort_column_id(2, Gtk.SortType.ASCENDING);
+        
+        base.set_model(this.data);
+        base.set_headers_visible(true);
+        base.set_grid_lines(Gtk.TreeViewGridLines.NONE);
+        this.set_fixed_height_mode(true);
+        
+        var main_column = new Gtk.TreeViewColumn();
+            main_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED);
+            main_column.title = _("Slice types");
+            var icon_render = new Gtk.CellRendererPixbuf();
+                main_column.pack_start(icon_render, false);
+        
+            var name_render = new Gtk.CellRendererText();
+                main_column.pack_start(name_render, true);
+        
+        base.append_column(main_column);
+        
+        main_column.add_attribute(icon_render, "pixbuf", DataPos.ICON);
+        main_column.add_attribute(name_render, "markup", DataPos.NAME);
+        
+        this.get_selection().changed.connect(() => {
+            Gtk.TreeIter active;
+            if (this.get_selection().get_selected(null, out active)) {
+                string id = "";
+                string icon = "";
+                this.data.get(active, DataPos.ID, out id);
+                this.data.get(active, DataPos.ICON_NAME, out icon);
+                this.on_select(id, icon);
+            }
+        });
+        
+        reload_all();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Loads a registered actions and action groups.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void reload_all() {
+        Gtk.TreeIter active;
+        string current_id = "";
+        if (this.get_selection().get_selected(null, out active))
+            this.data.get(active, DataPos.ID, out current_id);
+    
+        data.clear();
+        
+        foreach (var action_type in ActionRegistry.types) {
+            var description = ActionRegistry.descriptions[action_type];
+            
+            Gtk.TreeIter current;
+            data.append(out current);
+            var icon = new Icon(description.icon, 36);
+            data.set(current, DataPos.ICON, icon.to_pixbuf()); 
+            data.set(current, DataPos.ICON_NAME, description.icon); 
+            data.set(current, DataPos.NAME, "<b>" + description.name + "</b>\n"
+                                 + "<small>" + description.description + "</small>"); 
+            data.set(current, DataPos.ID, description.id); 
+        }
+        
+        foreach (var group_type in GroupRegistry.types) {
+            var description = GroupRegistry.descriptions[group_type];
+            
+            Gtk.TreeIter current;
+            data.append(out current);
+            var icon = new Icon(description.icon, 36);
+            data.set(current, DataPos.ICON, icon.to_pixbuf()); 
+            data.set(current, DataPos.ICON_NAME, description.icon);
+            data.set(current, DataPos.NAME, "<b>" + description.name + "</b>\n"
+                                 + "<small>" + description.description + "</small>"); 
+            data.set(current, DataPos.ID, description.id); 
+        }
+        
+        select_first();
+        select(current_id);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Selects the first type in the list.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void select_first() {
+        Gtk.TreeIter active;
+        
+        if(this.data.get_iter_first(out active) ) {
+            this.get_selection().select_iter(active);
+            string id = "";
+            string icon = "";
+            this.data.get(active, DataPos.ID, out id);
+            this.data.get(active, DataPos.ICON_NAME, out icon);
+            this.on_select(id, icon);
+        } else {
+            this.on_select("", "application-default-icon");
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Select the given slice type.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void select(string id) {
+        this.data.foreach((model, path, iter) => {
+            string pie_id;
+            this.data.get(iter, DataPos.ID, out pie_id);
+            
+            if (id == pie_id) {
+                this.get_selection().select_iter(iter);
+                string icon = "";
+                this.data.get(iter, DataPos.ICON_NAME, out icon);
+                this.on_select(pie_id, icon);
+                this.scroll_to_cell(path, null, true, 0.5f, 0.5f);
+                this.has_focus = true;
+                
+                return true;
+            }
+            
+            return false;
+        });
+    }
+}
+
+}
diff --git a/src/gui/themeList.vala b/src/gui/themeList.vala
index 7eadcdb..62e0721 100644
--- a/src/gui/themeList.vala
+++ b/src/gui/themeList.vala
@@ -28,6 +28,12 @@ class ThemeList : Gtk.TreeView {
     /////////////////////////////////////////////////////////////////////
 
     private Gtk.TreeIter active { private get; private set; }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The positions in the data list store.
+    /////////////////////////////////////////////////////////////////////
+    
+    private enum DataPos {ICON, NAME}
 
     /////////////////////////////////////////////////////////////////////
     /// C'tor, constructs the Widget.
@@ -36,58 +42,50 @@ class ThemeList : Gtk.TreeView {
     public ThemeList() {
         GLib.Object();
         
-        var data = new Gtk.ListStore(2, typeof(bool),    // selected
-                                        typeof(string)); // description
-        base.set_model(data);
-        base.set_headers_visible(false);
-        base.set_rules_hint(true);
-        base.set_grid_lines(Gtk.TreeViewGridLines.NONE);
+        var data = new Gtk.ListStore(2, typeof(Gdk.Pixbuf), 
+                                        typeof(string));
+        this.set_model(data);
+        this.set_headers_visible(true);
+        this.set_grid_lines(Gtk.TreeViewGridLines.NONE);
+        this.set_fixed_height_mode(true);
         
         var main_column = new Gtk.TreeViewColumn();
-            var check_render = new Gtk.CellRendererToggle();
-                check_render.set_radio(true);
-                check_render.set_activatable(true);
-                main_column.pack_start(check_render, false);
-                
-                // switch the theme if the entry has been toggled
-                check_render.toggled.connect((r, path) => {
-                    Gtk.TreeIter toggled;
-                    data.get_iter(out toggled, new Gtk.TreePath.from_string(path));
-                    
-                    if (toggled != this.active) {
-                        Timeout.add(10, () => {
-                            int index = int.parse(path);
-                            Config.global.theme = Config.global.themes[index];
-                            Config.global.theme.load();
-                            Config.global.theme.load_images();
-                            return false;
-                        });
-                        
-                        data.set(this.active, 0, false); 
-                        data.set(toggled, 0, true);
-                        
-                        this.active = toggled;
-                    }
-                });
+            main_column.title = _("Themes");
+            main_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED);
+            var icon_render = new Gtk.CellRendererPixbuf();
+                main_column.pack_start(icon_render, false);
         
             var theme_render = new Gtk.CellRendererText();
                 main_column.pack_start(theme_render, true);
         
-        base.append_column(main_column);
+        this.append_column(main_column);
+        
+        main_column.add_attribute(icon_render, "pixbuf", DataPos.ICON);
+        main_column.add_attribute(theme_render, "markup", DataPos.NAME);
         
-        main_column.add_attribute(check_render, "active", 0);
-        main_column.add_attribute(theme_render, "markup", 1);
+        this.get_selection().changed.connect(() => {
+            Gtk.TreeIter active;
+            if (this.get_selection().get_selected(null, out active)) {
+                Timeout.add(10, () => {
+                    int index = int.parse(data.get_path(active).to_string());
+                    Config.global.theme = Config.global.themes[index];
+                    Config.global.theme.load();
+                    Config.global.theme.load_images();
+                    return false;
+                });  
+            }
+        });
         
         // load all themes into the list
         var themes = Config.global.themes;
         foreach(var theme in themes) {
             Gtk.TreeIter current;
             data.append(out current);
-            data.set(current, 0, theme == Config.global.theme); 
-            data.set(current, 1, "<b>" + theme.name + "</b>\n" + theme.description
-                                 + "  <small> - " + _("by") + " " + theme.author + "</small>"); 
+            data.set(current, DataPos.ICON, theme.preview_icon.to_pixbuf()); 
+            data.set(current, DataPos.NAME, "<b>"+theme.name+"</b><small>  -  "+theme.description+"\n"
+                                           +"<i>"+_("By")+" "+theme.author+"</i></small>"); 
             if(theme == Config.global.theme)
-                this.active = current;
+                get_selection().select_iter(current);
         }  
     }
 }
diff --git a/src/gui/tipViewer.vala b/src/gui/tipViewer.vala
deleted file mode 100644
index c653dd9..0000000
--- a/src/gui/tipViewer.vala
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 
-Copyright (c) 2011 by Simon Schneegans
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program 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 General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program.  If not, see <http://www.gnu.org/licenses/>. 
-*/
-
-namespace GnomePie {
-
-/////////////////////////////////////////////////////////////////////////    
-/// A widget showing tips. The tips are beautifully faded in and out.
-/////////////////////////////////////////////////////////////////////////
-
-public class TipViewer : Gtk.Label {
-
-    /////////////////////////////////////////////////////////////////////
-    /// Some settings tweaking the behavior of the TipViewer.
-    /////////////////////////////////////////////////////////////////////
-
-    private const double fade_time = 0.5;
-    private const double frame_rate = 20.0;
-    private const double delay = 7.0;
-
-    /////////////////////////////////////////////////////////////////////
-    /// False, if the playback of tips is stopped.
-    /////////////////////////////////////////////////////////////////////
-    
-    private bool playing = false;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// An array containing all tips.
-    /////////////////////////////////////////////////////////////////////
-    
-    private string[] tips;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// The index of the currently displayed tip.
-    /////////////////////////////////////////////////////////////////////
-    
-    private int index = -1;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Colors of the font and the background. Used for fading effects.
-    /////////////////////////////////////////////////////////////////////
-    
-    private Gdk.Color fg;
-    private Gdk.Color bg;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// The fading value.
-    /////////////////////////////////////////////////////////////////////
-    
-    private AnimatedValue alpha;
-    
-    /////////////////////////////////////////////////////////////////////
-    /// C'tor, initializes all members and sets the basic layout.
-    /////////////////////////////////////////////////////////////////////
-    
-    public TipViewer(string[] tips) {
-        this.tips = tips;
-        this.fg = this.get_style().fg[0];
-        this.bg = this.get_style().bg[0];
-        
-        this.alpha = new AnimatedValue.linear(1.0, 0.0, this.fade_time);
-        
-        this.set_alignment (0.0f, 0.5f);
-        this.wrap = true;
-        this.set_use_markup(true);
-        this.modify_font(Pango.FontDescription.from_string("9"));
-        
-        this.set_random_tip();
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Starts the playback of tips.
-    /////////////////////////////////////////////////////////////////////
-    
-    public void start_slide_show() {
-        if (!this.playing && tips.length > 1) {
-            this.playing = true;
-            GLib.Timeout.add((uint)(this.delay*1000.0), () => {
-                this.fade_out();
-                
-                GLib.Timeout.add((uint)(1000.0*this.fade_time), () => {
-                    this.set_random_tip();
-                    this.fade_in();
-                    return false;
-                });
-                
-                return this.playing;
-            });
-        }
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Stops the playback of tips.
-    /////////////////////////////////////////////////////////////////////
-    
-    public void stop_slide_show() {
-        this.playing = false;
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Starts the fading in.
-    /////////////////////////////////////////////////////////////////////
-    
-    private void fade_in() {
-        this.alpha = new AnimatedValue.linear(this.alpha.val, 1.0, this.fade_time);
-        
-        GLib.Timeout.add((uint)(1000.0/this.frame_rate), () => {
-            this.alpha.update(1.0/this.frame_rate);
-            this.update_label();
-            
-            return (this.alpha.val != 1.0);
-        });
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Starts the fading out.
-    /////////////////////////////////////////////////////////////////////
-    
-    private void fade_out() {
-        this.alpha = new AnimatedValue.linear(this.alpha.val, 0.0, this.fade_time);
-        
-        GLib.Timeout.add((uint)(1000.0/this.frame_rate), () => {
-            this.alpha.update(1.0/this.frame_rate);
-            this.update_label();
-            
-            return (this.alpha.val != 0.0);
-        });
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Updates the color of the label. Called every frame while fading.
-    /////////////////////////////////////////////////////////////////////
-    
-    private void update_label() {
-        Gdk.Color color = {(uint32)(fg.pixel*this.alpha.val + bg.pixel*(1.0 - this.alpha.val)),
-                           (uint16)(fg.red*this.alpha.val + bg.red*(1.0 - this.alpha.val)),
-                           (uint16)(fg.green*this.alpha.val + bg.green*(1.0 - this.alpha.val)),
-                           (uint16)(fg.blue*this.alpha.val + bg.blue*(1.0 - this.alpha.val))};
-        
-        this.modify_fg(Gtk.StateType.NORMAL, color);
-    }
-    
-    /////////////////////////////////////////////////////////////////////
-    /// Chooses the next random tip.
-    /////////////////////////////////////////////////////////////////////
-    
-    private void set_random_tip() {
-        if (tips.length > 1) {
-            int next_index = -1;
-            do {
-                next_index = GLib.Random.int_range(0, tips.length);
-            } while (next_index == this.index);
-            this.index = next_index;
-            this.label = tips[this.index];
-        }
-    }
-}
-
-}
diff --git a/src/gui/triggerSelectButton.vala b/src/gui/triggerSelectButton.vala
new file mode 100644
index 0000000..eeb37e2
--- /dev/null
+++ b/src/gui/triggerSelectButton.vala
@@ -0,0 +1,161 @@
+/* 
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program 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 General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program.  If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////    
+/// This window allows the selection of a hotkey. It is returned in form
+/// of a Trigger. Therefore it can be either a keyboard driven hotkey or
+/// a mouse based hotkey.
+/////////////////////////////////////////////////////////////////////////
+
+public class TriggerSelectButton : Gtk.ToggleButton {
+    
+    /////////////////////////////////////////////////////////////////////
+    /// This signal is emitted when the user selects a new hot key.
+    /////////////////////////////////////////////////////////////////////
+    
+    public signal void on_select(Trigger trigger);
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The currently contained Trigger.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Trigger trigger = null;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// True, if mouse buttons can be bound as well.
+    /////////////////////////////////////////////////////////////////////
+     
+    private bool enable_mouse = false;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// These modifiers are ignored.
+    /////////////////////////////////////////////////////////////////////
+    
+    private Gdk.ModifierType lock_modifiers = Gdk.ModifierType.MOD2_MASK
+                                             |Gdk.ModifierType.LOCK_MASK
+                                             |Gdk.ModifierType.MOD5_MASK;
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, constructs a new TriggerSelectWindow.
+    /////////////////////////////////////////////////////////////////////
+    
+    public TriggerSelectButton(bool enable_mouse) {
+        this.enable_mouse = enable_mouse;
+    
+        this.toggled.connect(() => {
+            if (this.active) {
+                this.set_label(_("Press a hotkey ..."));
+                Gtk.grab_add(this);
+                FocusGrabber.grab(this.get_window(), true, true, true);
+            }
+        });
+        
+        this.button_press_event.connect(this.on_button_press);
+        this.key_press_event.connect(this.on_key_press);
+        this.set_trigger(new Trigger());
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes the button display the given Trigger.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_trigger(Trigger trigger) {
+        this.trigger = trigger;
+        this.set_label(trigger.label);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Can be called to cancel the selection process.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void cancel() {
+        this.set_label(trigger.label);
+        this.set_active(false);
+        Gtk.grab_remove(this);
+        FocusGrabber.ungrab(true, true);
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Makes the button display the given Trigger.
+    /////////////////////////////////////////////////////////////////////
+    
+    private void update_trigger(Trigger trigger) {
+        if (this.trigger.name != trigger.name) {
+            this.set_trigger(trigger);
+            this.on_select(this.trigger);
+        }
+        
+        this.cancel();
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user presses a keyboard key.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool on_key_press(Gdk.EventKey event) {
+        if (this.active) {
+            if (Gdk.keyval_name(event.keyval) == "Escape") {
+                this.cancel();
+            } else if (Gdk.keyval_name(event.keyval) == "BackSpace") {
+                this.update_trigger(new Trigger());
+            } else if (event.is_modifier == 0) {
+                Gdk.ModifierType state = event.state & ~ this.lock_modifiers;
+                this.update_trigger(new Trigger.from_values(event.keyval, state, false, false, false, false));
+            }
+            
+            return true;
+        }
+        return false;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Called when the user presses a button of the mouse.
+    /////////////////////////////////////////////////////////////////////
+    
+    private bool on_button_press(Gdk.EventButton event) {
+        if (this.active) {
+                Gtk.Allocation rect;
+                this.get_allocation(out rect);
+                if (event.x < rect.x || event.x > rect.x + rect.width
+                 || event.y < rect.y || event.y > rect.y + rect.height) {
+                 
+                    this.cancel();
+                    return true;
+                }
+            }
+            
+            if (this.active && this.enable_mouse) {
+                Gdk.ModifierType state = event.state & ~ this.lock_modifiers;
+                var new_trigger = new Trigger.from_values((int)event.button, state, true,
+                                                          false, false, false);
+                                                          
+                if (new_trigger.key_code != 1) this.update_trigger(new_trigger);
+                else                           this.cancel();
+                
+                return true;
+            } else if (this.active) {
+                this.cancel();
+                return true;
+            }
+            
+            return false;
+    }
+}
+
+}
diff --git a/src/gui/triggerSelectWindow.vala b/src/gui/triggerSelectWindow.vala
index e003a84..23eea3c 100644
--- a/src/gui/triggerSelectWindow.vala
+++ b/src/gui/triggerSelectWindow.vala
@@ -23,21 +23,23 @@ namespace GnomePie {
 /// a mouse based hotkey.
 /////////////////////////////////////////////////////////////////////////
 
-public class TriggerSelectWindow : Gtk.Dialog {
+public class TriggerSelectWindow : GLib.Object {
     
     /////////////////////////////////////////////////////////////////////
     /// This signal is emitted when the user selects a new hot key.
     /////////////////////////////////////////////////////////////////////
     
-    public signal void on_select(Trigger trigger);
+    public signal void on_ok(Trigger trigger);
     
     /////////////////////////////////////////////////////////////////////
     /// Some private members which are needed by other methods.
     /////////////////////////////////////////////////////////////////////
     
+    private Gtk.Dialog window;
     private Gtk.CheckButton turbo;
     private Gtk.CheckButton delayed;
-    private Gtk.Label preview;
+    private Gtk.CheckButton centered;
+    private TriggerSelectButton button;
     
     /////////////////////////////////////////////////////////////////////
     /// The currently configured trigger.
@@ -53,205 +55,134 @@ public class TriggerSelectWindow : Gtk.Dialog {
     
     private Trigger original_trigger = null;
     
-    /////////////////////////////////////////////////////////////////////
-    /// These modifiers are ignored.
-    /////////////////////////////////////////////////////////////////////
-    
-    private Gdk.ModifierType lock_modifiers = Gdk.ModifierType.MOD2_MASK
-                                             |Gdk.ModifierType.LOCK_MASK
-                                             |Gdk.ModifierType.MOD5_MASK;
-    
     /////////////////////////////////////////////////////////////////////
     /// C'tor, constructs a new TriggerSelectWindow.
     /////////////////////////////////////////////////////////////////////
     
     public TriggerSelectWindow() {
-        this.title = _("Define an open-command");
-        this.resizable = false;
-        this.delete_event.connect(hide_on_delete);
-        this.key_press_event.connect(on_key_press);
-        this.button_press_event.connect(on_button_press);
-        
-        this.show.connect_after(() => {
-            FocusGrabber.grab(this);
-        });
+        try {
         
-        this.hide.connect(() => {
-            FocusGrabber.ungrab(this);
-        });
+            Gtk.Builder builder = new Gtk.Builder();
+
+            builder.add_from_file (Paths.ui_files + "/trigger_select.ui");
 
-        var container = new Gtk.VBox(false, 6);
-            container.set_border_width(6);
-             
-             // click area
-             var click_frame = new Gtk.Frame(_("Click here if you want to bind a mouse button!"));
+            this.window = builder.get_object("window") as Gtk.Dialog;
+            this.button = new TriggerSelectButton(true);
+            this.button.show();
             
-                var click_box = new Gtk.EventBox();
-                    click_box.height_request = 100;
-                    click_box.button_press_event.connect(on_area_clicked);
-                    
-                    this.preview = new Gtk.Label(null);
-                    
-                    click_box.add(this.preview);
-                    
-                click_frame.add(click_box);
-                
-            container.pack_start(click_frame, false);
+            this.button.on_select.connect((trigger) => {
+                this.trigger = new Trigger.from_values(trigger.key_sym,
+                                                       trigger.modifiers,
+                                                       trigger.with_mouse,
+                                                       this.turbo.active,
+                                                       this.delayed.active,
+                                                       this.centered.active);
+            });
             
-            // turbo checkbox
-            this.turbo = new Gtk.CheckButton.with_label (_("Turbo mode"));
-                this.turbo.tooltip_text = _("If checked, the Pie will close when you " + 
-                                            "release the chosen hot key.");
-                this.turbo.active = false;
-                this.turbo.toggled.connect(() => {
-                	if (this.trigger != null)
-		            	this.update_trigger(new Trigger.from_values(
-		            		this.trigger.key_sym, this.trigger.modifiers,
-							this.trigger.with_mouse, this.turbo.active,
-							this.delayed.active));
-                });
-                
-            container.pack_start(turbo, false);
+            (builder.get_object("trigger-box") as Gtk.VBox).pack_start(this.button, true, true);
+            
+            (builder.get_object("ok-button") as Gtk.Button).clicked.connect(this.on_ok_button_clicked);
+            (builder.get_object("cancel-button") as Gtk.Button).clicked.connect(this.on_cancel_button_clicked);
+            
+            this.turbo = builder.get_object("turbo-check") as Gtk.CheckButton;
+            this.turbo.toggled.connect(this.on_check_toggled);
             
-            // delayed checkbox
-            this.delayed = new Gtk.CheckButton.with_label (_("Long press for activation"));
-                this.delayed.tooltip_text = _("If checked, the Pie will only open if you " + 
-                                              "press this hot key a bit longer.");
-                this.delayed.active = false;
-                this.delayed.toggled.connect(() => {
-                	if (this.trigger != null)
-		            	this.update_trigger(new Trigger.from_values(
-		            		this.trigger.key_sym, this.trigger.modifiers,
-							this.trigger.with_mouse, this.turbo.active,
-							this.delayed.active));
-                });
+            this.delayed = builder.get_object("delay-check") as Gtk.CheckButton;
+            this.delayed.toggled.connect(this.on_check_toggled);
+            
+            this.centered = builder.get_object("center-check") as Gtk.CheckButton;
+            this.centered.toggled.connect(this.on_check_toggled);
+            
+            this.window.delete_event.connect(this.window.hide_on_delete);
                 
-            container.pack_start(delayed, false);
-
-        container.show_all();
-        
-        this.vbox.pack_start(container, true, true);
-        
-        this.add_button(Gtk.Stock.CANCEL, 1);
-        this.add_button(Gtk.Stock.OK, 0);
-        
-        // select a new trigger on OK, hide on CANCEL
-        this.response.connect((id) => {
-        	if (id == 1)
-        		this.hide();
-        	else if (id == 0) {
-        		var assigned_id = PieManager.get_assigned_id(this.trigger);
+        } catch (GLib.Error e) {
+            error("Could not load UI: %s\n", e.message);
+        }
+    }
     
-				if (this.trigger == this.original_trigger) {
-					// nothing did change
-					this.hide();
-				} else if (this.trigger.key_code == this.original_trigger.key_code
-						   && this.trigger.modifiers == this.original_trigger.modifiers
-						   && this.trigger.with_mouse == this.original_trigger.with_mouse) {
-					// only turbo and/or delayed mode changed, no need to check for double assignment
-					this.on_select(this.trigger);
-				    this.hide();
-				} else if (assigned_id != "") {
-					// it's already assigned
-				    var error = _("This hotkey is already assigned to the pie \"%s\"! \n\nPlease select " +
-				                  "another one or cancel your selection.").printf(PieManager.get_name_of(assigned_id));
-				    var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), 
-				    									Gtk.DialogFlags.MODAL, 
-				                                        Gtk.MessageType.ERROR, 
-				                                        Gtk.ButtonsType.CANCEL, 
-				                                        error);
-				    dialog.run();
-				    dialog.destroy();
-				} else {
-					// a unused hot key has been chosen, great!
-				    this.on_select(this.trigger);
-				    this.hide();
-				}
-        	}
-        });
+    /////////////////////////////////////////////////////////////////////
+    /// Sets the parent window, in order to make this window stay in
+    /// front.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void set_parent(Gtk.Window parent) {
+        this.window.set_transient_for(parent);
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Used to set the currently selected trigger on opening.
+    /// Displays the window on the screen.
     /////////////////////////////////////////////////////////////////////
     
-    public void set_trigger(Trigger trigger) {
-        this.turbo.active = trigger.turbo;
-        this.delayed.active = trigger.delayed;
-        this.original_trigger = trigger;
-        this.update_trigger(trigger);
+    public void show() {
+        this.window.show_all();
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Called when the user clicks in the click area.
+    /// Initilizes all members to match the Trigger of the Pie with the
+    /// given ID.
     /////////////////////////////////////////////////////////////////////
     
-    private bool on_area_clicked(Gdk.EventButton event) {
-        Gdk.ModifierType state = event.state & ~ this.lock_modifiers;
+    public void set_pie(string id) {
+        var trigger = new Trigger.from_string(PieManager.get_accelerator_of(id));
         
-        var new_trigger = new Trigger.from_values((int)event.button, state, true, 
-                                                  this.turbo.active, this.delayed.active);
-        if (new_trigger.key_code == 1) {
-            var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, 
-                                                Gtk.MessageType.WARNING, 
-                                                Gtk.ButtonsType.YES_NO, 
-                                                _("It possible to make your system unusable if " +
-                                                  "you bind a Pie to your left mouse button. Do " +
-                                                  "you really want to do this?"));
-                                                 
-            dialog.response.connect((response) => {
-                if (response == Gtk.ResponseType.YES) {
-                    this.update_trigger(new_trigger);
-                }
-            });
-            
-            dialog.run();
-            dialog.destroy();
-        } else {
-            this.update_trigger(new_trigger);
-        }
+        this.turbo.active = trigger.turbo;
+        this.delayed.active = trigger.delayed;
+        this.centered.active = trigger.centered;
+        this.original_trigger = trigger;
+        this.trigger = trigger;
         
-        return true;
+        this.button.set_trigger(trigger);
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Called when the user presses a keyboard key.
+    /// Called when one of the three checkoxes is toggled.
     /////////////////////////////////////////////////////////////////////
     
-    private bool on_key_press(Gdk.EventKey event) {
-        if (Gdk.keyval_name(event.keyval) == "Escape") {
-            this.hide();
-        } else if (Gdk.keyval_name(event.keyval) == "BackSpace") {
-            this.update_trigger(new Trigger());
-        } else if (event.is_modifier == 0) {
-            Gdk.ModifierType state = event.state & ~ this.lock_modifiers;
-            this.update_trigger(new Trigger.from_values((int)event.keyval, state, false, 
-                                                   this.turbo.active, this.delayed.active));
-        }
-        
-        return true;
+    private void on_check_toggled() {
+        if (this.trigger != null)
+            this.trigger = new Trigger.from_values(this.trigger.key_sym, this.trigger.modifiers,
+                                                   this.trigger.with_mouse, this.turbo.active,
+                                                   this.delayed.active, this.centered.active);
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Called when the user presses a mouse button.
+    /// Called when the OK-button is pressed.
     /////////////////////////////////////////////////////////////////////
     
-    private bool on_button_press(Gdk.EventButton event) {
-        int width = 0, height = 0;
-        this.window.get_geometry(null, null, out width, out height, null);
-        if (event.x < 0 || event.x > width || event.y < 0 || event.y > height)
-            this.hide();
-        return true;
+    private void on_ok_button_clicked() {
+        var assigned_id = PieManager.get_assigned_id(this.trigger);
+    
+        if (this.trigger == this.original_trigger) {
+            // nothing did change
+            this.window.hide();
+        } else if (this.trigger.key_code == this.original_trigger.key_code
+                && this.trigger.modifiers == this.original_trigger.modifiers
+                && this.trigger.with_mouse == this.original_trigger.with_mouse) {
+            // only turbo and/or delayed mode changed, no need to check for double assignment
+            this.on_ok(this.trigger);
+            this.window.hide();
+        } else if (assigned_id != "") {
+            // it's already assigned
+            var error = _("This hotkey is already assigned to the pie \"%s\"! \n\nPlease select " +
+                          "another one or cancel your selection.").printf(PieManager.get_name_of(assigned_id));
+            var dialog = new Gtk.MessageDialog((Gtk.Window)this.window.get_toplevel(), Gtk.DialogFlags.MODAL,
+                                               Gtk.MessageType.ERROR, Gtk.ButtonsType.CANCEL, error);
+            dialog.run();
+            dialog.destroy();
+        } else {
+            // a unused hot key has been chosen, great!
+            this.on_ok(this.trigger);
+            this.window.hide();
+        }
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Helper method to update the content of the trigger preview label.
+    /// Called when the cancel button is pressed.
     /////////////////////////////////////////////////////////////////////
     
-    private void update_trigger(Trigger new_trigger) {
-    	this.trigger = new_trigger;
-        this.preview.set_markup("<big><b>" + this.trigger.label + "</b></big>");
-    }     
+    private void on_cancel_button_clicked() {
+        this.window.hide();
+    } 
 }
 
 }
diff --git a/src/images/icon.vala b/src/images/icon.vala
index 1c8a9f4..81eb2d9 100644
--- a/src/images/icon.vala
+++ b/src/images/icon.vala
@@ -80,7 +80,17 @@ public class Icon : Image {
     
     public static string get_icon_file(string icon_name, int size) {
         string result = "";
-    
+        
+        if (icon_name.contains("/")) {
+            var file = GLib.File.new_for_path(icon_name);
+            if(file.query_exists())
+                return icon_name;
+            
+            warning("Icon \"" + icon_name + "\" not found! Using default icon...");
+            icon_name = "application-default-icon";
+        }
+            
+        
         var icon_theme = Gtk.IconTheme.get_default();
         var file = icon_theme.lookup_icon(icon_name, size, 0);
         if (file != null) result = file.get_filename();
diff --git a/src/images/image.vala b/src/images/image.vala
index 836e4e2..1d9674b 100644
--- a/src/images/image.vala
+++ b/src/images/image.vala
@@ -65,14 +65,39 @@ public class Image : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public Image.from_pixbuf(Gdk.Pixbuf pixbuf) {
-        this.load_pixbuf(pixbuf);
+        if (pixbuf != null) this.load_pixbuf(pixbuf);
+        else                this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, 1, 1);
     }
     
-    public Image.capture_screen(int posx, int posy, int width, int height) {
+    /////////////////////////////////////////////////////////////////////
+    /// Captures a part of the screen.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Image.capture_screen(int posx, int posy, int width, int height, bool hide_pies = true) {
         Gdk.Window root = Gdk.get_default_root_window();
-        Gdk.Pixbuf pixbuf = Gdk.pixbuf_get_from_drawable(null, root, null, posx, posy, 0, 0, width, height);
+        #if HAVE_GTK_3
+            Gdk.Pixbuf pixbuf = Gdk.pixbuf_get_from_window(root, posx, posy, width, height);
+        #else
+            Gdk.Pixbuf pixbuf = Gdk.pixbuf_get_from_drawable(null, root, null, posx, posy, 0, 0, width, height);
+        #endif
+
 
         this.load_pixbuf(pixbuf);
+        
+        if (hide_pies) {
+            // check for opened pies
+            foreach (var window in PieManager.opened_windows) {
+                if (window.background != null) {
+                    int x=0, y=0, dx=0, dy=0;
+                    window.get_position(out x, out y);
+                    window.get_size(out dx, out dy);
+
+                    var ctx = this.context();
+                    ctx.translate((int)(x-posx + (dx+3)/2), (int)(y-posy + (dy+3)/2));                    
+                    window.background.paint_on(ctx);
+                }
+            }
+        }
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -87,6 +112,7 @@ public class Image : GLib.Object {
                 this.load_pixbuf(pixbuf);
             } else {
                 warning("Failed to load " + filename + "!");
+                this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, 1, 1);
             }
         } catch (GLib.Error e) {
             message("Error loading image file: %s", e.message);
@@ -106,6 +132,7 @@ public class Image : GLib.Object {
                 this.load_pixbuf(pixbuf);
             } else {
                 warning("Failed to load " + filename + "!");
+                this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height);
             }
         } catch (GLib.Error e) {
             message("Error loading image file: %s", e.message);
@@ -130,17 +157,39 @@ public class Image : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public void paint_on(Cairo.Context ctx, double alpha = 1.0) {
-        ctx.set_source_surface(this.surface, -0.5*this.width()-1, -0.5*this.height()-1);
+        ctx.set_source_surface(this.surface, (int)(-0.5*this.width()-1), (int)(-0.5*this.height()-1));
         if (alpha >= 1.0) ctx.paint();
         else              ctx.paint_with_alpha(alpha);
     }
     
+    /////////////////////////////////////////////////////////////////////
+    /// Converts the image to a Gdk.Pixbuf.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Gdk.Pixbuf to_pixbuf() {
+        var pixbuf = new Gdk.Pixbuf.from_data(surface.get_data(), Gdk.Colorspace.RGB, true, 8, 
+                                              width(), height(), surface.get_stride(), null);
+        
+        pixbuf = pixbuf.copy();
+                                       
+        // funny stuff here --- need to swap Red end Blue because Cairo 
+        // and Gdk are different...
+        uint8* p = pixbuf.pixels;
+        for (int i=0; i<width()*height()*4-4; i+=4) {
+            var tmp = *(p + i);
+            *(p + i) = *(p + i + 2);
+            *(p + i + 2) = tmp;
+        }
+		
+		return pixbuf;
+    }
+    
     /////////////////////////////////////////////////////////////////////
     /// Returns a Cairo.Context for the Image.
     /////////////////////////////////////////////////////////////////////
     
     public Cairo.Context context() {
-        return new Cairo.Context(this.surface);;
+        return new Cairo.Context(this.surface);
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -148,7 +197,9 @@ public class Image : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public int width() {
-        return this.surface.get_width();
+        if (this.surface != null)
+            return this.surface.get_width();
+        return 0;
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -156,7 +207,9 @@ public class Image : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public int height() {
-        return this.surface.get_height();
+        if (this.surface != null)
+            return this.surface.get_height();
+        return 0;
     }
 }
 
diff --git a/src/images/renderedText.vala b/src/images/renderedText.vala
index 924742a..e4bb4cb 100644
--- a/src/images/renderedText.vala
+++ b/src/images/renderedText.vala
@@ -55,12 +55,36 @@ public class RenderedText : Image {
     /// C'tor, creates a new image representation of a string.
     /////////////////////////////////////////////////////////////////////
     
-    public RenderedText(string text, int width, int height, string font) {
-        var cached = this.cache.get("%s@%ux%u:%s".printf(text, width, height, font));
+    public RenderedText(string text, int width, int height, string font,
+                        Color color, double scale) {
+                        
+        var cached = this.cache.get("%s@%ux%u@%f:%s:%f:%f:%f:%f".printf(text, width, height, scale, font,
+                                                               color.r, color.g, color.b, color.a));
         
         if (cached == null) {
-            this.render_text(text, width, height, font);
-            this.cache.set("%s@%ux%u:%s".printf(text, width, height, font), this.surface);
+            this.render_text(text, width, height, font, color, scale);
+            this.cache.set("%s@%ux%u@%f:%s:%f:%f:%f:%f".printf(text, width, height, scale, font,
+                                                 color.r, color.g, color.b, color.a), this.surface);
+        } else {
+            this.surface = cached;
+        }
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, creates a new image representation of a string. This
+    /// string may contain markup information.
+    /////////////////////////////////////////////////////////////////////
+    
+    public RenderedText.with_markup(string text, int width, int height, string font,
+                        Color color, double scale) {
+                        
+        var cached = this.cache.get("%s@%ux%u@%f:%s:%f:%f:%f:%f".printf(text, width, height, scale, font,
+                                                               color.r, color.g, color.b, color.a));
+        
+        if (cached == null) {
+            this.render_markup(text, width, height, font, color, scale);
+            this.cache.set("%s@%ux%u@%f:%s:%f:%f:%f:%f".printf(text, width, height, scale, font,
+                                                 color.r, color.g, color.b, color.a), this.surface);
         } else {
             this.surface = cached;
         }
@@ -70,20 +94,21 @@ public class RenderedText : Image {
     /// Creates a new transparent image, with text written onto.
     /////////////////////////////////////////////////////////////////////
     
-    public void render_text(string text, int width, int height, string font) {
+    public void render_text(string text, int width, int height, string font, 
+                            Color color, double scale) {
+                            
         this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height);
 
         var ctx = this.context();
         
-        // set the color as specified in the current theme
-        Color color = Config.global.theme.caption_color;
+        // set the color
         ctx.set_source_rgb(color.r, color.g, color.g);
         
         var layout = Pango.cairo_create_layout(ctx);        
         layout.set_width(Pango.units_from_double(width));
         
         var font_description = Pango.FontDescription.from_string(font);
-        font_description.set_size((int)(font_description.get_size() * Config.global.global_scale));
+        font_description.set_size((int)(font_description.get_size() * scale));
         
         layout.set_font_description(font_description);
         layout.set_text(text, -1);
@@ -105,6 +130,40 @@ public class RenderedText : Image {
         Pango.cairo_update_layout(ctx, layout);
         Pango.cairo_show_layout(ctx, layout);
     }
+    
+    /////////////////////////////////////////////////////////////////////
+    /// Creates a new transparent image, with text written onto.
+    /////////////////////////////////////////////////////////////////////
+    
+    public void render_markup(string text, int width, int height, string font, 
+                            Color color, double scale) {
+                            
+        this.surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height);
+
+        var ctx = this.context();
+        
+        // set the color 
+        ctx.set_source_rgb(color.r, color.g, color.g);
+        
+        var layout = Pango.cairo_create_layout(ctx);        
+        layout.set_width(Pango.units_from_double(width));
+        
+        var font_description = Pango.FontDescription.from_string(font);
+        font_description.set_size((int)(font_description.get_size() * scale));
+        
+        layout.set_font_description(font_description);
+        layout.set_markup(text, -1);
+        
+        layout.set_ellipsize(Pango.EllipsizeMode.END);
+        layout.set_alignment(Pango.Alignment.CENTER);
+        
+        Pango.Rectangle extents;
+        layout.get_pixel_extents(null, out extents);
+        ctx.move_to(0, (int)(0.5*(height - extents.height)));
+        
+        Pango.cairo_update_layout(ctx, layout);
+        Pango.cairo_show_layout(ctx, layout);
+    }
 }
 
 }
diff --git a/src/images/themedIcon.vala b/src/images/themedIcon.vala
index 29ae380..6c904a6 100644
--- a/src/images/themedIcon.vala
+++ b/src/images/themedIcon.vala
@@ -76,7 +76,7 @@ public class ThemedIcon : Image {
         var layers = active ? Config.global.theme.active_slice_layers : Config.global.theme.inactive_slice_layers;
         
         // get max size
-        int size = 0;
+        int size = 1;
         foreach (var layer in layers) {
             if (layer.image.width() > size) size = layer.image.width();
         }
diff --git a/src/pies/load.vala b/src/pies/load.vala
index 98fd72f..b606cf5 100644
--- a/src/pies/load.vala
+++ b/src/pies/load.vala
@@ -80,7 +80,7 @@ namespace Pies {
         string name = "";
         string icon = "";
         string id = "";
-        int quick_action = -1;
+        int quickaction = -1;
         
         // parse all attributes of this node
         for (Xml.Attr* attribute = node->properties; attribute != null; attribute = attribute->next) {
@@ -92,7 +92,7 @@ namespace Pies {
                     hotkey = attr_content;
                     break;
                 case "quickaction":
-                    quick_action = int.parse(attr_content);
+                    quickaction = int.parse(attr_content);
                     break;
                 case "name":
                     name = attr_content;
@@ -145,7 +145,7 @@ namespace Pies {
         string icon="";
         string command="";
         string type="";
-        bool quick_action = false;
+        bool quickaction = false;
         
         // parse all attributes of this node
         for (Xml.Attr* attribute = slice->properties; attribute != null; attribute = attribute->next) {
@@ -166,7 +166,7 @@ namespace Pies {
                     type = attr_content;
                     break;
                 case "quickaction":
-                    quick_action = bool.parse(attr_content);
+                    quickaction = bool.parse(attr_content);
                     break;
                 default:
                     warning("Invalid attribute \"" + attr_name + "\" in <slice> element in pies.conf!");
@@ -174,19 +174,8 @@ namespace Pies {
             }
         }
         
-        Action action = null;
-        
         // create a new Action according to the loaded type
-        foreach (var action_type in ActionRegistry.types) {
-            if (ActionRegistry.settings_names[action_type] == type) {
-            
-                action = GLib.Object.new(action_type, "name", name, 
-                                                      "icon", icon, 
-                                              "real_command", command, 
-                                           "is_quick_action", quick_action) as Action;
-                break;
-            } 
-        }
+        Action action = ActionRegistry.create_action(type, name, icon, command, quickaction);
         
         if (action != null) pie.add_action(action);
     }
@@ -213,15 +202,7 @@ namespace Pies {
             }
         }
         
-        ActionGroup group = null;
-        
-        // create a new ActionGroup according to the loaded type
-        foreach (var group_type in GroupRegistry.types) {
-            if (GroupRegistry.settings_names[group_type] == type) {
-                group = GLib.Object.new(group_type, "parent_id", pie.id) as ActionGroup;
-                break;
-            } 
-        }
+        ActionGroup group = GroupRegistry.create_group(type, pie.id);
 
         if (group != null) pie.add_group(group);
     }
diff --git a/src/pies/pie.vala b/src/pies/pie.vala
index 0f87d8f..fa205c7 100644
--- a/src/pies/pie.vala
+++ b/src/pies/pie.vala
@@ -29,14 +29,14 @@ public class Pie : GLib.Object {
     /// The name of this Pie. It has not to be unique.
     /////////////////////////////////////////////////////////////////////
     
-    public string name { get; construct; }
+    public string name { get; set; }
     
     /////////////////////////////////////////////////////////////////////
     /// The name of the icon to be used for this Pie. It should exist in
     /// the users current icon theme, else a standard icon will be used.
     /////////////////////////////////////////////////////////////////////
     
-    public string icon { get; construct; }
+    public string icon { get; set; }
     
     /////////////////////////////////////////////////////////////////////
     /// The ID of this Pie. It has to be unique among all Pies. This ID
@@ -77,18 +77,44 @@ public class Pie : GLib.Object {
     /// Adds an Action to this Pie.
     /////////////////////////////////////////////////////////////////////
     
-    public void add_action(Action action) {
+    public void add_action(Action action, int at_position = -1) {
         var group = new ActionGroup(this.id);
             group.add_action(action);
-        this.add_group(group);
+        this.add_group(group, at_position);
     }
     
     /////////////////////////////////////////////////////////////////////
     /// Adds an ActionGroup to this Pie.
     /////////////////////////////////////////////////////////////////////
     
-    public void add_group(ActionGroup group) {
-        this.action_groups.add(group);
+    public void add_group(ActionGroup group, int at_position = -1) {     
+        if (group.has_quickaction()) {
+            foreach (var action_group in action_groups)
+                action_group.disable_quickactions();
+        }
+            
+        if (at_position < 0 || at_position >= this.action_groups.size) 
+            this.action_groups.add(group);
+        else
+            this.action_groups.insert(at_position, group);
+    }
+    
+    public void remove_group(int index) {
+        if (this.action_groups.size > index)
+            this.action_groups.remove_at(index);
+    }
+    
+    public void move_group(int from, int to) {
+        if (this.action_groups.size > from && this.action_groups.size > to) {
+            var tmp = this.action_groups[from];
+            this.remove_group(from);
+            this.add_group(tmp, to);
+        }
+    }
+    
+    public void update_group(ActionGroup group, int index) {
+        if (this.action_groups.size > index)
+            this.action_groups.set(index, group);
     }
 }
 
diff --git a/src/pies/pieManager.vala b/src/pies/pieManager.vala
index 5f84ea0..0263d23 100644
--- a/src/pies/pieManager.vala
+++ b/src/pies/pieManager.vala
@@ -31,6 +31,13 @@ public class PieManager : GLib.Object {
 
     public static Gee.HashMap<string, Pie?> all_pies { get; private set; }
     
+    /////////////////////////////////////////////////////////////////////
+    /// Stores all PieWindows which are currently opened. Should be
+    /// rarely more than two...
+    /////////////////////////////////////////////////////////////////////
+    
+    public static Gee.HashSet<PieWindow?> opened_windows { get; private set; }
+    
     /////////////////////////////////////////////////////////////////////
     /// Stores all global hotkeys.
     /////////////////////////////////////////////////////////////////////
@@ -42,7 +49,7 @@ public class PieManager : GLib.Object {
     /// will be false already.
     /////////////////////////////////////////////////////////////////////
     
-    private static bool a_pie_is_opened = false;
+    private static bool a_pie_is_active = false;
     
     /////////////////////////////////////////////////////////////////////
     /// Initializes all Pies. They are loaded from the pies.conf file.
@@ -50,6 +57,7 @@ public class PieManager : GLib.Object {
     
     public static void init() {
         all_pies = new Gee.HashMap<string, Pie?>();
+        opened_windows = new Gee.HashSet<PieWindow?>();
         bindings = new BindingManager();
         
         // load all Pies from th pies.conf file
@@ -66,19 +74,27 @@ public class PieManager : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public static void open_pie(string id) {
-        if (!a_pie_is_opened) {
+        if (!a_pie_is_active) {
             Pie? pie = all_pies[id];
             
             if (pie != null) {
-                a_pie_is_opened = true;
+                a_pie_is_active = true;
                 
                 var window = new PieWindow();
                 window.load_pie(pie);
                 window.open();
                 
+                opened_windows.add(window);
+                
+                window.on_closed.connect(() => {
+                    opened_windows.remove(window);
+                });
+                
                 window.on_closing.connect(() => {
-                    a_pie_is_opened = false;
+                    a_pie_is_active = false;
                 });
+                
+                
             } else {
                 warning("Failed to open pie with ID \"" + id + "\": ID does not exist!");
             }
@@ -102,6 +118,15 @@ public class PieManager : GLib.Object {
         return bindings.get_accelerator_label_of(id);
     }
     
+    /////////////////////////////////////////////////////////////////////
+    /// Bind the Pie with the given ID to the given trigger.
+    /////////////////////////////////////////////////////////////////////
+    
+    public static void bind_trigger(Trigger trigger, string id) {
+        bindings.unbind(id);
+        bindings.bind(trigger, id);
+    }
+    
     /////////////////////////////////////////////////////////////////////
     /// Returns true if the pie with the given id is in turbo mode.
     /////////////////////////////////////////////////////////////////////
@@ -110,6 +135,15 @@ public class PieManager : GLib.Object {
         return bindings.get_is_turbo(id);
     }
     
+    /////////////////////////////////////////////////////////////////////
+    /// Returns true if the pie with the given id opens in the middle of
+    /// the screen.
+    /////////////////////////////////////////////////////////////////////
+    
+    public static bool get_is_centered(string id) {
+        return bindings.get_is_centered(id);
+    }
+    
     /////////////////////////////////////////////////////////////////////
     /// Returns the name of the Pie with the given ID.
     /////////////////////////////////////////////////////////////////////
@@ -212,7 +246,11 @@ public class PieManager : GLib.Object {
         }
     }
     
-    private static void create_launcher(string id) {
+    /////////////////////////////////////////////////////////////////////
+    /// Creates a desktop file for which opens the Pie with given ID.
+    /////////////////////////////////////////////////////////////////////
+    
+    public static void create_launcher(string id) {
         if (all_pies.has_key(id)) {
             Pie? pie = all_pies[id];
             
@@ -220,7 +258,7 @@ public class PieManager : GLib.Object {
                 "#!/usr/bin/env xdg-open\n" + 
                 "[Desktop Entry]\n" +
                 "Name=%s\n".printf(pie.name) +
-                "Exec=gnome-pie -o %s\n".printf(pie.id) +
+                "Exec=%s -o %s\n".printf(Paths.executable, pie.id) +
                 "Encoding=UTF-8\n" +
                 "Type=Application\n" +
                 "Icon=%s\n".printf(pie.icon);
@@ -237,6 +275,10 @@ public class PieManager : GLib.Object {
         }
     }
     
+    /////////////////////////////////////////////////////////////////////
+    /// Deletes the desktop file for the Pie with the given ID.
+    /////////////////////////////////////////////////////////////////////
+    
     private static void remove_launcher(string id) {
         string launcher = Paths.launchers + "/%s.desktop".printf(id);
         if (FileUtils.test(launcher, FileTest.EXISTS)) {
diff --git a/src/pies/save.vala b/src/pies/save.vala
index d691a95..c940e5a 100644
--- a/src/pies/save.vala
+++ b/src/pies/save.vala
@@ -55,18 +55,18 @@ namespace Pies {
                     if (group.get_type().depth() == 2) {
                         foreach (var action in group.actions) {
                             writer.start_element("slice");
-                            writer.write_attribute("type", ActionRegistry.settings_names[action.get_type()]);
-                            if (ActionRegistry.icon_name_editables[action.get_type()]) {
+                            writer.write_attribute("type", ActionRegistry.descriptions[action.get_type().name()].id);
+                            if (ActionRegistry.descriptions[action.get_type().name()].icon_name_editable) {
                                 writer.write_attribute("name", action.name);
                                 writer.write_attribute("icon", action.icon);
                             }
                             writer.write_attribute("command", action.real_command);
-                            writer.write_attribute("quickAction", action.is_quick_action ? "true" : "false");
+                            writer.write_attribute("quickAction", action.is_quickaction ? "true" : "false");
                             writer.end_element();
                         }
                     } else {
                         writer.start_element("group");
-                            writer.write_attribute("type", GroupRegistry.settings_names[group.get_type()]);
+                            writer.write_attribute("type", GroupRegistry.descriptions[group.get_type().name()].id);
                         writer.end_element();
                     }
                 }
diff --git a/src/renderers/pieRenderer.vala b/src/renderers/pieRenderer.vala
index ffaf776..67a6b56 100644
--- a/src/renderers/pieRenderer.vala
+++ b/src/renderers/pieRenderer.vala
@@ -31,7 +31,7 @@ public class PieRenderer : GLib.Object {
     /// gets executed when the user clicks on the middle of the pie)
     /////////////////////////////////////////////////////////////////////
 
-    public int quick_action { get; private set; }
+    public int quickaction { get; private set; }
 
     /////////////////////////////////////////////////////////////////////
     /// The index of the currently active slice.
@@ -83,13 +83,13 @@ public class PieRenderer : GLib.Object {
     public PieRenderer() {
         this.slices = new Gee.ArrayList<SliceRenderer?>(); 
         this.center = new CenterRenderer(this);
-        this.quick_action = -1;
+        this.quickaction = -1;
         this.active_slice = -2;
         this.size = 0;
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Loads an Pie. All members are initialized accordingly.
+    /// Loads a Pie. All members are initialized accordingly.
     /////////////////////////////////////////////////////////////////////
     
     public void load_pie(Pie pie) {
@@ -102,8 +102,8 @@ public class PieRenderer : GLib.Object {
                 this.slices.add(renderer);
                 renderer.load(action, slices.size-1);
                 
-                if (action.is_quick_action) {
-                    this.quick_action = count;
+                if (action.is_quickaction) {
+                    this.quickaction = count;
                 }
                 
                 ++count;
@@ -112,7 +112,7 @@ public class PieRenderer : GLib.Object {
         
         this.turbo_mode = PieManager.get_is_turbo(pie.id);
         
-        this.set_highlighted_slice(this.quick_action);
+        this.set_highlighted_slice(this.quickaction);
         
         this.size = (int)fmax(2*Config.global.theme.radius + 2*Config.global.theme.slice_radius*Config.global.theme.max_zoom,
                               2*Config.global.theme.center_radius);
@@ -227,39 +227,41 @@ public class PieRenderer : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public void draw(double frame_time, Cairo.Context ctx, int mouse_x, int mouse_y) {
-	    double distance = sqrt(mouse_x*mouse_x + mouse_y*mouse_y);
-	    double angle = 0.0;
+        if (this.size > 0) {
+	        double distance = sqrt(mouse_x*mouse_x + mouse_y*mouse_y);
+	        double angle = 0.0;
 
-	    if (this.key_board_control) {
-	        angle = 2.0*PI*this.active_slice/(double)slice_count();
-	    } else {
-	    
-	        if (distance > 0) {
-	            angle = acos(mouse_x/distance);
-		        if (mouse_y < 0) 
-		            angle = 2*PI - angle;
-	        }
+	        if (this.key_board_control) {
+	            angle = 2.0*PI*this.active_slice/(double)slice_count();
+	        } else {
 	        
-	        int next_active_slice = this.active_slice;
+	            if (distance > 0) {
+	                angle = acos(mouse_x/distance);
+		            if (mouse_y < 0) 
+		                angle = 2*PI - angle;
+	            }
+	            
+	            int next_active_slice = this.active_slice;
+	            
+	            if (distance < Config.global.theme.active_radius
+	                && this.quickaction >= 0 && this.quickaction < this.slices.size) {
+	             
+	                next_active_slice = this.quickaction;   
+	                angle = 2.0*PI*quickaction/(double)slice_count();
+	            } else if (distance > Config.global.theme.active_radius && this.slice_count() > 0) {
+	                next_active_slice = (int)(angle*slices.size/(2*PI) + 0.5) % this.slice_count();
+	            } else {
+	                next_active_slice = -1;
+	            }
 	        
-	        if (distance < Config.global.theme.active_radius
-	            && this.quick_action >= 0 && this.quick_action < this.slices.size) {
-	         
-	            next_active_slice = this.quick_action;   
-	            angle = 2.0*PI*quick_action/(double)slice_count();
-	        } else if (distance > Config.global.theme.active_radius && this.slice_count() > 0) {
-	            next_active_slice = (int)(angle*slices.size/(2*PI) + 0.5) % this.slice_count();
-	        } else {
-	            next_active_slice = -1;
+	            this.set_highlighted_slice(next_active_slice);
 	        }
-	    
-	        this.set_highlighted_slice(next_active_slice);
-	    }
 
-        center.draw(frame_time, ctx, angle, distance);
-	    
-	    foreach (var slice in this.slices)
-		    slice.draw(frame_time, ctx, angle, distance);
+            center.draw(frame_time, ctx, angle, distance);
+	        
+	        foreach (var slice in this.slices)
+		        slice.draw(frame_time, ctx, angle, distance);
+		}
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -278,8 +280,8 @@ public class PieRenderer : GLib.Object {
         if (index != this.active_slice) {
             if (index >= 0 && index < this.slice_count()) 
                 this.active_slice = index;
-            else if (this.quick_action >= 0)
-                this.active_slice = this.quick_action;
+            else if (this.quickaction >= 0)
+                this.active_slice = this.quickaction;
             else
                 this.active_slice = -1;
             
diff --git a/src/renderers/pieWindow.vala b/src/renderers/pieWindow.vala
index 59117df..0a26110 100644
--- a/src/renderers/pieWindow.vala
+++ b/src/renderers/pieWindow.vala
@@ -31,6 +31,19 @@ public class PieWindow : Gtk.Window {
     
     public signal void on_closing();
     
+    /////////////////////////////////////////////////////////////////////
+    /// Signal which gets emitted when the PieWindow is closed.
+    /////////////////////////////////////////////////////////////////////
+    
+    public signal void on_closed();
+    
+    /////////////////////////////////////////////////////////////////////
+    /// The background image used for fake transparency if
+    /// has_compositing is false.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Image background { get; private set; default=null; }
+    
     /////////////////////////////////////////////////////////////////////
     /// The owned renderer.
     /////////////////////////////////////////////////////////////////////
@@ -55,13 +68,6 @@ public class PieWindow : Gtk.Window {
     
     private bool has_compositing = false;
     
-    /////////////////////////////////////////////////////////////////////
-    /// The background image used for fake transparency if
-    /// has_compositing is false.
-    /////////////////////////////////////////////////////////////////////
-    
-    private Image background = null;
-    
     /////////////////////////////////////////////////////////////////////
     /// C'tor, sets up the window.
     /////////////////////////////////////////////////////////////////////
@@ -73,7 +79,7 @@ public class PieWindow : Gtk.Window {
         this.set_skip_taskbar_hint(true);
         this.set_skip_pager_hint(true);
         this.set_keep_above(true);
-        this.set_type_hint(Gdk.WindowTypeHint.SPLASHSCREEN);
+        this.set_type_hint(Gdk.WindowTypeHint.UTILITY);
         this.set_decorated(false);
         this.set_resizable(false);
         this.icon_name = "gnome-pie";
@@ -81,7 +87,11 @@ public class PieWindow : Gtk.Window {
         
         // check for compositing
         if (this.screen.is_composited()) {
-            this.set_colormap(this.screen.get_rgba_colormap());
+            #if HAVE_GTK_3
+                this.set_visual(this.screen.get_rgba_visual());
+            #else
+                this.set_colormap(this.screen.get_rgba_colormap());
+            #endif
             this.has_compositing = true;
         }
         
@@ -128,9 +138,18 @@ public class PieWindow : Gtk.Window {
             this.renderer.on_mouse_move();
             return true;
         });
+        
+        this.show.connect_after(() => {
+            Gtk.grab_add(this);
+            FocusGrabber.grab(this.get_window(), true, true, false);
+        });
 
         // draw the pie on expose
-        this.expose_event.connect(this.draw);
+        #if HAVE_GTK_3
+            this.draw.connect(this.draw_window);
+        #else
+            this.expose_event.connect(this.draw_window);
+        #endif
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -139,7 +158,7 @@ public class PieWindow : Gtk.Window {
 
     public void load_pie(Pie pie) {
         this.renderer.load_pie(pie);
-        this.set_window_position();
+        this.set_window_position(pie);
         this.set_size_request(renderer.size, renderer.size);
     }
     
@@ -160,7 +179,6 @@ public class PieWindow : Gtk.Window {
     
         // capture the input focus
         this.show();
-        FocusGrabber.grab(this);
 
         // start the timer
         this.timer = new GLib.Timer();
@@ -178,10 +196,13 @@ public class PieWindow : Gtk.Window {
     /// Draw the Pie.
     /////////////////////////////////////////////////////////////////////
 
-    private bool draw(Gtk.Widget da, Gdk.EventExpose event) {    
-        // clear the window
-        var ctx = Gdk.cairo_create(this.window);
-
+    #if HAVE_GTK_3
+        private bool draw_window(Cairo.Context ctx) { 
+    #else
+        private bool draw_window(Gtk.Widget da, Gdk.EventExpose event) {    
+            // clear the window
+            var ctx = Gdk.cairo_create(this.get_window());
+    #endif
         // paint the background image if there is no compositing
         if (this.has_compositing) {
             ctx.set_operator (Cairo.Operator.CLEAR);
@@ -219,12 +240,13 @@ public class PieWindow : Gtk.Window {
         if (!this.closing) {
             this.closing = true;
             this.on_closing();
-            FocusGrabber.ungrab(this);
+            Gtk.grab_remove(this);
+            FocusGrabber.ungrab();
             this.renderer.activate();
             
             Timeout.add((uint)(Config.global.theme.fade_out_time*1000), () => {
+                this.on_closed();
                 this.destroy();
-                ThemedIcon.clear_cache();
                 return false;
             });
         }
@@ -238,12 +260,13 @@ public class PieWindow : Gtk.Window {
         if (!this.closing) {
             this.closing = true;
             this.on_closing();
-            FocusGrabber.ungrab(this);
+            Gtk.grab_remove(this);
+            FocusGrabber.ungrab();
             this.renderer.cancel();
             
             Timeout.add((uint)(Config.global.theme.fade_out_time*1000), () => {
+                this.on_closed();
                 this.destroy();
-                ThemedIcon.clear_cache();
                 return false;
             });
         }
@@ -254,9 +277,9 @@ public class PieWindow : Gtk.Window {
     /// the mouse.
     /////////////////////////////////////////////////////////////////////
     
-    private void set_window_position() {
-        if(Config.global.open_at_mouse) this.set_position(Gtk.WindowPosition.MOUSE);
-        else                            this.set_position(Gtk.WindowPosition.CENTER);
+    private void set_window_position(Pie pie) {
+        if(PieManager.get_is_centered(pie.id)) this.set_position(Gtk.WindowPosition.CENTER);
+        else                                   this.set_position(Gtk.WindowPosition.MOUSE);
     }
     
     /////////////////////////////////////////////////////////////////////
diff --git a/src/renderers/sliceRenderer.vala b/src/renderers/sliceRenderer.vala
index 61c50b1..4803070 100644
--- a/src/renderers/sliceRenderer.vala
+++ b/src/renderers/sliceRenderer.vala
@@ -20,7 +20,7 @@ using GLib.Math;
 namespace GnomePie {
 
 /////////////////////////////////////////////////////////////////////////    
-///  Renders a Slice of a Pie. According to the current theme.
+/// Renders a Slice of a Pie. According to the current theme.
 /////////////////////////////////////////////////////////////////////////
 
 public class SliceRenderer : GLib.Object {
@@ -123,7 +123,9 @@ public class SliceRenderer : GLib.Object {
             this.caption = new RenderedText(action.name, 
                                             Config.global.theme.caption_width,
                                             Config.global.theme.caption_height,
-                                            Config.global.theme.caption_font);
+                                            Config.global.theme.caption_font,
+                                            Config.global.theme.caption_color,
+                                            Config.global.global_scale);
             
         this.active_icon = new ThemedIcon(action.icon, true);
         this.inactive_icon = new ThemedIcon(action.icon, false);
@@ -138,7 +140,8 @@ public class SliceRenderer : GLib.Object {
         }
         
         this.hotkey = new RenderedText(hotkey_label, (int)Config.global.theme.slice_radius*2,
-                         (int)Config.global.theme.slice_radius*2, "sans 20");
+                         (int)Config.global.theme.slice_radius*2, "sans 20",
+                         Config.global.theme.caption_color, Config.global.global_scale);
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -185,6 +188,13 @@ public class SliceRenderer : GLib.Object {
     /////////////////////////////////////////////////////////////////////
 
     public void draw(double frame_time, Cairo.Context ctx, double angle, double distance) {
+    
+        // update the AnimatedValues
+        this.scale.update(frame_time);
+        this.alpha.update(frame_time);
+        this.fade.update(frame_time);
+        this.fade_scale.update(frame_time);
+        this.fade_rotation.update(frame_time);
 	    
 	    double direction = 2.0 * PI * position/parent.slice_count() + this.fade_rotation.val;
 	    double max_scale = 1.0/Config.global.theme.max_zoom;
@@ -205,13 +215,6 @@ public class SliceRenderer : GLib.Object {
         if (fabs(this.scale.end - max_scale) > Config.global.theme.max_zoom*0.005)
             this.scale.reset_target(max_scale, Config.global.theme.transition_time);
         
-        // update the AnimatedValues
-        this.scale.update(frame_time);
-        this.alpha.update(frame_time);
-        this.fade.update(frame_time);
-        this.fade_scale.update(frame_time);
-        this.fade_rotation.update(frame_time);
-	    
         ctx.save();
         
         // distance from the center
diff --git a/src/themes/theme.vala b/src/themes/theme.vala
index 284e1ef..269a574 100644
--- a/src/themes/theme.vala
+++ b/src/themes/theme.vala
@@ -55,6 +55,7 @@ public class Theme : GLib.Object {
     public int    caption_height   {get; private set; default=100;}
     public double caption_position {get; private set; default=0.0;}
     public Color  caption_color    {get; private set; default=new Color();}
+    public Icon   preview_icon     {get; private set; default=new Icon("gnome-pie", 36);}
     
     public Gee.ArrayList<CenterLayer?> center_layers         {get; private set;}
     public Gee.ArrayList<SliceLayer?>  active_slice_layers   {get; private set;}
@@ -82,6 +83,8 @@ public class Theme : GLib.Object {
         this.center_layers.clear();
         this.active_slice_layers.clear();
         this.inactive_slice_layers.clear();
+        
+        this.preview_icon = new Icon(this.directory + "/preview.png", 36);
     
         Xml.Parser.init();
         string path = this.directory + "/theme.xml";
diff --git a/src/utilities/animatedValue.vala b/src/utilities/animatedValue.vala
index 32ab889..7acc7a7 100644
--- a/src/utilities/animatedValue.vala
+++ b/src/utilities/animatedValue.vala
@@ -116,10 +116,16 @@ public class AnimatedValue : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public void reset_target(double end, double duration) {
-        this.start = this.val;
         this.end = end;
         this.duration = duration;
-        this.state = 0.0;
+        this.start = this.val;
+        
+        if (duration == 0.0) {
+            this.val = end;
+            this.state = 1.0;
+        } else {
+            this.state = 0.0;
+        }
     }
     
     /////////////////////////////////////////////////////////////////////
@@ -129,7 +135,7 @@ public class AnimatedValue : GLib.Object {
     public void update(double time) {
         this.state += time/this.duration;
         
-        if (state < 1) {
+        if (this.state < 1) {
         
             switch (this.type) {
                 case Type.LINEAR:
@@ -152,6 +158,7 @@ public class AnimatedValue : GLib.Object {
                 }
                 break;
             }
+            
         } else if (this.val != this.end) {
              this.val = this.end;
         }  
diff --git a/src/utilities/bindingManager.vala b/src/utilities/bindingManager.vala
index 437f4c1..5a4548e 100644
--- a/src/utilities/bindingManager.vala
+++ b/src/utilities/bindingManager.vala
@@ -54,6 +54,12 @@ public class BindingManager : GLib.Object {
         Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK
     };
     
+    /////////////////////////////////////////////////////////////////////
+    /// Some variables to remember which delayed binding was delayed.
+    /// When the delay passes without another event indicating that the
+    /// Trigger was released, the stored binding will be activated.
+    /////////////////////////////////////////////////////////////////////
+    
     private uint32 delayed_count = 0;
     private X.Event? delayed_event = null;
     private Keybinding? delayed_binding = null;
@@ -91,9 +97,8 @@ public class BindingManager : GLib.Object {
      
     public void bind(Trigger trigger, string id) {
         if(trigger.key_code != 0) {
-            Gdk.Window rootwin = Gdk.get_default_root_window();
-            X.Display display = Gdk.x11_drawable_get_xdisplay(rootwin);
-            X.ID xid = Gdk.x11_drawable_get_xid(rootwin);
+            X.Display display = Gdk.x11_get_default_xdisplay();
+            X.ID xid = Gdk.x11_get_default_root_xwindow();
         
             Gdk.error_trap_push();
  
@@ -121,9 +126,9 @@ public class BindingManager : GLib.Object {
     /////////////////////////////////////////////////////////////////////
  
     public void unbind(string id) {
-        Gdk.Window rootwin = Gdk.get_default_root_window();
-        X.Display display = Gdk.x11_drawable_get_xdisplay(rootwin);
-        X.ID xid = Gdk.x11_drawable_get_xid(rootwin);
+        X.Display display = Gdk.x11_get_default_xdisplay();
+        X.ID xid = Gdk.x11_get_default_root_xwindow();
+            
         Gee.List<Keybinding> remove_bindings = new Gee.ArrayList<Keybinding>();
         foreach(var binding in bindings) {
             if(id == binding.id) {
@@ -184,6 +189,20 @@ public class BindingManager : GLib.Object {
         return false;
     }
     
+    /////////////////////////////////////////////////////////////////////
+    /// Returns whether the pie with the given ID opens centered.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool get_is_centered(string id) {
+        foreach (var binding in bindings) {
+            if (binding.id == id) {
+                return binding.trigger.centered;
+            }
+        }
+        
+        return false;
+    }
+    
     /////////////////////////////////////////////////////////////////////
     /// Returns the name ID of the Pie bound to the given Trigger.
     /// Returns "" if there is nothing bound to this trigger.
@@ -258,8 +277,7 @@ public class BindingManager : GLib.Object {
         	// if the trigger is released and an event is currently waiting
 		    // simulate that the trigger has been pressed without any inter-
 		    // ference of Gnome-Pie
-            Gdk.Window rootwin = Gdk.get_default_root_window();
-       		X.Display display = Gdk.x11_drawable_get_xdisplay(rootwin);
+       		X.Display display = Gdk.x11_get_default_xdisplay();
        		
        		// unbind the trigger, else we'll capture that event again ;)
        		unbind(delayed_binding.id);
diff --git a/src/utilities/config.vala b/src/utilities/config.vala
index cf4311d..5790eef 100644
--- a/src/utilities/config.vala
+++ b/src/utilities/config.vala
@@ -55,7 +55,6 @@ public class Config : GLib.Object {
     public double refresh_rate { get; set; default = 60.0; }
     public double global_scale { get; set; default = 1.0; }
     public bool show_indicator { get; set; default = true; }
-    public bool open_at_mouse { get; set; default = true; }
     public bool auto_start { get; set; default = false; }
     public Gee.ArrayList<Theme?> themes { get; private set; }
     
@@ -71,7 +70,6 @@ public class Config : GLib.Object {
                 writer.write_attribute("refresh_rate", refresh_rate.to_string());
                 writer.write_attribute("global_scale", global_scale.to_string());
                 writer.write_attribute("show_indicator", show_indicator ? "true" : "false");
-                writer.write_attribute("open_at_mouse", open_at_mouse ? "true" : "false");
             writer.end_element();
         writer.end_document();
     }
@@ -114,9 +112,6 @@ public class Config : GLib.Object {
                         case "show_indicator":
                             show_indicator = bool.parse(attr_content);
                             break;
-                        case "open_at_mouse":
-                            open_at_mouse = bool.parse(attr_content);
-                            break;
                         default:
                             warning("Invalid setting \"" + attr_name + "\" in gnome-pie.conf!");
                             break;
diff --git a/src/utilities/focusGrabber.vala b/src/utilities/focusGrabber.vala
index 0e07b39..293e103 100644
--- a/src/utilities/focusGrabber.vala
+++ b/src/utilities/focusGrabber.vala
@@ -25,48 +25,95 @@ public class FocusGrabber : GLib.Object {
 
     /////////////////////////////////////////////////////////////////////
     /// Utilities for grabbing focus.
-    /// Code from Gnome-Do/Synapse.
+    /// Code roughly from Gnome-Do/Synapse.
     /////////////////////////////////////////////////////////////////////
     
-    public static void grab(Gtk.Window window) {
-        window.present_with_time(Gdk.CURRENT_TIME);
-        window.get_window().raise();
-        window.get_window().focus(Gdk.CURRENT_TIME);
+    public static void grab(Gdk.Window window, bool keyboard = true, bool pointer = true, bool owner_events = true) {
+        if (keyboard || pointer) {
+            window.raise();
+            window.focus(Gdk.CURRENT_TIME);
 
-        int i = 0;
-        Timeout.add(100, () => {
-            if (++i >= 100) return false;
-            return !try_grab_window(window);
-        });
+            if (!try_grab_window(window, keyboard, pointer, owner_events)) {
+                int i = 0;
+                Timeout.add(100, () => {
+                    if (++i >= 100) return false;
+                    return !try_grab_window(window, keyboard, pointer, owner_events);
+                });
+            }
+        }
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Code from Gnome-Do/Synapse.
+    /// Code roughly from Gnome-Do/Synapse.
     /////////////////////////////////////////////////////////////////////
     
-    public static void ungrab(Gtk.Window window) {
-        Gdk.pointer_ungrab(Gdk.CURRENT_TIME);
-        Gdk.keyboard_ungrab(Gdk.CURRENT_TIME);
-        Gtk.grab_remove(window);
+    public static void ungrab(bool keyboard = true, bool pointer = true) {
+        #if HAVE_GTK_3
+        
+            var display = Gdk.Display.get_default();
+            var manager = display.get_device_manager();
+            
+            unowned GLib.List<weak Gdk.Device?> list = manager.list_devices(Gdk.DeviceType.MASTER);
+            foreach(var device in list) {
+                if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard)
+                 || (device.input_source != Gdk.InputSource.KEYBOARD && pointer)) 
+                 
+                    device.ungrab(Gdk.CURRENT_TIME);
+            }
+            
+        #else
+        
+            if (pointer)  Gdk.pointer_ungrab(Gdk.CURRENT_TIME);
+            if (keyboard) Gdk.keyboard_ungrab(Gdk.CURRENT_TIME);
+            
+        #endif
     }
     
     /////////////////////////////////////////////////////////////////////
-    /// Code from Gnome-Do/Synapse.
+    /// Code roughly from Gnome-Do/Synapse.
     /////////////////////////////////////////////////////////////////////
     
-    private static bool try_grab_window(Gtk.Window window) {
-        if (Gdk.pointer_grab(window.get_window(), true, Gdk.EventMask.BUTTON_PRESS_MASK | 
-                             Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK,
-                             null, null, Gdk.CURRENT_TIME) == Gdk.GrabStatus.SUCCESS) {
+    private static bool try_grab_window(Gdk.Window window, bool keyboard, bool pointer, bool owner_events) {
+        #if HAVE_GTK_3
+        
+            var display = Gdk.Display.get_default();
+            var manager = display.get_device_manager();
             
-            if (Gdk.keyboard_grab(window.get_window(), true, Gdk.CURRENT_TIME) == Gdk.GrabStatus.SUCCESS) {
-                Gtk.grab_add(window);
+            bool grabbed_all = true;
+            
+            unowned GLib.List<weak Gdk.Device?> list = manager.list_devices(Gdk.DeviceType.MASTER);
+            foreach(var device in list) {
+                if ((device.input_source == Gdk.InputSource.KEYBOARD && keyboard) 
+                 || (device.input_source != Gdk.InputSource.KEYBOARD && pointer)) {
+                 
+                    var status = device.grab(window, Gdk.GrabOwnership.APPLICATION, owner_events, 
+                                             Gdk.EventMask.ALL_EVENTS_MASK, null, Gdk.CURRENT_TIME);
+                    
+                    if (status != Gdk.GrabStatus.SUCCESS)
+                        grabbed_all = false;
+                }
+            }
+            
+            if (grabbed_all)
                 return true;
-            } else {
-                Gdk.pointer_ungrab(Gdk.CURRENT_TIME);
-                return false;
+            
+            ungrab(keyboard, pointer);
+            
+        #else
+        
+            if (!pointer || Gdk.pointer_grab(window, owner_events, Gdk.EventMask.BUTTON_PRESS_MASK |
+                                             Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK,
+                                 null, null, Gdk.CURRENT_TIME) == Gdk.GrabStatus.SUCCESS) {
+                
+                if (!keyboard || Gdk.keyboard_grab(window, owner_events, Gdk.CURRENT_TIME) == Gdk.GrabStatus.SUCCESS) {
+                    return true;
+                } else if (pointer) {
+                    ungrab(false, true);
+                    return false;
+                }
             }
-        }
+        #endif
+        
         return false;
     }  
 }
diff --git a/src/utilities/key.vala b/src/utilities/key.vala
index 6700b16..5f27a1e 100644
--- a/src/utilities/key.vala
+++ b/src/utilities/key.vala
@@ -54,11 +54,22 @@ public class Key : GLib.Object {
     private int key_code;
     private Gdk.ModifierType modifiers;
     
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, initializes all members to defaults.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Key() {
+        this.accelerator = "";
+        this.modifiers = 0;
+        this.key_code = 0;
+        this.label = _("Not bound");
+    }
+    
     /////////////////////////////////////////////////////////////////////
     /// C'tor, initializes all members.
     /////////////////////////////////////////////////////////////////////
     
-    public Key(string stroke) {
+    public Key.from_string(string stroke) {
         this.accelerator = stroke;
         
         uint keysym;
@@ -67,6 +78,17 @@ public class Key : GLib.Object {
         this.label = Gtk.accelerator_get_label(keysym, this.modifiers);
     }
     
+    /////////////////////////////////////////////////////////////////////
+    /// C'tor, initializes all members.
+    /////////////////////////////////////////////////////////////////////
+    
+    public Key.from_values(uint keysym, Gdk.ModifierType modifiers) {
+        this.accelerator = Gtk.accelerator_name(keysym, modifiers);
+        this.label = Gtk.accelerator_get_label(keysym, modifiers);
+        this.key_code = display.keysym_to_keycode(keysym);
+        this.modifiers = modifiers;
+    }
+    
     /////////////////////////////////////////////////////////////////////
     /// Initializes static members.
     /////////////////////////////////////////////////////////////////////
@@ -113,7 +135,7 @@ public class Key : GLib.Object {
     
     private Gdk.ModifierType get_modifiers() {
         Gdk.ModifierType modifiers;
-        Gdk.Display.get_default().get_pointer(null, null, null, out modifiers);
+        Gtk.get_current_event_state(out modifiers);
         return modifiers;
     }
     
diff --git a/src/utilities/paths.vala b/src/utilities/paths.vala
index 1c42176..589cc36 100644
--- a/src/utilities/paths.vala
+++ b/src/utilities/paths.vala
@@ -59,6 +59,13 @@ public class Paths : GLib.Object {
     
     public static string locales { get; private set; default=""; }
     
+    /////////////////////////////////////////////////////////////////////
+    /// The directory containing UI declaration files
+    /// usually /usr/share/gnome-pie/ui/.
+    /////////////////////////////////////////////////////////////////////
+    
+    public static string ui_files { get; private set; default=""; }
+    
     /////////////////////////////////////////////////////////////////////
     /// The autostart file of gnome-pie_config
     /// usually ~/.config/autostart/gnome-pie.desktop.
@@ -73,44 +80,48 @@ public class Paths : GLib.Object {
     
     public static string launchers { get; private set; default=""; }
     
+    /////////////////////////////////////////////////////////////////////
+    /// The path to the executable.
+    /////////////////////////////////////////////////////////////////////
+    
+    public static string executable { get; private set; default=""; }
+    
     /////////////////////////////////////////////////////////////////////
     /// Initializes all values above.
     /////////////////////////////////////////////////////////////////////
     
     public static void init() {
     
-        // append resources to icon search path to icon theme, if neccasary
+        // get path of executable
         try {
-            var icon_dir = GLib.File.new_for_path(GLib.Path.get_dirname(
-                        GLib.FileUtils.read_link("/proc/self/exe"))).get_child("resources");
-                        
-            if (icon_dir.query_exists()) {
-                string path = icon_dir.get_path();
-                Gtk.IconTheme.get_default().append_search_path(path);
-            }
-            
-            Gtk.IconTheme.get_default().append_search_path("/usr/share/pixmaps/");
-            
+            executable = GLib.File.new_for_path(GLib.FileUtils.read_link("/proc/self/exe")).get_path();
         } catch (GLib.FileError e) {
             warning("Failed to get path of executable!");
         }
     
+        // append resources to icon search path to icon theme, if neccasary
+        var icon_dir = GLib.File.new_for_path(GLib.Path.get_dirname(executable)).get_child("resources");
+                    
+        if (icon_dir.query_exists()) {
+            string path = icon_dir.get_path();
+            Gtk.IconTheme.get_default().append_search_path(path);
+        }
+        
+        Gtk.IconTheme.get_default().append_search_path("/usr/share/pixmaps/");
+    
         // get global paths
         var default_dir = GLib.File.new_for_path("/usr/share/gnome-pie/");
         if(!default_dir.query_exists()) {
             default_dir = GLib.File.new_for_path("/usr/local/share/gnome-pie/");
             
             if(!default_dir.query_exists()) {
-                try {
-                    default_dir = GLib.File.new_for_path(GLib.Path.get_dirname(
-                        GLib.FileUtils.read_link("/proc/self/exe"))).get_child("resources");
-                } catch (GLib.FileError e) {
-                    warning("Failed to get path of executable!");
-                }
+                default_dir = GLib.File.new_for_path(GLib.Path.get_dirname(
+                    executable)).get_child("resources");
             }
         }
         
         global_themes = default_dir.get_path() + "/themes";
+        ui_files = default_dir.get_path() + "/ui";
         
         // get locales path
         var locale_dir = GLib.File.new_for_path("/usr/share/locale/de/LC_MESSAGES/gnomepie.mo");
@@ -121,22 +132,12 @@ public class Paths : GLib.Object {
             if(locale_dir.query_exists()) {
                 locale_dir = GLib.File.new_for_path("/usr/local/share/locale");
             } else {
-            
-                try {
-                    locale_dir = GLib.File.new_for_path(GLib.Path.get_dirname(
-                        GLib.FileUtils.read_link("/proc/self/exe"))).get_child(
-                        "resources/locale/de/LC_MESSAGES/gnomepie.mo");
-                } catch (GLib.FileError e) {
-                    warning("Failed to get path of executable!");
-                }
+                locale_dir = GLib.File.new_for_path(GLib.Path.get_dirname(
+                    executable)).get_child("resources/locale/de/LC_MESSAGES/gnomepie.mo");
                 
                 if(locale_dir.query_exists()) {
-                    try {
-                        locale_dir = GLib.File.new_for_path(GLib.Path.get_dirname(
-                            GLib.FileUtils.read_link("/proc/self/exe"))).get_child("resources/locale");
-                    } catch (GLib.FileError e) {
-                        warning("Failed to get path of executable!");
-                    }
+                    locale_dir = GLib.File.new_for_path(GLib.Path.get_dirname(
+                        executable)).get_child("resources/locale");
                 }
             }
         }
@@ -204,7 +205,10 @@ public class Paths : GLib.Object {
             warning("Failed to find launchers directory!");
             
         if (!GLib.File.new_for_path(global_themes).query_exists()) 
-            warning("Failed to find global themes directory!");     
+            warning("Failed to find global themes directory!");   
+            
+        if (!GLib.File.new_for_path(ui_files).query_exists()) 
+            warning("Failed to find UI files directory!");     
     }    
 }
 
diff --git a/src/utilities/trigger.vala b/src/utilities/trigger.vala
index 1f6fcfe..4b6167b 100644
--- a/src/utilities/trigger.vala
+++ b/src/utilities/trigger.vala
@@ -80,6 +80,12 @@ public class Trigger : GLib.Object {
     
     public bool delayed { get; private set; default=false; }
     
+    /////////////////////////////////////////////////////////////////////
+    /// True if the pie opens in the middle of the screen.
+    /////////////////////////////////////////////////////////////////////
+    
+    public bool centered { get; private set; default=false; }
+    
     /////////////////////////////////////////////////////////////////////
     /// C'tor, creates a new, "unbound" Trigger.
     /////////////////////////////////////////////////////////////////////
@@ -93,7 +99,7 @@ public class Trigger : GLib.Object {
     /// in this format: "[option(s)]<modifier(s)>button" where
     /// "<modifier>" is something like "<Alt>" or "<Control>", "button"
     /// something like "s", "F4" or "button0" and "[option]" is either
-    /// "[turbo]" or "["delayed"]".
+    /// "[turbo]", "[centered]" or "["delayed"]".
     /////////////////////////////////////////////////////////////////////
     
     public Trigger.from_string(string trigger) {
@@ -105,9 +111,12 @@ public class Trigger : GLib.Object {
     /////////////////////////////////////////////////////////////////////
     
     public Trigger.from_values(uint key_sym, Gdk.ModifierType modifiers, 
-                               bool with_mouse, bool turbo, bool delayed ) {
+                               bool with_mouse, bool turbo, bool delayed,
+                               bool centered ) {
         
-        string trigger = (turbo ? "[turbo]" : "") + (delayed ? "[delayed]" : "");
+        string trigger = (turbo ? "[turbo]" : "")
+                       + (delayed ? "[delayed]" : "")
+                       + (centered ? "[centered]" : "");
         
         if (with_mouse) {
             trigger += Gtk.accelerator_name(0, modifiers) + "button%u".printf(key_sym);
@@ -123,7 +132,7 @@ public class Trigger : GLib.Object {
     /// in this format: "[option(s)]<modifier(s)>button" where
     /// "<modifier>" is something like "<Alt>" or "<Control>", "button"
     /// something like "s", "F4" or "button0" and "[option]" is either
-    /// "[turbo]" or "["delayed"]".
+    /// "[turbo]", "[centered]" or "["delayed"]".
     /////////////////////////////////////////////////////////////////////
     
     public void parse_string(string trigger) {
@@ -135,10 +144,12 @@ public class Trigger : GLib.Object {
             
             this.turbo = check_string.contains("[turbo]");
             this.delayed = check_string.contains("[delayed]");
+            this.centered = check_string.contains("[centered]");
             
             // remove optional arguments
             check_string = check_string.replace("[turbo]", "");
             check_string = check_string.replace("[delayed]", "");
+            check_string = check_string.replace("[centered]", "");
             
             int button = this.get_mouse_button(check_string);
             if (button > 0) {
@@ -177,12 +188,20 @@ public class Trigger : GLib.Object {
             
             this.label_with_specials = this.label;
             
-            if (this.turbo && this.delayed)
-                this.label_with_specials += ("\n<small><span weight='light'>" + _("Turbo") + " | " + _("Delayed") + "</span></small>");
+            if (this.turbo && this.delayed && this.centered)
+                this.label_with_specials += ("  <small><span weight='light'>[ " + _("Turbo") + " | " + _("Delayed") + " | " + _("Centered") + " ]</span></small>");
+            else if (this.turbo && this.centered)
+                this.label_with_specials += ("  <small><span weight='light'>[ " + _("Turbo") + " | " + _("Centered") + " ]</span></small>");
+            else if (this.turbo && this.delayed)
+                this.label_with_specials += ("  <small><span weight='light'>[ " + _("Turbo") + " | " + _("Delayed") + " ]</span></small>");
+            else if (this.centered && this.delayed)
+                this.label_with_specials += ("  <small><span weight='light'>[ " + _("Delayed") + " | " + _("Centered") + " ]</span></small>");
             else if (this.turbo)
-                this.label_with_specials += ("\n<small><span weight='light'>" + _("Turbo") + "</span></small>");
+                this.label_with_specials += ("  <small><span weight='light'>[ " + _("Turbo") + " ]</span></small>");
             else if (this.delayed)
-                this.label_with_specials += ("\n<small><span weight='light'>" + _("Delayed") + "</span></small>");
+                this.label_with_specials += ("  <small><span weight='light'>[ " + _("Delayed") + " ]</span></small>");
+            else if (this.centered)
+                this.label_with_specials += ("  <small><span weight='light'>[ " + _("Centered") + " ]</span></small>");
             
         } else {
             this.set_unbound();
@@ -216,6 +235,7 @@ public class Trigger : GLib.Object {
         // remove optional arguments
         check_string = check_string.replace("[turbo]", "");
         check_string = check_string.replace("[delayed]", "");
+        check_string = check_string.replace("[centered]", "");
          
         if (this.get_mouse_button(check_string) > 0) {
             // it seems to be a valid mouse-trigger so replace button part,
-- 
cgit v1.2.3