[Goodies-commits] r3204 - in xfce4-places-plugin/trunk: . panel-plugin

Diego Ongaro ongardie at xfce.org
Wed Sep 12 04:34:10 CEST 2007


Author: ongardie
Date: 2007-09-12 02:34:09 +0000 (Wed, 12 Sep 2007)
New Revision: 3204

Modified:
   xfce4-places-plugin/trunk/ChangeLog
   xfce4-places-plugin/trunk/panel-plugin/cfg.c
   xfce4-places-plugin/trunk/panel-plugin/cfg.h
   xfce4-places-plugin/trunk/panel-plugin/places.c
   xfce4-places-plugin/trunk/panel-plugin/places.h
   xfce4-places-plugin/trunk/panel-plugin/view.c
   xfce4-places-plugin/trunk/panel-plugin/view.h
Log:
2007-09-11	Diego Ongaro <ongardie at gmail.com>

* places.{c,h}, view.{c,h}, cfg.{c,h}: Large shuffling of GUI code



Modified: xfce4-places-plugin/trunk/ChangeLog
===================================================================
--- xfce4-places-plugin/trunk/ChangeLog	2007-09-11 22:02:15 UTC (rev 3203)
+++ xfce4-places-plugin/trunk/ChangeLog	2007-09-12 02:34:09 UTC (rev 3204)
@@ -1,3 +1,8 @@
+2007-09-11	Diego Ongaro <ongardie at gmail.com>
+
+	* places.{c,h}, view.{c,h}, cfg.{c,h}: Large shuffling of GUI
+	code
+
 2007-09-07	Diego Ongaro <ongardie at gmail.com>
 
 	* view.c: places_load_thunar_wrapper() should load thunar, not

Modified: xfce4-places-plugin/trunk/panel-plugin/cfg.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/cfg.c	2007-09-11 22:02:15 UTC (rev 3203)
+++ xfce4-places-plugin/trunk/panel-plugin/cfg.c	2007-09-12 02:34:09 UTC (rev 3204)
@@ -34,34 +34,110 @@
 #include "model.h"
 
 /* Init */
-static void     places_cfg_init_defaults(PlacesConfig *cfg);
+static void     pcfg_init_defaults(PlacesCfg *cfg);
 
 /* Configuration File */
-static void     places_cfg_load(PlacesData*);
-static void     places_cfg_save(PlacesData*);
+static void     pcfg_load(PlacesCfg*);
+static void     pcfg_save(PlacesCfg*);
 
 /* Configuration Dialog */
-static void     places_cfg_button_show_cb(GtkComboBox*, PlacesData*);
-static gboolean places_cfg_button_label_cb(GtkWidget *entry, GdkEventFocus*, PlacesData*);
+static void     pcfg_button_show_cb(GtkComboBox*, PlacesCfg*);
+static gboolean pcfg_button_label_cb(GtkWidget *entry, GdkEventFocus*, PlacesCfg*);
 #if USE_RECENT_DOCUMENTS
-static void     places_cfg_recent_num_cb(GtkAdjustment*, PlacesData*);
+static void     pcfg_recent_num_cb(GtkAdjustment*, PlacesCfg*);
 #endif
-static void     places_cfg_menu_cb(GtkToggleButton*, PlacesData*);
-static void     places_cfg_model_cb(GtkToggleButton*, PlacesData*);
-static void     places_cfg_dialog_cb(GtkDialog*, gint response, PlacesData*);
-static void     places_cfg_launch_dialog(PlacesData*);
+static void     pcfg_menu_cb(GtkToggleButton*, PlacesCfg*);
+static void     pcfg_model_cb(GtkToggleButton*, PlacesCfg*);
+//static void     pcfg_dialog_cb(GtkDialog*, gint response, PlacesCfg*);
+static void     pcfg_open_dialog(PlacesCfg*);
 
+
+/********** PlacesCfgViewIface helpers **********/
+
+inline PlacesCfg*
+places_cfg_view_iface_get_cfg(PlacesCfgViewIface *iface)
+{
+    return iface->cfg;
+}
+
+inline void
+places_cfg_view_iface_open_dialog(PlacesCfgViewIface *iface)
+{
+    iface->open_dialog(iface->cfg);
+}
+
+inline void
+places_cfg_view_iface_load(PlacesCfgViewIface *iface)
+{
+    iface->load(iface->cfg);
+}
+
+inline void
+places_cfg_view_iface_save(PlacesCfgViewIface *iface)
+{
+    iface->save(iface->cfg);
+}
+
+inline void
+places_cfg_view_iface_finalize(PlacesCfgViewIface *iface)
+{
+    iface->finalize(iface);
+}
+
 /********** Initialization & Finalization **********/
-PlacesConfig*
-places_cfg_new(PlacesData *pd)
+
+static void 
+pcfg_finalize(PlacesCfgViewIface *cfg_iface)
 {
-    pd->cfg = g_new0(PlacesConfig, 1);
-    places_cfg_load(pd);
-    return pd->cfg;
+    PlacesCfg *cfg;
+
+    g_assert(cfg_iface != NULL);
+
+    cfg = cfg_iface->cfg;
+    g_assert(cfg != NULL);
+
+    if(cfg->label != NULL)
+        g_free(cfg->label);
+    if(cfg->search_cmd != NULL)
+        g_free(cfg->search_cmd);
+
+    if(cfg->read_path != NULL)
+        g_free(cfg->read_path);
+    if(cfg->write_path != NULL)
+        g_free(cfg->write_path);
+
+    g_free(cfg);
+    g_free(cfg_iface);
 }
 
+PlacesCfgViewIface*
+places_cfg_new(PlacesViewCfgIface *view_iface, gchar *read_path, gchar *write_path)
+{
+    PlacesCfgViewIface *cfg_iface;
+    PlacesCfg *cfg;
+
+    g_assert(view_iface != NULL);
+
+    cfg                     = g_new0(PlacesCfg, 1);
+    cfg->read_path          = read_path;
+    cfg->write_path         = write_path;
+    cfg->view_iface         = view_iface;
+
+    pcfg_load(cfg);
+    
+    cfg_iface               = g_new0(PlacesCfgViewIface, 1);
+    cfg_iface->cfg          = cfg;
+    cfg_iface->open_dialog  = pcfg_open_dialog;
+    cfg_iface->save         = pcfg_save;
+    cfg_iface->finalize     = pcfg_finalize;
+
+    return cfg_iface;
+}
+
+/********** Configuration File **********/
+
 static void
-places_cfg_init_defaults(PlacesConfig *cfg)
+pcfg_init_defaults(PlacesCfg *cfg)
 {
 
     cfg->show_button_icon   = TRUE;
@@ -85,46 +161,19 @@
 
 }
 
-void
-places_cfg_init_signals(PlacesData *pd)
-{
-    g_signal_connect_swapped(G_OBJECT(pd->plugin), "configure-plugin",
-                             G_CALLBACK(places_cfg_launch_dialog), pd);
-
-    g_signal_connect_swapped(G_OBJECT(pd->plugin), "save",
-                             G_CALLBACK(places_cfg_save), pd);
-    
-    xfce_panel_plugin_menu_show_configure(pd->plugin);
-}
-
-void 
-places_cfg_finalize(PlacesData *pd)
-{
-    if(pd->cfg->label != NULL)
-        g_free(pd->cfg->label);
-    if(pd->cfg->search_cmd != NULL)
-        g_free(pd->cfg->search_cmd);
-}
-
-/********** Configuration File **********/
 static void
-places_cfg_load(PlacesData *pd)
+pcfg_load(PlacesCfg *cfg)
 {
-    PlacesConfig *cfg = pd->cfg;
-
     XfceRc *rcfile;
-    gchar *rcpath;
 
-    rcpath = xfce_panel_plugin_lookup_rc_file(pd->plugin);
-    if(rcpath == NULL){
-        places_cfg_init_defaults(cfg);
+    if(cfg->read_path == NULL){
+        pcfg_init_defaults(cfg);
         return;
     }
 
-    rcfile = xfce_rc_simple_open(rcpath, TRUE);
-    g_free(rcpath);
+    rcfile = xfce_rc_simple_open(cfg->read_path, TRUE);
     if(rcfile == NULL){
-        places_cfg_init_defaults(cfg);
+        pcfg_init_defaults(cfg);
         return;
     }
 
@@ -166,18 +215,14 @@
 }
 
 static void
-places_cfg_save(PlacesData *pd)
+pcfg_save(PlacesCfg *cfg)
 {
-    PlacesConfig *cfg = pd->cfg;
     XfceRc *rcfile;
-    gchar *rcpath;
     
-    rcpath = xfce_panel_plugin_save_location(pd->plugin, TRUE);
-    if(rcpath == NULL)
+    if(cfg->write_path == NULL)
         return;
 
-    rcfile = xfce_rc_simple_open(rcpath, FALSE);
-    g_free(rcpath);
+    rcfile = xfce_rc_simple_open(cfg->write_path, FALSE);
     if(rcfile == NULL)
         return;
 
@@ -209,138 +254,83 @@
 /********** Dialog **********/
 
 static void
-places_cfg_button_show_cb(GtkComboBox *combo, PlacesData *pd)
+pcfg_button_show_cb(GtkComboBox *combo, PlacesCfg *cfg)
 {
-    PlacesConfig *cfg = pd->cfg;
     gint option;
-    gboolean show_icon, show_label;
     
     option = gtk_combo_box_get_active(combo);
-    show_icon  = (option == 0 || option == 2);
-    show_label = (option == 1 || option == 2);
+    cfg->show_button_icon  = (option == 0 || option == 2);
+    cfg->show_button_label = (option == 1 || option == 2);
 
-    if(show_icon && !cfg->show_button_icon){
-        cfg->show_button_icon = TRUE;
-
-        if(pd->view_button_image == NULL){
-            pd->view_button_image = g_object_ref(gtk_image_new());
-            gtk_widget_show(pd->view_button_image);
-            gtk_box_pack_start(GTK_BOX(pd->view_button_box), pd->view_button_image, TRUE, TRUE, 0);
-        }
-
-    }else if(!show_icon && cfg->show_button_icon){
-        cfg->show_button_icon = FALSE;
-
-        if(pd->view_button_image != NULL){
-            g_object_unref(pd->view_button_image);
-            gtk_widget_destroy(pd->view_button_image);
-            pd->view_button_image = NULL;
-        }
-
-    }
-
-    if(show_label && !cfg->show_button_label){
-        cfg->show_button_label = TRUE;
-
-        if(pd->view_button_label == NULL){
-            pd->view_button_label = g_object_ref(gtk_label_new(cfg->label));
-            gtk_widget_show(pd->view_button_label);
-            gtk_box_pack_end(GTK_BOX(pd->view_button_box), pd->view_button_label, TRUE, TRUE, 0);
-        }
-
-    }else if(!show_label && cfg->show_button_label){
-        cfg->show_button_label = FALSE;
-        
-        if(pd->view_button_label != NULL){
-            g_object_unref(pd->view_button_label);
-            gtk_widget_destroy(pd->view_button_label);
-            pd->view_button_label = NULL;
-        }
-
-    }
-    
-    places_view_button_update(pd);
+    cfg->view_iface->update_button(cfg->view_iface->places_view);
 }
 
 static gboolean
-places_cfg_button_label_cb(GtkWidget *label_entry, GdkEventFocus *event, PlacesData *pd)
+pcfg_button_label_cb(GtkWidget *label_entry, GdkEventFocus *event, PlacesCfg *cfg)
 {
-    if(pd->cfg->label != NULL)
-        g_free(pd->cfg->label);
+    if(cfg->label != NULL)
+        g_free(cfg->label);
     
-    pd->cfg->label = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(label_entry))));
-    if(strlen(pd->cfg->label) == 0){
-        g_free(pd->cfg->label);
-        pd->cfg->label = g_strdup(_("Places"));
-        gtk_entry_set_text(GTK_ENTRY(label_entry), pd->cfg->label);
+    cfg->label = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(label_entry))));
+    if(strlen(cfg->label) == 0){
+        g_free(cfg->label);
+        cfg->label = g_strdup(_("Places"));
+        gtk_entry_set_text(GTK_ENTRY(label_entry), cfg->label);
     }
 
