summaryrefslogtreecommitdiff
path: root/gtk/gtktoolitemgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtktoolitemgroup.c')
-rw-r--r--gtk/gtktoolitemgroup.c2333
1 files changed, 0 insertions, 2333 deletions
diff --git a/gtk/gtktoolitemgroup.c b/gtk/gtktoolitemgroup.c
deleted file mode 100644
index f2c9c51051..0000000000
--- a/gtk/gtktoolitemgroup.c
+++ /dev/null
@@ -1,2333 +0,0 @@
-/* GtkToolPalette -- A tool palette with categories and DnD support
- * Copyright (C) 2008 Openismus GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Mathias Hasselmann
- * Jan Arne Petersen
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <string.h>
-
-#include "gtktoolpaletteprivate.h"
-#include "gtktypebuiltins.h"
-#include "gtkprivate.h"
-#include "gtkintl.h"
-#include "gtkcssnodeprivate.h"
-#include "gtkstylecontextprivate.h"
-#include "gtkwidgetprivate.h"
-
-
-#define ANIMATION_TIMEOUT 50
-#define ANIMATION_DURATION (ANIMATION_TIMEOUT * 4)
-#define DEFAULT_ANIMATION_STATE TRUE
-#define DEFAULT_EXPANDER_SIZE 16
-#define DEFAULT_HEADER_SPACING 2
-
-#define DEFAULT_LABEL ""
-#define DEFAULT_COLLAPSED FALSE
-#define DEFAULT_ELLIPSIZE PANGO_ELLIPSIZE_NONE
-
-/**
- * SECTION:gtktoolitemgroup
- * @Short_description: A sub container used in a tool palette
- * @Title: GtkToolItemGroup
- *
- * A #GtkToolItemGroup is used together with #GtkToolPalette to add
- * #GtkToolItems to a palette like container with different
- * categories and drag and drop support.
- *
- * # CSS nodes
- *
- * GtkToolItemGroup has a single CSS node named toolitemgroup.
- *
- * Since: 2.20
- */
-
-enum
-{
- PROP_NONE,
- PROP_LABEL,
- PROP_LABEL_WIDGET,
- PROP_COLLAPSED,
- PROP_ELLIPSIZE,
- PROP_RELIEF
-};
-
-enum
-{
- CHILD_PROP_NONE,
- CHILD_PROP_HOMOGENEOUS,
- CHILD_PROP_EXPAND,
- CHILD_PROP_FILL,
- CHILD_PROP_NEW_ROW,
- CHILD_PROP_POSITION,
-};
-
-typedef struct _GtkToolItemGroupChild GtkToolItemGroupChild;
-
-struct _GtkToolItemGroupPrivate
-{
- GtkWidget *header;
- GtkWidget *label_widget;
-
- GtkCssNode *arrow_node;
-
- GList *children;
-
- gint64 animation_start;
- GSource *animation_timeout;
-
- gulong focus_set_id;
- GtkWidget *toplevel;
-
- GtkSettings *settings;
- gulong settings_connection;
-
- PangoEllipsizeMode ellipsize;
-
- guint animation : 1;
- guint collapsed : 1;
-};
-
-struct _GtkToolItemGroupChild
-{
- GtkToolItem *item;
-
- guint homogeneous : 1;
- guint expand : 1;
- guint fill : 1;
- guint new_row : 1;
-};
-
-static void gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (GtkToolItemGroup, gtk_tool_item_group, GTK_TYPE_CONTAINER,
- G_ADD_PRIVATE (GtkToolItemGroup)
- G_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL,
- gtk_tool_item_group_tool_shell_init));
-
-static GtkWidget*
-gtk_tool_item_group_get_frame (GtkToolItemGroup *group)
-{
- return gtk_bin_get_child (GTK_BIN (group->priv->header));
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_orientation (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_orientable_get_orientation (GTK_ORIENTABLE (parent));
-
- return GTK_ORIENTATION_VERTICAL;
-}
-
-static GtkToolbarStyle
-gtk_tool_item_group_get_style (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_style (GTK_TOOL_PALETTE (parent));
-
- return GTK_TOOLBAR_ICONS;
-}
-
-static PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize_mode (GtkToolShell *shell)
-{
- return GTK_TOOL_ITEM_GROUP (shell)->priv->ellipsize;
-}
-
-static gfloat
-gtk_tool_item_group_get_text_alignment (GtkToolShell *shell)
-{
- if (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell) ||
- GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell))
- return 0.0;
-
- return 0.5;
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_text_orientation (GtkToolShell *shell)
-{
- return GTK_ORIENTATION_HORIZONTAL;
-}
-
-static GtkSizeGroup *
-gtk_tool_item_group_get_text_size_group (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return _gtk_tool_palette_get_size_group (GTK_TOOL_PALETTE (parent));
-
- return NULL;
-}
-
-static void
-animation_change_notify (GtkToolItemGroup *group)
-{
- GtkSettings *settings = group->priv->settings;
- gboolean animation;
-
- if (settings)
- g_object_get (settings,
- "gtk-enable-animations", &animation,
- NULL);
- else
- animation = DEFAULT_ANIMATION_STATE;
-
- group->priv->animation = animation;
-}
-
-static void
-gtk_tool_item_group_settings_change_notify (GtkSettings *settings,
- const GParamSpec *pspec,
- GtkToolItemGroup *group)
-{
- if (strcmp (pspec->name, "gtk-enable-animations") == 0)
- animation_change_notify (group);
-}
-
-static void
-gtk_tool_item_group_display_changed (GtkWidget *widget,
- GdkDisplay *previous_display)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkSettings *old_settings = priv->settings;
- GtkSettings *settings;
-
- settings = gtk_widget_get_settings (GTK_WIDGET (group));
-
- if (settings == old_settings)
- return;
-
- if (old_settings)
- {
- g_signal_handler_disconnect (old_settings, priv->settings_connection);
- priv->settings_connection = 0;
- g_object_unref (old_settings);
- }
-
- if (settings)
- {
- priv->settings_connection =
- g_signal_connect (settings, "notify",
- G_CALLBACK (gtk_tool_item_group_settings_change_notify),
- group);
- priv->settings = g_object_ref (settings);
- }
- else
- priv->settings = NULL;
-
- animation_change_notify (group);
-}
-
-static void
-gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface)
-{
- iface->get_orientation = gtk_tool_item_group_get_orientation;
- iface->get_style = gtk_tool_item_group_get_style;
- iface->get_text_alignment = gtk_tool_item_group_get_text_alignment;
- iface->get_text_orientation = gtk_tool_item_group_get_text_orientation;
- iface->get_text_size_group = gtk_tool_item_group_get_text_size_group;
- iface->get_ellipsize_mode = gtk_tool_item_group_get_ellipsize_mode;
-}
-
-static gboolean
-gtk_tool_item_group_header_draw_cb (GtkWidget *widget,
- cairo_t *cr,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkOrientation orientation;
- gint x, y, width, height;
- GtkTextDirection direction;
- GtkStyleContext *context;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- direction = gtk_widget_get_direction (widget);
- width = gtk_widget_get_allocated_width (widget);
- height = gtk_widget_get_allocated_height (widget);
- context = gtk_widget_get_style_context (widget);
-
- gtk_style_context_save_to_node (context, priv->arrow_node);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- gtk_style_context_add_class (context, GTK_STYLE_CLASS_VERTICAL);
-
- if (GTK_TEXT_DIR_RTL == direction)
- x = width;
- else
- x = 0;
-
- y = height / 2 - (DEFAULT_EXPANDER_SIZE / 2);
- }
- else
- {
- gtk_style_context_add_class (context, GTK_STYLE_CLASS_HORIZONTAL);
- x = width / 2 - (DEFAULT_EXPANDER_SIZE / 2);
- y = 0;
- }
-
- gtk_render_expander (context, cr, x, y,
- DEFAULT_EXPANDER_SIZE,
- DEFAULT_EXPANDER_SIZE);
-
- gtk_style_context_restore (context);
-
- return FALSE;
-}
-
-static void
-gtk_tool_item_group_header_clicked_cb (GtkButton *button,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkWidget *parent = gtk_widget_get_parent (data);
-
- if (priv->collapsed ||
- !GTK_IS_TOOL_PALETTE (parent) ||
- !gtk_tool_palette_get_exclusive (GTK_TOOL_PALETTE (parent), data))
- gtk_tool_item_group_set_collapsed (group, !priv->collapsed);
-}
-
-static void
-gtk_tool_item_group_header_adjust_style (GtkToolItemGroup *group)
-{
- GtkWidget *frame = gtk_bin_get_child (GTK_BIN (group->priv->header));
- GtkWidget *label_widget = gtk_bin_get_child (GTK_BIN (frame));
- GtkToolItemGroupPrivate* priv = group->priv;
- gint dx = 0, dy = 0;
-
- switch (gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)))
- {
- case GTK_ORIENTATION_HORIZONTAL:
- dy = DEFAULT_HEADER_SPACING + DEFAULT_EXPANDER_SIZE;
-
- if (GTK_IS_LABEL (label_widget))
- {
- gtk_label_set_ellipsize (GTK_LABEL (label_widget), PANGO_ELLIPSIZE_NONE);
- }
- break;
-
- case GTK_ORIENTATION_VERTICAL:
- dx = DEFAULT_HEADER_SPACING + DEFAULT_EXPANDER_SIZE;
-
- if (GTK_IS_LABEL (label_widget))
- {
- gtk_label_set_ellipsize (GTK_LABEL (label_widget), priv->ellipsize);
- }
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
-
- gtk_widget_set_margin_start (frame, dx);
- gtk_widget_set_margin_top (frame, dy);
-}
-
-static void
-update_arrow_state (GtkToolItemGroup *group)
-{
- GtkToolItemGroupPrivate *priv = group->priv;
- GtkStateFlags state;
-
- state = gtk_widget_get_state_flags (GTK_WIDGET (group));
-
- if (priv->collapsed)
- state &= ~GTK_STATE_FLAG_CHECKED;
- else
- state |= GTK_STATE_FLAG_CHECKED;
- gtk_css_node_set_state (priv->arrow_node, state);
-}
-
-static void
-gtk_tool_item_group_init (GtkToolItemGroup *group)
-{
- GtkWidget *frame;
- GtkToolItemGroupPrivate* priv;
- GtkCssNode *widget_node;
-
- gtk_widget_set_has_window (GTK_WIDGET (group), FALSE);
-
- group->priv = priv = gtk_tool_item_group_get_instance_private (group);
-
- priv->children = NULL;
- priv->collapsed = DEFAULT_COLLAPSED;
-
- priv->label_widget = gtk_label_new (NULL);
- gtk_widget_set_halign (priv->label_widget, GTK_ALIGN_START);
- gtk_widget_set_valign (priv->label_widget, GTK_ALIGN_CENTER);
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
- gtk_container_add (GTK_CONTAINER (frame), priv->label_widget);
-
- priv->header = gtk_button_new ();
- g_object_ref_sink (priv->header);
- gtk_widget_set_focus_on_click (priv->header, FALSE);
- gtk_container_add (GTK_CONTAINER (priv->header), frame);
- gtk_widget_set_parent (priv->header, GTK_WIDGET (group));
-
- gtk_tool_item_group_header_adjust_style (group);
-
- g_signal_connect_after (frame, "draw",
- G_CALLBACK (gtk_tool_item_group_header_draw_cb),
- group);
-
- g_signal_connect (priv->header, "clicked",
- G_CALLBACK (gtk_tool_item_group_header_clicked_cb),
- group);
-
- widget_node = gtk_widget_get_css_node (GTK_WIDGET (group));
- priv->arrow_node = gtk_css_node_new ();
- gtk_css_node_set_name (priv->arrow_node, I_("arrow"));
- gtk_css_node_set_parent (priv->arrow_node, widget_node);
- gtk_css_node_set_state (priv->arrow_node, gtk_css_node_get_state (widget_node));
- g_object_unref (priv->arrow_node);
-
- update_arrow_state (group);
-}
-
-static void
-gtk_tool_item_group_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_LABEL:
- gtk_tool_item_group_set_label (group, g_value_get_string (value));
- break;
-
- case PROP_LABEL_WIDGET:
- gtk_tool_item_group_set_label_widget (group, g_value_get_object (value));
- break;
-
- case PROP_COLLAPSED:
- gtk_tool_item_group_set_collapsed (group, g_value_get_boolean (value));
- break;
-
- case PROP_ELLIPSIZE:
- gtk_tool_item_group_set_ellipsize (group, g_value_get_enum (value));
- break;
-
- case PROP_RELIEF:
- gtk_tool_item_group_set_header_relief (group, g_value_get_enum(value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_LABEL:
- g_value_set_string (value, gtk_tool_item_group_get_label (group));
- break;
-
- case PROP_LABEL_WIDGET:
- g_value_set_object (value,
- gtk_tool_item_group_get_label_widget (group));
- break;
-
- case PROP_COLLAPSED:
- g_value_set_boolean (value, gtk_tool_item_group_get_collapsed (group));
- break;
-
- case PROP_ELLIPSIZE:
- g_value_set_enum (value, gtk_tool_item_group_get_ellipsize (group));
- break;
-
- case PROP_RELIEF:
- g_value_set_enum (value, gtk_tool_item_group_get_header_relief (group));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_finalize (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- g_list_free (group->priv->children);
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->finalize (object);
-}
-
-static void
-gtk_tool_item_group_dispose (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
- GtkToolItemGroupPrivate* priv = group->priv;
-
- if (priv->toplevel)
- {
- /* disconnect focus tracking handler */
- g_signal_handler_disconnect (priv->toplevel,
- priv->focus_set_id);
-
- priv->focus_set_id = 0;
- priv->toplevel = NULL;
- }
-
- if (priv->settings_connection > 0)
- {
- g_signal_handler_disconnect (priv->settings, priv->settings_connection);
- priv->settings_connection = 0;
- }
-
- g_clear_object (&priv->settings);
- if (priv->header)
- gtk_widget_unparent (priv->header);
- g_clear_object (&priv->header);
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->dispose (object);
-}
-
-static void
-gtk_tool_item_group_get_item_size (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_get_item_size (GTK_TOOL_PALETTE (parent), item_size, homogeneous_only, requested_rows);
- else
- _gtk_tool_item_group_item_size_request (group, item_size, homogeneous_only, requested_rows);
-}
-
-static void
-gtk_tool_item_group_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkOrientation orientation;
- GtkRequisition item_size;
- gint requested_rows;
-
- if (priv->children && gtk_tool_item_group_get_label_widget (group))
- {
- gtk_widget_get_preferred_size (priv->header,
- requisition, NULL);
- gtk_widget_show (priv->header);
- }
- else
- {
- requisition->width = requisition->height = 0;
- gtk_widget_hide (priv->header);
- }
-
- gtk_tool_item_group_get_item_size (group, &item_size, FALSE, &requested_rows);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- requisition->width = MAX (requisition->width, item_size.width);
- else
- requisition->height = MAX (requisition->height, item_size.height * requested_rows);
-}
-
-static void
-gtk_tool_item_group_measure (GtkWidget *widget,
- GtkOrientation orientation,
- int for_size,
- int *minimum,
- int *natural,
- int *minimum_baseline,
- int *natural_baseline)
-{
- GtkRequisition requisition;
-
- gtk_tool_item_group_size_request (widget, &requisition);
-
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- *minimum = *natural = requisition.width;
- else
- *minimum = *natural = requisition.height;
-}
-
-static gboolean
-gtk_tool_item_group_is_item_visible (GtkToolItemGroup *group,
- GtkToolItemGroupChild *child)
-{
- GtkToolbarStyle style;
- GtkOrientation orientation;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* horizontal tool palettes with text style support only homogeneous items */
- if (!child->homogeneous &&
- GTK_ORIENTATION_HORIZONTAL == orientation &&
- GTK_TOOLBAR_TEXT == style)
- return FALSE;
-
- return
- (gtk_widget_get_visible (GTK_WIDGET (child->item))) &&
- (GTK_ORIENTATION_VERTICAL == orientation ?
- gtk_tool_item_get_visible_vertical (child->item) :
- gtk_tool_item_get_visible_horizontal (child->item));
-}
-
-static inline unsigned
-udiv (unsigned x,
- unsigned y)
-{
- return (x + y - 1) / y;
-}
-
-static void
-gtk_tool_item_group_real_size_query (GtkWidget *widget,
- GtkAllocation *allocation,
- GtkRequisition *inquery)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkToolItemGroupPrivate* priv = group->priv;
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
-
- gint min_rows;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- item_size.width = MIN (item_size.width, allocation->width);
- else
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_size.width = MAX (item_size.width, 1);
- item_size.height = MAX (item_size.height, 1);
-
- item_area.width = 0;
- item_area.height = 0;
-
- /* figure out the required columns (n_columns) and rows (n_rows)
- * to place all items
- */
- if (!priv->collapsed || !priv->animation || priv->animation_timeout)
- {
- guint n_columns;
- gint n_rows;
- GList *it;
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- gboolean new_row = FALSE;
- gint row = -1;
- guint col = 0;
-
- item_area.width = allocation->width;
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- /* calculate required rows for n_columns columns */
- for (it = priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_get_preferred_size (GTK_WIDGET (child->item),
- &req, NULL);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
- n_rows = row + 2;
- }
- else
- {
- guint *row_min_width;
- gint row = -1;
- gboolean new_row = TRUE;
- guint col = 0, min_col, max_col = 0, all_items = 0;
- gint i;
-
- item_area.height = allocation->height;
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- row_min_width = g_new0 (guint, n_rows);
-
- /* calculate minimal and maximal required cols and minimal
- * required rows
- */
- for (it = priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- row_min_width[row] = 1;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- all_items++;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_get_preferred_size (GTK_WIDGET (child->item),
- &req, NULL);
-
- width = udiv (req.width, item_size.width);
-
- col += width;
- all_items += width;
-
- row_min_width[row] = MAX (row_min_width[row], width);
- }
-
- max_col = MAX (max_col, col);
- }
-
- /* calculate minimal required cols */
- min_col = udiv (all_items, n_rows);
-
- for (i = 0; i <= row; i++)
- {
- min_col = MAX (min_col, row_min_width[i]);
- }
-
- /* simple linear search for minimal required columns
- * for the given maximal number of rows (n_rows)
- */
- for (n_columns = min_col; n_columns < max_col; n_columns ++)
- {
- new_row = TRUE;
- row = -1;
- /* calculate required rows for n_columns columns */
- for (it = priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_get_preferred_size (GTK_WIDGET (child->item),
- &req, NULL);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
-
- if (row < n_rows)
- break;
- }
- }
-
- item_area.width = item_size.width * n_columns;
- item_area.height = item_size.height * n_rows;
- }
-
- inquery->width = 0;
- inquery->height = 0;
-
- /* figure out header widget size */
- if (gtk_widget_get_visible (priv->header))
- {
- GtkRequisition child_requisition;
-
- gtk_widget_get_preferred_size (priv->header,
- &child_requisition, NULL);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- inquery->height += child_requisition.height;
- else
- inquery->width += child_requisition.width;
- }
-
- /* report effective widget size */
- inquery->width += item_area.width;
- inquery->height += item_area.height;
-}
-
-static void
-gtk_tool_item_group_real_size_allocate (GtkWidget *widget,
- const GtkAllocation *allocation,
- int baseline,
- GtkAllocation *out_clip)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkRequisition child_requisition;
- GtkAllocation child_allocation;
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
-
- GList *it;
-
- gint n_columns, n_rows = 1;
- gint min_rows;
- GtkTextDirection direction;
-
- direction = gtk_widget_get_direction (widget);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- /* chain up */
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->size_allocate (widget, allocation,
- baseline, out_clip);
-
- child_allocation.x = 0;
- child_allocation.y = 0;
-
- /* place the header widget */
- if (gtk_widget_get_visible (priv->header))
- {
- gtk_widget_get_preferred_size (priv->header,
- &child_requisition, NULL);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- child_allocation.width = allocation->width;
- child_allocation.height = child_requisition.height;
- }
- else
- {
- child_allocation.width = child_requisition.width;
- child_allocation.height = allocation->height;
-
- if (GTK_TEXT_DIR_RTL == direction)
- child_allocation.x = allocation->width - child_allocation.width;
- }
-
- gtk_widget_size_allocate (priv->header, &child_allocation, -1, out_clip);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- child_allocation.y += child_allocation.height;
- else if (GTK_TEXT_DIR_RTL != direction)
- child_allocation.x += child_allocation.width;
- else
- child_allocation.x = 0;
- }
- else
- child_requisition.width = child_requisition.height = 0;
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- item_size.width = MAX (item_size.width, 1);
- item_size.height = MAX (item_size.height, 1);
-
- /* figure out the available columns and size of item_area */
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- item_size.width = MIN (item_size.width, allocation->width);
-
- item_area.width = allocation->width;
- item_area.height = allocation->height - child_requisition.height;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- item_size.width = item_area.width / n_columns;
- }
- else
- {
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_area.width = allocation->width - child_requisition.width;
- item_area.height = allocation->height;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- item_size.height = item_area.height / n_rows;
- }
-
- item_area.x = child_allocation.x;
- item_area.y = child_allocation.y;
-
- /* when expanded or in transition, place the tool items in a grid like layout */
- if (!priv->collapsed || !priv->animation || priv->animation_timeout)
- {
- gint col = 0, row = 0;
-
- for (it = priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- gint col_child;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- {
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
-
- continue;
- }
-
- /* for non homogeneous widgets request the required size */
- child_requisition.width = 0;
-
- if (!child->homogeneous)
- {
- gtk_widget_get_preferred_size (GTK_WIDGET (child->item),
- &child_requisition, NULL);
- child_requisition.width = MIN (child_requisition.width, item_area.width);
- }
-
- /* select next row if at end of row */
- if (col > 0 && (child->new_row || (col * item_size.width) + MAX (child_requisition.width, item_size.width) > item_area.width))
- {
- row++;
- col = 0;
- child_allocation.y += child_allocation.height;
- }
-
- col_child = col;
-
- /* calculate the position and size of the item */
- if (!child->homogeneous)
- {
- gint col_width;
- gint width;
-
- if (!child->expand)
- col_width = udiv (child_requisition.width, item_size.width);
- else
- col_width = n_columns - col;
-
- width = col_width * item_size.width;
-
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - col_width);
-
- if (child->fill)
- {
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = width;
- }
- else
- {
- child_allocation.x =
- (item_area.x + col_child * item_size.width +
- (width - child_requisition.width) / 2);
- child_allocation.width = child_requisition.width;
- }
-
- col += col_width;
- }
- else
- {
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - 1);
-
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = item_size.width;
-
- col++;
- }
-
- child_allocation.height = item_size.height;
-
- gtk_widget_size_allocate (GTK_WIDGET (child->item), &child_allocation, -1, out_clip);
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), TRUE);
- }
-
- child_allocation.y += item_size.height;
- }
-
- /* or just hide all items, when collapsed */
-
- else
- {
- for (it = priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
- }
- }
-}
-
-static void
-gtk_tool_item_group_size_allocate (GtkWidget *widget,
- const GtkAllocation *allocation,
- int baseline,
- GtkAllocation *out_clip)
-{
- gtk_tool_item_group_real_size_allocate (widget, allocation, baseline, out_clip);
-}
-
-static void
-gtk_tool_item_group_set_focus_cb (GtkWidget *window,
- GtkWidget *widget,
- gpointer user_data)
-{
- GtkAdjustment *adjustment;
- GtkAllocation allocation, p_allocation;
- GtkWidget *p;
-
- /* Find this group's parent widget in the focused widget's anchestry. */
- for (p = widget; p; p = gtk_widget_get_parent (p))
- if (p == user_data)
- {
- p = gtk_widget_get_parent (p);
- break;
- }
-
- if (GTK_IS_TOOL_PALETTE (p))
- {
- /* Check that the focused widgets is fully visible within
- * the group's parent widget and make it visible otherwise. */
-
- adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (p));
-
- if (adjustment)
- {
- int y;
-
- gtk_widget_get_allocation (widget, &allocation);
- gtk_widget_get_allocation (p, &p_allocation);
-
- /* Handle vertical adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, NULL, &y) && y < 0)
- {
- y += gtk_adjustment_get_value (adjustment);
- gtk_adjustment_clamp_page (adjustment, y, y + allocation.height);
- }
- else if (gtk_widget_translate_coordinates (widget, p, 0, allocation.height, NULL, &y) &&
- y > p_allocation.height)
- {
- y += gtk_adjustment_get_value (adjustment);
- gtk_adjustment_clamp_page (adjustment, y - allocation.height, y);
- }
- }
-
- adjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (p));
-
- if (adjustment)
- {
- int x;
-
- gtk_widget_get_allocation (widget, &allocation);
- gtk_widget_get_allocation (p, &p_allocation);
-
- /* Handle horizontal adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, &x, NULL) && x < 0)
- {
- x += gtk_adjustment_get_value (adjustment);
- gtk_adjustment_clamp_page (adjustment, x, x + allocation.width);
- }
- else if (gtk_widget_translate_coordinates (widget, p, allocation.width, 0, &x, NULL) &&
- x > p_allocation.width)
- {
- x += gtk_adjustment_get_value (adjustment);
- gtk_adjustment_clamp_page (adjustment, x - allocation.width, x);
- }
-
- return;
- }
- }
-}
-
-static void
-gtk_tool_item_group_set_toplevel_window (GtkToolItemGroup *group,
- GtkWidget *toplevel)
-{
- GtkToolItemGroupPrivate* priv = group->priv;
-
- if (toplevel != priv->toplevel)
- {
- if (priv->toplevel)
- {
- /* Disconnect focus tracking handler. */
- g_signal_handler_disconnect (priv->toplevel,
- priv->focus_set_id);
-
- priv->focus_set_id = 0;
- priv->toplevel = NULL;
- }
-
- if (toplevel)
- {
- /* Install focus tracking handler. We connect to the window's
- * set-focus signal instead of connecting to the focus signal of
- * each child to:
- *
- * 1) Reduce the number of signal handlers used.
- * 2) Avoid special handling for group headers.
- * 3) Catch focus grabs not only for direct children,
- * but also for nested widgets.
- */
- priv->focus_set_id =
- g_signal_connect (toplevel, "set-focus",
- G_CALLBACK (gtk_tool_item_group_set_focus_cb),
- group);
-
- priv->toplevel = toplevel;
- }
- }
-}
-
-static void
-gtk_tool_item_group_realize (GtkWidget *widget)
-{
- GtkWidget *toplevel_window;
-
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->realize (widget);
-
- toplevel_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget),
- toplevel_window);
-}
-
-static void
-gtk_tool_item_group_unrealize (GtkWidget *widget)
-{
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget), NULL);
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->unrealize (widget);
-}
-
-static void
-gtk_tool_item_group_style_updated (GtkWidget *widget)
-{
- gtk_tool_item_group_header_adjust_style (GTK_TOOL_ITEM_GROUP (widget));
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->style_updated (widget);
-}
-
-static void
-gtk_tool_item_group_state_flags_changed (GtkWidget *widget,
- GtkStateFlags previous_flags)
-{
- update_arrow_state (GTK_TOOL_ITEM_GROUP (widget));
-}
-
-static void
-gtk_tool_item_group_add (GtkContainer *container,
- GtkWidget *widget)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- g_return_if_fail (GTK_IS_TOOL_ITEM (widget));
-
- gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (container),
- GTK_TOOL_ITEM (widget), -1);
-}
-
-static void
-gtk_tool_item_group_remove (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolItemGroup *group;
- GtkToolItemGroupPrivate* priv;
- GList *it;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- group = GTK_TOOL_ITEM_GROUP (container);
- priv = group->priv;
-
- for (it = priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child_info = it->data;
-
- if ((GtkWidget *)child_info->item == child)
- {
- g_object_unref (child);
- gtk_widget_unparent (child);
-
- g_free (child_info);
- priv->children = g_list_delete_link (priv->children, it);
-
- gtk_widget_queue_resize (GTK_WIDGET (container));
- break;
- }
- }
-}
-
-static void
-gtk_tool_item_group_forall (GtkContainer *container,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItemGroupPrivate* priv = group->priv;
- GList *children;
-
- children = priv->children;
- while (children)
- {
- GtkToolItemGroupChild *child = children->data;
- children = children->next; /* store pointer before call to callback
- because the child pointer is invalid if the
- child->item is removed from the item group
- in callback */
-
- callback (GTK_WIDGET (child->item), callback_data);
- }
-}
-
-static GType
-gtk_tool_item_group_child_type (GtkContainer *container)
-{
- return GTK_TYPE_TOOL_ITEM;
-}
-
-static GtkToolItemGroupChild *
-gtk_tool_item_group_get_child (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint *position,
- GList **link)
-{
- guint i;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), NULL);
-
- for (it = group->priv->children, i = 0; it != NULL; it = it->next, ++i)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (child->item == item)
- {
- if (position)
- *position = i;
-
- if (link)
- *link = it;
-
- return child;
- }
- }
-
- return NULL;
-}
-
-static void
-gtk_tool_item_group_get_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean *homogeneous,
- gboolean *expand,
- gboolean *fill,
- gboolean *new_row)
-{
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- if (expand)
- *expand = child->expand;
-
- if (homogeneous)
- *homogeneous = child->homogeneous;
-
- if (fill)
- *fill = child->fill;
-
- if (new_row)
- *new_row = child->new_row;
-}
-
-static void
-gtk_tool_item_group_set_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean homogeneous,
- gboolean expand,
- gboolean fill,
- gboolean new_row)
-{
- GtkToolItemGroupChild *child;
- gboolean changed = FALSE;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- gtk_widget_freeze_child_notify (GTK_WIDGET (item));
-
- if (child->homogeneous != homogeneous)
- {
- child->homogeneous = homogeneous;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "homogeneous");
- }
- if (child->expand != expand)
- {
- child->expand = expand;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "expand");
- }
- if (child->fill != fill)
- {
- child->fill = fill;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "fill");
- }
- if (child->new_row != new_row)
- {
- child->new_row = new_row;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "new-row");
- }
-
- gtk_widget_thaw_child_notify (GTK_WIDGET (item));
-
- if (changed
- && gtk_widget_get_visible (GTK_WIDGET (group))
- && gtk_widget_get_visible (GTK_WIDGET (item)))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-static void
-gtk_tool_item_group_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- gtk_tool_item_group_set_item_packing (group, item,
- g_value_get_boolean (value),
- expand,
- fill,
- new_row);
- break;
-
- case CHILD_PROP_EXPAND:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- g_value_get_boolean (value),
- fill,
- new_row);
- break;
-
- case CHILD_PROP_FILL:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- g_value_get_boolean (value),
- new_row);
- break;
-
- case CHILD_PROP_NEW_ROW:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- fill,
- g_value_get_boolean (value));
- break;
-
- case CHILD_PROP_POSITION:
- gtk_tool_item_group_set_item_position (group, item, g_value_get_int (value));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- g_value_set_boolean (value, homogeneous);
- break;
-
- case CHILD_PROP_EXPAND:
- g_value_set_boolean (value, expand);
- break;
-
- case CHILD_PROP_FILL:
- g_value_set_boolean (value, fill);
- break;
-
- case CHILD_PROP_NEW_ROW:
- g_value_set_boolean (value, new_row);
- break;
-
- case CHILD_PROP_POSITION:
- g_value_set_int (value, gtk_tool_item_group_get_item_position (group, item));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_class_init (GtkToolItemGroupClass *cls)
-{
- GObjectClass *oclass = G_OBJECT_CLASS (cls);
- GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
- GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
-
- oclass->set_property = gtk_tool_item_group_set_property;
- oclass->get_property = gtk_tool_item_group_get_property;
- oclass->finalize = gtk_tool_item_group_finalize;
- oclass->dispose = gtk_tool_item_group_dispose;
-
- wclass->measure = gtk_tool_item_group_measure;
- wclass->size_allocate = gtk_tool_item_group_size_allocate;
- wclass->realize = gtk_tool_item_group_realize;
- wclass->unrealize = gtk_tool_item_group_unrealize;
- wclass->style_updated = gtk_tool_item_group_style_updated;
- wclass->display_changed = gtk_tool_item_group_display_changed;
- wclass->state_flags_changed = gtk_tool_item_group_state_flags_changed;
-
- cclass->add = gtk_tool_item_group_add;
- cclass->remove = gtk_tool_item_group_remove;
- cclass->forall = gtk_tool_item_group_forall;
- cclass->child_type = gtk_tool_item_group_child_type;
- cclass->set_child_property = gtk_tool_item_group_set_child_property;
- cclass->get_child_property = gtk_tool_item_group_get_child_property;
-
- g_object_class_install_property (oclass, PROP_LABEL,
- g_param_spec_string ("label",
- P_("Label"),
- P_("The human-readable title of this item group"),
- DEFAULT_LABEL,
- GTK_PARAM_READWRITE));
-
- g_object_class_install_property (oclass, PROP_LABEL_WIDGET,
- g_param_spec_object ("label-widget",
- P_("Label widget"),
- P_("A widget to display in place of the usual label"),
- GTK_TYPE_WIDGET,
- GTK_PARAM_READWRITE));
-
- g_object_class_install_property (oclass, PROP_COLLAPSED,
- g_param_spec_boolean ("collapsed",
- P_("Collapsed"),
- P_("Whether the group has been collapsed and items are hidden"),
- DEFAULT_COLLAPSED,
- GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
- g_object_class_install_property (oclass, PROP_ELLIPSIZE,
- g_param_spec_enum ("ellipsize",
- P_("ellipsize"),
- P_("Ellipsize for item group headers"),
- PANGO_TYPE_ELLIPSIZE_MODE, DEFAULT_ELLIPSIZE,
- GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
- g_object_class_install_property (oclass, PROP_RELIEF,
- g_param_spec_enum ("header-relief",
- P_("Header Relief"),
- P_("Relief of the group header button"),
- GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NORMAL,
- GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_HOMOGENEOUS,
- g_param_spec_boolean ("homogeneous",
- P_("Homogeneous"),
- P_("Whether the item should be the same size as other homogeneous items"),
- TRUE,
- GTK_PARAM_READWRITE));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND,
- g_param_spec_boolean ("expand",
- P_("Expand"),
- P_("Whether the item should receive extra space when the group grows"),
- FALSE,
- GTK_PARAM_READWRITE));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_FILL,
- g_param_spec_boolean ("fill",
- P_("Fill"),
- P_("Whether the item should fill the available space"),
- TRUE,
- GTK_PARAM_READWRITE));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_NEW_ROW,
- g_param_spec_boolean ("new-row",
- P_("New Row"),
- P_("Whether the item should start a new row"),
- FALSE,
- GTK_PARAM_READWRITE));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_POSITION,
- g_param_spec_int ("position",
- P_("Position"),
- P_("Position of the item within this group"),
- 0,
- G_MAXINT,
- 0,
- GTK_PARAM_READWRITE));
-
- gtk_widget_class_set_css_name (wclass, I_("toolitemgroup"));
-}
-
-/**
- * gtk_tool_item_group_new:
- * @label: the label of the new group
- *
- * Creates a new tool item group with label @label.
- *
- * Returns: a new #GtkToolItemGroup.
- *
- * Since: 2.20
- */
-GtkWidget*
-gtk_tool_item_group_new (const gchar *label)
-{
- return g_object_new (GTK_TYPE_TOOL_ITEM_GROUP, "label", label, NULL);
-}
-
-/**
- * gtk_tool_item_group_set_label:
- * @group: a #GtkToolItemGroup
- * @label: the new human-readable label of of the group
- *
- * Sets the label of the tool item group. The label is displayed in the header
- * of the group.
- *
- * Since: 2.20
- */
-void
-gtk_tool_item_group_set_label (GtkToolItemGroup *group,
- const gchar *label)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- if (!label)
- gtk_tool_item_group_set_label_widget (group, NULL);
- else
- {
- GtkWidget *child = gtk_label_new (label);
- gtk_widget_show (child);
-
- gtk_tool_item_group_set_label_widget (group, child);
- }
-
- g_object_notify (G_OBJECT (group), "label");
-}
-
-/**
- * gtk_tool_item_group_set_label_widget:
- * @group: a #GtkToolItemGroup
- * @label_widget: the widget to be displayed in place of the usual label
- *
- * Sets the label of the tool item group.
- * The label widget is displayed in the header of the group, in place
- * of the usual label.
- *
- * Since: 2.20
- */
-void
-gtk_tool_item_group_set_label_widget (GtkToolItemGroup *group,
- GtkWidget *label_widget)
-{
- GtkToolItemGroupPrivate* priv;
- GtkWidget *frame;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
- g_return_if_fail (label_widget == NULL || gtk_widget_get_parent (label_widget) == NULL);
-
- priv = group->priv;
-
- if (priv->label_widget == label_widget)
- return;
-
- frame = gtk_tool_item_group_get_frame (group);
-
- if (priv->label_widget)
- {
- gtk_widget_set_state_flags (priv->label_widget, 0, TRUE);
- gtk_container_remove (GTK_CONTAINER (frame), priv->label_widget);
- }
-
-
- if (label_widget)
- gtk_container_add (GTK_CONTAINER (frame), label_widget);
-
- priv->label_widget = label_widget;
-
- if (gtk_widget_get_visible (GTK_WIDGET (group)))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-
- /* Only show the header widget if the group has children: */
- if (label_widget && priv->children)
- gtk_widget_show (priv->header);
- else
- gtk_widget_hide (priv->header);
-
- g_object_freeze_notify (G_OBJECT (group));
- g_object_notify (G_OBJECT (group), "label-widget");
- g_object_notify (G_OBJECT (group), "label");
- g_object_thaw_notify (G_OBJECT (group));
-}
-
-/**
- * gtk_tool_item_group_set_header_relief:
- * @group: a #GtkToolItemGroup
- * @style: the #GtkReliefStyle
- *
- * Set the button relief of the group header.
- * See gtk_button_set_relief() for details.
- *
- * Since: 2.20
- */
-void
-gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group,
- GtkReliefStyle style)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- if (gtk_button_get_relief (GTK_BUTTON (group->priv->header)) != style)
- {
- gtk_button_set_relief (GTK_BUTTON (group->priv->header), style);
- g_object_notify (G_OBJECT (group), "header-relief");
- }
-}
-
-static gint64
-gtk_tool_item_group_get_animation_timestamp (GtkToolItemGroup *group)
-{
- return (g_source_get_time (group->priv->animation_timeout) -
- group->priv->animation_start) / 1000;
-}
-
-static void
-gtk_tool_item_group_force_expose (GtkToolItemGroup *group)
-{
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkWidget *widget = GTK_WIDGET (group);
-
- if (gtk_widget_get_realized (priv->header))
- {
- GtkAllocation frame_allocation;
- GtkWidget *frame = gtk_tool_item_group_get_frame (group);
-
- /* Find the header button's arrow area and
- * invalidate it to get it animated. */
- gtk_widget_get_allocation (frame, &frame_allocation);
- gtk_widget_queue_draw_area (priv->header,
- frame_allocation.x,
- frame_allocation.y + (frame_allocation.height - DEFAULT_EXPANDER_SIZE) / 2,
- DEFAULT_EXPANDER_SIZE,
- DEFAULT_EXPANDER_SIZE);
- }
-
- if (gtk_widget_get_realized (widget))
- {
- GtkAllocation allocation;
- GtkWidget *parent = gtk_widget_get_parent (widget);
- int x, y, width, height;
-
- /* Find the tool item area button's arrow area... */
- gtk_widget_get_allocation (widget, &allocation);
- width = allocation.width;
- height = allocation.height;
-
- gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y);
-
- if (gtk_widget_get_visible (priv->header))
- {
- GtkAllocation header_allocation;
-
- gtk_widget_get_allocation (priv->header, &header_allocation);
- height -= header_allocation.height;
- y += header_allocation.height;
- }
-
- /* ... and invalidated it to get it animated. */
- gtk_widget_queue_draw_area (parent, x, y, width, height);
- }
-}
-
-static gboolean
-gtk_tool_item_group_animation_cb (gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkToolItemGroupPrivate* priv = group->priv;
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
- gboolean retval;
-
- gdk_threads_enter ();
-
- /* Enque this early to reduce number of expose events. */
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group));
-
- gtk_tool_item_group_force_expose (group);
-
- /* Finish animation when done. */
- if (timestamp >= ANIMATION_DURATION)
- priv->animation_timeout = NULL;
-
- retval = (priv->animation_timeout != NULL);
-
- gdk_threads_leave ();
-
- return retval;
-}
-
-/**
- * gtk_tool_item_group_set_collapsed:
- * @group: a #GtkToolItemGroup
- * @collapsed: whether the @group should be collapsed or expanded
- *
- * Sets whether the @group should be collapsed or expanded.
- *
- * Since: 2.20
- */
-void
-gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group,
- gboolean collapsed)
-{
- GtkWidget *parent;
- GtkToolItemGroupPrivate* priv;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- priv = group->priv;
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
- if (GTK_IS_TOOL_PALETTE (parent) && !collapsed)
- _gtk_tool_palette_set_expanding_child (GTK_TOOL_PALETTE (parent),
- GTK_WIDGET (group));
- if (collapsed != priv->collapsed)
- {
- if (priv->animation)
- {
- if (priv->animation_timeout)
- g_source_destroy (priv->animation_timeout);
-
- priv->animation_start = g_get_monotonic_time ();
- priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT);
-
- g_source_set_callback (priv->animation_timeout,
- gtk_tool_item_group_animation_cb,
- group, NULL);
- g_source_attach (priv->animation_timeout, NULL);
- }
- else
- gtk_tool_item_group_force_expose (group);
-
- priv->collapsed = collapsed;
- update_arrow_state (group);
- g_object_notify (G_OBJECT (group), "collapsed");
- }
-}
-
-/**
- * gtk_tool_item_group_set_ellipsize:
- * @group: a #GtkToolItemGroup
- * @ellipsize: the #PangoEllipsizeMode labels in @group should use
- *
- * Sets the ellipsization mode which should be used by labels in @group.
- *
- * Since: 2.20
- */
-void
-gtk_tool_item_group_set_ellipsize (GtkToolItemGroup *group,
- PangoEllipsizeMode ellipsize)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- if (ellipsize != group->priv->ellipsize)
- {
- group->priv->ellipsize = ellipsize;
- gtk_tool_item_group_header_adjust_style (group);
- g_object_notify (G_OBJECT (group), "ellipsize");
- _gtk_tool_item_group_palette_reconfigured (group);
- }
-}
-
-/**
- * gtk_tool_item_group_get_label:
- * @group: a #GtkToolItemGroup
- *
- * Gets the label of @group.
- *
- * Returns: the label of @group. The label is an internal string of @group
- * and must not be modified. Note that %NULL is returned if a custom
- * label has been set with gtk_tool_item_group_set_label_widget()
- *
- * Since: 2.20
- */
-const gchar*
-gtk_tool_item_group_get_label (GtkToolItemGroup *group)
-{
- GtkToolItemGroupPrivate *priv;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- priv = group->priv;
-
- if (GTK_IS_LABEL (priv->label_widget))
- return gtk_label_get_label (GTK_LABEL (priv->label_widget));
- else
- return NULL;
-}
-
-/**
- * gtk_tool_item_group_get_label_widget:
- * @group: a #GtkToolItemGroup
- *
- * Gets the label widget of @group.
- * See gtk_tool_item_group_set_label_widget().
- *
- * Returns: (transfer none): the label widget of @group
- *
- * Since: 2.20
- */
-GtkWidget*
-gtk_tool_item_group_get_label_widget (GtkToolItemGroup *group)
-{
- GtkWidget *frame = gtk_tool_item_group_get_frame (group);
-
- return gtk_bin_get_child (GTK_BIN (frame));
-}
-
-/**
- * gtk_tool_item_group_get_collapsed:
- * @group: a GtkToolItemGroup
- *
- * Gets whether @group is collapsed or expanded.
- *
- * Returns: %TRUE if @group is collapsed, %FALSE if it is expanded
- *
- * Since: 2.20
- */
-gboolean
-gtk_tool_item_group_get_collapsed (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_COLLAPSED);
-
- return group->priv->collapsed;
-}
-
-/**
- * gtk_tool_item_group_get_ellipsize:
- * @group: a #GtkToolItemGroup
- *
- * Gets the ellipsization mode of @group.
- *
- * Returns: the #PangoEllipsizeMode of @group
- *
- * Since: 2.20
- */
-PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_ELLIPSIZE);
-
- return group->priv->ellipsize;
-}
-
-/**
- * gtk_tool_item_group_get_header_relief:
- * @group: a #GtkToolItemGroup
- *
- * Gets the relief mode of the header button of @group.
- *
- * Returns: the #GtkReliefStyle
- *
- * Since: 2.20
- */
-GtkReliefStyle
-gtk_tool_item_group_get_header_relief (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), GTK_RELIEF_NORMAL);
-
- return gtk_button_get_relief (GTK_BUTTON (group->priv->header));
-}
-
-/**
- * gtk_tool_item_group_insert:
- * @group: a #GtkToolItemGroup
- * @item: the #GtkToolItem to insert into @group
- * @position: the position of @item in @group, starting with 0.
- * The position -1 means end of list.
- *
- * Inserts @item at @position in the list of children of @group.
- *
- * Since: 2.20
- */
-void
-gtk_tool_item_group_insert (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- GtkWidget *parent, *child_widget;
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
- g_return_if_fail (position >= -1);
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- child = g_new (GtkToolItemGroupChild, 1);
- child->item = g_object_ref_sink (item);
- child->homogeneous = TRUE;
- child->expand = FALSE;
- child->fill = TRUE;
- child->new_row = FALSE;
-
- group->priv->children = g_list_insert (group->priv->children, child, position);
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_child_set_drag_source (GTK_WIDGET (item), parent);
-
- child_widget = gtk_bin_get_child (GTK_BIN (item));
-
- gtk_widget_set_focus_on_click (child_widget, TRUE);
-
- gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_set_item_position:
- * @group: a #GtkToolItemGroup
- * @item: the #GtkToolItem to move to a new position, should
- * be a child of @group.
- * @position: the new position of @item in @group, starting with 0.
- * The position -1 means end of list.
- *
- * Sets the position of @item in the list of children of @group.
- *
- * Since: 2.20
- */
-void
-gtk_tool_item_group_set_item_position (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- gint old_position;
- GList *link;
- GtkToolItemGroupChild *child;
- GtkToolItemGroupPrivate* priv;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
- g_return_if_fail (position >= -1);
-
- child = gtk_tool_item_group_get_child (group, item, &old_position, &link);
- priv = group->priv;
-
- g_return_if_fail (child != NULL);
-
- if (position == old_position)
- return;
-
- priv->children = g_list_delete_link (priv->children, link);
- priv->children = g_list_insert (priv->children, child, position);
-
- gtk_widget_child_notify (GTK_WIDGET (item), "position");
- if (gtk_widget_get_visible (GTK_WIDGET (group)) &&
- gtk_widget_get_visible (GTK_WIDGET (item)))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_get_item_position:
- * @group: a #GtkToolItemGroup
- * @item: a #GtkToolItem
- *
- * Gets the position of @item in @group as index.
- *
- * Returns: the index of @item in @group or -1 if @item is no child of @group
- *
- * Since: 2.20
- */
-gint
-gtk_tool_item_group_get_item_position (GtkToolItemGroup *group,
- GtkToolItem *item)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
-
- if (gtk_tool_item_group_get_child (group, item, &position, NULL))
- return position;
-
- return -1;
-}
-
-/**
- * gtk_tool_item_group_get_n_items:
- * @group: a #GtkToolItemGroup
- *
- * Gets the number of tool items in @group.
- *
- * Returns: the number of tool items in @group
- *
- * Since: 2.20
- */
-guint
-gtk_tool_item_group_get_n_items (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), 0);
-
- return g_list_length (group->priv->children);
-}
-
-/**
- * gtk_tool_item_group_get_nth_item:
- * @group: a #GtkToolItemGroup
- * @index: the index
- *
- * Gets the tool item at @index in group.
- *
- * Returns: (transfer none): the #GtkToolItem at index
- *
- * Since: 2.20
- */
-GtkToolItem*
-gtk_tool_item_group_get_nth_item (GtkToolItemGroup *group,
- guint index)
-{
- GtkToolItemGroupChild *child;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- child = g_list_nth_data (group->priv->children, index);
-
- return child != NULL ? child->item : NULL;
-}
-
-/**
- * gtk_tool_item_group_get_drop_item:
- * @group: a #GtkToolItemGroup
- * @x: the x position
- * @y: the y position
- *
- * Gets the tool item at position (x, y).
- *
- * Returns: (transfer none): the #GtkToolItem at position (x, y)
- *
- * Since: 2.20
- */
-GtkToolItem*
-gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group,
- gint x,
- gint y)
-{
- GtkAllocation allocation;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- gtk_widget_get_allocation (GTK_WIDGET (group), &allocation);
-
- g_return_val_if_fail (x >= 0 && x < allocation.width, NULL);
- g_return_val_if_fail (y >= 0 && y < allocation.height, NULL);
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- GtkToolItem *item = child->item;
- gint x0, y0;
-
- if (!item || !gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- gtk_widget_get_allocation (GTK_WIDGET (item), &allocation);
-
- x0 = x - allocation.x;
- y0 = y - allocation.y;
-
- if (x0 >= 0 && x0 < allocation.width &&
- y0 >= 0 && y0 < allocation.height)
- return item;
- }
-
- return NULL;
-}
-
-void
-_gtk_tool_item_group_item_size_request (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkRequisition child_requisition;
- GList *it;
- gint rows = 0;
- gboolean new_row = TRUE;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (NULL != item_size);
-
- item_size->width = item_size->height = 0;
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (child->new_row || new_row)
- {
- rows++;
- new_row = FALSE;
- }
-
- if (!child->homogeneous && child->expand)
- new_row = TRUE;
-
- gtk_widget_get_preferred_size (GTK_WIDGET (child->item),
- &child_requisition, NULL);
-
- if (!homogeneous_only || child->homogeneous)
- item_size->width = MAX (item_size->width, child_requisition.width);
- item_size->height = MAX (item_size->height, child_requisition.height);
- }
-
- if (requested_rows)
- *requested_rows = rows;
-}
-
-gint
-_gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group,
- gint limit,
- gboolean vertical,
- gboolean animation)
-{
- GtkRequisition requisition;
- GtkToolItemGroupPrivate* priv = group->priv;
-
- gtk_widget_get_preferred_size (GTK_WIDGET (group),
- &requisition, NULL);
-
- if (!priv->collapsed || priv->animation_timeout)
- {
- GtkAllocation allocation = { 0, 0, requisition.width, requisition.height };
- GtkRequisition inquery;
-
- if (vertical)
- allocation.width = limit;
- else
- allocation.height = limit;
-
- gtk_tool_item_group_real_size_query (GTK_WIDGET (group),
- &allocation, &inquery);
-
- if (vertical)
- inquery.height -= requisition.height;
- else
- inquery.width -= requisition.width;
-
- if (priv->animation_timeout && animation)
- {
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
-
- timestamp = MIN (timestamp, ANIMATION_DURATION);
-
- if (priv->collapsed)
- timestamp = ANIMATION_DURATION - timestamp;
-
- if (vertical)
- {
- inquery.height *= timestamp;
- inquery.height /= ANIMATION_DURATION;
- }
- else
- {
- inquery.width *= timestamp;
- inquery.width /= ANIMATION_DURATION;
- }
- }
-
- if (vertical)
- requisition.height += inquery.height;
- else
- requisition.width += inquery.width;
- }
-
- return (vertical ? requisition.height : requisition.width);
-}
-
-gint
-_gtk_tool_item_group_get_height_for_width (GtkToolItemGroup *group,
- gint width)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, width, TRUE, group->priv->animation);
-}
-
-gint
-_gtk_tool_item_group_get_width_for_height (GtkToolItemGroup *group,
- gint height)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, height, FALSE, TRUE);
-}
-
-static void
-gtk_tool_palette_reconfigured_foreach_item (GtkWidget *child,
- gpointer data)
-{
- if (GTK_IS_TOOL_ITEM (child))
- gtk_tool_item_toolbar_reconfigured (GTK_TOOL_ITEM (child));
-}
-
-
-void
-_gtk_tool_item_group_palette_reconfigured (GtkToolItemGroup *group)
-{
- gtk_container_foreach (GTK_CONTAINER (group),
- gtk_tool_palette_reconfigured_foreach_item,
- NULL);
-
- gtk_tool_item_group_header_adjust_style (group);
-}