[gnome-panel/wip-geiger-applets-list] properties-dialog: show list of applets




commit f616ab3cc2c905557eac1ef39e657460d22e8c3c
Author: Sebastian Geiger <sbastig gmx net>
Date:   Mon Apr 13 21:02:40 2020 +0200

    properties-dialog: show list of applets
    
    This adds a new tab to the gnome-panel properties
    dialog which is titled 'Applets' and which shows
    the list of currently added applets for this panel.
    
    The list of applets is grouped into the three
    locations on the panel (left, right, center) and
    its possible to remove applets from the panel.
    
    Additionally a kebab-menu (three dots) allows
    access to 'About' and 'Help' dialogs for each
    applet if they are implemented by that applet.

 gnome-panel/Makefile.am             |   2 +
 gnome-panel/applet.c                |   2 +-
 gnome-panel/applet.h                |   2 +
 gnome-panel/gp-applet-list-row.c    | 384 ++++++++++++++++++++++++++++++++++++
 gnome-panel/gp-applet-list-row.h    |  44 +++++
 gnome-panel/gp-properties-dialog.c  | 207 +++++++++++++++++++
 gnome-panel/gp-properties-dialog.ui |  91 ++++++++-
 7 files changed, 729 insertions(+), 3 deletions(-)
---
diff --git a/gnome-panel/Makefile.am b/gnome-panel/Makefile.am
index bd3f88c1e..976d37f0b 100644
--- a/gnome-panel/Makefile.am
+++ b/gnome-panel/Makefile.am
@@ -11,6 +11,8 @@ bin_PROGRAMS = \
 panel_sources =                        \
        gp-add-applet-window.c \
        gp-add-applet-window.h \
+       gp-applet-list-row.c \
+       gp-applet-list-row.h \
        gp-applet-manager.c \
        gp-applet-manager.h \
        gp-applet-row.c \
diff --git a/gnome-panel/applet.c b/gnome-panel/applet.c
index 6c30930de..0e86df1b2 100644
--- a/gnome-panel/applet.c
+++ b/gnome-panel/applet.c
@@ -75,7 +75,7 @@ panel_applet_destroy (GtkWidget  *widget,
        g_free (info);
 }
 