-    if(pd->cfg->show_button_label){
-        gtk_label_set_text(GTK_LABEL(pd->view_button_label), pd->cfg->label);
-        gtk_tooltips_set_tip(pd->view_tooltips, pd->view_button, pd->cfg->label, NULL);
-        places_view_button_update(pd);
-    }
+    cfg->view_iface->update_button(cfg->view_iface->places_view);
 
     return FALSE;
 }
 
 static gboolean
-places_cfg_search_cmd_cb(GtkWidget *label_entry, GdkEventFocus *event, PlacesData *pd)
+pcfg_search_cmd_cb(GtkWidget *label_entry, GdkEventFocus *event, PlacesCfg *cfg)
 {
-    if(pd->cfg->search_cmd != NULL)
-        g_free(pd->cfg->search_cmd);
+    if(cfg->search_cmd != NULL)
+        g_free(cfg->search_cmd);
     
-    pd->cfg->search_cmd = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(label_entry))));
+    cfg->search_cmd = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(label_entry))));
 
-    places_view_destroy_menu(pd);
+    cfg->view_iface->update_menu(cfg->view_iface->places_view);
 
     return FALSE;
 }
 
 #if USE_RECENT_DOCUMENTS
 static void
-places_cfg_recent_num_cb(GtkAdjustment *adj, PlacesData *pd)
+pcfg_recent_num_cb(GtkAdjustment *adj, PlacesCfg *cfg)
 {
-    pd->cfg->show_recent_number = (gint) gtk_adjustment_get_value(adj);
-    DBG("Show %d recent documents", pd->cfg->show_recent_number);
-    places_view_destroy_menu(pd);
+    cfg->show_recent_number = (gint) gtk_adjustment_get_value(adj);
+    DBG("Show %d recent documents", cfg->show_recent_number);
+    cfg->view_iface->update_menu(cfg->view_iface->places_view);
 }
 #endif
 
 static void
-places_cfg_menu_cb(GtkToggleButton *toggle, PlacesData *pd)
+pcfg_menu_cb(GtkToggleButton *toggle, PlacesCfg *cfg)
 {
-    gboolean *cfg = g_object_get_data(G_OBJECT(toggle), "cfg_opt");
-    g_assert(cfg != NULL);
-    *cfg = gtk_toggle_button_get_active(toggle);
+    gboolean *opt = g_object_get_data(G_OBJECT(toggle), "cfg_opt");
+    g_assert(opt != NULL);
+    *opt = gtk_toggle_button_get_active(toggle);
 
-    places_view_destroy_menu(pd);
+    cfg->view_iface->update_menu(cfg->view_iface->places_view);
 }
 
 static void
-places_cfg_model_cb(GtkToggleButton *toggle, PlacesData *pd)
+pcfg_model_cb(GtkToggleButton *toggle, PlacesCfg *cfg)
 {
-    gboolean *cfg = g_object_get_data(G_OBJECT(toggle), "cfg_opt");
-    g_assert(cfg != NULL);
-    *cfg = gtk_toggle_button_get_active(toggle);
+    gboolean *opt = g_object_get_data(G_OBJECT(toggle), "cfg_opt");
+    g_assert(opt != NULL);
+    *opt = gtk_toggle_button_get_active(toggle);
 
-    places_view_reconfigure_model(pd);
-    places_view_destroy_menu(pd);
+    cfg->view_iface->reconfigure_model(cfg->view_iface->places_view);
+    cfg->view_iface->update_menu(cfg->view_iface->places_view);
 }
 
 static void
-places_cfg_dialog_cb(GtkDialog *dialog, gint response, PlacesData *pd)
+pcfg_open_dialog(PlacesCfg *cfg)
 {
-    gtk_widget_destroy(GTK_WIDGET(dialog));
-    xfce_panel_plugin_unblock_menu(pd->plugin);
-    places_cfg_save(pd);
-}
-
-static void
-places_cfg_launch_dialog(PlacesData *pd)
-{
     DBG("configure plugin");
-    PlacesConfig *cfg = pd->cfg;
 
     GtkWidget *dlg;
     GtkWidget *frame_button, *vbox_button;
@@ -353,20 +343,8 @@
     GtkWidget *tmp_box, *tmp_label, *tmp_widget;
     gint active;
     
-    xfce_panel_plugin_block_menu(pd->plugin);
+    dlg = cfg->view_iface->make_empty_cfg_dialog(cfg->view_iface->places_view);
 
-    dlg = xfce_titled_dialog_new_with_buttons(_("Places"),
-              GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pd->plugin))),
-              GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
-              GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
-
-    gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
-    gtk_window_set_icon_name(GTK_WINDOW(dlg), "xfce4-settings");
-
-    g_signal_connect(G_OBJECT(dlg), "response",
-                     G_CALLBACK(places_cfg_dialog_cb), pd);
-
-
     /* BUTTON: frame, vbox */
     vbox_button = gtk_vbox_new(FALSE, 4);
     gtk_widget_show(vbox_button);
@@ -400,7 +378,7 @@
     gtk_combo_box_set_active(GTK_COMBO_BOX(tmp_widget), active);
     
     g_signal_connect(G_OBJECT(tmp_widget), "changed",
-                     G_CALLBACK(places_cfg_button_show_cb), pd);
+                     G_CALLBACK(pcfg_button_show_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(tmp_box), tmp_widget, FALSE, FALSE, 0);
@@ -419,7 +397,7 @@
     gtk_entry_set_text(GTK_ENTRY(tmp_widget), cfg->label);
 
     g_signal_connect(G_OBJECT(tmp_widget), "focus-out-event",
-                     G_CALLBACK(places_cfg_button_label_cb), pd);
+                     G_CALLBACK(pcfg_button_label_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(tmp_box), tmp_widget, FALSE, FALSE, 0);
@@ -437,7 +415,7 @@
 
     g_object_set_data(G_OBJECT(tmp_widget), "cfg_opt", &(cfg->show_icons));
     g_signal_connect(G_OBJECT(tmp_widget), "toggled",
-                     G_CALLBACK(places_cfg_menu_cb), pd);
+                     G_CALLBACK(pcfg_menu_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(vbox_menu), tmp_widget, FALSE, FALSE, 0);
@@ -449,7 +427,7 @@
 
     g_object_set_data(G_OBJECT(tmp_widget), "cfg_opt", &(cfg->show_volumes));
     g_signal_connect(G_OBJECT(tmp_widget), "toggled",
-                     G_CALLBACK(places_cfg_model_cb), pd);
+                     G_CALLBACK(pcfg_model_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(vbox_menu), tmp_widget, FALSE, FALSE, 0);   
@@ -460,7 +438,7 @@
 
     g_object_set_data(G_OBJECT(tmp_widget), "cfg_opt", &(cfg->show_bookmarks));
     g_signal_connect(G_OBJECT(tmp_widget), "toggled",
-                     G_CALLBACK(places_cfg_model_cb), pd);
+                     G_CALLBACK(pcfg_model_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(vbox_menu), tmp_widget, FALSE, FALSE, 0);
@@ -473,7 +451,7 @@
 
     g_object_set_data(G_OBJECT(tmp_widget), "cfg_opt", &(cfg->show_recent));
     g_signal_connect(G_OBJECT(tmp_widget), "toggled",
-                     G_CALLBACK(places_cfg_menu_cb), pd);
+                     G_CALLBACK(pcfg_menu_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(vbox_menu), tmp_widget, FALSE, FALSE, 0);
@@ -491,7 +469,7 @@
 
     g_object_set_data(G_OBJECT(tmp_widget), "cfg_opt", &(cfg->show_recent_clear));
     g_signal_connect(G_OBJECT(tmp_widget), "toggled",
-                     G_CALLBACK(places_cfg_menu_cb), pd);
+                     G_CALLBACK(pcfg_menu_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(vbox_recent), tmp_widget, FALSE, FALSE, 0);
@@ -511,7 +489,7 @@
     gtk_label_set_mnemonic_widget(GTK_LABEL(tmp_label), tmp_widget);
 
     g_signal_connect(G_OBJECT(adj), "value-changed",
-                     G_CALLBACK(places_cfg_recent_num_cb), pd);
+                     G_CALLBACK(pcfg_recent_num_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(tmp_box), tmp_widget, FALSE, FALSE, 0);
@@ -538,7 +516,7 @@
     gtk_entry_set_text(GTK_ENTRY(tmp_widget), cfg->search_cmd);
 
     g_signal_connect(G_OBJECT(tmp_widget), "focus-out-event",
-                     G_CALLBACK(places_cfg_search_cmd_cb), pd);
+                     G_CALLBACK(pcfg_search_cmd_cb), cfg);
 
     gtk_widget_show(tmp_widget);
     gtk_box_pack_start(GTK_BOX(tmp_box), tmp_widget, FALSE, FALSE, 0);

