From 96b13cdf40cdbacf6e2c5f5373e181b494b370a7 Mon Sep 17 00:00:00 2001 From: Andrzej Date: Mon, 19 Mar 2012 20:56:37 +0900 Subject: [PATCH] Added support for multi-row layout. Layout mechanism implemented in a new class XfceIndicatorBox. --- panel-plugin/Makefile.am | 2 + panel-plugin/indicator-box.c | 408 +++++++++++++++++++++++++++++++++++++++ panel-plugin/indicator-box.h | 65 ++++++ panel-plugin/indicator-button.c | 5 +- panel-plugin/indicator.c | 82 ++------- 5 files changed, 492 insertions(+), 70 deletions(-) create mode 100644 panel-plugin/indicator-box.c create mode 100644 panel-plugin/indicator-box.h diff --git a/panel-plugin/Makefile.am b/panel-plugin/Makefile.am index de8c63a..5327a91 100644 --- a/panel-plugin/Makefile.am +++ b/panel-plugin/Makefile.am @@ -16,6 +16,8 @@ plugindir = \ xfce4_indicator_plugin_SOURCES = \ indicator-button.c \ indicator-button.h \ + indicator-box.c \ + indicator-box.h \ indicator.c \ indicator.h diff --git a/panel-plugin/indicator-box.c b/panel-plugin/indicator-box.c new file mode 100644 index 0000000..e8ccb8a --- /dev/null +++ b/panel-plugin/indicator-box.c @@ -0,0 +1,408 @@ +/* Copyright (c) 2012 Andrzej + * + * 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 Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include "indicator-box.h" +#include "indicator-button.h" + +static void xfce_indicator_box_finalize (GObject *object); +static void xfce_indicator_box_add (GtkContainer *container, + GtkWidget *child); +static void xfce_indicator_box_remove (GtkContainer *container, + GtkWidget *child); +static void xfce_indicator_box_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static GType xfce_indicator_box_child_type (GtkContainer *container); +static void xfce_indicator_box_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void xfce_indicator_box_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); + + +G_DEFINE_TYPE (XfceIndicatorBox, xfce_indicator_box, GTK_TYPE_CONTAINER) + +static void +xfce_indicator_box_class_init (XfceIndicatorBoxClass *klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *gtkwidget_class; + GtkContainerClass *gtkcontainer_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = xfce_indicator_box_finalize; + + gtkwidget_class = GTK_WIDGET_CLASS (klass); + gtkwidget_class->size_request = xfce_indicator_box_size_request; + gtkwidget_class->size_allocate = xfce_indicator_box_size_allocate; + + gtkcontainer_class = GTK_CONTAINER_CLASS (klass); + gtkcontainer_class->add = xfce_indicator_box_add; + gtkcontainer_class->remove = xfce_indicator_box_remove; + gtkcontainer_class->forall = xfce_indicator_box_forall; + gtkcontainer_class->child_type = xfce_indicator_box_child_type; +} + + + +static void +xfce_indicator_box_init (XfceIndicatorBox *box) +{ + GTK_WIDGET_SET_FLAGS (box, GTK_NO_WINDOW); + + gtk_widget_set_can_focus(GTK_WIDGET(box), TRUE); + gtk_container_set_border_width(GTK_CONTAINER(box), 0); + + box->children = NULL; + + box->nrows = 1; + box->panel_size = 16; + box->panel_orientation = GTK_ORIENTATION_HORIZONTAL; + box->orientation = GTK_ORIENTATION_HORIZONTAL; +} + + + +static void +xfce_indicator_box_finalize (GObject *object) +{ + XfceIndicatorBox *box = XFCE_INDICATOR_BOX (object); + + if (box->children != NULL) + { + g_slist_free (box->children); + g_debug ("Not all icons have been removed from the indicator icon box."); + } + + G_OBJECT_CLASS (xfce_indicator_box_parent_class)->finalize (object); +} + + + +void +xfce_indicator_box_set_orientation (XfceIndicatorBox *box, + GtkOrientation panel_orientation, + GtkOrientation orientation) +{ + gboolean needs_update = FALSE; + XfceIndicatorButton *child; + GSList *li; + + g_return_if_fail (XFCE_IS_INDICATOR_BOX (box)); + + if (box->orientation != orientation) + { + box->orientation = orientation; + needs_update = TRUE; + } + + if (box->panel_orientation != panel_orientation) + { + box->panel_orientation = panel_orientation; + needs_update = TRUE; + } + + if (needs_update) + { + for (li = box->children; li != NULL; li = li->next) + { + child = XFCE_INDICATOR_BUTTON (li->data); + g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child)); + xfce_indicator_button_set_orientation (child, panel_orientation, orientation); + } + gtk_widget_queue_resize (GTK_WIDGET (box)); + } +} + + + +void +xfce_indicator_box_set_size (XfceIndicatorBox *box, + gint panel_size, + gint nrows) +{ + gboolean needs_update = FALSE; + XfceIndicatorButton *child; + GSList *li; + + g_return_if_fail (XFCE_IS_INDICATOR_BOX (box)); + + if (box->nrows != nrows) + { + box->nrows = nrows; + needs_update = TRUE; + } + + if (box->panel_size != panel_size) + { + box->panel_size = panel_size; + needs_update = TRUE; + } + + if (needs_update) + { + for (li = box->children; li != NULL; li = li->next) + { + child = XFCE_INDICATOR_BUTTON (li->data); + g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child)); + xfce_indicator_button_set_size (child, panel_size, panel_size / nrows); + } + gtk_widget_queue_resize (GTK_WIDGET (box)); + } +} + + + +GtkWidget * +xfce_indicator_box_new () +{ + XfceIndicatorBox *box = g_object_new (XFCE_TYPE_INDICATOR_BOX, NULL); + return GTK_WIDGET (box); +} + + + +static void +xfce_indicator_box_add (GtkContainer *container, + GtkWidget *child) +{ + XfceIndicatorBox *box = XFCE_INDICATOR_BOX (container); + XfceIndicatorButton *button = XFCE_INDICATOR_BUTTON (child); + + g_return_if_fail (XFCE_IS_INDICATOR_BOX (box)); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child->parent == NULL); + + box->children = g_slist_append (box->children, child); + + gtk_widget_set_parent (child, GTK_WIDGET (box)); + xfce_indicator_button_set_orientation (button, box->panel_orientation, box->orientation); + xfce_indicator_button_set_size (button, box->panel_size, box->panel_size / box->nrows); + + gtk_widget_queue_resize (GTK_WIDGET (container)); +} + + + +static void +xfce_indicator_box_remove (GtkContainer *container, + GtkWidget *child) +{ + XfceIndicatorBox *box = XFCE_INDICATOR_BOX (container); + GSList *li; + + /* search the child */ + li = g_slist_find (box->children, child); + if (G_LIKELY (li != NULL)) + { + g_assert (GTK_WIDGET (li->data) == child); + + /* unparent widget */ + box->children = g_slist_remove_link (box->children, li); + gtk_widget_unparent (child); + + /* resize, so we update has-hidden */ + gtk_widget_queue_resize (GTK_WIDGET (container)); + } +} + + + +static void +xfce_indicator_box_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + XfceIndicatorBox *box = XFCE_INDICATOR_BOX (container); + GSList *li, *lnext; + + /* run callback for all children */ + for (li = box->children; li != NULL; li = lnext) + { + lnext = li->next; + (*callback) (GTK_WIDGET (li->data), callback_data); + } +} + + + +static GType +xfce_indicator_box_child_type (GtkContainer *container) +{ + return GTK_TYPE_WIDGET; +} + + + +static void +xfce_indicator_box_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + XfceIndicatorBox *box = XFCE_INDICATOR_BOX (widget); + GtkWidget *child; + GtkRequisition child_req; + GSList *li; + gint panel_size; + gint length; + gint row; + gint x; + gboolean has_label; + + panel_size = box->panel_size; + row = 0; + length = 0; + x = 0; + + for (li = box->children; li != NULL; li = li->next) + { + child = GTK_WIDGET (li->data); + g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child)); + + gtk_widget_size_request (child, &child_req); + has_label = (xfce_indicator_button_get_label (XFCE_INDICATOR_BUTTON (child)) != NULL); + + /* wrap rows if column is overflowing or a label is encountered */ + if (row > 0 && (has_label || row >= box->nrows)) + { + x += length; + row = 0; + length = 0; + } + + length = + MAX (length, (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL) ? child_req.width :child_req.height); + + if (has_label || row >= box->nrows) + { + x += length; + row = 0; + length = 0; + } + else + { + row += 1; + } + } + + x += length; + + if (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL) + { + requisition->width = x; + requisition->height = panel_size; + } + else + { + requisition->width = panel_size; + requisition->height = x; + } + g_debug ("indicator-box size request: w=%d h=%d", requisition->width, requisition->height); +} + + + +static void +xfce_indicator_box_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + XfceIndicatorBox *box = XFCE_INDICATOR_BOX (widget); + GtkWidget *child; + GtkAllocation child_alloc; + GtkRequisition child_req; + gint panel_size, size; + gint x, y; + gint x0, y0; + GSList *li; + gint length, width; + gint row; + gboolean has_label; + + row = 0; + length = 0; + width = 0; + x = y = 0; + x0 = allocation->x; + y0 = allocation->y; + + panel_size = box->panel_size; + size = panel_size / box->nrows; + + for (li = box->children; li != NULL; li = li->next) + { + child = GTK_WIDGET (li->data); + g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child)); + + gtk_widget_get_child_requisition (child, &child_req); + + has_label = (xfce_indicator_button_get_label (XFCE_INDICATOR_BUTTON (child)) != NULL); + + /* wrap rows if column is overflowing or a label is encountered */ + if (row > 0 && (has_label || row >= box->nrows)) + { + x += length; + y = 0; + row = 0; + length = 0; + } + + width = (has_label) ? panel_size : size; + length = MAX (length, + (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL) ? child_req.width :child_req.height); + + if (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL) + { + child_alloc.x = x0 + x; + child_alloc.y = y0 + y; + child_alloc.width = length; + child_alloc.height = width; + } + else + { + child_alloc.x = x0 + y; + child_alloc.y = y0 + x; + child_alloc.width = width; + child_alloc.height = length; + } + + g_debug ("indicator-box size allocate: x=%d y=%d w=%d h=%d", + child_alloc.x, child_alloc.y, child_alloc.width, child_alloc.height); + + gtk_widget_size_allocate (child, &child_alloc); + + if (has_label || row >= box->nrows) + { + x += length; + y = 0; + row = 0; + length = 0; + } + else + { + row += 1; + y += size; + } + } +} + + + diff --git a/panel-plugin/indicator-box.h b/panel-plugin/indicator-box.h new file mode 100644 index 0000000..fafaa37 --- /dev/null +++ b/panel-plugin/indicator-box.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2012 Andrzej + * + * 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 Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __INDICATOR_BOX_H__ +#define __INDICATOR_BOX_H__ + +G_BEGIN_DECLS + +GType xfce_indicator_box_get_type (void); + +#define XFCE_TYPE_INDICATOR_BOX (xfce_indicator_box_get_type()) +#define XFCE_INDICATOR_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XFCE_TYPE_INDICATOR_BOX, XfceIndicatorBox)) +#define XFCE_INDICATOR_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XFCE_TYPE_INDICATOR_BOX, XfceIndicatorBoxClass)) +#define XFCE_IS_INDICATOR_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XFCE_TYPE_INDICATOR_BOX)) +#define XFCE_IS_INDICATOR_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), XFCE_TYPE_INDICATOR_BOX)) +#define XFCE_INDICATOR_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XFCE_TYPE_INDICATOR_BOX, XfceIndicatorBoxClass)) + +typedef struct _XfceIndicatorBox XfceIndicatorBox; +typedef struct _XfceIndicatorBoxClass XfceIndicatorBoxClass; + +struct _XfceIndicatorBox +{ + GtkContainer __parent__; + + GSList *children; + + gint panel_size; + gint nrows; + + GtkOrientation panel_orientation; + GtkOrientation orientation; +}; + +struct _XfceIndicatorBoxClass +{ + GtkContainerClass __parent__; +}; + +void xfce_indicator_box_set_orientation (XfceIndicatorBox *button, + GtkOrientation panel_orientation, + GtkOrientation orientation); + +void xfce_indicator_box_set_size (XfceIndicatorBox *button, + gint panel_size, + gint nrows); + +GtkWidget *xfce_indicator_box_new (); + +G_END_DECLS + +#endif /* !__INDICATOR_BOX_H__ */ diff --git a/panel-plugin/indicator-button.c b/panel-plugin/indicator-button.c index 709f79e..c846848 100644 --- a/panel-plugin/indicator-button.c +++ b/panel-plugin/indicator-button.c @@ -133,7 +133,10 @@ xfce_indicator_button_update_layout (XfceIndicatorButton *button) { gtk_widget_size_request (button->label, &label_size); - if (label_size.width > button->panel_size - icon_size - border_thickness) + /* put icon above the label if number of rows > 1 (they look better) + or if they don't fit when arranged horizontally */ + if (button->panel_size != button->size || + label_size.width > button->panel_size - icon_size - border_thickness) gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box), GTK_ORIENTATION_VERTICAL); else gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box), GTK_ORIENTATION_HORIZONTAL); diff --git a/panel-plugin/indicator.c b/panel-plugin/indicator.c index 2867833..a28e359 100644 --- a/panel-plugin/indicator.c +++ b/panel-plugin/indicator.c @@ -28,6 +28,7 @@ #include #include "indicator.h" +#include "indicator-box.h" #include "indicator-button.h" #define DEFAULT_EXCLUDED_MODULES NULL @@ -146,8 +147,7 @@ indicator_new (XfcePanelPlugin *plugin) INDICATOR_ICONS_DIR); /*gtk_widget_set_name(GTK_WIDGET (indicator->plugin), "indicator-plugin");*/ - indicator->buttonbox = gtk_hbox_new(FALSE,0); - gtk_widget_set_can_focus(GTK_WIDGET(indicator->buttonbox), TRUE); + indicator->buttonbox = xfce_indicator_box_new ();; gtk_rc_parse_string ( "style \"indicator-plugin-style\"\n" "{\n" @@ -157,9 +157,6 @@ indicator_new (XfcePanelPlugin *plugin) " GtkWidget::focus-padding = 0\n" "}\n" "widget \"*.indicator-button\" style \"indicator-plugin-style\""); - - gtk_widget_set_name(GTK_WIDGET (indicator->buttonbox), "indicator-button"); - gtk_container_set_border_width(GTK_CONTAINER(indicator->buttonbox), 0); /* get the list of excluded modules */ indicator_read (indicator); @@ -237,42 +234,26 @@ indicator_mode_changed (XfcePanelPlugin *plugin, XfcePanelPluginMode mode, IndicatorPlugin *indicator) { - GList *buttons; - GList *button; GtkOrientation orientation; GtkOrientation panel_orientation = xfce_panel_plugin_get_orientation (plugin); - gtk_orientable_set_orientation (GTK_ORIENTABLE(indicator->buttonbox), panel_orientation); - orientation = (mode == XFCE_PANEL_PLUGIN_MODE_VERTICAL) ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL; - buttons = gtk_container_get_children (GTK_CONTAINER (indicator->buttonbox)); - for (button = buttons; button != NULL; button = g_list_next (button)) - { - xfce_indicator_button_set_orientation (XFCE_INDICATOR_BUTTON (button->data), - panel_orientation, orientation); - } + xfce_indicator_box_set_orientation (XFCE_INDICATOR_BOX (indicator->buttonbox), panel_orientation, orientation); + indicator_size_changed (plugin, xfce_panel_plugin_get_size (plugin), indicator); } + + #else static void indicator_orientation_changed (XfcePanelPlugin *plugin, GtkOrientation orientation, IndicatorPlugin *indicator) { - GList *buttons; - GList *button; - - gtk_orientable_set_orientation (GTK_ORIENTABLE(indicator->buttonbox), orientation); - - buttons = gtk_container_get_children (GTK_CONTAINER (indicator->buttonbox)); - for (button = buttons; button != NULL; button = g_list_next (button)) - { - xfce_indicator_button_set_orientation (XFCE_INDICATOR_BUTTON (button->data), - orientation, GTK_ORIENTATION_HORIZONTAL); - } + xfce_indicator_box_set_orientation (XFCE_INDICATOR_BOX (indicator->buttonbox), orientation, GTK_ORIENTATION_HORIZONTAL); indicator_size_changed (plugin, xfce_panel_plugin_get_size (plugin), indicator); } @@ -284,30 +265,13 @@ indicator_size_changed (XfcePanelPlugin *plugin, gint size, IndicatorPlugin *indicator) { - GtkOrientation orientation; - GList *buttons; - GList *button; - - /* get the orientation of the plugin */ - orientation = xfce_panel_plugin_get_orientation (plugin); - - /* set the widget size */ - if (orientation == GTK_ORIENTATION_HORIZONTAL) - gtk_widget_set_size_request (GTK_WIDGET (plugin), -1, size); - else - gtk_widget_set_size_request (GTK_WIDGET (plugin), size, -1); - - - buttons = gtk_container_get_children (GTK_CONTAINER (indicator->buttonbox)); - for (button = buttons; button != NULL; button = g_list_next (button)) - { #if LIBXFCE4PANEL_CHECK_VERSION (4,9,0) - xfce_indicator_button_set_size (XFCE_INDICATOR_BUTTON (button->data), - size, size / xfce_panel_plugin_get_nrows (plugin)); + xfce_indicator_box_set_size (XFCE_INDICATOR_BOX (indicator->buttonbox), + size, xfce_panel_plugin_get_nrows (plugin)); #else - xfce_indicator_button_set_size (XFCE_INDICATOR_BUTTON (button->data), size, size); + xfce_indicator_box_set_size (XFCE_INDICATOR_BOX (indicator->buttonbox), + size, 1); #endif - } return TRUE; } @@ -371,11 +335,9 @@ indicator_construct (XfcePanelPlugin *plugin) #if LIBXFCE4PANEL_CHECK_VERSION (4,9,0) g_signal_connect (G_OBJECT (plugin), "mode-changed", G_CALLBACK (indicator_mode_changed), indicator); - indicator_mode_changed (plugin, xfce_panel_plugin_get_mode (plugin), indicator); #else g_signal_connect (G_OBJECT (plugin), "orientation-changed", G_CALLBACK (indicator_orientation_changed), indicator); - indicator_orientation_changed (plugin, xfce_panel_plugin_get_orientation (plugin), indicator); #endif } @@ -422,27 +384,9 @@ entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_d user_data); g_signal_connect(button, "scroll-event", G_CALLBACK(entry_scrolled), user_data); - gtk_box_pack_start(GTK_BOX(((IndicatorPlugin *)user_data)->buttonbox), button, TRUE, TRUE, 0); - gtk_widget_show(button); -#if LIBXFCE4PANEL_CHECK_VERSION (4,9,0) - xfce_indicator_button_set_orientation - (XFCE_INDICATOR_BUTTON (button), - xfce_panel_plugin_get_orientation (plugin), - (xfce_panel_plugin_get_mode (plugin) == XFCE_PANEL_PLUGIN_MODE_VERTICAL) ? - GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); - xfce_indicator_button_set_size - (XFCE_INDICATOR_BUTTON (button), - xfce_panel_plugin_get_size (plugin), - xfce_panel_plugin_get_size (plugin) / xfce_panel_plugin_get_nrows (plugin)); -#else - xfce_indicator_button_set_orientation (XFCE_INDICATOR_BUTTON (button), - xfce_panel_plugin_get_orientation (plugin), - GTK_ORIENTATION_HORIZONTAL); - xfce_indicator_button_set_size (XFCE_INDICATOR_BUTTON (button), - xfce_panel_plugin_get_size (plugin), - xfce_panel_plugin_get_size (plugin)); -#endif + gtk_container_add(XFCE_INDICATOR_BOX (((IndicatorPlugin *)user_data)->buttonbox), button); + gtk_widget_show(button); } -- 1.7.5.4