-static const char *
+const char *
 panel_applet_get_toplevel_id (AppletInfo *applet)
 {
        PanelWidget *panel_widget;
diff --git a/gnome-panel/applet.h b/gnome-panel/applet.h
index a6bc78086..ae3814765 100644
--- a/gnome-panel/applet.h
+++ b/gnome-panel/applet.h
@@ -27,6 +27,8 @@ AppletInfo *panel_applet_register           (GtkWidget   *applet,
 
 const char *panel_applet_get_id             (AppletInfo  *info);
 
+const char *panel_applet_get_toplevel_id    (AppletInfo  *info);
+
 gboolean    panel_applet_activate_main_menu (guint32      activate_time);
 
 GSList     *panel_applet_list_applets       (void);
diff --git a/gnome-panel/gp-applet-list-row.c b/gnome-panel/gp-applet-list-row.c
new file mode 100644
index 000000000..77e9df859
--- /dev/null
+++ b/gnome-panel/gp-applet-list-row.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2020 Alberts Muktupāvels
+ * Copyright (C) 2021 Sebastian Geiger
+ *
+ * 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 2 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/>.
+ */
+
+#include "config.h"
+#include "gp-applet-list-row.h"
+
+#include <glib/gi18n.h>
+
+#include "panel-applets-manager.h"
+#include "panel-layout.h"
+#include "panel-lockdown.h"
+
+struct _GpAppletListRow
+{
+    GtkListBoxRow  parent;
+
+    GpModule      *module;
+    char          *applet_id;
+
+    AppletInfo    *info;
+
+    char          *iid;
+
+    GtkWidget     *event_box;
+
+    GtkWidget     *about_dialog;
+};
+
+enum
+{
+    PROP_0,
+
+    PROP_MODULE,
+    PROP_APPLET_ID,
+    PROP_APPLET_INFO,
+
+    LAST_PROP
+};
+
+static GParamSpec *row_properties[LAST_PROP] = { NULL };
+
+G_DEFINE_TYPE (GpAppletListRow, gp_applet_list_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+help_cb (GtkMenuItem     *menuitem,
+         GpAppletListRow *self)
+{
+  gp_module_show_help (self->module, NULL, self->applet_id, NULL);
+}
+
+static void
+about_cb (GtkMenuItem     *menuitem,
+          GpAppletListRow *self)
+{
+  if (self->about_dialog != NULL)
+    {
+      gtk_window_present (GTK_WINDOW (self->about_dialog));
+      return;
+    }
+
+  self->about_dialog = gp_module_create_about_dialog (self->module,
+                                                      NULL,
+                                                      self->applet_id);
+
+  if (self->about_dialog == NULL)
+    return;
+
+  g_object_add_weak_pointer (G_OBJECT (self->about_dialog),
+                             (gpointer *) &self->about_dialog);
+
+  gtk_window_present (GTK_WINDOW (self->about_dialog));
+}
+
+static void
+setup_view_more_button (GpAppletListRow *self,
+                        GtkWidget       *button,
+                        GpAppletInfo    *info)
+{
+  GtkWidget *image;
+  GtkWidget *menu;
+  gboolean sensitive;
+  GtkWidget *item;
+
+  image = gtk_image_new_from_icon_name ("view-more-symbolic",
+                                        GTK_ICON_SIZE_MENU);
+
+  gtk_button_set_image (GTK_BUTTON (button), image);
+  gtk_image_set_pixel_size (GTK_IMAGE (image), 16);
+
+  menu = gtk_menu_new ();
+  sensitive = FALSE;
+
+  gtk_menu_button_set_popup (GTK_MENU_BUTTON (button), menu);
+  gtk_widget_set_halign (menu, GTK_ALIGN_END);
+
+  if (info->help_uri && info->help_uri[0] != '\0')
+    {
+      sensitive = TRUE;
+      item = gtk_menu_item_new_with_label (_("Help"));
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      gtk_widget_show (item);
+
+      g_signal_connect (item, "activate", G_CALLBACK (help_cb), self);
+    }
+
+  if (info->about_dialog_func != NULL)
+    {
+      sensitive = TRUE;
+      item = gtk_menu_item_new_with_label (_("About"));
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      gtk_widget_show (item);
+
+      g_signal_connect (item, "activate", G_CALLBACK (about_cb), self);
+    }
+
+  gtk_widget_set_sensitive (button, sensitive);
+}
+
+static void
+lockdown_changed_cb (PanelLockdown *lockdown,
+                     gpointer       user_data)
+{
+  GpAppletListRow *self;
+
+  self = GP_APPLET_LIST_ROW (user_data);
+
+  if (!panel_layout_is_writable () ||
+      panel_lockdown_get_panels_locked_down_s () ||
+      panel_applets_manager_is_applet_disabled (self->iid, NULL))
+    {
+      gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+      return;
+    }
+
+  gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
+}
+
+static void
+remove_clicked_cb (GtkButton       *button,
+                   GpAppletListRow *self)
+{
+  GtkListBoxRow *row;
+
+  row = GTK_LIST_BOX_ROW (self);
+
+  GTK_LIST_BOX_ROW_GET_CLASS (row)->activate (row);
+}
+
+static void
+setup_row (GpAppletListRow *self)
+{
+  GpAppletInfo *info;
+  GtkWidget *hbox;
+  GtkWidget *icon_image;
+  GtkWidget *vbox;
+  GtkWidget *remove_button;
+  GtkWidget *menu_button;
+  GtkWidget *title_label;
+  GtkWidget *description_label;
+  GtkStyleContext *remove_button_style_context;
+  char * name;
+
+  info = gp_module_get_applet_info (self->module, self->applet_id, NULL);
+  g_assert (info != NULL);
+
+  self->iid = g_strdup_printf ("%s::%s",
+                               gp_module_get_id (self->module),
+                               self->applet_id);
+
+  self->event_box = gtk_event_box_new ();
+  gtk_container_add (GTK_CONTAINER (self), self->event_box);
+  gtk_widget_show (self->event_box);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_container_add (GTK_CONTAINER (self->event_box), hbox);
+  gtk_widget_show (hbox);
+
+  g_object_set (hbox,
+                "margin-start", 6,
+                "margin-end", 6,
+                NULL);
+
+  icon_image = gtk_image_new_from_icon_name (info->icon_name, GTK_ICON_SIZE_DND);
+  gtk_image_set_pixel_size (GTK_IMAGE (icon_image), 32);
+  gtk_box_pack_start (GTK_BOX (hbox), icon_image, FALSE, FALSE, 0);
+  gtk_widget_show (icon_image);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+  gtk_widget_show (vbox);
+
+  remove_button = gtk_button_new_with_label (_("Remove"));
+  gtk_box_pack_start (GTK_BOX (hbox), remove_button, FALSE, FALSE, 0);
+  gtk_widget_set_valign (remove_button, GTK_ALIGN_CENTER);
+
+  remove_button_style_context = gtk_widget_get_style_context (remove_button);
+  gtk_style_context_add_class (remove_button_style_context,
+                               GTK_STYLE_CLASS_DESTRUCTIVE_ACTION);
+
+  gtk_widget_show (remove_button);
+
+  g_signal_connect (remove_button, "clicked", G_CALLBACK (remove_clicked_cb), self);
+
+  menu_button = gtk_menu_button_new ();
+  gtk_box_pack_end (GTK_BOX (hbox), menu_button, FALSE, FALSE, 0);
+  gtk_widget_set_valign (menu_button, GTK_ALIGN_CENTER);
+  setup_view_more_button (self, menu_button, info);
+  gtk_widget_show (menu_button);
+
+  title_label = gtk_label_new (NULL);
+  name = g_strdup_printf ("<b>%s</b>", info->name);
+  gtk_label_set_markup (GTK_LABEL (title_label), name);
+  g_free (name);
+
+  gtk_box_pack_start (GTK_BOX (vbox), title_label, FALSE, FALSE, 0);
+  gtk_label_set_xalign (GTK_LABEL (title_label), 0);
+  gtk_widget_show (title_label);
+
+  description_label = gtk_label_new (info->description);
+  gtk_box_pack_start (GTK_BOX (vbox), description_label, FALSE, FALSE, 0);
+  gtk_label_set_max_width_chars (GTK_LABEL (description_label), 20);
+  gtk_label_set_line_wrap (GTK_LABEL (description_label), TRUE);
+  gtk_label_set_xalign (GTK_LABEL (description_label), 0);
+  gtk_widget_show (description_label);
+
+  panel_lockdown_on_notify (panel_lockdown_get (),
+                            NULL,
+                            G_OBJECT (self),
+                            lockdown_changed_cb,
+                            self);
+
+  lockdown_changed_cb (panel_lockdown_get (), self);
+}
+
+static void
+gp_applet_list_row_constructed (GObject *object)
+{
+  G_OBJECT_CLASS (gp_applet_list_row_parent_class)->constructed (object);
+  setup_row (GP_APPLET_LIST_ROW (object));
+}
+
+static void
+gp_applet_list_row_dispose (GObject *object)
+{
+  GpAppletListRow *self;
+
+  self = GP_APPLET_LIST_ROW (object);
+
+  g_clear_object (&self->module);
+
+  g_clear_pointer (&self->about_dialog, gtk_widget_destroy);
+
+  G_OBJECT_CLASS (gp_applet_list_row_parent_class)->dispose (object);
+}
+
+static void
+gp_applet_list_row_finalize (GObject *object)
+{
+  GpAppletListRow *self;
+
+  self = GP_APPLET_LIST_ROW (object);
+
+  g_clear_pointer (&self->applet_id, g_free);
+
+  G_OBJECT_CLASS (gp_applet_list_row_parent_class)->finalize (object);
+}
+
+static void
+gp_applet_list_row_set_property (GObject      *object,
+                                 guint         property_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  GpAppletListRow *self;
+
+  self = GP_APPLET_LIST_ROW (object);
+
+  switch (property_id)
+    {
+      case PROP_MODULE:
+        g_assert (self->module == NULL);
+        self->module = g_value_dup_object (value);
+        break;
+
+      case PROP_APPLET_ID:
+        g_assert (self->applet_id == NULL);
+        self->applet_id = g_value_dup_string (value);
+        break;
+
+      case PROP_APPLET_INFO:
+        g_assert (self->info == NULL);
+        self->info = g_value_get_pointer (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+install_properties (GObjectClass *object_class)
+{
+  row_properties[PROP_MODULE] =
+      g_param_spec_object ("module",
+                           "module",
+                           "module",
+                           GP_TYPE_MODULE,
+                           G_PARAM_WRITABLE |
+                           G_PARAM_CONSTRUCT_ONLY |
+                           G_PARAM_STATIC_STRINGS);
+
+  row_properties[PROP_APPLET_ID] =
+      g_param_spec_string ("applet-id",
+                           "applet-id",
+                           "applet-id",
+                           NULL,
+                           G_PARAM_WRITABLE |
+                           G_PARAM_CONSTRUCT_ONLY |
+                           G_PARAM_STATIC_STRINGS);
+
+  row_properties[PROP_APPLET_INFO] =
+      g_param_spec_pointer("applet-info",
+                           "applet-info",
+                           "applet-info",
+                           G_PARAM_WRITABLE |
+                           G_PARAM_CONSTRUCT_ONLY |
+                           G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, row_properties);
+}
+
+static void
+gp_applet_list_row_class_init (GpAppletListRowClass *self_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (self_class);
+
+  object_class->constructed = gp_applet_list_row_constructed;
+  object_class->dispose = gp_applet_list_row_dispose;
+  object_class->finalize = gp_applet_list_row_finalize;
+  object_class->set_property = gp_applet_list_row_set_property;
+
+  install_properties (object_class);
+}
+
+static void
+gp_applet_list_row_init (GpAppletListRow *self)
+{
+}
+
+GtkWidget *
+gp_applet_list_row_new (GpModule   *module,
+                        const char *applet_id,
+                        AppletInfo *info)
+{
+  return g_object_new (GP_TYPE_APPLET_LIST_ROW,
+                       "module", module,
+                       "applet-id", applet_id,
+                       "applet-info", info,
+                       NULL);
+}
+
+AppletInfo *
+gp_applet_list_row_get_applet_info (GpAppletListRow *self)
+{
+  return self->info;
+}
diff --git a/gnome-panel/gp-applet-list-row.h b/gnome-panel/gp-applet-list-row.h
new file mode 100644
index 000000000..7d5e4780b
--- /dev/null
+++ b/gnome-panel/gp-applet-list-row.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 Alberts Muktupāvels
+ * Copyright (C) 2021 Sebastian Geiger
+ *
+ * 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 2 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/>.
+ */
+
+#ifndef GP_APPLET_ROW_H
+#define GP_APPLET_ROW_H
+
+#include "libgnome-panel/gp-applet-info-private.h"
+#include "libgnome-panel/gp-module-private.h"
+
+#include "applet.h"
+
+G_BEGIN_DECLS
+
+#define GP_TYPE_APPLET_LIST_ROW (gp_applet_list_row_get_type ())
+G_DECLARE_FINAL_TYPE (GpAppletListRow, gp_applet_list_row, GP, APPLET_LIST_ROW, GtkListBoxRow)
+
+GtkWidget    *gp_applet_list_row_new             (GpModule        *module,
+                                                  const char      *applet_id,
+                                                  AppletInfo      *info);
+
+GpAppletInfo *gp_applet_list_row_get_info        (GpAppletListRow *self);
+
+const char   *gp_applet_list_row_get_iid         (GpAppletListRow *self);
+
+AppletInfo   *gp_applet_list_row_get_applet_info (GpAppletListRow *self);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-panel/gp-properties-dialog.c b/gnome-panel/gp-properties-dialog.c
index 5e619b318..07e9a7f24 100644
--- a/gnome-panel/gp-properties-dialog.c
+++ b/gnome-panel/gp-properties-dialog.c
@@ -18,8 +18,13 @@
 #include "config.h"
 
 #include <glib/gi18n.h>
+#include <libgnome-panel/gp-applet-info.h>
 
 #include "gp-properties-dialog.h"
+#include "panel-schemas.h"
+#include "panel-applets-manager.h"
+#include "gp-applet-list-row.h"
+#include "panel-layout.h"
 
 struct _GpPropertiesDialog
 {
@@ -56,6 +61,11 @@ struct _GpPropertiesDialog
   GtkWidget *custom_fg_color;
   GtkWidget *fg_color_box;
   GtkWidget *fg_color;
+
+  GtkWidget *applet_box;
+  GtkWidget *applet_box_left;
+  GtkWidget *applet_box_center;
+  GtkWidget *applet_box_right;
 };
 
 enum
@@ -322,6 +332,197 @@ setup_theme_bindings (GpPropertiesDialog *dialog)
   bg_image_changed_cb (dialog->theme, "bg-image", dialog);
 }
 
+static char *
+get_applet_iid (AppletInfo *info)
+{
+  return g_settings_get_string (info->settings, PANEL_OBJECT_IID_KEY);
+}
+
+static char *
+get_applet_id (AppletInfo *info)
+{
+  return g_strrstr (get_applet_iid(info), "::") + 2;
+}
+
+static PanelObjectPackType
+get_applet_pack_type (AppletInfo *info)
+{
+  return g_settings_get_enum (info->settings, PANEL_OBJECT_PACK_TYPE_KEY);
+}
+
+static int
+get_applet_pack_index (AppletInfo *info)
+{
+  return g_settings_get_int (info->settings, PANEL_OBJECT_PACK_INDEX_KEY);
+}
+
+static GpModule *
+get_module_from_id (GpModuleManager *manager,
+                    char            *iid)
+{
+  const gchar *applet_id;
+  gchar *module_id;
+  GpModule *module;
+
+  applet_id = g_strrstr (iid, "::");
+
+  if (!applet_id)
+    return FALSE;
+
+  module_id = g_strndup (iid, strlen (iid) - strlen (applet_id));
+
+  module = gp_module_manager_get_module (manager, module_id);
+  g_free (module_id);
+
+  return module;
+}
+
+static void
+insert_applet_entry (GpPropertiesDialog *dialog,
+                     AppletInfo         *info,
+                     GtkWidget          *applet_entry)
+{
+  PanelObjectPackType pack_type;
+  int pack_index;
+
+  pack_type = get_applet_pack_type (info);
+  pack_index = get_applet_pack_index (info);
+
+  g_object_set_data (G_OBJECT (applet_entry), "pack-index", GINT_TO_POINTER (pack_index));
+
+  if (pack_type == PANEL_OBJECT_PACK_START)
+    {
+      gtk_container_add (GTK_CONTAINER (dialog->applet_box_left), applet_entry);
+    }
+
+  if (pack_type == PANEL_OBJECT_PACK_CENTER)
+    {
+      gtk_container_add (GTK_CONTAINER (dialog->applet_box_center), applet_entry);
+    }
+
+  if (pack_type == PANEL_OBJECT_PACK_END)
+    {
+      gtk_container_add (GTK_CONTAINER (dialog->applet_box_right), applet_entry);
+    }
+}
+
+static gint
+applet_sort_func (GtkListBoxRow *row1,
+                  GtkListBoxRow *row2,
+                  gpointer       user_data)
+{
+  gpointer index_1;
+  gpointer index_2;
+
+  index_1 = g_object_get_data (G_OBJECT (row1), "pack-index");
+  index_2 = g_object_get_data (G_OBJECT (row2), "pack-index");
+
+  return GPOINTER_TO_INT (index_1) - GPOINTER_TO_INT (index_2);
+}
+
+static gint
+applet_sort_func_reverse (GtkListBoxRow *row1,
+                          GtkListBoxRow *row2,
+                          gpointer       user_data)
+{
+  gpointer index_1;
+  gpointer index_2;
+
+  index_1 = g_object_get_data (G_OBJECT (row1), "pack-index");
+  index_2 = g_object_get_data (G_OBJECT (row2), "pack-index");
+
+  return GPOINTER_TO_INT (index_2) - GPOINTER_TO_INT (index_1);
+}
+
+static void
+row_activated_cb (GtkListBox         *box,
+                  GtkListBoxRow      *row,
+                  GpPropertiesDialog *self)
+{
+  AppletInfo *info;
+
+  info = gp_applet_list_row_get_applet_info (GP_APPLET_LIST_ROW (row));
+
+  gtk_container_remove (GTK_CONTAINER (box), GTK_WIDGET (row));
+
+  panel_layout_delete_object (panel_applet_get_id (info));
+}
+
+static void
+setup_applet_box_structure (GpPropertiesDialog *dialog)
+{
+  gtk_list_box_set_sort_func (GTK_LIST_BOX (dialog->applet_box_left), applet_sort_func, NULL, NULL);
+  gtk_list_box_set_sort_func (GTK_LIST_BOX (dialog->applet_box_center), applet_sort_func, NULL, NULL);
+  gtk_list_box_set_sort_func (GTK_LIST_BOX (dialog->applet_box_right), applet_sort_func_reverse, NULL, NULL);
+
+  gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (dialog->applet_box_left), FALSE);
+  gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (dialog->applet_box_center), FALSE);
+  gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (dialog->applet_box_right), FALSE);
+
+  g_signal_connect (dialog->applet_box_left,
+                    "row-activated",
+                    G_CALLBACK (row_activated_cb),
+                    dialog);
+
+  g_signal_connect (dialog->applet_box_center,
+                    "row-activated",
+                    G_CALLBACK (row_activated_cb),
+                    dialog);
+
+  g_signal_connect (dialog->applet_box_right,
+                    "row-activated",
+                    G_CALLBACK (row_activated_cb),
+                    dialog);
+}
+
+static void
+setup_applet_box_add_applets (GpPropertiesDialog *dialog,
+                              GSList             *applets)
+{
+  GSList *iter;
+  GpModuleManager *manager;
+  GpModule *module;
+
+  manager = panel_applets_manager_get_module_manager ();
+
+  for (iter = applets; iter; iter = iter->next)
+    {
+      AppletInfo *info;
+      GtkWidget *applet_entry;
+
+      const char * applet_toplevel_id;
+      const char * applet_id;
+
+      info = iter->data;
+
+      applet_toplevel_id = panel_applet_get_toplevel_id (info);
+
+      if (g_strcmp0 (applet_toplevel_id, dialog->toplevel_id) != 0)
+        continue;
+
+      module = get_module_from_id (manager, get_applet_iid (info));
+      applet_id = get_applet_id (info);
+
+      applet_entry = gp_applet_list_row_new (module, applet_id, info);
+
+      insert_applet_entry (dialog, info, applet_entry);
+    }
+
+  gtk_widget_show_all (dialog->applet_box);
+}
+
+static void
+setup_applet_box (GpPropertiesDialog *dialog)
+{
+  GSList *applets;
+
+  setup_applet_box_structure (dialog);
+
+  applets = panel_applet_list_applets ();
+
+  setup_applet_box_add_applets (dialog, applets);
+}
+
 static gboolean
 all_keys_writable (GSettings    *settings,
                    const gchar **keys)
@@ -416,6 +617,7 @@ gp_properties_dialog_constructed (GObject *object)
 
   setup_writability (dialog);
   setup_bindings (dialog);
+  setup_applet_box (dialog);
 }
 
 static void
@@ -515,6 +717,11 @@ bind_template (GtkWidgetClass *widget_class)
   gtk_widget_class_bind_template_callback (widget_class, custom_fg_color_toggled_cb);
   gtk_widget_class_bind_template_child (widget_class, GpPropertiesDialog, fg_color_box);
   gtk_widget_class_bind_template_child (widget_class, GpPropertiesDialog, fg_color);
+
+  gtk_widget_class_bind_template_child (widget_class, GpPropertiesDialog, applet_box);
+  gtk_widget_class_bind_template_child (widget_class, GpPropertiesDialog, applet_box_left);
+  gtk_widget_class_bind_template_child (widget_class, GpPropertiesDialog, applet_box_center);
+  gtk_widget_class_bind_template_child (widget_class, GpPropertiesDialog, applet_box_right);
 }
 
 static void
diff --git a/gnome-panel/gp-properties-dialog.ui b/gnome-panel/gp-properties-dialog.ui
index 6ff17729d..d470339c4 100644
--- a/gnome-panel/gp-properties-dialog.ui
+++ b/gnome-panel/gp-properties-dialog.ui
@@ -17,6 +17,9 @@
     <property name="window-position">center</property>
     <property name="default-width">340</property>
     <property name="type-hint">dialog</property>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
     <child>
       <object class="GtkNotebook">
         <property name="visible">True</property>
@@ -655,10 +658,94 @@
           </packing>
         </child>
         <child>
-          <placeholder/>
+          <object class="GtkBox" id="applet_box">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Left</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkListBox" id="applet_box_left">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Center</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkListBox" id="applet_box_center">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Right</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkListBox" id="applet_box_right">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">5</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">2</property>
+          </packing>
         </child>
         <child type="tab">
-          <placeholder/>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Applets</property>
+          </object>
+          <packing>
+            <property name="position">2</property>
+            <property name="tab_fill">False</property>
+          </packing>
         </child>
       </object>
     </child>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]