Modified: xfce4-places-plugin/trunk/panel-plugin/cfg.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/cfg.h	2007-09-11 22:02:15 UTC (rev 3203)
+++ xfce4-places-plugin/trunk/panel-plugin/cfg.h	2007-09-12 02:34:09 UTC (rev 3204)
@@ -25,22 +25,56 @@
 
 typedef struct
 {
-  gboolean           show_button_icon;
-  gboolean           show_button_label;
-  gchar             *label;
-  gboolean           show_icons;
-  gboolean           show_volumes;
-  gboolean           show_bookmarks;
-  gboolean           show_recent;
-  gboolean           show_recent_clear;
-  gint               show_recent_number;
-  gchar             *search_cmd;
-} PlacesConfig;
+    /* "private" */
+    PlacesViewCfgIface  *view_iface;
+    gchar               *read_path;
+    gchar               *write_path;
 
-/* Init & Finalize */
-PlacesConfig* places_cfg_new(PlacesData*);
-void          places_cfg_init_signals(PlacesData*);
-void          places_cfg_finalize(PlacesData*);
+    /* "public" for view's access */
+    gboolean            show_button_icon;
+    gboolean            show_button_label;
+    gchar               *label;
+    gboolean            show_icons;
+    gboolean            show_volumes;
+    gboolean            show_bookmarks;
+    gboolean            show_recent;
+    gboolean            show_recent_clear;
+    gint                show_recent_number;
+    gchar               *search_cmd;
+} PlacesCfg;
 
+typedef struct _PlacesCfgViewIface PlacesCfgViewIface;
+struct _PlacesCfgViewIface {
+    
+    PlacesCfg           *cfg;
+
+    void                (*open_dialog)         (PlacesCfg*);
+    void                (*load)                (PlacesCfg*);
+    void                (*save)                (PlacesCfg*);
+    void                (*finalize)            (PlacesCfgViewIface*);
+    
+};
+
+inline PlacesCfg*
+places_cfg_view_iface_get_cfg(PlacesCfgViewIface*);
+
+inline void
+places_cfg_view_iface_open_dialog(PlacesCfgViewIface*);
+
+inline void
+places_cfg_view_iface_load(PlacesCfgViewIface*);
+
+inline void
+places_cfg_view_iface_save(PlacesCfgViewIface*);
+
+inline void
+places_cfg_view_iface_finalize(PlacesCfgViewIface*);
+
+
+/* PlacesCfg will take ownership of the paths */
+PlacesCfgViewIface*        places_cfg_new(PlacesViewCfgIface*,
+                                          gchar *read_path,
+                                          gchar *write_path);
+
 #endif
 /* vim: set ai et tabstop=4: */

Modified: xfce4-places-plugin/trunk/panel-plugin/places.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/places.c	2007-09-11 22:02:15 UTC (rev 3203)
+++ xfce4-places-plugin/trunk/panel-plugin/places.c	2007-09-12 02:34:09 UTC (rev 3204)
@@ -21,61 +21,59 @@
 #  include <config.h>
 #endif
 
-#include <gtk/gtk.h>
+#include <glib.h>
+
 #include <libxfce4panel/xfce-panel-plugin.h>
 #include <libxfcegui4/libxfcegui4.h>
 #include <exo/exo.h>
 
+#include "string.h"
+
 #include "places.h"
 #include "view.h"
 
-#include "string.h"
 
-static void places_construct(XfcePanelPlugin*);
-static void places_finalize(XfcePanelPlugin*, PlacesData*);
+/**
+ * Cleans up resources.
+ */
+static void 
+places_finalize(XfcePanelPlugin *plugin, PlacesView *view)
+{
+    DBG("Finalize: %s", PLUGIN_NAME);
+    g_assert(plugin != NULL);
+    g_assert(view != NULL);
+   
+    /* Finalize view */
+    places_view_finalize(view);
+}
 
-XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL(places_construct);
-
 /**
- * Initializes the plugin:
+ * Initializes the plugin.
  */
 static void 
 places_construct(XfcePanelPlugin *plugin)
 {
+    PlacesView *view;
+
     DBG("Construct: %s", PLUGIN_NAME);
    
     /* Set up i18n */
     xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8"); 
 
-    /* Create the PlacesData struct */
-    PlacesData *pd = panel_slice_new0(PlacesData);
-    pd->plugin = plugin;
-
     /* Initialize view */
-    places_view_init(pd);
+    view = places_view_init(plugin);
 
     /* Connect the finalize callback */
-    g_signal_connect(pd->plugin, "free-data", 
-                     G_CALLBACK(places_finalize), pd);
+    g_signal_connect(plugin, "free-data", 
+                     G_CALLBACK(places_finalize), view);
 
+    DBG("done");
 }
 
-/**
- * Cleans up resources.
- */
-static void 
-places_finalize(XfcePanelPlugin *plugin, PlacesData *pd)
-{
-    DBG("Free data: %s", PLUGIN_NAME);
-    g_assert(pd != NULL);
-   
-    /* finalize the view */
-    places_view_finalize(pd);
-    
-    /* free the PlacesData struct */
-    panel_slice_free(PlacesData, pd);
-}
+XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL(places_construct);
 
+
+
 /**
  * Opens Thunar at the location given by path.
  * If path is NULL or empty, it will open Thunar at the default location (home).
@@ -143,6 +141,11 @@
         exo_url_show(path, NULL, NULL);
 }
 
+/**
+ * Runs the graphical command given by cmd
+ * If cmd is NULL or empty, it will do nothing.
+ * The caller is in charge of freeing cmd.
+ */
 void
 places_gui_exec(const gchar *cmd)
 {

Modified: xfce4-places-plugin/trunk/panel-plugin/places.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/places.h	2007-09-11 22:02:15 UTC (rev 3203)
+++ xfce4-places-plugin/trunk/panel-plugin/places.h	2007-09-12 02:34:09 UTC (rev 3204)
@@ -20,36 +20,10 @@
 #ifndef _XFCE_PANEL_PLACES_H
 #define _XFCE_PANEL_PLACES_H
 
-#include <gtk/gtk.h>
-#include <libxfce4panel/xfce-panel-plugin.h>
+#include <glib.h>
 
-typedef struct _PlacesData PlacesData;
-#include "cfg.h"
-
 #define PLUGIN_NAME "places"
 
-struct _PlacesData
-{
-  /* plugin */
-  XfcePanelPlugin   *plugin;
-
-  /* configuration */
-  PlacesConfig      *cfg;
-
-  /* view */
-  GtkWidget         *view_button;
-  GtkWidget         *view_button_box;
-  GtkWidget         *view_button_image;
-  GtkWidget         *view_button_label;
-  GtkWidget         *view_menu;
-  GtkTooltips       *view_tooltips;
-  gboolean           view_needs_separator;
-  guint              view_menu_timeout_id;
-
-  /* model */
-  GList *bookmark_groups;
-};
-
 void places_load_thunar(const gchar *path);
 void places_load_terminal(const gchar *path);
 void places_load_file(const gchar *path);

Modified: xfce4-places-plugin/trunk/panel-plugin/view.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/view.c	2007-09-11 22:02:15 UTC (rev 3203)
+++ xfce4-places-plugin/trunk/panel-plugin/view.c	2007-09-12 02:34:09 UTC (rev 3204)
@@ -40,14 +40,53 @@
 
 #include <string.h>
 
+#include "places.h"
 #include "view.h"
-#include "places.h"
+#include "cfg.h"
 #include "model.h"
 #include "model_system.h"
 #include "model_volumes.h"
 #include "model_user.h"
-#include "cfg.h"
 
+
+#if GTK_CHECK_VERSION(2,10,0)
+#  define USE_RECENT_DOCUMENTS TRUE
+#endif
+
+#define BORDER 4
+
+struct _PlacesView
+{
+    /* plugin */
+    XfcePanelPlugin           *plugin;
+    
+    /* configuration */
+    PlacesCfg                 *cfg;
+    PlacesCfgViewIface        *cfg_iface;
+    PlacesViewCfgIface        *view_cfg_iface;
+    
+    /* view */
+    GtkWidget                 *button;
+    GtkWidget                 *button_image;
+    GtkWidget                 *button_label;
+    GtkWidget                 *menu;
+    GtkTooltips               *tooltips;
+    gboolean                  needs_separator;
+    guint                     menu_timeout_id;
+    
+    GtkOrientation            orientation;
+    gint                      size;
+    gboolean                  show_button_icon;
+    gboolean                  show_button_label;
+    gchar                     *label_tooltip_text;
+    gboolean                  force_update_theme;
+
+    
+    
+    /* model */
+    GList                     *bookmark_groups;
+};
+
 /* Debugging */
 #if defined(DEBUG) && (DEBUG > 0)
 
@@ -60,9 +99,9 @@
                  places_debug_menu_timeout_count == 1);                     \
         if(pd != NULL){                                                     \
             if(places_debug_menu_timeout_count == 0)                        \
-                    g_assert(pd->view_menu_timeout_id == 0);                \
+                    g_assert(pd->menu_timeout_id == 0);                \
             else                                                            \
-                    g_assert(pd->view_menu_timeout_id > 0);                 \
+                    g_assert(pd->menu_timeout_id > 0);                 \
         }                                                                   \
     }G_STMT_END
 
@@ -76,286 +115,45 @@
 #endif
 
 /* UI Helpers */
-static void     places_view_update_menu(PlacesData*);
+static void     pview_open_menu(PlacesView*);
+static void     pview_update_menu(PlacesView*);
+static void     pview_destroy_menu(PlacesView*);
+static void     pview_button_update(PlacesView*);
 
