[Xfce4-commits] <ristretto:stephan/icon-bar> Place the icon-bar inside the ristretto source-tree (origin: exo)
Stephan Arts
noreply at xfce.org
Thu Feb 2 21:36:04 CET 2012
Updating branch refs/heads/stephan/icon-bar
to ab008e3447cfdfe52ef3d05f79ed0217daf3a002 (commit)
from 7849789b80e74dca4b086abb58ff638705b10bb5 (commit)
commit ab008e3447cfdfe52ef3d05f79ed0217daf3a002
Author: Stephan Arts <stephan at xfce.org>
Date: Thu Feb 2 21:32:36 2012 +0100
Place the icon-bar inside the ristretto source-tree (origin: exo)
src/Makefile.am | 5 +-
src/icon_bar.c | 2157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/icon_bar.h | 120 +++
src/image_list.c | 88 +++
src/image_viewer.c | 2 +-
src/main_window.c | 35 +-
src/thumbnailer.c | 2 +-
7 files changed, 2387 insertions(+), 22 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index b211c95..513ec83 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,6 +18,7 @@ ristretto_SOURCES = \
file.c file.h \
privacy_dialog.h privacy_dialog.c \
util.c util.h \
+ icon_bar.c icon_bar.h \
main.c
ristretto_CFLAGS = \
@@ -78,7 +79,7 @@ stamp-marshal.h: marshal.list Makefile
&& echo "#ifndef __RSTTO_MARSHAL_H__" > xgen-tmh \
&& echo "#define __RSTTO_MARSHAL_H__" >> xgen-tmh \
&& ( glib-genmarshal \
- --prefix=rstto_marshal \
+ --prefix=_rstto_marshal \
--header marshal.list ) >> xgen-tmh \
&& echo "#endif /* !__RSTTO_MARSHAL_H__ */" >> xgen-tmh \
&& ( cmp -s xgen-tmh marshal.h || cp xgen-tmh marshal.h ) \
@@ -91,7 +92,7 @@ marshal.c: marshal.list Makefile
cd $(srcdir) \
&& echo "#include \"marshal.h\"" > xgen-tmc \
&& ( glib-genmarshal \
- --prefix=rstto_marshal \
+ --prefix=_rstto_marshal \
--body marshal.list ) >> xgen-tmc \
&& cp xgen-tmc marshal.c \
&& rm -f xgen-tmc \
diff --git a/src/icon_bar.c b/src/icon_bar.c
new file mode 100644
index 0000000..5e5410d
--- /dev/null
+++ b/src/icon_bar.c
@@ -0,0 +1,2157 @@
+/*-
+ * Copyright (c) 2004-2006 os-cillation e.K.
+ *
+ * Written by Benedikt Meurer <benny at xfce.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkmarshal.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "marshal.h"
+#include "icon_bar.h"
+
+/**
+ * SECTION: rstto-icon-bar
+ * @title: RsttoIconBar
+ * @short_description: A widget for displaying icon bars
+ * @include: rstto/rstto.h
+ * @see_also: <ulink url="http://library.gnome.org/devel/gtk/stable/GtkTreeModel.html">
+ * GtkTreeModel</ulink>,
+ * <ulink url="http://library.gnome.org/devel/gtk/stable/TreeWidget.html">
+ * Tree and List Widget Overview</ulink>
+ *
+ * A widget that displays any object that implements the #GtkTreeModel interface
+ * in an icon bar.
+ *
+ * <example>
+ * <title>
+ * Creating a new <structname>RsttoIconBar</structname> with a <structname>GtkListStore</structname>
+ * </title>
+ * <programlisting>
+ * enum
+ * {
+ * PIXBUF_COLUMN,
+ * STRING_COLUMN,
+ * N_COLUMNS,
+ * };
+ *
+ * {
+ * GtkListStore *store;
+ * GtkWidget *bar;
+ *
+ * // make a new list store
+ * store = gtk_list_store_new (N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+ *
+ * // fill the store with data
+ * fill_store (store);
+ *
+ * // create the icon bar
+ * bar = rstto_icon_bar_new_with_model (GTK_TREE_MODEL (store));
+ * rstto_icon_bar_set_pixbuf_column (RSTTO_ICON_BAR (bar), PIXBUF_COLUMN);
+ * rstto_icon_bar_set_text_column (RSTTO_ICON_BAR (bar), TEXT_COLUMN);
+ * gtk_widget_show (bar);
+ *
+ * // the icon bar keeps a reference on the store now
+ * g_object_unref (G_OBJECT (store));
+ *
+ * // add the bar to your GUI now...
+ * }
+ * </programlisting>
+ * </example>
+ **/
+
+
+
+#define MINIMUM_ICON_ITEM_WIDTH 32
+#define ICON_TEXT_PADDING 1
+
+#define RSTTO_ICON_BAR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), RSTTO_TYPE_ICON_BAR, RsttoIconBarPrivate))
+
+#define RSTTO_ICON_BAR_VALID_MODEL_AND_COLUMNS(obj) ((obj)->priv->model != NULL && \
+ (obj)->priv->pixbuf_column != -1 && \
+ (obj)->priv->text_column != -1)
+
+
+
+typedef struct _RsttoIconBarItem RsttoIconBarItem;
+
+enum
+{
+ PROP_0,
+ PROP_ORIENTATION,
+ PROP_PIXBUF_COLUMN,
+ PROP_TEXT_COLUMN,
+ PROP_MODEL,
+ PROP_ACTIVE,
+ PROP_SHOW_TEXT,
+};
+
+enum
+{
+ SELECTION_CHANGED,
+ LAST_SIGNAL,
+};
+
+
+
+static void rstto_icon_bar_destroy (GtkObject *object);
+static void rstto_icon_bar_finalize (GObject *object);
+static void rstto_icon_bar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void rstto_icon_bar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void rstto_icon_bar_style_set (GtkWidget *widget,
+ GtkStyle *previous_style);
+static void rstto_icon_bar_realize (GtkWidget *widget);
+static void rstto_icon_bar_unrealize (GtkWidget *widget);
+static void rstto_icon_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void rstto_icon_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gboolean rstto_icon_bar_expose (GtkWidget *widget,
+ GdkEventExpose *expose);
+static gboolean rstto_icon_bar_leave (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean rstto_icon_bar_motion (GtkWidget *widget,
+ GdkEventMotion *event);
+static gboolean rstto_icon_bar_scroll (GtkWidget *widget,
+ GdkEventScroll *event);
+static gboolean rstto_icon_bar_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean rstto_icon_bar_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static void rstto_icon_bar_set_adjustments (RsttoIconBar *icon_bar,
+ GtkAdjustment *hadj,
+ GtkAdjustment *vadj);
+static void rstto_icon_bar_adjustment_changed (GtkAdjustment *adjustment,
+ RsttoIconBar *icon_bar);
+static void rstto_icon_bar_invalidate (RsttoIconBar *icon_bar);
+static RsttoIconBarItem *rstto_icon_bar_get_item_at_pos (RsttoIconBar *icon_bar,
+ gint x,
+ gint y);
+static void rstto_icon_bar_queue_draw_item (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item);
+static void rstto_icon_bar_paint_item (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item,
+ GdkRectangle *area);
+static void rstto_icon_bar_calculate_item_size (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item);
+static void rstto_icon_bar_update_item_text (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item);
+static GdkPixbuf *rstto_icon_bar_get_item_icon (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item);
+static RsttoIconBarItem *rstto_icon_bar_item_new (void);
+static void rstto_icon_bar_item_free (RsttoIconBarItem *item);
+static void rstto_icon_bar_item_invalidate (RsttoIconBarItem *item);
+static void rstto_icon_bar_build_items (RsttoIconBar *icon_bar);
+static void rstto_icon_bar_row_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ RsttoIconBar *icon_bar);
+static void rstto_icon_bar_row_inserted (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ RsttoIconBar *icon_bar);
+static void rstto_icon_bar_row_deleted (GtkTreeModel *model,
+ GtkTreePath *path,
+ RsttoIconBar *icon_bar);
+static void rstto_icon_bar_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order,
+ RsttoIconBar *icon_bar);
+
+
+
+struct _RsttoIconBarItem
+{
+ GtkTreeIter iter;
+ gint index;
+
+ gint width;
+ gint height;
+
+ gint pixbuf_width;
+ gint pixbuf_height;
+
+ gint layout_width;
+ gint layout_height;
+};
+
+struct _RsttoIconBarPrivate
+{
+ GdkWindow *bin_window;
+
+ gint width;
+ gint height;
+
+ gint pixbuf_column;
+ gint text_column;
+
+ RsttoIconBarItem *active_item;
+ RsttoIconBarItem *single_click_item;
+ RsttoIconBarItem *cursor_item;
+
+ GList *items;
+ gint item_width;
+ gint item_height;
+
+ GtkAdjustment *hadjustment;
+ GtkAdjustment *vadjustment;
+
+ gboolean auto_center; /* automatically center the active item */
+
+ GtkOrientation orientation;
+
+ GtkTreeModel *model;
+
+ PangoLayout *layout;
+
+ gboolean show_text;
+};
+
+
+
+static guint icon_bar_signals[LAST_SIGNAL];
+
+
+
+G_DEFINE_TYPE (RsttoIconBar, rstto_icon_bar, GTK_TYPE_CONTAINER)
+
+
+
+static void
+rstto_icon_bar_class_init (RsttoIconBarClass *klass)
+{
+ GtkObjectClass *gtkobject_class;
+ GtkWidgetClass *gtkwidget_class;
+ GObjectClass *gobject_class;
+
+ g_type_class_add_private (klass, sizeof (RsttoIconBarPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = rstto_icon_bar_finalize;
+ gobject_class->get_property = rstto_icon_bar_get_property;
+ gobject_class->set_property = rstto_icon_bar_set_property;
+
+ gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = rstto_icon_bar_destroy;
+
+ gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->style_set = rstto_icon_bar_style_set;
+ gtkwidget_class->realize = rstto_icon_bar_realize;
+ gtkwidget_class->unrealize = rstto_icon_bar_unrealize;
+ gtkwidget_class->size_request = rstto_icon_bar_size_request;
+ gtkwidget_class->size_allocate = rstto_icon_bar_size_allocate;
+ gtkwidget_class->expose_event = rstto_icon_bar_expose;
+ gtkwidget_class->leave_notify_event = rstto_icon_bar_leave;
+ gtkwidget_class->motion_notify_event = rstto_icon_bar_motion;
+ gtkwidget_class->scroll_event = rstto_icon_bar_scroll;
+ gtkwidget_class->button_press_event = rstto_icon_bar_button_press;
+ gtkwidget_class->button_release_event = rstto_icon_bar_button_release;
+
+ klass->set_scroll_adjustments = rstto_icon_bar_set_adjustments;
+
+ /**
+ * RsttoIconBar:orientation:
+ *
+ * The orientation of the icon bar.
+ *
+ * Default value: %GTK_ORIENTATION_VERTICAL
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation",
+ _("Orientation"),
+ _("The orientation of the iconbar"),
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_VERTICAL,
+ G_PARAM_READWRITE));
+
+ /**
+ * RsttoIconBar:pixbuf-column:
+ *
+ * The ::pixbuf-column property contains the number of the model column
+ * containing the pixbufs which are displyed. The pixbuf column must be
+ * of type #GDK_TYPE_PIXBUF. Setting this property to -1 turns off the
+ * display of pixbufs.
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_PIXBUF_COLUMN,
+ g_param_spec_int ("pixbuf-column",
+ _("Pixbuf column"),
+ _("Model column used to retrieve the icon pixbuf from"),
+ -1, G_MAXINT, -1,
+ G_PARAM_READWRITE));
+
+ /**
+ * RsttoIconBar:text-column:
+ *
+ * The ::text-column property contains the number of the model column
+ * containing the texts which are displayed. The text column must be
+ * of type #G_TYPE_STRING. If this property is set to -1, no texts
+ * are displayed.
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_TEXT_COLUMN,
+ g_param_spec_int ("text-column",
+ _("Text column"),
+ _("Model column used to retrieve the text from"),
+ -1, G_MAXINT, -1,
+ G_PARAM_READWRITE));
+
+ /**
+ * RsttoIconBar:model:
+ *
+ * The model for the icon bar.
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_MODEL,
+ g_param_spec_object ("model",
+ _("Icon Bar Model"),
+ _("Model for the icon bar"),
+ GTK_TYPE_TREE_MODEL,
+ G_PARAM_READWRITE));
+
+ /**
+ * RsttoIconBar:active:
+ *
+ * The item which is currently active.
+ *
+ * Allowed values: >= -1
+ *
+ * Default value: -1
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_ACTIVE,
+ g_param_spec_int ("active",
+ _("Active"),
+ _("Active item index"),
+ -1, G_MAXINT, -1,
+ G_PARAM_READWRITE));
+
+ /**
+ * RsttoIconBar:show-text:
+ *
+ * Show text under icon.
+ *
+ * Allowed values: TRUE, FALSE
+ *
+ * Default value: TRUE
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_SHOW_TEXT,
+ g_param_spec_boolean ("show-text",
+ _("Show Text"),
+ _("Show Text"),
+ TRUE,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (gtkwidget_class,
+ g_param_spec_boxed ("active-item-fill-color",
+ _("Active item fill color"),
+ _("Active item fill color"),
+ GDK_TYPE_COLOR,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (gtkwidget_class,
+ g_param_spec_boxed ("active-item-border-color",
+ _("Active item border color"),
+ _("Active item border color"),
+ GDK_TYPE_COLOR,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (gtkwidget_class,
+ g_param_spec_boxed ("active-item-text-color",
+ _("Active item text color"),
+ _("Active item text color"),
+ GDK_TYPE_COLOR,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (gtkwidget_class,
+ g_param_spec_boxed ("cursor-item-fill-color",
+ _("Cursor item fill color"),
+ _("Cursor item fill color"),
+ GDK_TYPE_COLOR,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (gtkwidget_class,
+ g_param_spec_boxed ("cursor-item-border-color",
+ _("Cursor item border color"),
+ _("Cursor item border color"),
+ GDK_TYPE_COLOR,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (gtkwidget_class,
+ g_param_spec_boxed ("cursor-item-text-color",
+ _("Cursor item text color"),
+ _("Cursor item text color"),
+ GDK_TYPE_COLOR,
+ G_PARAM_READABLE));
+
+ /**
+ * RsttoIconBar::set-scroll-adjustments:
+ * @icon_bar : The #RsttoIconBar.
+ * @hadjustment : The horizontal adjustment.
+ * @vadjustment : The vertical adjustment.
+ *
+ * Used internally to make the #RsttoIconBar scrollable.
+ **/
+ gtkwidget_class->set_scroll_adjustments_signal =
+ g_signal_new ("set-scroll-adjustments",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RsttoIconBarClass, set_scroll_adjustments),
+ NULL, NULL,
+ _rstto_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_ADJUSTMENT,
+ GTK_TYPE_ADJUSTMENT);
+
+ /**
+ * RsttoIconBar::selection-changed:
+ * @icon_bar : The #RsttoIconBar.
+ *
+ * This signal is emitted whenever the currently selected icon
+ * changes.
+ **/
+ icon_bar_signals[SELECTION_CHANGED] =
+ g_signal_new ("selection-changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (RsttoIconBarClass, selection_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+
+
+static void
+rstto_icon_bar_init (RsttoIconBar *icon_bar)
+{
+ icon_bar->priv = RSTTO_ICON_BAR_GET_PRIVATE (icon_bar);
+
+ icon_bar->priv->orientation = GTK_ORIENTATION_VERTICAL;
+ icon_bar->priv->pixbuf_column = -1;
+ icon_bar->priv->text_column = -1;
+ icon_bar->priv->show_text = TRUE;
+ icon_bar->priv->auto_center = TRUE;
+
+ icon_bar->priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (icon_bar), NULL);
+ pango_layout_set_width (icon_bar->priv->layout, -1);
+ pango_layout_set_wrap (icon_bar->priv->layout,
+ PANGO_WRAP_WORD_CHAR);
+ pango_layout_set_ellipsize (icon_bar->priv->layout,
+ PANGO_ELLIPSIZE_END);
+
+ GTK_WIDGET_UNSET_FLAGS (icon_bar, GTK_CAN_FOCUS);
+
+ rstto_icon_bar_set_adjustments (icon_bar, NULL, NULL);
+}
+
+
+
+static void
+rstto_icon_bar_destroy (GtkObject *object)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (object);
+
+ rstto_icon_bar_set_model (icon_bar, NULL);
+
+ (*GTK_OBJECT_CLASS (rstto_icon_bar_parent_class)->destroy) (object);
+}
+
+
+
+static void
+rstto_icon_bar_finalize (GObject *object)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (object);
+
+ g_object_unref (G_OBJECT (icon_bar->priv->layout));
+
+ (*G_OBJECT_CLASS (rstto_icon_bar_parent_class)->finalize) (object);
+}
+
+
+
+static void
+rstto_icon_bar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, icon_bar->priv->orientation);
+ break;
+
+ case PROP_PIXBUF_COLUMN:
+ g_value_set_int (value, icon_bar->priv->pixbuf_column);
+ break;
+
+ case PROP_TEXT_COLUMN:
+ g_value_set_int (value, icon_bar->priv->text_column);
+ break;
+
+ case PROP_MODEL:
+ g_value_set_object (value, icon_bar->priv->model);
+ break;
+
+ case PROP_ACTIVE:
+ g_value_set_int (value, rstto_icon_bar_get_active (icon_bar));
+ break;
+
+ case PROP_SHOW_TEXT:
+ g_value_set_boolean (value, rstto_icon_bar_get_show_text (icon_bar));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+rstto_icon_bar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ rstto_icon_bar_set_orientation (icon_bar, g_value_get_enum (value));
+ break;
+
+ case PROP_PIXBUF_COLUMN:
+ rstto_icon_bar_set_pixbuf_column (icon_bar, g_value_get_int (value));
+ break;
+
+ case PROP_TEXT_COLUMN:
+ rstto_icon_bar_set_text_column (icon_bar, g_value_get_int (value));
+ break;
+
+ case PROP_MODEL:
+ rstto_icon_bar_set_model (icon_bar, g_value_get_object (value));
+ break;
+
+ case PROP_ACTIVE:
+ rstto_icon_bar_set_active (icon_bar, g_value_get_int (value));
+ break;
+
+ case PROP_SHOW_TEXT:
+ rstto_icon_bar_set_show_text (icon_bar, g_value_get_boolean (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+rstto_icon_bar_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+
+ (*GTK_WIDGET_CLASS (rstto_icon_bar_parent_class)->style_set) (widget, previous_style);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_set_background (icon_bar->priv->bin_window,
+ &widget->style->base[widget->state]);
+ }
+}
+
+
+
+static void
+rstto_icon_bar_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+ gint attributes_mask;
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ attributes.x = 0;
+ attributes.y = 0;
+ attributes.width = MAX (icon_bar->priv->width, widget->allocation.width);
+ attributes.height = MAX (icon_bar->priv->height, widget->allocation.height);
+ attributes.event_mask = (GDK_SCROLL_MASK
+ | GDK_EXPOSURE_MASK
+ | GDK_LEAVE_NOTIFY_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_KEY_PRESS_MASK
+ | GDK_KEY_RELEASE_MASK)
+ | gtk_widget_get_events (widget);
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ icon_bar->priv->bin_window = gdk_window_new (widget->window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (icon_bar->priv->bin_window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
+ gdk_window_set_background (icon_bar->priv->bin_window, &widget->style->base[widget->state]);
+ gdk_window_show (icon_bar->priv->bin_window);
+}
+
+
+
+static void
+rstto_icon_bar_unrealize (GtkWidget *widget)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+
+ gdk_window_set_user_data (icon_bar->priv->bin_window, NULL);
+ gdk_window_destroy (icon_bar->priv->bin_window);
+ icon_bar->priv->bin_window = NULL;
+
+ /* GtkWidget::unrealize destroys children and widget->window */
+ (*GTK_WIDGET_CLASS (rstto_icon_bar_parent_class)->unrealize) (widget);
+}
+
+
+
+static void
+rstto_icon_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ RsttoIconBarItem *item;
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+ GList *lp;
+ gint n = 0;
+ gint max_width = 0;
+ gint max_height = 0;
+
+ if (!RSTTO_ICON_BAR_VALID_MODEL_AND_COLUMNS (icon_bar)
+ || icon_bar->priv->items == NULL)
+ {
+ icon_bar->priv->width = requisition->width = 0;
+ icon_bar->priv->height = requisition->height = 0;
+ return;
+ }
+
+ /* calculate max item size */
+ for (lp = icon_bar->priv->items; lp != NULL; ++n, lp = lp->next)
+ {
+ item = lp->data;
+ rstto_icon_bar_calculate_item_size (icon_bar, item);
+ if (item->width > max_width)
+ max_width = item->width;
+ if (item->height > max_height)
+ max_height = item->height;
+ }
+
+ icon_bar->priv->item_width = max_width;
+ icon_bar->priv->item_height = max_height;
+
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ icon_bar->priv->width = requisition->width = icon_bar->priv->item_width;
+ icon_bar->priv->height = requisition->height = icon_bar->priv->item_height * n;
+ }
+ else
+ {
+ icon_bar->priv->width = requisition->width = icon_bar->priv->item_width * n;
+ icon_bar->priv->height = requisition->height = icon_bar->priv->item_height;
+ }
+}
+
+
+
+static void
+rstto_icon_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+ gdouble value = 0.0;
+ gdouble page_size = 0.0;
+
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+ gdk_window_resize (icon_bar->priv->bin_window,
+ MAX (icon_bar->priv->width, allocation->width),
+ MAX (icon_bar->priv->height, allocation->height));
+ }
+
+ icon_bar->priv->hadjustment->page_size = allocation->width;
+ icon_bar->priv->hadjustment->page_increment = allocation->width * 0.9;
+ icon_bar->priv->hadjustment->step_increment = allocation->width * 0.1;
+ icon_bar->priv->hadjustment->lower = 0;
+ icon_bar->priv->hadjustment->upper = MAX (allocation->width, icon_bar->priv->width);
+ gtk_adjustment_changed (icon_bar->priv->hadjustment);
+
+ icon_bar->priv->vadjustment->page_size = allocation->height;
+ icon_bar->priv->vadjustment->page_increment = allocation->height * 0.9;
+ icon_bar->priv->vadjustment->step_increment = allocation->height * 0.1;
+ icon_bar->priv->vadjustment->lower = 0;
+ icon_bar->priv->vadjustment->upper = MAX (allocation->height, icon_bar->priv->height);
+ gtk_adjustment_changed (icon_bar->priv->vadjustment);
+
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ icon_bar->priv->width = allocation->width;
+ icon_bar->priv->item_width = icon_bar->priv->width;
+ icon_bar->priv->hadjustment->value = 0;
+
+ /* If auto-center is true, center the selected item */
+ if (icon_bar->priv->auto_center == TRUE)
+ {
+ page_size = gtk_adjustment_get_page_size (icon_bar->priv->vadjustment);
+ value = icon_bar->priv->active_item->index * icon_bar->priv->item_width - ((page_size-icon_bar->priv->item_width)/2);
+
+ if (value > (gtk_adjustment_get_upper (icon_bar->priv->vadjustment)-page_size))
+ value = (gtk_adjustment_get_upper (icon_bar->priv->vadjustment)-page_size);
+
+ gtk_adjustment_set_value (icon_bar->priv->vadjustment, value);
+ gtk_adjustment_value_changed (icon_bar->priv->vadjustment);
+ gtk_adjustment_value_changed (icon_bar->priv->hadjustment);
+ icon_bar->priv->auto_center = TRUE;
+ }
+ else
+ {
+ gtk_adjustment_value_changed (icon_bar->priv->hadjustment);
+ }
+ }
+ else
+ {
+ icon_bar->priv->height = allocation->height;
+ icon_bar->priv->item_height = icon_bar->priv->height;
+ icon_bar->priv->vadjustment->value = 0;
+
+ /* If auto-center is true, center the selected item */
+ if (icon_bar->priv->auto_center == TRUE)
+ {
+ page_size = gtk_adjustment_get_page_size (icon_bar->priv->hadjustment);
+ value = icon_bar->priv->active_item->index * icon_bar->priv->item_width - ((page_size-icon_bar->priv->item_width)/2);
+
+ if (value > (gtk_adjustment_get_upper (icon_bar->priv->hadjustment)-page_size))
+ value = (gtk_adjustment_get_upper (icon_bar->priv->hadjustment)-page_size);
+
+ gtk_adjustment_set_value (icon_bar->priv->hadjustment, value);
+ gtk_adjustment_value_changed (icon_bar->priv->hadjustment);
+ gtk_adjustment_value_changed (icon_bar->priv->vadjustment);
+ icon_bar->priv->auto_center = TRUE;
+ }
+ else
+ {
+ gtk_adjustment_value_changed (icon_bar->priv->vadjustment);
+ }
+ }
+}
+
+
+
+static gboolean
+rstto_icon_bar_expose (GtkWidget *widget,
+ GdkEventExpose *expose)
+{
+ RsttoIconBarItem *item;
+ GdkRectangle area;
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+ GList *lp;
+
+ if (expose->window != icon_bar->priv->bin_window)
+ return FALSE;
+
+ for (lp = icon_bar->priv->items; lp != NULL; lp = lp->next)
+ {
+ item = lp->data;
+
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ area.x = 0;
+ area.y = item->index * icon_bar->priv->item_height;
+ }
+ else
+ {
+ area.x = item->index * icon_bar->priv->item_width;
+ area.y = 0;
+ }
+
+ area.width = icon_bar->priv->item_width;
+ area.height = icon_bar->priv->item_height;
+
+ if (gdk_region_rect_in (expose->region, &area) != GDK_OVERLAP_RECTANGLE_OUT)
+ rstto_icon_bar_paint_item (icon_bar, item, &expose->area);
+ }
+
+ return TRUE;
+}
+
+
+
+static gboolean
+rstto_icon_bar_leave (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+
+ if (icon_bar->priv->cursor_item != NULL)
+ {
+ rstto_icon_bar_queue_draw_item (icon_bar, icon_bar->priv->cursor_item);
+ icon_bar->priv->cursor_item = NULL;
+ }
+
+ return FALSE;
+}
+
+
+
+static gboolean
+rstto_icon_bar_motion (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ RsttoIconBarItem *item;
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+
+ item = rstto_icon_bar_get_item_at_pos (icon_bar, event->x, event->y);
+ if (item != NULL && icon_bar->priv->cursor_item != item)
+ {
+ if (icon_bar->priv->cursor_item != NULL)
+ rstto_icon_bar_queue_draw_item (icon_bar, icon_bar->priv->cursor_item);
+ icon_bar->priv->cursor_item = item;
+ rstto_icon_bar_queue_draw_item (icon_bar, item);
+ }
+ else if (icon_bar->priv->cursor_item != NULL
+ && icon_bar->priv->cursor_item != item)
+ {
+ rstto_icon_bar_queue_draw_item (icon_bar, icon_bar->priv->cursor_item);
+ icon_bar->priv->cursor_item = NULL;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+rstto_icon_bar_scroll (GtkWidget *widget,
+ GdkEventScroll *event)
+{
+ RsttoIconBar *icon_bar = RSTTO_ICON_BAR (widget);
+ GtkAdjustment *adjustment = NULL;
+ gdouble val = 0;
+ gdouble step_size = 0;
+ gdouble max_value = 0;
+
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ adjustment = icon_bar->priv->vadjustment;
+ step_size = icon_bar->priv->item_height / 2;
+ }
+ else
+ {
+ adjustment = icon_bar->priv->hadjustment;
+ step_size = icon_bar->priv->item_width / 2;
+ }
+
+ val = gtk_adjustment_get_value (adjustment);
+ max_value = gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment);
+
+ switch (event->direction)
+ {
+ case GDK_SCROLL_UP:
+ case GDK_SCROLL_LEFT:
+ val-=step_size;
+ if (val<0) val = 0.0;
+ break;
+ case GDK_SCROLL_DOWN:
+ case GDK_SCROLL_RIGHT:
+ val+=step_size;
+ if (val > max_value) val = max_value;
+ break;
+ }
+ gtk_adjustment_set_value (adjustment, val);
+ return TRUE;
+}
+
+
+static gboolean
+rstto_icon_bar_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ RsttoIconBar *icon_bar;
+ RsttoIconBarItem *item;
+
+ icon_bar = RSTTO_ICON_BAR (widget);
+
+ if (G_UNLIKELY (!GTK_WIDGET_HAS_FOCUS (widget)))
+ gtk_widget_grab_focus (widget);
+
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+ {
+ item = rstto_icon_bar_get_item_at_pos (icon_bar, event->x, event->y);
+ icon_bar->priv->single_click_item = item;
+ }
+ return TRUE;
+}
+
+static gboolean
+rstto_icon_bar_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ RsttoIconBar *icon_bar;
+ RsttoIconBarItem *item;
+
+ icon_bar = RSTTO_ICON_BAR (widget);
+
+ if (event->button == 1 && event->type == GDK_BUTTON_RELEASE)
+ {
+ item = rstto_icon_bar_get_item_at_pos (icon_bar, event->x, event->y);
+ if (G_LIKELY (item != NULL && item != icon_bar->priv->active_item && item == icon_bar->priv->single_click_item))
+ rstto_icon_bar_set_active (icon_bar, item->index);
+ }
+ return TRUE;
+}
+
+
+static void
+rstto_icon_bar_set_adjustments (RsttoIconBar *icon_bar,
+ GtkAdjustment *hadj,
+ GtkAdjustment *vadj)
+{
+ gboolean need_adjust = FALSE;
+
+ if (hadj != NULL)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
+ else
+ hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+
+ if (vadj != NULL)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
+ else
+ vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+
+ if (icon_bar->priv->hadjustment && (icon_bar->priv->hadjustment != hadj))
+ {
+ g_signal_handlers_disconnect_matched (icon_bar->priv->hadjustment, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, icon_bar);
+ g_object_unref (icon_bar->priv->hadjustment);
+ }
+
+ if (icon_bar->priv->vadjustment && (icon_bar->priv->vadjustment != vadj))
+ {
+ g_signal_handlers_disconnect_matched (icon_bar->priv->vadjustment, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, icon_bar);
+ g_object_unref (icon_bar->priv->vadjustment);
+ }
+
+ if (icon_bar->priv->hadjustment != hadj)
+ {
+ icon_bar->priv->hadjustment = hadj;
+ g_object_ref (icon_bar->priv->hadjustment);
+ gtk_object_sink (GTK_OBJECT (icon_bar->priv->hadjustment));
+
+ g_signal_connect (icon_bar->priv->hadjustment, "value_changed",
+ G_CALLBACK (rstto_icon_bar_adjustment_changed), icon_bar);
+ need_adjust = TRUE;
+ }
+
+ if (icon_bar->priv->vadjustment != vadj)
+ {
+ icon_bar->priv->vadjustment = vadj;
+ g_object_ref (icon_bar->priv->vadjustment);
+ gtk_object_sink (GTK_OBJECT (icon_bar->priv->vadjustment));
+
+ g_signal_connect (icon_bar->priv->vadjustment, "value_changed",
+ G_CALLBACK (rstto_icon_bar_adjustment_changed), icon_bar);
+ need_adjust = TRUE;
+ }
+
+ if (need_adjust)
+ rstto_icon_bar_adjustment_changed (NULL, icon_bar);
+}
+
+
+
+static void
+rstto_icon_bar_adjustment_changed (GtkAdjustment *adjustment,
+ RsttoIconBar *icon_bar)
+{
+ if (GTK_WIDGET_REALIZED (icon_bar))
+ {
+ /* Set auto_center to false, this should be the default behaviour
+ * in case a user changes the value of the adjustments.
+ *
+ * If the value is set internally, and auto-center was enabled
+ * the function calling gtk_adjustment_value_changed should set
+ * auto_center to TRUE afterwards.
+ */
+ icon_bar->priv->auto_center = FALSE;
+
+ gdk_window_move (icon_bar->priv->bin_window,
+ - icon_bar->priv->hadjustment->value,
+ - icon_bar->priv->vadjustment->value);
+
+ gdk_window_process_updates (icon_bar->priv->bin_window, TRUE);
+ }
+}
+
+
+
+static void
+rstto_icon_bar_invalidate (RsttoIconBar *icon_bar)
+{
+ g_list_foreach (icon_bar->priv->items, (GFunc) rstto_icon_bar_item_invalidate, NULL);
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+}
+
+
+
+static RsttoIconBarItem*
+rstto_icon_bar_get_item_at_pos (RsttoIconBar *icon_bar,
+ gint x,
+ gint y)
+{
+ GList *lp;
+
+ if (G_UNLIKELY (icon_bar->priv->item_height == 0))
+ return NULL;
+
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ lp = g_list_nth (icon_bar->priv->items, y / icon_bar->priv->item_height);
+ else
+ lp = g_list_nth (icon_bar->priv->items, x / icon_bar->priv->item_width);
+
+ return (lp != NULL) ? lp->data : NULL;
+}
+
+
+
+static void
+rstto_icon_bar_queue_draw_item (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item)
+{
+ GdkRectangle area;
+
+ if (GTK_WIDGET_REALIZED (icon_bar))
+ {
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ area.x = 0;
+ area.y = icon_bar->priv->item_height * item->index;
+ }
+ else
+ {
+ area.x = icon_bar->priv->item_width * item->index;
+ area.y = 0;
+ }
+
+ area.width = icon_bar->priv->item_width;
+ area.height = icon_bar->priv->item_height;
+
+ gdk_window_invalidate_rect (icon_bar->priv->bin_window, &area, TRUE);
+ }
+}
+
+
+
+static void
+rstto_icon_bar_paint_item (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item,
+ GdkRectangle *area)
+{
+ GdkPixbuf *pixbuf;
+ GdkColor *border_color;
+ GdkColor *fill_color;
+ GdkColor *text_color;
+ GdkGC *gc;
+ gint focus_width;
+ gint focus_pad;
+ gint x, y;
+ gint px, py;
+ gint lx, ly;
+
+ if (!RSTTO_ICON_BAR_VALID_MODEL_AND_COLUMNS (icon_bar))
+ return;
+
+ gtk_widget_style_get (GTK_WIDGET (icon_bar),
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ NULL);
+
+ /* calculate pixbuf/layout location */
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ x = 0;
+ y = icon_bar->priv->item_height * item->index;
+
+ px = (icon_bar->priv->item_width - item->pixbuf_width) / 2 + focus_pad + focus_width;
+ if (icon_bar->priv->text_column != -1 && icon_bar->priv->show_text == TRUE)
+ {
+ py = (icon_bar->priv->item_height - (item->pixbuf_height + item->layout_height + ICON_TEXT_PADDING)) / 2
+ + icon_bar->priv->item_height * item->index + focus_pad + focus_width;
+ }
+ else
+ {
+ py = (icon_bar->priv->item_height - (item->pixbuf_height)) / 2
+ + icon_bar->priv->item_height * item->index + focus_pad + focus_width;
+ }
+ lx = (icon_bar->priv->item_width - (item->layout_width + ICON_TEXT_PADDING)) / 2 + focus_pad;
+ ly = py + item->pixbuf_height + ICON_TEXT_PADDING;
+ }
+ else
+ {
+ x = icon_bar->priv->item_width * item->index;
+ y = 0;
+
+ px = (icon_bar->priv->item_width - item->pixbuf_width) / 2 + focus_pad + focus_width
+ + icon_bar->priv->item_width * item->index;
+ if (icon_bar->priv->text_column != -1 && icon_bar->priv->show_text == TRUE)
+ {
+ py = (icon_bar->priv->item_height - (item->pixbuf_height + item->layout_height)) / 2
+ + focus_pad + focus_width;
+ }
+ else
+ {
+ py = (icon_bar->priv->item_height - (item->pixbuf_height)) / 2
+ + focus_pad + focus_width;
+ }
+ lx = (icon_bar->priv->item_width - (item->layout_width)) / 2 + x;
+ ly = py + item->pixbuf_height + ICON_TEXT_PADDING;
+ }
+
+ if (icon_bar->priv->active_item == item)
+ {
+ gtk_widget_style_get (GTK_WIDGET (icon_bar),
+ "active-item-fill-color", &fill_color,
+ "active-item-border-color", &border_color,
+ NULL);
+
+ if (fill_color == NULL)
+ {
+ fill_color = gdk_color_copy (>K_WIDGET (icon_bar)->style->base[GTK_STATE_SELECTED]);
+ gdk_color_parse ("#c1d2ee", fill_color);
+ }
+
+ if (border_color == NULL)
+ {
+ border_color = gdk_color_copy (>K_WIDGET (icon_bar)->style->base[GTK_STATE_SELECTED]);
+ gdk_color_parse ("#316ac5", border_color);
+ }
+
+ gc = gdk_gc_new (icon_bar->priv->bin_window);
+ gdk_gc_set_clip_rectangle (gc, area);
+ gdk_gc_set_rgb_fg_color (gc, fill_color);
+ gdk_draw_rectangle (icon_bar->priv->bin_window, gc, TRUE,
+ x + focus_pad + focus_width,
+ y + focus_pad + focus_width,
+ icon_bar->priv->item_width - 2 * (focus_width + focus_pad) + 1,
+ icon_bar->priv->item_height - 2 * (focus_width + focus_pad) + 1);
+ gdk_gc_set_rgb_fg_color (gc, border_color);
+ gdk_gc_set_line_attributes (gc, focus_width, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
+ gdk_draw_rectangle (icon_bar->priv->bin_window, gc, FALSE,
+ x + focus_pad + focus_width / 2,
+ y + focus_pad + focus_width / 2,
+ icon_bar->priv->item_width - (2 * focus_pad + focus_width) + 1,
+ icon_bar->priv->item_height - (2 * focus_pad + focus_width) + 1);
+ gdk_color_free (border_color);
+ gdk_color_free (fill_color);
+ g_object_unref (gc);
+ }
+ else if (icon_bar->priv->cursor_item == item)
+ {
+ gtk_widget_style_get (GTK_WIDGET (icon_bar),
+ "cursor-item-fill-color", &fill_color,
+ "cursor-item-border-color", &border_color,
+ NULL);
+
+ if (fill_color == NULL)
+ {
+ fill_color = gdk_color_copy (>K_WIDGET (icon_bar)->style->base[GTK_STATE_SELECTED]);
+ gdk_color_parse ("#e0e8f6", fill_color);
+ }
+
+ if (border_color == NULL)
+ {
+ border_color = gdk_color_copy (>K_WIDGET (icon_bar)->style->base[GTK_STATE_SELECTED]);
+ gdk_color_parse ("#98b4e2", border_color);
+ }
+
+ gc = gdk_gc_new (icon_bar->priv->bin_window);
+ gdk_gc_set_clip_rectangle (gc, area);
+ gdk_gc_set_rgb_fg_color (gc, fill_color);
+ gdk_draw_rectangle (icon_bar->priv->bin_window, gc, TRUE,
+ x + focus_pad + focus_width,
+ y + focus_pad + focus_width,
+ icon_bar->priv->item_width - 2 * (focus_width + focus_pad) + 1,
+ icon_bar->priv->item_height - 2 * (focus_width + focus_pad) + 1);
+ gdk_gc_set_rgb_fg_color (gc, border_color);
+ gdk_gc_set_line_attributes (gc, focus_width, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
+ gdk_draw_rectangle (icon_bar->priv->bin_window, gc, FALSE,
+ x + focus_pad + focus_width / 2,
+ y + focus_pad + focus_width / 2,
+ icon_bar->priv->item_width - (2 * focus_pad + focus_width) + 1,
+ icon_bar->priv->item_height - (2 * focus_pad + focus_width) + 1);
+ gdk_color_free (border_color);
+ gdk_color_free (fill_color);
+ g_object_unref (gc);
+ }
+
+ if (icon_bar->priv->pixbuf_column != -1)
+ {
+ pixbuf = rstto_icon_bar_get_item_icon (icon_bar, item);
+ if (G_LIKELY (pixbuf != NULL))
+ {
+ gdk_draw_pixbuf (icon_bar->priv->bin_window, NULL, pixbuf, 0, 0,
+ px-1, py-1, item->pixbuf_width, item->pixbuf_height,
+ GDK_RGB_DITHER_NORMAL, item->pixbuf_width,
+ item->pixbuf_height);
+ g_object_unref (pixbuf);
+ }
+ }
+
+ if (icon_bar->priv->text_column != -1 && icon_bar->priv->show_text == TRUE)
+ {
+ rstto_icon_bar_update_item_text (icon_bar, item);
+
+ if (icon_bar->priv->active_item == item)
+ {
+ gtk_widget_style_get (GTK_WIDGET (icon_bar),
+ "active-item-text-color", &text_color,
+ NULL);
+
+ if (text_color == NULL)
+ {
+ text_color = gdk_color_copy (>K_WIDGET (icon_bar)->style->base[GTK_STATE_SELECTED]);
+ gdk_color_parse ("#000000", text_color);
+ }
+
+ gc = gdk_gc_new (GDK_DRAWABLE (icon_bar->priv->bin_window));
+ gdk_gc_copy (gc, GTK_WIDGET (icon_bar)->style->text_gc[GTK_STATE_SELECTED]);
+ gdk_gc_set_clip_rectangle (gc, area);
+ gdk_gc_set_rgb_fg_color (gc, text_color);
+ gdk_draw_layout (icon_bar->priv->bin_window, gc, lx, ly, icon_bar->priv->layout);
+ g_object_unref (G_OBJECT (gc));
+ gdk_color_free (text_color);
+ }
+ else if (icon_bar->priv->cursor_item == item)
+ {
+ gtk_widget_style_get (GTK_WIDGET (icon_bar),
+ "cursor-item-text-color", &text_color,
+ NULL);
+
+ if (text_color == NULL)
+ {
+ text_color = gdk_color_copy (>K_WIDGET (icon_bar)->style->base[GTK_STATE_SELECTED]);
+ gdk_color_parse ("#000000", text_color);
+ }
+
+ gc = gdk_gc_new (GDK_DRAWABLE (icon_bar->priv->bin_window));
+ gdk_gc_copy (gc, GTK_WIDGET (icon_bar)->style->text_gc[GTK_STATE_SELECTED]);
+ gdk_gc_set_clip_rectangle (gc, area);
+ gdk_gc_set_rgb_fg_color (gc, text_color);
+ gdk_draw_layout (icon_bar->priv->bin_window, gc, lx, ly, icon_bar->priv->layout);
+ g_object_unref (G_OBJECT (gc));
+ gdk_color_free (text_color);
+ }
+ else
+ {
+ gtk_paint_layout (GTK_WIDGET (icon_bar)->style,
+ icon_bar->priv->bin_window,
+ GTK_STATE_NORMAL, TRUE, area,
+ GTK_WIDGET (icon_bar), "icon_bar",
+ lx, ly, icon_bar->priv->layout);
+ }
+ }
+}
+
+
+
+static void
+rstto_icon_bar_calculate_item_size (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item)
+{
+ GdkPixbuf *pixbuf;
+ gint focus_width;
+ gint focus_pad;
+
+ if (G_LIKELY (item->width != -1 && item->width != -1))
+ return;
+
+ gtk_widget_style_get (GTK_WIDGET (icon_bar),
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ NULL);
+
+ if (icon_bar->priv->pixbuf_column != -1)
+ {
+ pixbuf = rstto_icon_bar_get_item_icon (icon_bar, item);
+ if (G_LIKELY (pixbuf != NULL))
+ {
+ item->pixbuf_width = gdk_pixbuf_get_width (pixbuf);
+ item->pixbuf_height = gdk_pixbuf_get_height (pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ else
+ {
+ item->pixbuf_width = 0;
+ item->pixbuf_height = 0;
+ }
+ }
+ else
+ {
+ item->pixbuf_width = 0;
+ item->pixbuf_height = 0;
+ }
+
+ if (icon_bar->priv->text_column != -1 && icon_bar->priv->show_text == TRUE)
+ {
+ rstto_icon_bar_update_item_text (icon_bar, item);
+ pango_layout_get_pixel_size (icon_bar->priv->layout,
+ &item->layout_width,
+ &item->layout_height);
+ item->width = MAX (item->layout_width, item->pixbuf_width) + 2 * ICON_TEXT_PADDING
+ + 2 * (focus_width + focus_pad);
+ item->height = item->layout_height + 2 * (focus_width + focus_pad + ICON_TEXT_PADDING)
+ + item->pixbuf_height;
+ }
+ else
+ {
+ item->layout_width = 0;
+ item->layout_height = 0;
+
+ item->width = MAX (item->layout_width, item->pixbuf_width) + 2 * (focus_width + focus_pad);
+ item->height = item->layout_height + 2 * (focus_width + focus_pad ) + item->pixbuf_height;
+ }
+
+
+ if (item->width < item->height)
+ {
+ item->width = item->height;
+ }
+
+}
+
+
+
+static void
+rstto_icon_bar_update_item_text (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gchar *text;
+
+ if ((gtk_tree_model_get_flags (icon_bar->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST) == 0)
+ {
+ path = gtk_tree_path_new_from_indices (item->index, -1);
+ gtk_tree_model_get_iter (icon_bar->priv->model, &iter, path);
+ gtk_tree_path_free (path);
+ }
+ else
+ {
+ iter = item->iter;
+ }
+
+ gtk_tree_model_get (icon_bar->priv->model, &iter,
+ icon_bar->priv->text_column, &text,
+ -1);
+ pango_layout_set_text (icon_bar->priv->layout, text, -1);
+ g_free (text);
+}
+
+
+
+static GdkPixbuf*
+rstto_icon_bar_get_item_icon (RsttoIconBar *icon_bar,
+ RsttoIconBarItem *item)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GdkPixbuf *pixbuf;
+
+ if ((gtk_tree_model_get_flags (icon_bar->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST) == 0)
+ {
+ path = gtk_tree_path_new_from_indices (item->index, -1);
+ gtk_tree_model_get_iter (icon_bar->priv->model, &iter, path);
+ gtk_tree_path_free (path);
+ }
+ else
+ {
+ iter = item->iter;
+ }
+
+ gtk_tree_model_get (icon_bar->priv->model, &iter,
+ icon_bar->priv->pixbuf_column, &pixbuf,
+ -1);
+
+ return pixbuf;
+}
+
+
+
+static RsttoIconBarItem*
+rstto_icon_bar_item_new (void)
+{
+ RsttoIconBarItem *item;
+
+ item = g_slice_new0 (RsttoIconBarItem);
+ item->width = -1;
+ item->height = -1;
+
+ return item;
+}
+
+
+
+static void
+rstto_icon_bar_item_free (RsttoIconBarItem *item)
+{
+ g_slice_free (RsttoIconBarItem, item);
+}
+
+
+
+static void
+rstto_icon_bar_item_invalidate (RsttoIconBarItem *item)
+{
+ item->width = -1;
+ item->height = -1;
+}
+
+
+
+static void
+rstto_icon_bar_build_items (RsttoIconBar *icon_bar)
+{
+ RsttoIconBarItem *item;
+ GtkTreeIter iter;
+ GList *items = NULL;
+ gint i = 0;
+
+ if (!gtk_tree_model_get_iter_first (icon_bar->priv->model, &iter))
+ return;
+
+ do
+ {
+ item = rstto_icon_bar_item_new ();
+ item->iter = iter;
+ item->index = i++;
+
+ items = g_list_prepend (items, item);
+ }
+ while (gtk_tree_model_iter_next (icon_bar->priv->model, &iter));
+
+ icon_bar->priv->items = g_list_reverse (items);
+}
+
+
+
+static void
+rstto_icon_bar_row_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ RsttoIconBar *icon_bar)
+{
+ RsttoIconBarItem *item;
+ gint idx;
+
+ idx = gtk_tree_path_get_indices (path)[0];
+ item = g_list_nth (icon_bar->priv->items, idx)->data;
+ rstto_icon_bar_item_invalidate (item);
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+}
+
+
+
+static void
+rstto_icon_bar_row_inserted (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ RsttoIconBar *icon_bar)
+{
+ RsttoIconBarItem *item;
+ GList *lp;
+ gint idx;
+
+ idx = gtk_tree_path_get_indices (path)[0];
+ item = rstto_icon_bar_item_new ();
+
+ if ((gtk_tree_model_get_flags (icon_bar->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST) != 0)
+ item->iter = *iter;
+ item->index = idx;
+
+ icon_bar->priv->items = g_list_insert (icon_bar->priv->items, item, idx);
+
+ for (lp = g_list_nth (icon_bar->priv->items, idx + 1); lp != NULL; lp = lp->next)
+ {
+ item = lp->data;
+ item->index++;
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+}
+
+
+
+static void
+rstto_icon_bar_row_deleted (GtkTreeModel *model,
+ GtkTreePath *path,
+ RsttoIconBar *icon_bar)
+{
+ RsttoIconBarItem *item;
+ gboolean active = FALSE;
+ GList *lnext;
+ GList *lp;
+ gint idx;
+
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+
+ idx = gtk_tree_path_get_indices (path)[0];
+ lp = g_list_nth (icon_bar->priv->items, idx);
+ item = lp->data;
+
+ if (item == icon_bar->priv->active_item)
+ {
+ icon_bar->priv->active_item = NULL;
+ active = TRUE;
+ }
+
+ if (item == icon_bar->priv->cursor_item)
+ icon_bar->priv->cursor_item = NULL;
+
+ rstto_icon_bar_item_free (item);
+
+ for (lnext = lp->next; lnext != NULL; lnext = lnext->next)
+ {
+ item = lnext->data;
+ item->index--;
+ }
+
+ icon_bar->priv->items = g_list_delete_link (icon_bar->priv->items, lp);
+
+ if (active && icon_bar->priv->items != NULL)
+ icon_bar->priv->active_item = icon_bar->priv->items->data;
+
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+
+ if (active)
+ rstto_icon_bar_set_active (icon_bar, -1);
+}
+
+
+
+static void
+rstto_icon_bar_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order,
+ RsttoIconBar *icon_bar)
+{
+ RsttoIconBarItem **item_array;
+ GList *items = NULL;
+ GList *lp;
+ gint *inverted_order;
+ gint length;
+ gint i;
+
+ length = gtk_tree_model_iter_n_children (model, NULL);
+ inverted_order = g_newa (gint, length);
+
+ /* invert the array */
+ for (i = 0; i < length; ++i)
+ inverted_order[new_order[i]] = i;
+
+ item_array = g_newa (RsttoIconBarItem *, length);
+ for (i = 0, lp = icon_bar->priv->items; lp != NULL; ++i, lp = lp->next)
+ item_array[inverted_order[i]] = lp->data;
+
+ for (i = 0; i < length; ++i)
+ {
+ item_array[i]->index = i;
+ items = g_list_append (items, item_array[i]);
+ }
+
+ g_list_free (icon_bar->priv->items);
+ icon_bar->priv->items = g_list_reverse (items);
+
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+}
+
+
+
+/**
+ * rstto_icon_bar_new:
+ *
+ * Creates a new #RsttoIconBar without model.
+ *
+ * Returns: a newly allocated #RsttoIconBar.
+ **/
+GtkWidget*
+rstto_icon_bar_new (void)
+{
+ return g_object_new (RSTTO_TYPE_ICON_BAR, NULL);
+}
+
+
+
+/**
+ * rstto_icon_bar_new_with_model:
+ * @model : A #GtkTreeModel.
+ *
+ * Creates a new #RsttoIconBar and associates it with
+ * @model.
+ *
+ * Returns: a newly allocated #RsttoIconBar, which is associated with @model.
+ **/
+GtkWidget*
+rstto_icon_bar_new_with_model (GtkTreeModel *model)
+{
+ g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
+
+ return g_object_new (RSTTO_TYPE_ICON_BAR,
+ "model", model,
+ NULL);
+}
+
+
+
+/**
+ * rstto_icon_bar_get_model:
+ * @icon_bar : A #RsttoIconBar.
+ *
+ * Returns the model the #RsttoIconBar is based on. Returns %NULL if
+ * the model is unset.
+ *
+ * Returns: A #GtkTreeModel, or %NULL if none is currently being used.
+ **/
+GtkTreeModel*
+rstto_icon_bar_get_model (RsttoIconBar *icon_bar)
+{
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), NULL);
+ return icon_bar->priv->model;
+}
+
+
+
+/**
+ * rstto_icon_bar_set_model:
+ * @icon_bar : A #RsttoIconBar.
+ * @model : A #GtkTreeModel or %NULL.
+ *
+ * Sets the model for a #RsttoIconBar. If the @icon_bar already has a model
+ * set, it will remove it before settings the new model. If @model is %NULL,
+ * then it will unset the old model.
+ **/
+void
+rstto_icon_bar_set_model (RsttoIconBar *icon_bar,
+ GtkTreeModel *model)
+{
+ GType pixbuf_column_type;
+ GType text_column_type;
+ gint active = -1;
+
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (GTK_IS_TREE_MODEL (model) || model == NULL);
+
+ if (G_UNLIKELY (model == icon_bar->priv->model))
+ return;
+
+ if (model != NULL)
+ {
+ g_return_if_fail (gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY);
+
+ if (icon_bar->priv->pixbuf_column != -1)
+ {
+ pixbuf_column_type = gtk_tree_model_get_column_type (model, icon_bar->priv->pixbuf_column);
+ g_return_if_fail (pixbuf_column_type == GDK_TYPE_PIXBUF);
+ }
+
+ if (icon_bar->priv->text_column != -1)
+ {
+ text_column_type = gtk_tree_model_get_column_type (model, icon_bar->priv->text_column);
+ g_return_if_fail (text_column_type == G_TYPE_STRING);
+ }
+ }
+
+ if (icon_bar->priv->model)
+ {
+ g_signal_handlers_disconnect_by_func (icon_bar->priv->model,
+ rstto_icon_bar_row_changed,
+ icon_bar);
+ g_signal_handlers_disconnect_by_func (icon_bar->priv->model,
+ rstto_icon_bar_row_inserted,
+ icon_bar);
+ g_signal_handlers_disconnect_by_func (icon_bar->priv->model,
+ rstto_icon_bar_row_deleted,
+ icon_bar);
+ g_signal_handlers_disconnect_by_func (icon_bar->priv->model,
+ rstto_icon_bar_rows_reordered,
+ icon_bar);
+
+ g_object_unref (G_OBJECT (icon_bar->priv->model));
+
+ g_list_foreach (icon_bar->priv->items, (GFunc) rstto_icon_bar_item_free, NULL);
+ g_list_free (icon_bar->priv->items);
+ icon_bar->priv->active_item = NULL;
+ icon_bar->priv->cursor_item = NULL;
+ icon_bar->priv->items = NULL;
+ }
+
+ icon_bar->priv->model = model;
+
+ if (model != NULL)
+ {
+ g_object_ref (G_OBJECT (model));
+
+ g_signal_connect (G_OBJECT (model), "row-changed",
+ G_CALLBACK (rstto_icon_bar_row_changed), icon_bar);
+ g_signal_connect (G_OBJECT (model), "row-inserted",
+ G_CALLBACK (rstto_icon_bar_row_inserted), icon_bar);
+ g_signal_connect (G_OBJECT (model), "row-deleted",
+ G_CALLBACK (rstto_icon_bar_row_deleted), icon_bar);
+ g_signal_connect (G_OBJECT (model), "rows-reordered",
+ G_CALLBACK (rstto_icon_bar_rows_reordered), icon_bar);
+
+ rstto_icon_bar_build_items (icon_bar);
+
+ if (icon_bar->priv->items != NULL)
+ active = ((RsttoIconBarItem *) icon_bar->priv->items->data)->index;
+ }
+
+ rstto_icon_bar_invalidate (icon_bar);
+
+ g_object_notify (G_OBJECT (icon_bar), "model");
+
+ rstto_icon_bar_set_active (icon_bar, active);
+}
+
+
+
+/**
+ * rstto_icon_bar_get_pixbuf_column:
+ * @icon_bar : An #RsttoIconBar.
+ *
+ * Returns the column with pixbufs for @icon_bar.
+ *
+ * Returns: the pixbuf column, or -1 if it's unset.
+ **/
+gint
+rstto_icon_bar_get_pixbuf_column (RsttoIconBar *icon_bar)
+{
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), -1);
+ return icon_bar->priv->pixbuf_column;
+}
+
+
+
+/**
+ * rstto_icon_bar_set_pixbuf_column:
+ * @icon_bar : An #RsttoIconBar.
+ * @column : A column in the currently used model.
+ *
+ * Sets the column with pixbufs for @icon_bar to be @column. The pixbuf
+ * column must be of type #GDK_TYPE_PIXBUF.
+ **/
+void
+rstto_icon_bar_set_pixbuf_column (RsttoIconBar *icon_bar,
+ gint column)
+{
+ GType pixbuf_column_type;
+
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+
+ if (column == icon_bar->priv->pixbuf_column)
+ return;
+
+ if (column == -1)
+ {
+ icon_bar->priv->pixbuf_column = -1;
+ }
+ else
+ {
+ if (icon_bar->priv->model != NULL)
+ {
+ pixbuf_column_type = gtk_tree_model_get_column_type (icon_bar->priv->model, column);
+ g_return_if_fail (pixbuf_column_type == GDK_TYPE_PIXBUF);
+ }
+
+ icon_bar->priv->pixbuf_column = column;
+ }
+
+ rstto_icon_bar_invalidate (icon_bar);
+
+ g_object_notify (G_OBJECT (icon_bar), "pixbuf-column");
+}
+
+
+
+/**
+ * rstto_icon_bar_get_text_column:
+ * @icon_bar : An #RsttoIconBar.
+ *
+ * Returns the column with text for @icon_bar.
+ *
+ * Returns: the text column, or -1 if it's unset.
+ **/
+gint
+rstto_icon_bar_get_text_column (RsttoIconBar *icon_bar)
+{
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), -1);
+ return icon_bar->priv->text_column;
+}
+
+
+
+/**
+ * rstto_icon_bar_set_text_column:
+ * @icon_bar : An #RsttoIconBar.
+ * @column : A column in the currently used model or -1 to
+ * use no text in @icon_bar.
+ *
+ * Sets the column with text for @icon_bar to be @column. The
+ * text column must be of type #G_TYPE_STRING.
+ **/
+void
+rstto_icon_bar_set_text_column (RsttoIconBar *icon_bar,
+ gint column)
+{
+ GType text_column_type;
+
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+
+ if (column == icon_bar->priv->text_column)
+ return;
+
+ if (column == -1)
+ {
+ icon_bar->priv->text_column = -1;
+ }
+ else
+ {
+ if (icon_bar->priv->model != NULL)
+ {
+ text_column_type = gtk_tree_model_get_column_type (icon_bar->priv->model, column);
+ g_return_if_fail (text_column_type == G_TYPE_STRING);
+ }
+
+ icon_bar->priv->text_column = column;
+ }
+
+ rstto_icon_bar_invalidate (icon_bar);
+
+ g_object_notify (G_OBJECT (icon_bar), "text-column");
+}
+
+
+
+/**
+ * rstto_icon_bar_get_orientation:
+ * @icon_bar : An #RsttoIconBar.
+ *
+ * Retrieves the current orientation of the toolbar. See
+ * rstto_icon_bar_set_orientation().
+ *
+ * Returns: The orientation of @icon_bar.
+ **/
+GtkOrientation
+rstto_icon_bar_get_orientation (RsttoIconBar *icon_bar)
+{
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), GTK_ORIENTATION_VERTICAL);
+ return icon_bar->priv->orientation;
+}
+
+
+
+/**
+ * rstto_icon_bar_set_orientation:
+ * @icon_bar : An #RsttoIconBar.
+ * @orientation : A new #GtkOrientation.
+ *
+ * Sets whether the @icon_bar should appear horizontally
+ * or vertically.
+ **/
+void
+rstto_icon_bar_set_orientation (RsttoIconBar *icon_bar,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+
+ if (icon_bar->priv->orientation != orientation)
+ {
+ icon_bar->priv->orientation = orientation;
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+
+ /* If the orientation changes, focus the active item */
+ rstto_icon_bar_show_active (icon_bar);
+
+ g_object_notify (G_OBJECT (icon_bar), "orientation");
+ }
+}
+
+
+
+/**
+ * rstto_icon_bar_get_active:
+ * @icon_bar : An #RsttoIconBar.
+ *
+ * Returns the index of the currently active item, or -1 if there's no
+ * active item.
+ *
+ * Returns: An integer which is the index of the currently active item,
+ * or -1 if there's no active item.
+ **/
+gint
+rstto_icon_bar_get_active (RsttoIconBar *icon_bar)
+{
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), -1);
+
+ return (icon_bar->priv->active_item != NULL)
+ ? icon_bar->priv->active_item->index
+ : -1;
+}
+
+
+
+/**
+ * rstto_icon_bar_set_active:
+ * @icon_bar : An #RsttoIconBar.
+ * @idx : An index in the model passed during construction,
+ * or -1 to have no active item.
+ *
+ * Sets the active item of @icon_bar to be the item at @idx.
+ **/
+void
+rstto_icon_bar_set_active (RsttoIconBar *icon_bar,
+ gint idx)
+{
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (idx == -1 || g_list_nth (icon_bar->priv->items, idx) != NULL);
+
+ if ((icon_bar->priv->active_item == NULL && idx == -1)
+ || (icon_bar->priv->active_item != NULL && idx == icon_bar->priv->active_item->index))
+ return;
+
+ if (G_UNLIKELY (idx >= 0))
+ icon_bar->priv->active_item = g_list_nth (icon_bar->priv->items, idx)->data;
+ else
+ icon_bar->priv->active_item = NULL;
+
+ g_signal_emit (G_OBJECT (icon_bar), icon_bar_signals[SELECTION_CHANGED], 0);
+ g_object_notify (G_OBJECT (icon_bar), "active");
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+}
+
+
+
+/**
+ * rstto_icon_bar_get_active_iter:
+ * @icon_bar : An #RsttoIconBar.
+ * @iter : An uninitialized #GtkTreeIter.
+ *
+ * Sets @iter to point to the current active item, if it exists.
+ *
+ * Returns: %TRUE if @iter was set.
+ **/
+gboolean
+rstto_icon_bar_get_active_iter (RsttoIconBar *icon_bar,
+ GtkTreeIter *iter)
+{
+ RsttoIconBarItem *item;
+ GtkTreePath *path;
+
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ item = icon_bar->priv->active_item;
+ if (item == NULL)
+ return FALSE;
+
+ if ((gtk_tree_model_get_flags (icon_bar->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST) == 0)
+ {
+ path = gtk_tree_path_new_from_indices (item->index, -1);
+ gtk_tree_model_get_iter (icon_bar->priv->model, iter, path);
+ gtk_tree_path_free (path);
+ }
+ else
+ {
+ *iter = item->iter;
+ }
+
+ return TRUE;
+}
+
+
+
+/**
+ * rstto_icon_bar_set_active_iter:
+ * @icon_bar : An #RsttoIconBar.
+ * @iter : The #GtkTreeIter.
+ *
+ * Sets the current active item to be the one referenced by @iter. @iter
+ * must correspond to a path of depth one.
+ *
+ * This can only be called if @icon_bar is associated with #GtkTreeModel.
+ **/
+void
+rstto_icon_bar_set_active_iter (RsttoIconBar *icon_bar,
+ GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (icon_bar->priv->model != NULL);
+ g_return_if_fail (iter != NULL);
+
+ path = gtk_tree_model_get_path (icon_bar->priv->model, iter);
+ if (G_LIKELY (path != NULL))
+ {
+ rstto_icon_bar_set_active (icon_bar, gtk_tree_path_get_indices (path)[0]);
+ gtk_tree_path_free (path);
+ }
+}
+
+gint
+rstto_icon_bar_get_item_width (RsttoIconBar *icon_bar)
+{
+ return -1;
+}
+
+void
+rstto_icon_bar_set_item_width (RsttoIconBar *icon_bar,
+ gint item_width)
+{
+ pango_layout_set_width (icon_bar->priv->layout,
+ item_width*PANGO_SCALE);
+ return;
+}
+
+/**
+ * rstto_icon_bar_set_show_text:
+ * @icon_bar : An #RsttoIconBar.
+ * @show_text : TRUE if text should be visible
+ * or FALSE if text is hidden
+ *
+ * Toggles the visibility of the text-label
+ **/
+void
+rstto_icon_bar_set_show_text (RsttoIconBar *icon_bar,
+ gboolean show_text)
+{
+ g_return_if_fail (RSTTO_IS_ICON_BAR (icon_bar));
+ icon_bar->priv->show_text = show_text;
+}
+
+/**
+ * rstto_icon_bar_get_show_text:
+ * @icon_bar : An #RsttoIconBar.
+ *
+ * Returns: TRUE if text is visible.
+ **/
+gboolean
+rstto_icon_bar_get_show_text (RsttoIconBar *icon_bar)
+{
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), FALSE);
+ return icon_bar->priv->show_text;
+}
+
+/**
+ * rstto_icon_bar_show_active:
+ * @icon_bar : An #RsttoIconBar.
+ *
+ * Returns: TRUE on success
+ **/
+gboolean
+rstto_icon_bar_show_active (RsttoIconBar *icon_bar)
+{
+ gint page_size = 0;
+ gint value = 0;
+
+ g_return_val_if_fail (RSTTO_IS_ICON_BAR (icon_bar), FALSE);
+ if (NULL == icon_bar->priv->active_item)
+ return FALSE;
+
+ icon_bar->priv->auto_center = TRUE;
+
+ if (icon_bar->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ page_size = gtk_adjustment_get_page_size (icon_bar->priv->vadjustment);
+ value = icon_bar->priv->active_item->index * icon_bar->priv->item_height - ((page_size-icon_bar->priv->item_height)/2);
+
+ if (value > (gtk_adjustment_get_upper (icon_bar->priv->vadjustment)-page_size))
+ value = (gtk_adjustment_get_upper (icon_bar->priv->vadjustment)-page_size);
+
+ gtk_adjustment_set_value (icon_bar->priv->vadjustment, value);
+ gtk_adjustment_changed (icon_bar->priv->vadjustment);
+ icon_bar->priv->auto_center = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ page_size = gtk_adjustment_get_page_size (icon_bar->priv->hadjustment);
+ value = icon_bar->priv->active_item->index * icon_bar->priv->item_width - ((page_size-icon_bar->priv->item_width)/2);
+
+ if (value > (gtk_adjustment_get_upper (icon_bar->priv->hadjustment)-page_size))
+ value = (gtk_adjustment_get_upper (icon_bar->priv->hadjustment)-page_size);
+
+ gtk_adjustment_set_value (icon_bar->priv->hadjustment, value);
+ gtk_adjustment_changed (icon_bar->priv->hadjustment);
+ icon_bar->priv->auto_center = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/icon_bar.h b/src/icon_bar.h
new file mode 100644
index 0000000..6b9747c
--- /dev/null
+++ b/src/icon_bar.h
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2004 os-cillation e.K.
+ * Copyright (c) 2012 Stephan Arts <stephan at xfce.org>
+ *
+ * Written by Benedikt Meurer <benny at xfce.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __RSTTO_ICON_BAR_H__
+#define __RSTTO_ICON_BAR_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define RSTTO_TYPE_ICON_BAR (rstto_icon_bar_get_type ())
+#define RSTTO_ICON_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RSTTO_TYPE_ICON_BAR, RsttoIconBar))
+#define RSTTO_ICON_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RSTTO_TYPE_ICON_BAR, RsttoIconBarClass))
+#define RSTTO_IS_ICON_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RSTTO_TYPE_ICON_BAR))
+#define RSTTO_IS_ICON_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), RSTTO_TYPE_ICON_BAR))
+#define RSTTO_ICON_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RSTTO_TYPE_ICON_BAR, RsttoIconBarClass))
+
+typedef struct _RsttoIconBarPrivate RsttoIconBarPrivate;
+typedef struct _RsttoIconBarClass RsttoIconBarClass;
+typedef struct _RsttoIconBar RsttoIconBar;
+
+/**
+ * RsttoIconBarClass:
+ * @set_scroll_adjustments : Used internally to make the RsttoIconBar scrollable.
+ * @selection_changed : This signal is emitted whenever the currently selected icon changes.
+ **/
+struct _RsttoIconBarClass
+{
+ GtkContainerClass __parent__;
+
+ /* signals */
+ void (*set_scroll_adjustments) (RsttoIconBar *icon_bar,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+ void (*selection_changed) (RsttoIconBar *icon_bar);
+
+ /*< private >*/
+ void (*reserved1) (void);
+ void (*reserved2) (void);
+ void (*reserved3) (void);
+ void (*reserved4) (void);
+};
+
+/**
+ * RsttoIconBar:
+ *
+ * The #RsttoIconBar struct contains only private fields and should not
+ * be directly accessed.
+ **/
+struct _RsttoIconBar
+{
+ GtkContainer __parent__;
+
+ /*< private >*/
+ RsttoIconBarPrivate *priv;
+};
+
+GType rstto_icon_bar_get_type (void) G_GNUC_CONST;
+
+GtkWidget *rstto_icon_bar_new (void);
+GtkWidget *rstto_icon_bar_new_with_model (GtkTreeModel *model);
+
+GtkTreeModel *rstto_icon_bar_get_model (RsttoIconBar *icon_bar);
+void rstto_icon_bar_set_model (RsttoIconBar *icon_bar,
+ GtkTreeModel *model);
+
+gint rstto_icon_bar_get_pixbuf_column (RsttoIconBar *icon_bar);
+void rstto_icon_bar_set_pixbuf_column (RsttoIconBar *icon_bar,
+ gint column);
+
+gint rstto_icon_bar_get_text_column (RsttoIconBar *icon_bar);
+void rstto_icon_bar_set_text_column (RsttoIconBar *icon_bar,
+ gint column);
+
+GtkOrientation rstto_icon_bar_get_orientation (RsttoIconBar *icon_bar);
+void rstto_icon_bar_set_orientation (RsttoIconBar *icon_bar,
+ GtkOrientation orientation);
+
+gint rstto_icon_bar_get_active (RsttoIconBar *icon_bar);
+void rstto_icon_bar_set_active (RsttoIconBar *icon_bar,
+ gint idx);
+
+gboolean rstto_icon_bar_get_active_iter (RsttoIconBar *icon_bar,
+ GtkTreeIter *iter);
+void rstto_icon_bar_set_active_iter (RsttoIconBar *icon_bar,
+ GtkTreeIter *iter);
+
+gint rstto_icon_bar_get_item_width (RsttoIconBar *icon_bar);
+void rstto_icon_bar_set_item_width (RsttoIconBar *icon_bar,
+ gint item_width);
+
+gboolean rstto_icon_bar_get_show_text (RsttoIconBar *icon_bar);
+void rstto_icon_bar_set_show_text (RsttoIconBar *icon_bar,
+ gboolean show_text);
+
+gboolean rstto_icon_bar_show_active (RsttoIconBar *icon_bar);
+
+G_END_DECLS
+
+#endif /* !__RSTTO_ICON_BAR_H__ */
+
diff --git a/src/image_list.c b/src/image_list.c
index 428fc3b..2bacee0 100644
--- a/src/image_list.c
+++ b/src/image_list.c
@@ -78,6 +78,10 @@ rstto_image_list_monitor_dir (
GFile *dir );
static void
+rstto_image_list_update_missing_icon (
+ RsttoImageList *image_list);
+
+static void
rstto_image_list_remove_all (
RsttoImageList *image_list);
@@ -192,6 +196,11 @@ enum
RSTTO_IMAGE_LIST_ITER_SIGNAL_COUNT
};
+/* Missing image thumbnail, should be re-generated every time
+ * the thumbnail-size changed.
+ */
+static GdkPixbuf *thumbnail_missing = NULL;
+
struct _RsttoImageListIterPriv
{
RsttoImageList *image_list;
@@ -315,6 +324,8 @@ rstto_image_list_init(RsttoImageList *image_list)
image_list->priv->settings,
"thumbnail-size");
+ rstto_image_list_update_missing_icon (image_list);
+
g_signal_connect (
G_OBJECT(image_list->priv->settings),
"notify::wrap-images",
@@ -1246,6 +1257,8 @@ cb_rstto_thumbnail_size_changed (
image_list->priv->thumbnail_size = g_value_get_uint (&val_thumbnail_size);
+ rstto_image_list_update_missing_icon (image_list);
+
while (image_iter)
{
path_ = gtk_tree_path_new();
@@ -1567,6 +1580,9 @@ image_list_model_get_value (
}
else
{
+ g_value_set_object (
+ value,
+ thumbnail_missing);
}
g_free (checksum);
@@ -1575,3 +1591,75 @@ image_list_model_get_value (
break;
}
}
+
+static void
+rstto_image_list_update_missing_icon (
+ RsttoImageList *image_list)
+{
+
+ if (NULL != thumbnail_missing)
+ {
+ g_object_unref (thumbnail_missing);
+ }
+
+ switch (image_list->priv->thumbnail_size)
+ {
+ case THUMBNAIL_SIZE_VERY_SMALL:
+ thumbnail_missing = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default(),
+ "image-missing",
+ THUMBNAIL_SIZE_VERY_SMALL_SIZE,
+ 0,
+ NULL);
+ break;
+ case THUMBNAIL_SIZE_SMALLER:
+ thumbnail_missing = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default(),
+ "image-missing",
+ THUMBNAIL_SIZE_SMALLER_SIZE,
+ 0,
+ NULL);
+ break;
+ case THUMBNAIL_SIZE_SMALL:
+ thumbnail_missing = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default(),
+ "image-missing",
+ THUMBNAIL_SIZE_SMALL_SIZE,
+ 0,
+ NULL);
+ break;
+ case THUMBNAIL_SIZE_NORMAL:
+ thumbnail_missing = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default(),
+ "image-missing",
+ THUMBNAIL_SIZE_NORMAL_SIZE,
+ 0,
+ NULL);
+ break;
+ case THUMBNAIL_SIZE_LARGE:
+ thumbnail_missing = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default(),
+ "image-missing",
+ THUMBNAIL_SIZE_LARGE_SIZE,
+ 0,
+ NULL);
+ break;
+ case THUMBNAIL_SIZE_LARGER:
+ thumbnail_missing = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default(),
+ "image-missing",
+ THUMBNAIL_SIZE_LARGER_SIZE,
+ 0,
+ NULL);
+ break;
+ case THUMBNAIL_SIZE_VERY_LARGE:
+ thumbnail_missing = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default(),
+ "image-missing",
+ THUMBNAIL_SIZE_VERY_LARGE_SIZE,
+ 0,
+ NULL);
+ break;
+ }
+
+}
diff --git a/src/image_viewer.c b/src/image_viewer.c
index 18ee41a..8844dba 100644
--- a/src/image_viewer.c
+++ b/src/image_viewer.c
@@ -368,7 +368,7 @@ rstto_image_viewer_class_init(RsttoImageViewerClass *viewer_class)
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (RsttoImageViewerClass, set_scroll_adjustments),
NULL, NULL,
- rstto_marshal_VOID__OBJECT_OBJECT,
+ _rstto_marshal_VOID__OBJECT_OBJECT,
G_TYPE_NONE, 2,
GTK_TYPE_ADJUSTMENT,
GTK_TYPE_ADJUSTMENT);
diff --git a/src/main_window.c b/src/main_window.c
index e672fc8..06466c1 100644
--- a/src/main_window.c
+++ b/src/main_window.c
@@ -24,8 +24,6 @@
#include <gio/gio.h>
-#include <exo/exo.h>
-
#include <libxfce4ui/libxfce4ui.h>
#include <libexif/exif-data.h>
@@ -36,6 +34,7 @@
#include "settings.h"
#include "util.h"
#include "file.h"
+#include "icon_bar.h"
#include "image_list.h"
#include "image_viewer.h"
#include "main_window.h"
@@ -140,7 +139,7 @@ key_press_event (
static void
cb_icon_bar_selection_changed (
- ExoIconBar *icon_bar,
+ RsttoIconBar *icon_bar,
gpointer user_data);
static gboolean
@@ -646,8 +645,8 @@ rstto_main_window_init (RsttoMainWindow *window)
RSTTO_IMAGE_VIEWER(window->priv->image_viewer),
GTK_MENU(window->priv->image_viewer_menu));
- window->priv->thumbnailbar = exo_icon_bar_new();
- exo_icon_bar_set_show_text (EXO_ICON_BAR (window->priv->thumbnailbar), FALSE);
+ window->priv->thumbnailbar = rstto_icon_bar_new();
+ rstto_icon_bar_set_show_text (RSTTO_ICON_BAR (window->priv->thumbnailbar), FALSE);
g_signal_connect(G_OBJECT(window->priv->thumbnailbar), "selection-changed", G_CALLBACK(cb_icon_bar_selection_changed), window);
@@ -655,9 +654,9 @@ rstto_main_window_init (RsttoMainWindow *window)
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window->priv->t_bar_s_window), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
gtk_container_add (GTK_CONTAINER (window->priv->t_bar_s_window), window->priv->thumbnailbar);
- exo_icon_bar_set_text_column (EXO_ICON_BAR (window->priv->thumbnailbar), 0);
- exo_icon_bar_set_pixbuf_column (EXO_ICON_BAR (window->priv->thumbnailbar), 1);
- exo_icon_bar_set_item_width (EXO_ICON_BAR (window->priv->thumbnailbar), 96);
+ rstto_icon_bar_set_text_column (RSTTO_ICON_BAR (window->priv->thumbnailbar), 0);
+ rstto_icon_bar_set_pixbuf_column (RSTTO_ICON_BAR (window->priv->thumbnailbar), 1);
+ rstto_icon_bar_set_item_width (RSTTO_ICON_BAR (window->priv->thumbnailbar), 96);
window->priv->table = gtk_table_new (5, 5, FALSE);
@@ -959,8 +958,8 @@ rstto_main_window_new (RsttoImageList *image_list, gboolean fullscreen)
G_CALLBACK (cb_rstto_main_window_image_list_iter_changed),
window);
- exo_icon_bar_set_model (
- EXO_ICON_BAR (window->priv->thumbnailbar),
+ rstto_icon_bar_set_model (
+ RSTTO_ICON_BAR (window->priv->thumbnailbar),
GTK_TREE_MODEL (window->priv->image_list));
/*
rstto_thumbnail_bar_set_image_list (
@@ -1007,8 +1006,8 @@ rstto_main_window_image_list_iter_changed (RsttoMainWindow *window)
cur_file = rstto_image_list_iter_get_file (window->priv->iter);
if (NULL != cur_file)
{
- exo_icon_bar_set_active (EXO_ICON_BAR (window->priv->thumbnailbar), position);
- exo_icon_bar_show_active (EXO_ICON_BAR (window->priv->thumbnailbar));
+ rstto_icon_bar_set_active (RSTTO_ICON_BAR (window->priv->thumbnailbar), position);
+ rstto_icon_bar_show_active (RSTTO_ICON_BAR (window->priv->thumbnailbar));
content_type = rstto_file_get_content_type (cur_file);
rstto_image_viewer_set_file (
@@ -1850,7 +1849,7 @@ rstto_main_window_set_navigationbar_position (RsttoMainWindow *window, guint ori
0,
0);
gtk_orientable_set_orientation (GTK_ORIENTABLE(window->priv->image_list_toolbar), GTK_ORIENTATION_VERTICAL);
- exo_icon_bar_set_orientation (EXO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_VERTICAL);
+ rstto_icon_bar_set_orientation (RSTTO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_VERTICAL);
break;
case 1: /* Right */
g_object_ref (window->priv->image_list_toolbar);
@@ -1889,7 +1888,7 @@ rstto_main_window_set_navigationbar_position (RsttoMainWindow *window, guint ori
0,
0);
gtk_orientable_set_orientation (GTK_ORIENTABLE (window->priv->image_list_toolbar), GTK_ORIENTATION_VERTICAL);
- exo_icon_bar_set_orientation (EXO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_VERTICAL);
+ rstto_icon_bar_set_orientation (RSTTO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_VERTICAL);
break;
case 2: /* Top */
g_object_ref (window->priv->image_list_toolbar);
@@ -1928,7 +1927,7 @@ rstto_main_window_set_navigationbar_position (RsttoMainWindow *window, guint ori
0,
0);
gtk_orientable_set_orientation (GTK_ORIENTABLE (window->priv->image_list_toolbar), GTK_ORIENTATION_HORIZONTAL);
- exo_icon_bar_set_orientation (EXO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_HORIZONTAL);
+ rstto_icon_bar_set_orientation (RSTTO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_HORIZONTAL);
break;
case 3: /* Bottom */
g_object_ref (window->priv->image_list_toolbar);
@@ -1966,7 +1965,7 @@ rstto_main_window_set_navigationbar_position (RsttoMainWindow *window, guint ori
0,
0);
gtk_orientable_set_orientation (GTK_ORIENTABLE(window->priv->image_list_toolbar), GTK_ORIENTATION_HORIZONTAL);
- exo_icon_bar_set_orientation (EXO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_HORIZONTAL);
+ rstto_icon_bar_set_orientation (RSTTO_ICON_BAR(window->priv->thumbnailbar), GTK_ORIENTATION_HORIZONTAL);
break;
default:
break;
@@ -3657,12 +3656,12 @@ cb_rstto_desktop_type_changed (
static void
cb_icon_bar_selection_changed (
- ExoIconBar *icon_bar,
+ RsttoIconBar *icon_bar,
gpointer user_data)
{
RsttoMainWindow *window = RSTTO_MAIN_WINDOW (user_data);
gint position = rstto_image_list_iter_get_position (window->priv->iter);
- gint selection = exo_icon_bar_get_active (EXO_ICON_BAR(window->priv->thumbnailbar));
+ gint selection = rstto_icon_bar_get_active (RSTTO_ICON_BAR(window->priv->thumbnailbar));
if (position != selection )
{
diff --git a/src/thumbnailer.c b/src/thumbnailer.c
index a6a1a11..a3d2c85 100644
--- a/src/thumbnailer.c
+++ b/src/thumbnailer.c
@@ -150,7 +150,7 @@ rstto_thumbnailer_init (GObject *object)
"org.freedesktop.thumbnails.Thumbnailer1");
dbus_g_object_register_marshaller (
- (GClosureMarshal) rstto_marshal_VOID__UINT_BOXED,
+ (GClosureMarshal) _rstto_marshal_VOID__UINT_BOXED,
G_TYPE_NONE,
G_TYPE_UINT,
G_TYPE_STRV,
More information about the Xfce4-commits
mailing list