-/* GTK Callbacks */
-
-/*  - Panel */
-static gboolean places_view_cb_size_changed(PlacesData*, gint size);
-static void     places_view_cb_orientation_changed(PlacesData *pd, GtkOrientation orientation,
-                                                   XfcePanelPlugin *panel);
-
-static void     places_view_cb_theme_changed(PlacesData *pd);
-
-/*  - Menu */
-static gboolean places_view_cb_menu_timeout(PlacesData *pd);
-
-static void     places_view_cb_menu_position(GtkMenu*, 
-                                             gint *x, gint *y, 
-                                             gboolean *push_in, 
-                                             PlacesData*);
-static void     places_view_cb_menu_deact(PlacesData*, GtkWidget *menu);
-
-/*  - Button */
-static gboolean places_view_cb_button_pressed(PlacesData*, GdkEventButton *);
-
-/*  - Recent Documents */
-#if USE_RECENT_DOCUMENTS
-static void     places_view_cb_recent_item_open(GtkRecentChooser*, PlacesData*);
-static gboolean places_view_cb_recent_items_clear(GtkWidget *clear_item);
-#endif
-
-/* Model Visitor Callbacks */
-static void     places_view_add_menu_item(PlacesData*, PlacesBookmark*);
-
-/********** Initialization & Finalization **********/
-void
-places_view_init(PlacesData *pd)
+/********** Model Management **********/
+static void
+pview_reconfigure_model(PlacesView *view)
 {
-    DBG("initializing");
-    
-    pd->view_needs_separator = FALSE;
-    pd->view_menu = NULL;
-    pd->view_menu_timeout_id = 0;
+    /* destroy first */
+    if(view->bookmark_groups != NULL){
 
-    pd->cfg = places_cfg_new(pd);
-    places_view_reconfigure_model(pd);
-    
-    pd->view_tooltips = g_object_ref_sink(gtk_tooltips_new());
-
-    /* init button */
-
-    /* create the box */
-    if(xfce_panel_plugin_get_orientation(pd->plugin) == GTK_ORIENTATION_HORIZONTAL)
-        pd->view_button_box = gtk_hbox_new(FALSE, BORDER);
-    else
-        pd->view_button_box = gtk_vbox_new(FALSE, BORDER);
-    gtk_container_set_border_width(GTK_CONTAINER(pd->view_button_box), 0);
-    gtk_widget_show(pd->view_button_box);
-
-    /* create the button */
-    pd->view_button = xfce_create_panel_toggle_button();
-    gtk_widget_show(pd->view_button);
-    gtk_container_add(GTK_CONTAINER(pd->view_button), pd->view_button_box);
-    gtk_container_add(GTK_CONTAINER(pd->plugin), pd->view_button);
-    gtk_tooltips_set_tip(pd->view_tooltips, pd->view_button, pd->cfg->label, NULL);
-    xfce_panel_plugin_add_action_widget(pd->plugin, pd->view_button);
-    
-    /* create the image */
-    if(pd->cfg->show_button_icon){
-        pd->view_button_image = g_object_ref(gtk_image_new());
-        gtk_widget_show(pd->view_button_image);
-        gtk_box_pack_start(GTK_BOX(pd->view_button_box), pd->view_button_image, TRUE, TRUE, 0);
-    }else{
-        pd->view_button_image = NULL;
-    }
-
-    /* create the label */
-    if(pd->cfg->show_button_label){
-        pd->view_button_label = g_object_ref(gtk_label_new(pd->cfg->label));
-        gtk_widget_show(pd->view_button_label);
-        gtk_box_pack_end(GTK_BOX(pd->view_button_box), pd->view_button_label, TRUE, TRUE, 0);
-    }else{
-        pd->view_button_label = NULL;
-    }
-
-
-    /* signals for icon theme/screen changes */
-    g_signal_connect_swapped(pd->view_button, "style-set",
-                             G_CALLBACK(places_view_cb_theme_changed), pd);
-    g_signal_connect_swapped(pd->view_button, "screen-changed",
-                             G_CALLBACK(places_view_cb_theme_changed), pd);
-
-    
-    /* connect the signals */
-    g_signal_connect_swapped(pd->view_button, "button-press-event",
-                             G_CALLBACK(places_view_cb_button_pressed), pd);
-
-    g_signal_connect_swapped(G_OBJECT(pd->plugin), "size-changed",
-                             G_CALLBACK(places_view_cb_size_changed), pd);
-                             
-    g_signal_connect_swapped(G_OBJECT(pd->plugin), "orientation-changed",
-                             G_CALLBACK(places_view_cb_orientation_changed), pd);
-
-    places_cfg_init_signals(pd);
-}
-
-
-void 
-places_view_finalize(PlacesData *pd)
-{
-    places_view_destroy_menu(pd);
-    
-    if(pd->view_button_image != NULL)
-        g_object_unref(pd->view_button_image);
-    if(pd->view_button_label != NULL)
-        g_object_unref(pd->view_button_label);
-    g_object_unref(pd->view_tooltips);
-
-    if(pd->bookmark_groups != NULL){
-        GList *bookmark_group = pd->bookmark_groups;
+        GList *bookmark_group = view->bookmark_groups;
         while(bookmark_group != NULL){
-            if(bookmark_group->data != NULL)
-               places_bookmark_group_finalize((PlacesBookmarkGroup*) bookmark_group->data);
-            bookmark_group = bookmark_group->next;
-        }
-        g_list_free(pd->bookmark_groups);
-        pd->bookmark_groups = NULL;
-    }
 
-    places_cfg_finalize(pd);
-}
-
-void
-places_view_reconfigure_model(PlacesData *pd)
-{
-    /* destroy first */
-    if(pd->bookmark_groups != NULL){
-        GList *bookmark_group = pd->bookmark_groups;
-        while(bookmark_group != NULL){
             if(bookmark_group->data != NULL)
                 places_bookmark_group_finalize((PlacesBookmarkGroup*) bookmark_group->data);
+
             bookmark_group = bookmark_group->next;
         }
-        g_list_free(pd->bookmark_groups);
-        pd->bookmark_groups = NULL;
+
+        g_list_free(view->bookmark_groups);
+        view->bookmark_groups = NULL;
     }
 
     /* now create */
-    pd->bookmark_groups = g_list_append(pd->bookmark_groups, places_bookmarks_system_create());
+    view->bookmark_groups = g_list_append(view->bookmark_groups, places_bookmarks_system_create());
 
-    if(pd->cfg->show_volumes)
-        pd->bookmark_groups = g_list_append(pd->bookmark_groups, places_bookmarks_volumes_create());
+    if(view->cfg->show_volumes)
+        view->bookmark_groups = g_list_append(view->bookmark_groups, places_bookmarks_volumes_create());
 
-    if(pd->cfg->show_bookmarks){
-        pd->bookmark_groups = g_list_append(pd->bookmark_groups, NULL); /* separator */
-        pd->bookmark_groups = g_list_append(pd->bookmark_groups, places_bookmarks_user_create());
+    if(view->cfg->show_bookmarks){
+        view->bookmark_groups = g_list_append(view->bookmark_groups, NULL); /* separator */
+        view->bookmark_groups = g_list_append(view->bookmark_groups, places_bookmarks_user_create());
     }
 }
 
-/********** UI Helpers **********/
-
-static void
-places_view_update_menu(PlacesData *pd)
-{
-#if USE_RECENT_DOCUMENTS
-    GtkWidget *recent_menu;
-    GtkWidget *clear_item;
-    GtkWidget *recent_item;
-#endif
-
-    /* destroy the old menu, if it exists */
-    places_view_destroy_menu(pd);
-
-    /* Create a new menu */
-    pd->view_menu = gtk_menu_new();
-    
-    /* make sure the menu popups up in right screen */
-    gtk_menu_set_screen (GTK_MENU (pd->view_menu),
-                         gtk_widget_get_screen (GTK_WIDGET (pd->plugin)));
-
-    GList *bookmark_group = pd->bookmark_groups;
-    GList *bookmarks;
-    PlacesBookmark *bookmark;
-    while(bookmark_group != NULL){
-        
-        if(bookmark_group->data == NULL){ /* separator */
-
-            pd->view_needs_separator = TRUE;
-
-        }else{
-
-            bookmarks = places_bookmark_group_get_bookmarks((PlacesBookmarkGroup*) bookmark_group->data);
-    
-            while(bookmarks != NULL){
-                bookmark = (PlacesBookmark*) bookmarks->data;
-                places_view_add_menu_item(pd, bookmark);
-                bookmarks = bookmarks->next;
-            }
-
-            g_list_free(bookmarks);
-
-        }
-
-        bookmark_group = bookmark_group->next;
-    }
-
-    /* Recent Documents */
-#if USE_RECENT_DOCUMENTS
-    if(pd->cfg->show_recent || (pd->cfg->search_cmd != NULL && strlen(pd->cfg->search_cmd))){
-#else
-    if(pd->cfg->search_cmd != NULL && strlen(pd->cfg->search_cmd)){
-#endif
-        gtk_menu_shell_append(GTK_MENU_SHELL(pd->view_menu),
-                              gtk_separator_menu_item_new());
-    }
-
-    if(pd->cfg->search_cmd != NULL && strlen(pd->cfg->search_cmd)){
-        GtkWidget *search_item = gtk_image_menu_item_new_with_mnemonic(_("Search for Files"));
-        if(pd->cfg->show_icons){
-            GtkWidget *search_image = gtk_image_new_from_icon_name("system-search", GTK_ICON_SIZE_MENU);
-            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(search_item), search_image);
-        }
-        gtk_menu_shell_append(GTK_MENU_SHELL(pd->view_menu), search_item);
-        g_signal_connect_swapped(search_item, "activate",
-                                 G_CALLBACK(places_gui_exec), pd->cfg->search_cmd);
-
-    }
-
-#if USE_RECENT_DOCUMENTS
-    if(pd->cfg->show_recent){
-
-        recent_menu = gtk_recent_chooser_menu_new();
-        gtk_recent_chooser_set_show_icons(GTK_RECENT_CHOOSER(recent_menu), pd->cfg->show_icons);
-        gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(recent_menu), pd->cfg->show_recent_number);
-        g_signal_connect(recent_menu, "item-activated", 
-                         G_CALLBACK(places_view_cb_recent_item_open), pd);
-    
-        if(pd->cfg->show_recent_clear){
-    
-            gtk_menu_shell_append(GTK_MENU_SHELL(recent_menu),
-                                  gtk_separator_menu_item_new());
-        
-            if(pd->cfg->show_icons){
-                clear_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
-            }else{
-                GtkStockItem clear_stock_item;
-                gtk_stock_lookup(GTK_STOCK_CLEAR, &clear_stock_item);
-                clear_item = gtk_menu_item_new_with_mnemonic(clear_stock_item.label);
-            }
-            gtk_menu_shell_append(GTK_MENU_SHELL(recent_menu), clear_item);
-            /* try button-release-event to catch mouse clicks and not hide the menu after */
-            g_signal_connect(clear_item, "button-release-event",
-                             G_CALLBACK(places_view_cb_recent_items_clear), NULL);
-            /* use activate when button-release-event doesn't catch it (e.g., enter key pressed) */
-            g_signal_connect(clear_item, "activate",
-                             G_CALLBACK(places_view_cb_recent_items_clear), NULL);
-    
-        }
-    
-        recent_item = gtk_image_menu_item_new_with_label(_("Recent Documents"));
-        if(pd->cfg->show_icons){
-            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(recent_item), 
-                                          gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
-        }
-        gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent_item), recent_menu);
-        gtk_menu_shell_append(GTK_MENU_SHELL(pd->view_menu), recent_item);
-    }
-#endif
-
-    /* connect deactivate signal */
-    g_signal_connect_swapped(pd->view_menu, "deactivate",
-                             G_CALLBACK(places_view_cb_menu_deact), pd);
-
-    /* Quit hiding the menu */
-    gtk_widget_show_all(pd->view_menu);
-
-    /* This helps allocate resources beforehand so it'll pop up faster the first time */
-    gtk_widget_realize(pd->view_menu);
-}
-
 static gboolean
-places_view_bookmarks_changed(GList *bookmark_groups)
+pview_model_changed(GList *bookmark_groups)
 {
     gboolean ret = FALSE;
     GList *bookmark_group = bookmark_groups;
@@ -371,184 +169,66 @@
     return ret;
 }
 
-void
-places_view_open_menu(PlacesData *pd)
-{
-    /* check if menu is needed, or it needs an update */
-    if(pd->view_menu == NULL || places_view_bookmarks_changed(pd->bookmark_groups))
-        places_view_update_menu(pd);
 
-    /* toggle the button */
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pd->view_button), TRUE);
-
-    /* Register this menu (for focus, transparency, auto-hide, etc) */
-    /* We don't want to register if the menu is visible (hasn't been deactivated) */
-    if(!GTK_WIDGET_VISIBLE(pd->view_menu))
-        xfce_panel_plugin_register_menu(pd->plugin, GTK_MENU(pd->view_menu));
-
-    /* popup menu */
-    gtk_menu_popup (GTK_MENU (pd->view_menu), NULL, NULL,
-                    (GtkMenuPositionFunc) places_view_cb_menu_position,
-                    pd, 0,
-                    gtk_get_current_event_time ());
-    
-    /* menu timeout to poll for model changes */
-    if(pd->view_menu_timeout_id == 0){
-#if GLIB_CHECK_VERSION(2,14,0)
-        pd->view_menu_timeout_id = g_timeout_add_seconds_full(G_PRIORITY_LOW, 2, 
-                                   (GSourceFunc) places_view_cb_menu_timeout, pd,
-                                   NULL);
-#else
-        pd->view_menu_timeout_id = g_timeout_add_full(G_PRIORITY_LOW, 2000, 
-                                   (GSourceFunc) places_view_cb_menu_timeout, pd,
-                                   NULL);
-#endif
-        PLACES_DEBUG_MENU_TIMEOUT_COUNT(1);
-    }else{
-        PLACES_DEBUG_MENU_TIMEOUT_COUNT(0);
-    }
-}
-
-void
-places_view_destroy_menu(PlacesData *pd)
-{
-    if(pd->view_menu != NULL){
-        gtk_menu_shell_deactivate(GTK_MENU_SHELL(pd->view_menu));
-        gtk_widget_destroy(pd->view_menu);
-        pd->view_menu = NULL;
-    }
-    pd->view_needs_separator = FALSE;
-}
-
-void
-places_view_button_update(PlacesData *pd)
-{
-    DBG("button_update");
-
-    GdkPixbuf *icon;
-    gint wsize, size, width, height;
-    gint pix_w = 0, pix_h = 0;
-    GtkOrientation orientation = xfce_panel_plugin_get_orientation(pd->plugin);
-    
-    wsize = xfce_panel_plugin_get_size(pd->plugin);
-    size = wsize - 2 - 2 * MAX(pd->view_button->style->xthickness,
-                         pd->view_button->style->ythickness);
-
-    if(pd->view_button_image != NULL){
-        icon = xfce_themed_icon_load_category(2, size);
-        if(G_LIKELY(icon != NULL)){
-            
-            pix_w = gdk_pixbuf_get_width(icon);
-            pix_h = gdk_pixbuf_get_height(icon);
-            
-            gtk_image_set_from_pixbuf(GTK_IMAGE(pd->view_button_image), icon);
-            g_object_unref(G_OBJECT(icon));
-        }
-    }
-
-    width = pix_w + (wsize - size);
-    height = pix_h + (wsize - size);
-
-    if(pd->view_button_label != NULL){
-        GtkRequisition req;
-        gtk_widget_size_request(pd->view_button_label, &req);
-        if(orientation == GTK_ORIENTATION_HORIZONTAL)
-            width += req.width + BORDER;
-        else {
-            if(width <= req.width)
-                width = req.width + GTK_WIDGET(pd->view_button_label)->style->xthickness;
-            height += req.height + BORDER;
-        }
-    }
-
-    if(pd->view_button_image != NULL && pd->view_button_label != NULL){
-        gint delta = gtk_box_get_spacing(GTK_BOX(pd->view_button_box));
-        if(orientation == GTK_ORIENTATION_HORIZONTAL)
-            width += delta;
-        else
-            height += delta;
-    }
-
-    gtk_widget_set_size_request(pd->view_button, width, height);
-}
-
 /********** Gtk Callbacks **********/
 
 /* Panel callbacks */
 
 static gboolean
-places_view_cb_size_changed(PlacesData *pd, gint wsize)
+pview_cb_size_changed(PlacesView *pd, gint wsize)
 {
-    if(GTK_WIDGET_REALIZED(pd->view_button))
-        places_view_button_update(pd);
+    g_assert(pd != NULL);
+    g_assert(pd->button != NULL);
+    if(GTK_WIDGET_REALIZED(pd->button))
+        pview_button_update(pd);
 
     return TRUE;
 }
 
 static void
-places_view_cb_theme_changed(PlacesData *pd)
+pview_cb_theme_changed(PlacesView *view)
 {
+    g_assert(view != NULL);
+    g_assert(view->button != NULL);
+
     DBG("theme changed");
 
     /* update the button */
-    if(GTK_WIDGET_REALIZED(pd->view_button))
-        places_view_button_update(pd);
+    if(GTK_WIDGET_REALIZED(view->button)){
+        view->force_update_theme = TRUE;
+        pview_button_update(view);
+    }
     
     /* force a menu update */
-    places_view_destroy_menu(pd);
+    pview_destroy_menu(view);
 }
 
 static void
-places_view_cb_orientation_changed(PlacesData *pd, GtkOrientation orientation, XfcePanelPlugin *panel)
+pview_cb_orientation_changed(PlacesView *view, GtkOrientation orientation, XfcePanelPlugin *panel)
 {
     DBG("orientation changed");
-
-    gtk_widget_set_size_request(pd->view_button, -1, -1);
-
-    gtk_container_remove(GTK_CONTAINER(pd->view_button),
-                         gtk_bin_get_child(GTK_BIN(pd->view_button)));
-
-    if(orientation == GTK_ORIENTATION_HORIZONTAL)
-       pd->view_button_box = gtk_hbox_new(FALSE, BORDER);
-    else
-       pd->view_button_box = gtk_vbox_new(FALSE, BORDER);
-    
-    gtk_container_set_border_width(GTK_CONTAINER(pd->view_button_box), 0);
-    gtk_widget_show(pd->view_button_box);
-    gtk_container_add(GTK_CONTAINER(pd->view_button), pd->view_button_box);
-
-    if(pd->view_button_image != NULL){
-        gtk_widget_show(pd->view_button_image);
-        gtk_box_pack_start(GTK_BOX(pd->view_button_box), pd->view_button_image, TRUE, TRUE, 0);
-    }
-
-    if(pd->view_button_label != NULL){
-        gtk_widget_show(pd->view_button_label);
-        gtk_box_pack_end(GTK_BOX(pd->view_button_box), pd->view_button_label, TRUE, TRUE, 0);
-    }
-
-    places_view_button_update(pd);
+    pview_button_update(view);
 }
 
 /* Menu callbacks */
 static gboolean /* return false to stop calling it */
-places_view_cb_menu_timeout(PlacesData *pd){
+pview_cb_menu_timeout(PlacesView *pd){
 
-    if(!pd->view_menu_timeout_id)
+    if(!pd->menu_timeout_id)
         goto killtimeout;
 
-    if(pd->view_menu == NULL || !GTK_WIDGET_VISIBLE(pd->view_menu))
+    if(pd->menu == NULL || !GTK_WIDGET_VISIBLE(pd->menu))
         goto killtimeout;
 
-    if(places_view_bookmarks_changed(pd->bookmark_groups))
-        places_view_open_menu(pd);
+    if(pview_model_changed(pd->bookmark_groups))
+        pview_open_menu(pd);
 
     PLACES_DEBUG_MENU_TIMEOUT_COUNT(0);
     return TRUE;   
     
   killtimeout:
-        if(pd->view_menu_timeout_id){
-            pd->view_menu_timeout_id = 0;
+        if(pd->menu_timeout_id){
+            pd->menu_timeout_id = 0;
             PLACES_DEBUG_MENU_TIMEOUT_COUNT(-1);
         }else{
             PLACES_DEBUG_MENU_TIMEOUT_COUNT(0);
@@ -559,10 +239,10 @@
 
 /* Copied almost verbatim from xfdesktop plugin */
 static void
-places_view_cb_menu_position(GtkMenu *menu, 
+pview_cb_menu_position(GtkMenu *menu, 
                              gint *x, gint *y, 
                              gboolean *push_in, 
-                             PlacesData *pd)
+                             PlacesView *pd)
 {
     XfceScreenPosition pos;
     GtkRequisition req;
@@ -577,21 +257,21 @@
         case XFCE_SCREEN_POSITION_NW_V:
         case XFCE_SCREEN_POSITION_W:
         case XFCE_SCREEN_POSITION_SW_V:
-            *x += pd->view_button->allocation.width;
-            *y += pd->view_button->allocation.height - req.height;
+            *x += pd->button->allocation.width;
+            *y += pd->button->allocation.height - req.height;
             break;
         
         case XFCE_SCREEN_POSITION_NE_V:
         case XFCE_SCREEN_POSITION_E:
         case XFCE_SCREEN_POSITION_SE_V:
             *x -= req.width;
-            *y += pd->view_button->allocation.height - req.height;
+            *y += pd->button->allocation.height - req.height;
             break;
         
         case XFCE_SCREEN_POSITION_NW_H:
         case XFCE_SCREEN_POSITION_N:
         case XFCE_SCREEN_POSITION_NE_H:
-            *y += pd->view_button->allocation.height;
+            *y += pd->button->allocation.height;
             break;
         
         case XFCE_SCREEN_POSITION_SW_H:
@@ -627,15 +307,15 @@
 }
 
 static void 
-places_view_cb_menu_deact(PlacesData *pd, GtkWidget *menu)
+pview_cb_menu_deact(PlacesView *pd, GtkWidget *menu)
 {
     /* deactivate button */
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pd->view_button), FALSE);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pd->button), FALSE);
 
     /* remove the timeout to save a tick */
-    if(pd->view_menu_timeout_id){
-        g_source_remove(pd->view_menu_timeout_id);
-        pd->view_menu_timeout_id = 0;
+    if(pd->menu_timeout_id){
+        g_source_remove(pd->menu_timeout_id);
+        pd->menu_timeout_id = 0;
         PLACES_DEBUG_MENU_TIMEOUT_COUNT(-1);
     }else{
         PLACES_DEBUG_MENU_TIMEOUT_COUNT(0);
@@ -644,28 +324,28 @@
 
 /* Button */
 static gboolean
-places_view_cb_button_pressed(PlacesData *pd, GdkEventButton *evt)
+pview_cb_button_pressed(PlacesView *pd, GdkEventButton *evt)
 {
     /* (it's the way xfdesktop menu does it...) */
     if((evt->state & GDK_CONTROL_MASK) && !(evt->state & (GDK_MOD1_MASK|GDK_SHIFT_MASK|GDK_MOD4_MASK)))
         return FALSE;
 
     if(evt->button == 1)
-        places_view_open_menu(pd);
+        pview_open_menu(pd);
     else if(evt->button == 2)
         places_load_thunar(NULL);
 
     return FALSE;
 }
 
-void
-places_view_cb_menu_item_context_act(GtkWidget *item, PlacesData *pd)
+static void
+pview_cb_menu_item_context_act(GtkWidget *item, PlacesView *pd)
 {
     g_assert(pd != NULL);
-    g_assert(pd->view_menu != NULL && GTK_IS_WIDGET(pd->view_menu));
+    g_assert(pd->menu != NULL && GTK_IS_WIDGET(pd->menu));
 
     /* we want the menu gone - now - since it prevents mouse grabs */
-    gtk_menu_shell_deactivate(GTK_MENU_SHELL(pd->view_menu));
+    gtk_menu_shell_deactivate(GTK_MENU_SHELL(pd->menu));
     while(g_main_context_iteration(NULL, FALSE))
         /* no op */;
 
@@ -675,8 +355,8 @@
     
 }
 
-gboolean
-places_view_cb_menu_item_do_alt(PlacesData *pd, GtkWidget *menu_item)
+static gboolean
+pview_cb_menu_item_do_alt(PlacesView *pd, GtkWidget *menu_item)
 {
     
     GList *actions = (GList*) g_object_get_data(G_OBJECT(menu_item), "actions");
@@ -696,7 +376,7 @@
             g_object_set_data(G_OBJECT(context_item), "action", action);
             gtk_widget_show(context_item);
             g_signal_connect(context_item, "activate",
-                             G_CALLBACK(places_view_cb_menu_item_context_act), pd);
+                             G_CALLBACK(pview_cb_menu_item_context_act), pd);
             gtk_menu_shell_append(GTK_MENU_SHELL(context), context_item);
 
             actions = actions->next;
@@ -707,15 +387,15 @@
                        NULL, NULL,
                        0, gtk_get_current_event_time());
 
-        g_signal_connect_swapped(context, "deactivate", G_CALLBACK(places_view_open_menu), pd);
+        g_signal_connect_swapped(context, "deactivate", G_CALLBACK(pview_open_menu), pd);
 
     }
 
     return TRUE;
 }
 
-gboolean
-places_view_cb_menu_item_do_main(PlacesData *pd, GtkWidget *menu_item)
+static gboolean
+pview_cb_menu_item_do_main(PlacesView *pd, GtkWidget *menu_item)
 {
         const gchar *uri = (const gchar*) g_object_get_data(G_OBJECT(menu_item), "uri");
         if(uri != NULL){
@@ -726,15 +406,15 @@
 }
 
 
-gboolean
-places_view_cb_menu_item_press(GtkWidget *menu_item, GdkEventButton *event, PlacesData *pd)
+static gboolean
+pview_cb_menu_item_press(GtkWidget *menu_item, GdkEventButton *event, PlacesView *pd)
 {
 
     gboolean ctrl =  (event->state & GDK_CONTROL_MASK) && 
                     !(event->state & (GDK_MOD1_MASK|GDK_SHIFT_MASK|GDK_MOD4_MASK));
     gboolean sensitive = GTK_WIDGET_IS_SENSITIVE(gtk_bin_get_child(GTK_BIN(menu_item)));
     if(event->button == 3 || (event->button == 1 && (ctrl || !sensitive)))
-        return places_view_cb_menu_item_do_alt(pd, menu_item);
+        return pview_cb_menu_item_do_alt(pd, menu_item);
     else
         return FALSE;
 }
@@ -743,7 +423,7 @@
 
 #if USE_RECENT_DOCUMENTS
 static void
-places_view_cb_recent_item_open(GtkRecentChooser *chooser, PlacesData *pd)
+pview_cb_recent_item_open(GtkRecentChooser *chooser, PlacesView *pd)
 {
     gchar *uri = gtk_recent_chooser_get_current_uri(chooser);
     places_load_file(uri);
@@ -751,7 +431,7 @@
 }
 
 static gboolean
-places_view_cb_recent_items_clear(GtkWidget *clear_item)
+pview_cb_recent_items_clear(GtkWidget *clear_item)
 {
     GtkRecentManager *manager = gtk_recent_manager_get_default();
     gint removed = gtk_recent_manager_purge_items(manager, NULL);
@@ -763,7 +443,7 @@
 /********** Model Visitor Callbacks **********/
 
 static void
-places_view_load_thunar_wrapper(PlacesBookmarkAction *act)
+pview_load_thunar_wrapper(PlacesBookmarkAction *act)
 {
     g_assert(act != NULL);
     places_load_thunar((gchar*) act->priv);
@@ -772,34 +452,50 @@
 
 
 static void
-places_view_load_terminal_wrapper(PlacesBookmarkAction *act)
+pview_load_terminal_wrapper(PlacesBookmarkAction *act)
 {
     g_assert(act != NULL);
     places_load_terminal((gchar*) act->priv);
 }
 
 
+
+/********** UI Helpers **********/
 static void
-places_view_add_menu_item(PlacesData *pd, PlacesBookmark *bookmark)
+pview_destroy_menu(PlacesView *view)
 {
-    g_assert(pd != NULL);
+    if(view->menu != NULL){
+        gtk_menu_shell_deactivate(GTK_MENU_SHELL(view->menu));
+        gtk_widget_destroy(view->menu);
+        view->menu = NULL;
+    }
+    view->needs_separator = FALSE;
+}
+
+static void
+pview_add_menu_item(PlacesView *view, PlacesBookmark *bookmark)
+{
+    g_assert(view != NULL);
     g_assert(bookmark != NULL);
 
     GtkWidget *item;
+    GdkPixbuf *pb;
+    GtkWidget *image;
+    PlacesBookmarkAction *terminal, *open;
 
-    if(pd->view_needs_separator){
-        gtk_menu_shell_append(GTK_MENU_SHELL(pd->view_menu),
+    if(view->needs_separator){
+        gtk_menu_shell_append(GTK_MENU_SHELL(view->menu),
                               gtk_separator_menu_item_new());
-        pd->view_needs_separator = FALSE;
+        view->needs_separator = FALSE;
     }
 
     item = gtk_image_menu_item_new_with_label(bookmark->label);
 
-    if(pd->cfg->show_icons && bookmark->icon != NULL){
-        GdkPixbuf *pb = xfce_themed_icon_load(bookmark->icon, 16);
+    if(view->cfg->show_icons && bookmark->icon != NULL){
+        pb = xfce_themed_icon_load(bookmark->icon, 16);
         
         if(G_LIKELY(pb != NULL)){
-            GtkWidget *image = gtk_image_new_from_pixbuf(pb);
+            image = gtk_image_new_from_pixbuf(pb);
             g_object_unref(pb);
             gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
         }
@@ -810,18 +506,18 @@
         g_object_set_data(G_OBJECT(item), "uri", (gchar*) bookmark->uri);
 
         if(bookmark->uri_scheme != PLACES_URI_SCHEME_TRASH){
-            PlacesBookmarkAction *terminal  = g_new0(PlacesBookmarkAction, 1);
-            terminal->label                 = _("Open Terminal Here");
-            terminal->priv                  = bookmark->uri;
-            terminal->action                = places_view_load_terminal_wrapper;
-            bookmark->actions = g_list_prepend(bookmark->actions, terminal);
+            terminal            = g_new0(PlacesBookmarkAction, 1);
+            terminal->label     = _("Open Terminal Here");
+            terminal->priv      = bookmark->uri;
+            terminal->action    = pview_load_terminal_wrapper;
+            bookmark->actions   = g_list_prepend(bookmark->actions, terminal);
         }
 
-        PlacesBookmarkAction *open  = g_new0(PlacesBookmarkAction, 1);
-        open->label                 = _("Open");
-        open->priv                  = bookmark->uri;
-        open->action                = places_view_load_thunar_wrapper;
-        bookmark->actions = g_list_prepend(bookmark->actions, open);
+        open                = g_new0(PlacesBookmarkAction, 1);
+        open->label         = _("Open");
+        open->priv          = bookmark->uri;
+        open->action        = pview_load_thunar_wrapper;
+        bookmark->actions   = g_list_prepend(bookmark->actions, open);
 
     }else{
         /* Probably an unmounted volume. Gray it out. */
@@ -833,14 +529,528 @@
 
 
     g_signal_connect(item, "button-release-event",
-                     G_CALLBACK(places_view_cb_menu_item_press), pd);
+                     G_CALLBACK(pview_cb_menu_item_press), view);
     g_signal_connect_swapped(item, "activate",
-                     G_CALLBACK(places_view_cb_menu_item_do_main), pd);
+                     G_CALLBACK(pview_cb_menu_item_do_main), view);
     g_signal_connect_swapped(item, "destroy",
                      G_CALLBACK(places_bookmark_free), bookmark);
 
-    gtk_menu_shell_append(GTK_MENU_SHELL(pd->view_menu), item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view->menu), item);
 
 }
 
+static void
+pview_update_menu(PlacesView *pd)
+{
+#if USE_RECENT_DOCUMENTS
+    GtkWidget *recent_menu;
+    GtkWidget *clear_item;
+    GtkWidget *recent_item;
+#endif
+
+    /* destroy the old menu, if it exists */
+    pview_destroy_menu(pd);
+
+    /* Create a new menu */
+    pd->menu = gtk_menu_new();
+    
+    /* make sure the menu popups up in right screen */
+    gtk_menu_set_screen (GTK_MENU (pd->menu),
+                         gtk_widget_get_screen (GTK_WIDGET (pd->plugin)));
+
+    GList *bookmark_group = pd->bookmark_groups;
+    GList *bookmarks;
+    PlacesBookmark *bookmark;
+    while(bookmark_group != NULL){
+        
+        if(bookmark_group->data == NULL){ /* separator */
+
+            pd->needs_separator = TRUE;
+
+        }else{
+
+            bookmarks = places_bookmark_group_get_bookmarks((PlacesBookmarkGroup*) bookmark_group->data);
+    
+            while(bookmarks != NULL){
+                bookmark = (PlacesBookmark*) bookmarks->data;
+                pview_add_menu_item(pd, bookmark);
+                bookmarks = bookmarks->next;
+            }
+
+            g_list_free(bookmarks);
+
+        }
+
+        bookmark_group = bookmark_group->next;
+    }
+
+    /* Recent Documents */
+#if USE_RECENT_DOCUMENTS
+    if(pd->cfg->show_recent || (pd->cfg->search_cmd != NULL && strlen(pd->cfg->search_cmd))){
+#else
+    if(pd->cfg->search_cmd != NULL && strlen(pd->cfg->search_cmd)){
+#endif
+        gtk_menu_shell_append(GTK_MENU_SHELL(pd->menu),
+                              gtk_separator_menu_item_new());
+    }
+
+    if(pd->cfg->search_cmd != NULL && strlen(pd->cfg->search_cmd)){
+        GtkWidget *search_item = gtk_image_menu_item_new_with_mnemonic(_("Search for Files"));
+        if(pd->cfg->show_icons){
+            GtkWidget *search_image = gtk_image_new_from_icon_name("system-search", GTK_ICON_SIZE_MENU);
+            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(search_item), search_image);
+        }
+        gtk_menu_shell_append(GTK_MENU_SHELL(pd->menu), search_item);
+        g_signal_connect_swapped(search_item, "activate",
+                                 G_CALLBACK(places_gui_exec), pd->cfg->search_cmd);
+
+    }
+
+#if USE_RECENT_DOCUMENTS
+    if(pd->cfg->show_recent){
+
+        recent_menu = gtk_recent_chooser_menu_new();
+        gtk_recent_chooser_set_show_icons(GTK_RECENT_CHOOSER(recent_menu), pd->cfg->show_icons);
+        gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(recent_menu), pd->cfg->show_recent_number);
+        g_signal_connect(recent_menu, "item-activated", 
+                         G_CALLBACK(pview_cb_recent_item_open), pd);
+    
+        if(pd->cfg->show_recent_clear){
+    
+            gtk_menu_shell_append(GTK_MENU_SHELL(recent_menu),
+                                  gtk_separator_menu_item_new());
+        
+            if(pd->cfg->show_icons){
+                clear_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
+            }else{
+                GtkStockItem clear_stock_item;
+                gtk_stock_lookup(GTK_STOCK_CLEAR, &clear_stock_item);
+                clear_item = gtk_menu_item_new_with_mnemonic(clear_stock_item.label);
+            }
+            gtk_menu_shell_append(GTK_MENU_SHELL(recent_menu), clear_item);
+            /* try button-release-event to catch mouse clicks and not hide the menu after */
+            g_signal_connect(clear_item, "button-release-event",
+                             G_CALLBACK(pview_cb_recent_items_clear), NULL);
+            /* use activate when button-release-event doesn't catch it (e.g., enter key pressed) */
+            g_signal_connect(clear_item, "activate",
+                             G_CALLBACK(pview_cb_recent_items_clear), NULL);
+    
+        }
+    
+        recent_item = gtk_image_menu_item_new_with_label(_("Recent Documents"));
+        if(pd->cfg->show_icons){
+            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(recent_item), 
+                                          gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
+        }
+        gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent_item), recent_menu);
+        gtk_menu_shell_append(GTK_MENU_SHELL(pd->menu), recent_item);
+    }
+#endif
+
+    /* connect deactivate signal */
+    g_signal_connect_swapped(pd->menu, "deactivate",
+                             G_CALLBACK(pview_cb_menu_deact), pd);
+
+    /* Quit hiding the menu */
+    gtk_widget_show_all(pd->menu);
+
+    /* This helps allocate resources beforehand so it'll pop up faster the first time */
+    gtk_widget_realize(pd->menu);
+}
+
+static void
+pview_open_menu(PlacesView *pd)
+{
+    /* check if menu is needed, or it needs an update */
+    if(pd->menu == NULL || pview_model_changed(pd->bookmark_groups))
+        pview_update_menu(pd);
+
+    /* toggle the button */
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pd->button), TRUE);
+
+    /* Register this menu (for focus, transparency, auto-hide, etc) */
+    /* We don't want to register if the menu is visible (hasn't been deactivated) */
+    if(!GTK_WIDGET_VISIBLE(pd->menu))
+        xfce_panel_plugin_register_menu(pd->plugin, GTK_MENU(pd->menu));
+
+    /* popup menu */
+    gtk_menu_popup (GTK_MENU (pd->menu), NULL, NULL,
+                    (GtkMenuPositionFunc) pview_cb_menu_position,
+                    pd, 0,
+                    gtk_get_current_event_time ());
+    
+    /* menu timeout to poll for model changes */
+    if(pd->menu_timeout_id == 0){
+#if GLIB_CHECK_VERSION(2,14,0)
+        pd->menu_timeout_id = g_timeout_add_seconds_full(G_PRIORITY_LOW, 2, 
+                                   (GSourceFunc) pview_cb_menu_timeout, pd,
+                                   NULL);
+#else
+        pd->menu_timeout_id = g_timeout_add_full(G_PRIORITY_LOW, 2000, 
+                                   (GSourceFunc) pview_cb_menu_timeout, pd,
+                                   NULL);
+#endif
+        PLACES_DEBUG_MENU_TIMEOUT_COUNT(1);
+    }else{
+        PLACES_DEBUG_MENU_TIMEOUT_COUNT(0);
+    }
+}
+
+static inline GtkWidget*
+pview_gtk_obox_new(GtkOrientation orientation)
+{
+    GtkWidget *box;
+    if(orientation == GTK_ORIENTATION_HORIZONTAL)
+        box = gtk_hbox_new(FALSE, BORDER);
+    else
+        box = gtk_vbox_new(FALSE, BORDER);
+    gtk_container_set_border_width(GTK_CONTAINER(box), 0);
+    gtk_widget_show(box);
+    return box;
+}
+
+static void
+pview_button_update_orientation(PlacesView *view)
+{
+    GtkOrientation orientation;
+    GtkWidget *old_box, *new_box, *child;
+    GList *children;
+
+    DBG("-");
+
+    g_assert(view != NULL);
+
+    orientation = xfce_panel_plugin_get_orientation(view->plugin);
+    view->orientation = orientation;
+
+    old_box = gtk_bin_get_child(GTK_BIN(view->button));
+    g_assert(GTK_IS_WIDGET(old_box));
+    g_object_ref(old_box);
+    gtk_container_remove(GTK_CONTAINER(view->button), old_box);
+
+    gtk_widget_set_size_request(view->button, -1, -1); /* not sure why */
+
+    new_box = pview_gtk_obox_new(orientation);
+    gtk_container_add(GTK_CONTAINER(view->button), new_box);
+
+    /* move the contents of the old box to the new box */
+    children = gtk_container_get_children(GTK_CONTAINER(old_box));
+
+    while(children != NULL){
+        child = GTK_WIDGET(children->data);
+        
+        g_object_ref(child);
+        gtk_container_remove(GTK_CONTAINER(old_box), child);
+        gtk_box_pack_start_defaults(GTK_BOX(new_box), child);
+        g_object_unref(child);
+        
+        gtk_widget_show(child);
+
+        children = children->next;
+    }
+
+    gtk_widget_destroy(old_box);
+    g_object_unref(old_box);
+}   
+
+
+static void
+pview_button_update(PlacesView *view)
+{
+    
+    PlacesCfg *cfg = view->cfg;
+    gboolean orientation_changed, size_changed, 
+             icon_presence_changed, label_presence_changed, 
+             label_tooltip_changed, theme_changed;
+    static gboolean first_run = TRUE;
+
+    DBG("button_update (first run: %1x)", first_run);
+
+    if(first_run){
+        first_run = FALSE;
+        
+        orientation_changed = TRUE;
+        view->orientation = xfce_panel_plugin_get_orientation(view->plugin);
+        
+        size_changed = TRUE;
+        view->size = xfce_panel_plugin_get_size(view->plugin);
+        
+        icon_presence_changed = TRUE;
+        view->show_button_icon = cfg->show_button_icon;
+        
+        label_presence_changed = TRUE;
+        view->show_button_label = cfg->show_button_label;
+        
+        label_tooltip_changed = TRUE;
+        view->label_tooltip_text = g_strdup(cfg->label);
+
+        theme_changed = TRUE;
+        view->force_update_theme = FALSE;
+
+    }else{
+        orientation_changed    = (view->orientation != xfce_panel_plugin_get_orientation(view->plugin));
+        size_changed           = (view->size != xfce_panel_plugin_get_size(view->plugin));
+        icon_presence_changed  = (view->show_button_icon != cfg->show_button_icon);
+        label_presence_changed = (view->show_button_label != cfg->show_button_label);
+        label_tooltip_changed  = (strcmp(view->label_tooltip_text, cfg->label) != 0);
+        theme_changed          = view->force_update_theme;
+    }
+
+    DBG("orientation: %1x, size: %1x, icon_pr: %1x, label_pr: %1x, label_tooltip: %1x",
+        orientation_changed, size_changed, 
+        icon_presence_changed, label_presence_changed, 
+        label_tooltip_changed);
+
+    if(orientation_changed){
+        pview_button_update_orientation(view);
+        size_changed = TRUE;
+    }
+    
+    if(label_tooltip_changed){
+        g_free(view->label_tooltip_text);
+        view->label_tooltip_text = g_strdup(cfg->label);
+    }
+
+    if(theme_changed)
+        view->force_update_theme = FALSE;
+
+    if(size_changed || icon_presence_changed || label_presence_changed || theme_changed){
+        view->size              = xfce_panel_plugin_get_size(view->plugin);
+        DBG("size: %d", view->size);
+        view->show_button_icon  = cfg->show_button_icon;
+        view->show_button_label = cfg->show_button_label;
+        
+        GdkPixbuf *icon;
+        gint size, width, height;
+        gint pix_w = 0, pix_h = 0;
+        GtkWidget *button_box = gtk_bin_get_child(GTK_BIN(view->button));
+        
+        DBG("button thickness (%d, %d)", view->button->style->xthickness, view->button->style->ythickness);
+        size = view->size - 2 - 2 * MAX(view->button->style->xthickness,
+                                        view->button->style->ythickness);
+
+        if(view->show_button_icon){
+            icon = xfce_themed_icon_load_category(2, size);
+            if(G_LIKELY(icon != NULL)){
+                
+                pix_w = gdk_pixbuf_get_width(icon);
+                pix_h = gdk_pixbuf_get_height(icon);
+             
+                if(view->button_image == NULL){
+                    view->button_image = g_object_ref(gtk_image_new_from_pixbuf(icon));
+                    gtk_widget_show(view->button_image);
+                    gtk_box_pack_start_defaults(GTK_BOX(button_box),
+                                                view->button_image);
+                }else{
+                    g_assert(GTK_IS_WIDGET(view->button_image));
+                    gtk_image_set_from_pixbuf(GTK_IMAGE(view->button_image), icon);
+                }
+
+                g_object_unref(G_OBJECT(icon));
+            }else{
+                DBG("Could not load icon for button");
+            }
+
+        }else if(view->button_image != NULL){
+            g_assert(GTK_IS_WIDGET(view->button_image));
+            gtk_widget_destroy(view->button_image);
+            g_object_unref(view->button_image);
+            view->button_image = NULL;
+        }
+        DBG("button thickness (%d, %d)", view->button->style->xthickness, view->button->style->ythickness);
+
+        DBG("view->size=%d, size=%d", view->size, size);
+        width = pix_w + (view->size - size);
+        height = pix_h + (view->size - size);
+        if(view->orientation == GTK_ORIENTATION_HORIZONTAL)
+            height = MAX(width, size);
+        else
+            width = MAX(height, size);
+
+        if(view->show_button_label){
+            GtkRequisition req;
+            
+            if(view->button_label == NULL){
+                view->button_label = g_object_ref(gtk_label_new(cfg->label));
+                gtk_widget_show(view->button_label);
+                gtk_box_pack_end_defaults(GTK_BOX(button_box), 
+                                          view->button_label);
+            }else{
+                g_assert(GTK_IS_WIDGET(view->button_label));
+                if(label_tooltip_changed)
+                    gtk_label_set_text(GTK_LABEL(view->button_label), view->label_tooltip_text);
+            }
+
+            gtk_widget_size_request(view->button_label, &req);
+            DBG("label wants width: %d, width is now: %d", req.width, width);
+            if(view->orientation == GTK_ORIENTATION_HORIZONTAL)
+                width += req.width + BORDER;
+            else {
+                width = MAX(width, req.width + 2 + 2 * view->button->style->xthickness);
+                height += req.height + BORDER;
+            }
+        }else if(view->button_label != NULL){
+            g_assert(GTK_IS_WIDGET(view->button_label));
+            gtk_widget_destroy(view->button_label);
+            g_object_unref(view->button_label);
+            view->button_label = NULL;
+        }
+
+        if(view->button_image != NULL && view->button_label != NULL){
+
+            gint delta = gtk_box_get_spacing(GTK_BOX(button_box));
+
+            if(view->orientation == GTK_ORIENTATION_HORIZONTAL)
+                width += delta;
+            else
+                height += delta;
+        }
+
+        DBG("width=%d, height=%d", width, height);
+        gtk_widget_set_size_request(view->button, width, height);
+    }
+
+    if(label_tooltip_changed)
+        gtk_tooltips_set_tip(view->tooltips, view->button, view->label_tooltip_text, NULL);
+}
+
+
+
+static void
+pview_cfg_dialog_close_cb(GtkDialog *dialog, gint response, PlacesView *view)
+{
+    gtk_widget_destroy(GTK_WIDGET(dialog));
+    xfce_panel_plugin_unblock_menu(view->plugin);
+    places_cfg_view_iface_save(view->cfg_iface);
+}
+
+static GtkWidget*
+pview_make_empty_cfg_dialog(PlacesView *view)
+{
+    GtkWidget *dlg; /* we'll return this */
+
+    xfce_panel_plugin_block_menu(view->plugin);
+    
+    dlg = xfce_titled_dialog_new_with_buttons(_("Places"),
+              GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view->plugin))),
+              GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+              GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
+
+    gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
+    gtk_window_set_icon_name(GTK_WINDOW(dlg), "xfce4-settings");
+
+    g_signal_connect(dlg, "response",
+                     G_CALLBACK(pview_cfg_dialog_close_cb), view);
+
+    return dlg;
+}
+
+/********** Initialization & Finalization **********/
+PlacesView*
+places_view_init(XfcePanelPlugin *plugin)
+{
+    DBG("initializing");
+    g_assert(plugin != NULL);
+
+    PlacesView *view;                   /* internal use in this file */
+    PlacesViewCfgIface *view_cfg_iface; /* given to cfg */
+
+    view            = g_new0(PlacesView, 1);
+    view->plugin    = plugin;
+    
+    view_cfg_iface                          = g_new0(PlacesViewCfgIface, 1);
+    view_cfg_iface->places_view             = view;
+    view_cfg_iface->open_menu               = pview_open_menu;
+    view_cfg_iface->update_menu             = pview_update_menu;
+    view_cfg_iface->update_button           = pview_button_update;
+    view_cfg_iface->reconfigure_model       = pview_reconfigure_model;
+    view_cfg_iface->make_empty_cfg_dialog   = pview_make_empty_cfg_dialog;
+    
+    view->view_cfg_iface = view_cfg_iface;
+    view->cfg_iface      = places_cfg_new(view_cfg_iface, 
+                                          xfce_panel_plugin_lookup_rc_file(view->plugin),
+                                          xfce_panel_plugin_save_location(view->plugin, TRUE));
+    view->cfg            = places_cfg_view_iface_get_cfg(view->cfg_iface);
+
+    pview_reconfigure_model(view);
+    
+    view->tooltips = g_object_ref_sink(gtk_tooltips_new());
+
+    /* init button */
+
+    DBG("init GUI");
+
+    /* create the button */
+    view->button = g_object_ref(xfce_create_panel_toggle_button());
+    gtk_widget_show(view->button);
+    gtk_container_add(GTK_CONTAINER(view->plugin), view->button);
+    xfce_panel_plugin_add_action_widget(view->plugin, view->button);
+
+    /* create the box */
+    GtkWidget *button_box = pview_gtk_obox_new(xfce_panel_plugin_get_orientation(view->plugin));
+    gtk_container_add(GTK_CONTAINER(view->button), button_box);
+
+    pview_button_update(view);
+
+    /* signals for icon theme/screen changes */
+    g_signal_connect_swapped(view->button, "style-set",
+                             G_CALLBACK(pview_cb_theme_changed), view);
+    g_signal_connect_swapped(view->button, "screen-changed",
+                             G_CALLBACK(pview_cb_theme_changed), view);
+    
+    /* plugin signals */
+    g_signal_connect_swapped(G_OBJECT(view->plugin), "size-changed",
+                             G_CALLBACK(pview_cb_size_changed), view);
+    g_signal_connect_swapped(G_OBJECT(view->plugin), "orientation-changed",
+                             G_CALLBACK(pview_cb_orientation_changed), view);
+
+    /* button signal */
+    g_signal_connect_swapped(view->button, "button-press-event",
+                             G_CALLBACK(pview_cb_button_pressed), view);
+
+    /* cfg-related signals */
+    g_signal_connect_swapped(G_OBJECT(view->plugin), "configure-plugin",
+                             G_CALLBACK(places_cfg_view_iface_open_dialog), view->cfg_iface);
+    g_signal_connect_swapped(G_OBJECT(view->plugin), "save",
+                             G_CALLBACK(places_cfg_view_iface_save), view->cfg_iface);
+    xfce_panel_plugin_menu_show_configure(view->plugin);
+
+    DBG("done");
+
+    return view;
+}
+
+void 
+places_view_finalize(PlacesView *view)
+{
+    pview_destroy_menu(view);
+    
+    if(view->button_image != NULL)
+        g_object_unref(view->button_image);
+    if(view->button_label != NULL)
+        g_object_unref(view->button_label);
+    if(view->button != NULL)
+        g_object_unref(view->button);
+    if(view->label_tooltip_text != NULL)
+        g_free(view->label_tooltip_text);
+    g_object_unref(view->tooltips);
+
+    if(view->bookmark_groups != NULL){
+        GList *bookmark_group = view->bookmark_groups;
+        while(bookmark_group != NULL){
+            if(bookmark_group->data != NULL)
+               places_bookmark_group_finalize((PlacesBookmarkGroup*) bookmark_group->data);
+            bookmark_group = bookmark_group->next;
+        }
+        g_list_free(view->bookmark_groups);
+        view->bookmark_groups = NULL;
+    }
+
+    places_cfg_view_iface_finalize(view->cfg_iface);
+    
+    g_free(view->view_cfg_iface);
+    g_free(view);
+}
+
+
 /* vim: set ai et tabstop=4: */

Modified: xfce4-places-plugin/trunk/panel-plugin/view.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/view.h	2007-09-11 22:02:15 UTC (rev 3203)
+++ xfce4-places-plugin/trunk/panel-plugin/view.h	2007-09-12 02:34:09 UTC (rev 3204)
@@ -23,23 +23,27 @@
 #include <glib.h>
 #include "places.h"
 
-#if GTK_CHECK_VERSION(2,10,0)
-#  define USE_RECENT_DOCUMENTS TRUE
-#endif
+typedef struct _PlacesView PlacesView;
 
-#define BORDER 4
+typedef struct {
+    
+    PlacesView          *places_view;
 
+    void                (*open_menu)                (PlacesView*);
+    void                (*update_menu)              (PlacesView*);
+    void                (*update_button)            (PlacesView*);
+    void                (*reconfigure_model)        (PlacesView*);
+    GtkWidget*          (*make_empty_cfg_dialog)    (PlacesView*);
+    
+} PlacesViewCfgIface;
+
+#include "cfg.h"
+
+
 /* Init & Finalize */
-void     places_view_init(PlacesData*);
-void     places_view_finalize(PlacesData*);
+PlacesView*             places_view_init(XfcePanelPlugin*);
+void                    places_view_finalize(PlacesView*);
 
-/* UI control */
-void     places_view_open_menu(PlacesData*);
-void     places_view_destroy_menu(PlacesData*);
 
-/* cfg use */
-void     places_view_reconfigure_model(PlacesData*);
-void     places_view_button_update(PlacesData*);
-
 #endif
 /* vim: set ai et tabstop=4: */




More information about the Goodies-commits mailing list