From dad6e7343c1fbdbbe2a6ca765aabcf8b887933c9 Mon Sep 17 00:00:00 2001 From: Murray Cumming Date: Mon, 13 Jul 2009 19:13:59 +0200 Subject: [PATCH] ToolShell: Add ellipsize, text-orientation, text-alignment and size-group. * gtk/gtktoolshell.c: Added vfuncs to get/set ellipsize, text-orientation, text-alignment and size-group plus getter/setters to invoke these vfuncs. * gtk/gtktoolitem.[h|c]: Added getters and setters to get/set these from the parent GtkToolShell. This is in the style of the existing "properties". * gtk/gtktoolbutton.c: Updated to use the extra properties. * docs/reference/gtk/gtk-sections.txt * gtk/gtk.symbols: Updated to mention the new functions. These new "properties" are used by GtkToolPalette. --- docs/reference/ChangeLog | 6 + docs/reference/gtk/gtk-sections.txt | 6 + gtk/gtk.symbols | 8 + gtk/gtktoolbutton.c | 73 +- gtk/gtktoolitem.c | 106 + gtk/gtktoolitem.h | 5 + gtk/gtktoolshell.c | 92 + gtk/gtktoolshell.h | 46 +- gtktoolitemgroup.c | 6972 --------------------------- gtktoolitemgroup.h | 276 -- gtktoolpalette.c | 5055 ------------------- gtktoolpalette.h | 399 -- gtktoolpaletteprivate.h | 59 - 13 files changed, 318 insertions(+), 12785 deletions(-) delete mode 100644 gtktoolitemgroup.c delete mode 100644 gtktoolitemgroup.h delete mode 100644 gtktoolpalette.c delete mode 100644 gtktoolpalette.h delete mode 100644 gtktoolpaletteprivate.h diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 2447903bdc..0a6b97fddc 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,9 @@ +2009-07-13 Murray Cumming + + reviewed by: + + * gtk/gtk-sections.txt: + === ChangeLog discontinued === With the move to git, GTK+ is switching from a ChangeLog file diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt index 9509c29f9a..901f014f67 100644 --- a/docs/reference/gtk/gtk-sections.txt +++ b/docs/reference/gtk/gtk-sections.txt @@ -4166,10 +4166,13 @@ gtk_toggle_button_get_type GtkToolShell GtkToolShell GtkToolShellIface +gtk_tool_shell_get_ellipsize_mode gtk_tool_shell_get_icon_size gtk_tool_shell_get_orientation gtk_tool_shell_get_relief_style gtk_tool_shell_get_style +gtk_tool_shell_get_text_alignment +gtk_tool_shell_get_text_orientation gtk_tool_shell_rebuild_menu @@ -4257,10 +4260,13 @@ gtk_tool_item_set_visible_vertical gtk_tool_item_get_visible_vertical gtk_tool_item_set_is_important gtk_tool_item_get_is_important +gtk_tool_item_get_ellipsize_mode gtk_tool_item_get_icon_size gtk_tool_item_get_orientation gtk_tool_item_get_toolbar_style gtk_tool_item_get_relief_style +gtk_tool_item_get_text_alignment +gtk_tool_item_get_text_orientation gtk_tool_item_retrieve_proxy_menu_item gtk_tool_item_get_proxy_menu_item gtk_tool_item_set_proxy_menu_item diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 0c915dced4..a53fb5abbf 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -4320,10 +4320,14 @@ gtk_toolbar_unset_style #if IN_HEADER(__GTK_TOOL_SHELL_H__) #if IN_FILE(__GTK_TOOL_SHELL_C__) gtk_tool_shell_get_type G_GNUC_CONST +gtk_tool_shell_get_ellipsize_mode gtk_tool_shell_get_icon_size gtk_tool_shell_get_orientation gtk_tool_shell_get_style gtk_tool_shell_get_relief_style +gtk_tool_shell_get_text_alignment +gtk_tool_shell_get_text_orientation +gtk_tool_shell_get_text_size_group gtk_tool_shell_rebuild_menu #endif #endif @@ -4350,6 +4354,7 @@ gtk_tool_button_set_use_underline #if IN_HEADER(__GTK_TOOL_ITEM_H__) #if IN_FILE(__GTK_TOOL_ITEM_C__) +gtk_tool_item_get_ellipsize_mode gtk_tool_item_get_expand gtk_tool_item_get_homogeneous gtk_tool_item_get_icon_size @@ -4357,6 +4362,9 @@ gtk_tool_item_get_is_important gtk_tool_item_get_orientation gtk_tool_item_get_proxy_menu_item gtk_tool_item_get_relief_style +gtk_tool_item_get_text_alignment +gtk_tool_item_get_text_orientation +gtk_tool_item_get_text_size_group gtk_tool_item_get_toolbar_style gtk_tool_item_get_type G_GNUC_CONST gtk_tool_item_get_use_drag_window diff --git a/gtk/gtktoolbutton.c b/gtk/gtktoolbutton.c index 89231ea3ac..c9e63f6a68 100644 --- a/gtk/gtktoolbutton.c +++ b/gtk/gtktoolbutton.c @@ -96,7 +96,9 @@ struct _GtkToolButtonPrivate gchar *label_text; GtkWidget *label_widget; GtkWidget *icon_widget; - + + GtkSizeGroup *text_size_group; + guint use_underline : 1; guint contents_invalid : 1; }; @@ -318,6 +320,8 @@ gtk_tool_button_construct_contents (GtkToolItem *tool_item) GtkIconSize icon_size; GtkWidget *box = NULL; guint icon_spacing; + GtkOrientation text_orientation = GTK_ORIENTATION_HORIZONTAL; + GtkSizeGroup *size_group = NULL; button->priv->contents_invalid = FALSE; @@ -355,7 +359,8 @@ gtk_tool_button_construct_contents (GtkToolItem *tool_item) if (style == GTK_TOOLBAR_BOTH_HORIZ && (gtk_tool_item_get_is_important (GTK_TOOL_ITEM (button)) || - gtk_tool_item_get_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL)) + gtk_tool_item_get_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL || + gtk_tool_item_get_text_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL)) { need_label = TRUE; } @@ -415,6 +420,28 @@ gtk_tool_button_construct_contents (GtkToolItem *tool_item) gtk_widget_show (label); } + + gtk_label_set_ellipsize (GTK_LABEL (label), + gtk_tool_item_get_ellipsize_mode (GTK_TOOL_ITEM (button))); + text_orientation = gtk_tool_item_get_text_orientation (GTK_TOOL_ITEM (button)); + if (text_orientation == GTK_ORIENTATION_HORIZONTAL) + { + gtk_label_set_angle (GTK_LABEL (label), 0); + gtk_misc_set_alignment (GTK_MISC (label), + gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)), + 0.5); + } + else + { + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE); + if (gtk_widget_get_direction (GTK_WIDGET (tool_item)) == GTK_TEXT_DIR_RTL) + gtk_label_set_angle (GTK_LABEL (label), -90); + else + gtk_label_set_angle (GTK_LABEL (label), 90); + gtk_misc_set_alignment (GTK_MISC (label), + 0.5, + 1 - gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button))); + } } icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button)); @@ -442,6 +469,22 @@ gtk_tool_button_construct_contents (GtkToolItem *tool_item) icon = gtk_image_new_from_icon_name (button->priv->icon_name, icon_size); gtk_widget_show (icon); } + + if (icon && text_orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_misc_set_alignment (GTK_MISC (icon), + 1.0 - gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)), + 0.5); + else if (icon) + gtk_misc_set_alignment (GTK_MISC (icon), + 0.5, + gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button))); + + if (icon) + { + size_group = gtk_tool_item_get_text_size_group (GTK_TOOL_ITEM (button)); + if (size_group != NULL) + gtk_size_group_add_widget (size_group, icon); + } } switch (style) @@ -452,7 +495,10 @@ gtk_tool_button_construct_contents (GtkToolItem *tool_item) break; case GTK_TOOLBAR_BOTH: - box = gtk_vbox_new (FALSE, icon_spacing); + if (text_orientation == GTK_ORIENTATION_HORIZONTAL) + box = gtk_vbox_new (FALSE, icon_spacing); + else + box = gtk_hbox_new (FALSE, icon_spacing); if (icon) gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0); gtk_box_pack_end (GTK_BOX (box), label, FALSE, TRUE, 0); @@ -460,11 +506,22 @@ gtk_tool_button_construct_contents (GtkToolItem *tool_item) break; case GTK_TOOLBAR_BOTH_HORIZ: - box = gtk_hbox_new (FALSE, icon_spacing); - if (icon) - gtk_box_pack_start (GTK_BOX (box), icon, label? FALSE : TRUE, TRUE, 0); - if (label) - gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0); + if (text_orientation == GTK_ORIENTATION_HORIZONTAL) + { + box = gtk_hbox_new (FALSE, icon_spacing); + if (icon) + gtk_box_pack_start (GTK_BOX (box), icon, label? FALSE : TRUE, TRUE, 0); + if (label) + gtk_box_pack_end (GTK_BOX (box), label, TRUE, TRUE, 0); + } + else + { + box = gtk_vbox_new (FALSE, icon_spacing); + if (icon) + gtk_box_pack_end (GTK_BOX (box), icon, label ? FALSE : TRUE, TRUE, 0); + if (label) + gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0); + } gtk_container_add (GTK_CONTAINER (button->priv->button), box); break; diff --git a/gtk/gtktoolitem.c b/gtk/gtktoolitem.c index 9c00b0dab2..411cd1ca3a 100644 --- a/gtk/gtktoolitem.c +++ b/gtk/gtktoolitem.c @@ -687,6 +687,33 @@ gtk_tool_item_new (void) return item; } +/** + * gtk_tool_item_get_ellipsize_mode: + * @tool_item: a #GtkToolItem: + * + * Returns the ellipsize mode used for @tool_item. Custom subclasses of + * #GtkToolItem should call this function to find out how text should + * be ellipsized. + * + * Return value: a #PangoEllipsizeMode indicating how text in @tool_item + * should be ellipsized. + * + * Since: 2.14 + **/ +PangoEllipsizeMode +gtk_tool_item_get_ellipsize_mode (GtkToolItem *tool_item) +{ + GtkWidget *parent; + + g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_ORIENTATION_HORIZONTAL); + + parent = GTK_WIDGET (tool_item)->parent; + if (!parent || !GTK_IS_TOOL_SHELL (parent)) + return PANGO_ELLIPSIZE_NONE; + + return gtk_tool_shell_get_ellipsize_mode (GTK_TOOL_SHELL (parent)); +} + /** * gtk_tool_item_get_icon_size: * @tool_item: a #GtkToolItem @@ -811,6 +838,85 @@ gtk_tool_item_get_relief_style (GtkToolItem *tool_item) return gtk_tool_shell_get_relief_style (GTK_TOOL_SHELL (parent)); } +/** + * gtk_tool_item_get_text_alignment: + * @tool_item: a #GtkToolItem: + * + * Returns the text alignment used for @tool_item. Custom subclasses of + * #GtkToolItem should call this function to find out how text should + * be aligned. + * + * Return value: a #gfloat indicating the horizontal text alignment + * used for @tool_item + * + * Since: 2.14 + **/ +gfloat +gtk_tool_item_get_text_alignment (GtkToolItem *tool_item) +{ + GtkWidget *parent; + + g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_ORIENTATION_HORIZONTAL); + + parent = GTK_WIDGET (tool_item)->parent; + if (!parent || !GTK_IS_TOOL_SHELL (parent)) + return 0.5; + + return gtk_tool_shell_get_text_alignment (GTK_TOOL_SHELL (parent)); +} + +/** + * gtk_tool_item_get_text_orientation: + * @tool_item: a #GtkToolItem: + * + * Returns the text orientation used for @tool_item. Custom subclasses of + * #GtkToolItem should call this function to find out how text should + * be orientated. + * + * Return value: a #GtkOrientation indicating the text orientation + * used for @tool_item + * + * Since: 2.14 + **/ +GtkOrientation +gtk_tool_item_get_text_orientation (GtkToolItem *tool_item) +{ + GtkWidget *parent; + + g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_ORIENTATION_HORIZONTAL); + + parent = GTK_WIDGET (tool_item)->parent; + if (!parent || !GTK_IS_TOOL_SHELL (parent)) + return GTK_ORIENTATION_HORIZONTAL; + + return gtk_tool_shell_get_text_orientation (GTK_TOOL_SHELL (parent)); +} + +/** + * gtk_tool_item_get_text_size_group: + * @tool_item: a #GtkToolItem: + * + * Returns the size group used for labels in @tool_item. Custom subclasses of + * #GtkToolItem should call this function and use the size group for labels. + * + * Return value: a #GtkSizeGroup + * + * Since: 2.14 + **/ +GtkSizeGroup * +gtk_tool_item_get_text_size_group (GtkToolItem *tool_item) +{ + GtkWidget *parent; + + g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_ORIENTATION_HORIZONTAL); + + parent = GTK_WIDGET (tool_item)->parent; + if (!parent || !GTK_IS_TOOL_SHELL (parent)) + return NULL; + + return gtk_tool_shell_get_text_size_group (GTK_TOOL_SHELL (parent)); +} + /** * gtk_tool_item_set_expand: * @tool_item: a #GtkToolItem diff --git a/gtk/gtktoolitem.h b/gtk/gtktoolitem.h index a81b06bb80..7f8d9ada18 100644 --- a/gtk/gtktoolitem.h +++ b/gtk/gtktoolitem.h @@ -30,6 +30,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -113,10 +114,14 @@ gboolean gtk_tool_item_get_is_important (GtkToolItem *tool_item); void gtk_tool_item_set_is_important (GtkToolItem *tool_item, gboolean is_important); +PangoEllipsizeMode gtk_tool_item_get_ellipsize_mode (GtkToolItem *tool_item); GtkIconSize gtk_tool_item_get_icon_size (GtkToolItem *tool_item); GtkOrientation gtk_tool_item_get_orientation (GtkToolItem *tool_item); GtkToolbarStyle gtk_tool_item_get_toolbar_style (GtkToolItem *tool_item); GtkReliefStyle gtk_tool_item_get_relief_style (GtkToolItem *tool_item); +gfloat gtk_tool_item_get_text_alignment (GtkToolItem *tool_item); +GtkOrientation gtk_tool_item_get_text_orientation (GtkToolItem *tool_item); +GtkSizeGroup * gtk_tool_item_get_text_size_group (GtkToolItem *tool_item); GtkWidget * gtk_tool_item_retrieve_proxy_menu_item (GtkToolItem *tool_item); GtkWidget * gtk_tool_item_get_proxy_menu_item (GtkToolItem *tool_item, diff --git a/gtk/gtktoolshell.c b/gtk/gtktoolshell.c index e3e71c5086..f7be68a523 100644 --- a/gtk/gtktoolshell.c +++ b/gtk/gtktoolshell.c @@ -155,5 +155,97 @@ gtk_tool_shell_rebuild_menu (GtkToolShell *shell) iface->rebuild_menu (shell); } +/** + * gtk_tool_shell_get_text_orientation: + * @shell: a #GtkToolShell + * + * Retrieves the current text orientation for the tool shell. Tool items must not + * call this function directly, but rely on gtk_tool_item_get_text_orientation() + * instead. + * + * Return value: the current text orientation of @shell + * + * Since: 2.14 + **/ +GtkOrientation +gtk_tool_shell_get_text_orientation (GtkToolShell *shell) +{ + GtkToolShellIface *iface = GTK_TOOL_SHELL_GET_IFACE (shell); + + if (iface->get_text_orientation) + return GTK_TOOL_SHELL_GET_IFACE (shell)->get_text_orientation (shell); + + return GTK_ORIENTATION_HORIZONTAL; +} + +/** + * gtk_tool_shell_get_text_alignment: + * @shell: a #GtkToolShell + * + * Retrieves the current text alignment for the tool shell. Tool items must not + * call this function directly, but rely on gtk_tool_item_get_text_alignment() + * instead. + * + * Return value: the current text alignment of @shell + * + * Since: 2.14 + **/ +gfloat +gtk_tool_shell_get_text_alignment (GtkToolShell *shell) +{ + GtkToolShellIface *iface = GTK_TOOL_SHELL_GET_IFACE (shell); + + if (iface->get_text_alignment) + return GTK_TOOL_SHELL_GET_IFACE (shell)->get_text_alignment (shell); + + return 0.5f; +} + +/** + * gtk_tool_shell_get_ellipsize_mode + * @shell: a #GtkToolShell + * + * Retrieves the current ellipsize mode for the tool shell. Tool items must not + * call this function directly, but rely on gtk_tool_item_get_ellipsize_mode() + * instead. + * + * Return value: the current ellipsize mode of @shell + * + * Since: 2.14 + **/ +PangoEllipsizeMode +gtk_tool_shell_get_ellipsize_mode (GtkToolShell *shell) +{ + GtkToolShellIface *iface = GTK_TOOL_SHELL_GET_IFACE (shell); + + if (iface->get_ellipsize_mode) + return GTK_TOOL_SHELL_GET_IFACE (shell)->get_ellipsize_mode (shell); + + return PANGO_ELLIPSIZE_NONE; +} + +/** + * gtk_tool_shell_get_text_size_group: + * @shell: a #GtkToolShell + * + * Retrieves the current text size group for the tool shell. Tool items must not + * call this function directly, but rely on gtk_tool_item_get_text_size_group() + * instead. + * + * Return value: the current text size group of @shell + * + * Since: 2.14 + **/ +GtkSizeGroup * +gtk_tool_shell_get_text_size_group (GtkToolShell *shell) +{ + GtkToolShellIface *iface = GTK_TOOL_SHELL_GET_IFACE (shell); + + if (iface->get_text_size_group) + return GTK_TOOL_SHELL_GET_IFACE (shell)->get_text_size_group (shell); + + return NULL; +} + #define __GTK_TOOL_SHELL_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtktoolshell.h b/gtk/gtktoolshell.h index be49304445..0605a4006b 100644 --- a/gtk/gtktoolshell.h +++ b/gtk/gtktoolshell.h @@ -29,6 +29,8 @@ #include +#include +#include G_BEGIN_DECLS @@ -43,11 +45,15 @@ typedef struct _GtkToolShellIface GtkToolShellIface; /** * GtkToolShellIface: - * @get_icon_size: mandatory implementation of gtk_tool_shell_get_icon_size(). - * @get_orientation: mandatory implementation of gtk_tool_shell_get_orientation(). - * @get_style: mandatory implementation of gtk_tool_shell_get_style(). - * @get_relief_style: optional implementation of gtk_tool_shell_get_relief_style(). - * @rebuild_menu: optional implementation of gtk_tool_shell_rebuild_menu(). + * @get_icon_size: mandatory implementation of gtk_tool_shell_get_icon_size(). + * @get_orientation: mandatory implementation of gtk_tool_shell_get_orientation(). + * @get_style: mandatory implementation of gtk_tool_shell_get_style(). + * @get_relief_style: optional implementation of gtk_tool_shell_get_relief_style(). + * @rebuild_menu: optional implementation of gtk_tool_shell_rebuild_menu(). + * @get_text_orientation: optional implementation of gtk_tool_shell_get_text_orientation(). + * @get_text_alignment: optional implementation of gtk_tool_shell_get_text_alignment(). + * @get_ellipsize_mode: optional implementation of gtk_tool_shell_get_ellipsize_mode(). + * @get_text_size_group: optional implementation of gtk_tool_shell_get_text_size_group(). * * Virtual function table for the #GtkToolShell interface. */ @@ -57,20 +63,28 @@ struct _GtkToolShellIface GTypeInterface g_iface; /*< public >*/ - GtkIconSize (*get_icon_size) (GtkToolShell *shell); - GtkOrientation (*get_orientation) (GtkToolShell *shell); - GtkToolbarStyle (*get_style) (GtkToolShell *shell); - GtkReliefStyle (*get_relief_style) (GtkToolShell *shell); - void (*rebuild_menu) (GtkToolShell *shell); + GtkIconSize (*get_icon_size) (GtkToolShell *shell); + GtkOrientation (*get_orientation) (GtkToolShell *shell); + GtkToolbarStyle (*get_style) (GtkToolShell *shell); + GtkReliefStyle (*get_relief_style) (GtkToolShell *shell); + void (*rebuild_menu) (GtkToolShell *shell); + GtkOrientation (*get_text_orientation) (GtkToolShell *shell); + gfloat (*get_text_alignment) (GtkToolShell *shell); + PangoEllipsizeMode (*get_ellipsize_mode) (GtkToolShell *shell); + GtkSizeGroup * (*get_text_size_group) (GtkToolShell *shell); }; -GType gtk_tool_shell_get_type (void) G_GNUC_CONST; +GType gtk_tool_shell_get_type (void) G_GNUC_CONST; -GtkIconSize gtk_tool_shell_get_icon_size (GtkToolShell *shell); -GtkOrientation gtk_tool_shell_get_orientation (GtkToolShell *shell); -GtkToolbarStyle gtk_tool_shell_get_style (GtkToolShell *shell); -GtkReliefStyle gtk_tool_shell_get_relief_style (GtkToolShell *shell); -void gtk_tool_shell_rebuild_menu (GtkToolShell *shell); +GtkIconSize gtk_tool_shell_get_icon_size (GtkToolShell *shell); +GtkOrientation gtk_tool_shell_get_orientation (GtkToolShell *shell); +GtkToolbarStyle gtk_tool_shell_get_style (GtkToolShell *shell); +GtkReliefStyle gtk_tool_shell_get_relief_style (GtkToolShell *shell); +void gtk_tool_shell_rebuild_menu (GtkToolShell *shell); +GtkOrientation gtk_tool_shell_get_text_orientation (GtkToolShell *shell); +gfloat gtk_tool_shell_get_text_alignment (GtkToolShell *shell); +PangoEllipsizeMode gtk_tool_shell_get_ellipsize_mode (GtkToolShell *shell); +GtkSizeGroup * gtk_tool_shell_get_text_size_group (GtkToolShell *shell); G_END_DECLS diff --git a/gtktoolitemgroup.c b/gtktoolitemgroup.c deleted file mode 100644 index aac2e77ec4..0000000000 --- a/gtktoolitemgroup.c +++ /dev/null @@ -1,6972 +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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - * Jan Arne Petersen - */ - -#include "gtktoolpaletteprivate.h" - -#include -#include -#include - -#define P_(msgid) (msgid) - -#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_NAME NULL -#define DEFAULT_COLLAPSED FALSE -#define DEFAULT_ELLIPSIZE PANGO_ELLIPSIZE_NONE - -/** - * SECTION:GtkToolItemGroup - * @short_description: A sub container used in a tool palette - * @include: gtktoolitemgroup.h - * - * An #GtkToolItemGroup is used together with #GtkToolPalette to add #GtkToolItems to a palette like container - * with different categories and drag and drop support. - * - * Since: 2.18 - */ - -enum -{ - PROP_NONE, - PROP_NAME, - 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; - - GList *children; - - gboolean animation; - gint64 animation_start; - GSource *animation_timeout; - GtkExpanderStyle expander_style; - gint expander_size; - gint header_spacing; - PangoEllipsizeMode ellipsize; - - gulong focus_set_id; - GtkWidget *toplevel; - - GtkSettings *settings; - gulong settings_connection; - - 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_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL, gtk_tool_item_group_tool_shell_init)); - -static GtkWidget* -gtk_tool_item_group_get_alignment (GtkToolItemGroup *group) -{ - return gtk_bin_get_child (GTK_BIN (group->priv->header)); -} - -static GtkWidget* -gtk_tool_item_group_get_label (GtkToolItemGroup *group) -{ - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - return gtk_bin_get_child (GTK_BIN (alignment)); -} - -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_tool_palette_get_orientation (GTK_TOOL_PALETTE (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 GtkIconSize -gtk_tool_item_group_get_icon_size (GtkToolShell *shell) -{ - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell)); - - if (GTK_IS_TOOL_PALETTE (parent)) - return gtk_tool_palette_get_icon_size (GTK_TOOL_PALETTE (parent)); - - return GTK_ICON_SIZE_SMALL_TOOLBAR; -} - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - -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) -{ - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell)); - - if (GTK_IS_TOOL_PALETTE (parent)) - { - GtkOrientation orientation = gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent)); - if (GTK_ORIENTATION_HORIZONTAL == orientation && - (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell)/* || - GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell)*/)) - return GTK_ORIENTATION_VERTICAL; - } - - 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; -} - -#endif - -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")) - { - animation_change_notify (group); - } -} - -static void -gtk_tool_item_group_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkToolItemGroupPrivate* priv = group->priv; - GtkSettings *old_settings = priv->settings; - GtkSettings *settings; - - if (gtk_widget_has_screen (GTK_WIDGET (group))) - settings = gtk_widget_get_settings (GTK_WIDGET (group)); - else - settings = NULL; - - if (settings == old_settings) - return; - - if (old_settings) - { - g_signal_handler_disconnect (old_settings, priv->settings_connection); - 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_icon_size = gtk_tool_item_group_get_icon_size; - iface->get_orientation = gtk_tool_item_group_get_orientation; - iface->get_style = gtk_tool_item_group_get_style; -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - 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; -#endif -} - -static gboolean -gtk_tool_item_group_header_expose_event_cb (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - GtkExpanderStyle expander_style; - GtkOrientation orientation; - gint x, y; - GtkTextDirection direction; - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - expander_style = group->priv->expander_style; - direction = gtk_widget_get_direction (widget); - - if (GTK_ORIENTATION_VERTICAL == orientation) - { - if (GTK_TEXT_DIR_RTL == direction) - x = widget->allocation.x + widget->allocation.width - group->priv->expander_size / 2; - else - x = widget->allocation.x + group->priv->expander_size / 2; - y = widget->allocation.y + widget->allocation.height / 2; - } - else - { - x = widget->allocation.x + widget->allocation.width / 2; - y = widget->allocation.y + group->priv->expander_size / 2; - - /* Unfortunatly gtk_paint_expander() doesn't support rotated drawing - * modes. Luckily the following shady arithmetics produce the desired - * result. */ - expander_style = GTK_EXPANDER_EXPANDED - expander_style; /* XXX */ - } - - gtk_paint_expander (widget->style, widget->window, - group->priv->header->state, - &event->area, GTK_WIDGET (group), - "tool-palette-header", x, y, - expander_style); - - return FALSE; -} - -static void -gtk_tool_item_group_header_size_request_cb (GtkWidget *widget G_GNUC_UNUSED, - GtkRequisition *requisition, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - requisition->height = MAX (requisition->height, group->priv->expander_size); -} - -static void -gtk_tool_item_group_header_clicked_cb (GtkButton *button G_GNUC_UNUSED, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - GtkWidget *parent = gtk_widget_get_parent (data); - - if (group->priv->collapsed || - !GTK_IS_TOOL_PALETTE (parent) || - !gtk_tool_palette_get_exclusive (GTK_TOOL_PALETTE (parent), data)) - gtk_tool_item_group_set_collapsed (group, !group->priv->collapsed); -} - -static void -gtk_tool_item_group_header_adjust_style (GtkToolItemGroup *group) -{ - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - GtkWidget *label = gtk_bin_get_child (GTK_BIN (alignment)); - GtkWidget *widget = GTK_WIDGET (group); - gint dx = 0, dy = 0; - GtkTextDirection direction = gtk_widget_get_direction (widget); - - gtk_widget_style_get (widget, - "header-spacing", &group->priv->header_spacing, - "expander-size", &group->priv->expander_size, - NULL); - - switch (gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group))) - { - case GTK_ORIENTATION_HORIZONTAL: - dy = group->priv->header_spacing + group->priv->expander_size; - gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE); - if (GTK_TEXT_DIR_RTL == direction) - gtk_label_set_angle (GTK_LABEL (label), -90); - else - gtk_label_set_angle (GTK_LABEL (label), 90); - break; - - case GTK_ORIENTATION_VERTICAL: - dx = group->priv->header_spacing + group->priv->expander_size; - gtk_label_set_ellipsize (GTK_LABEL (label), group->priv->ellipsize); - gtk_label_set_angle (GTK_LABEL (label), 0); - break; - } - - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), dy, 0, dx, 0); -} - -static void -gtk_tool_item_group_init (GtkToolItemGroup *group) -{ - GtkWidget *alignment; - GtkWidget *label; - - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (group), FALSE); - - group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group, - GTK_TYPE_TOOL_ITEM_GROUP, - GtkToolItemGroupPrivate); - - group->priv->children = NULL; - group->priv->header_spacing = DEFAULT_HEADER_SPACING; - group->priv->expander_size = DEFAULT_EXPANDER_SIZE; - group->priv->expander_style = GTK_EXPANDER_EXPANDED; - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); - gtk_container_add (GTK_CONTAINER (alignment), label); - gtk_widget_show_all (alignment); - - gtk_widget_push_composite_child (); - group->priv->header = gtk_button_new (); - gtk_widget_set_composite_name (group->priv->header, "header"); - gtk_widget_pop_composite_child (); - - g_object_ref_sink (group->priv->header); - gtk_button_set_focus_on_click (GTK_BUTTON (group->priv->header), FALSE); - gtk_container_add (GTK_CONTAINER (group->priv->header), alignment); - gtk_widget_set_parent (group->priv->header, GTK_WIDGET (group)); - - gtk_tool_item_group_header_adjust_style (group); - - g_signal_connect_after (alignment, "expose-event", - G_CALLBACK (gtk_tool_item_group_header_expose_event_cb), - group); - g_signal_connect_after (alignment, "size-request", - G_CALLBACK (gtk_tool_item_group_header_size_request_cb), - group); - - g_signal_connect (group->priv->header, "clicked", - G_CALLBACK (gtk_tool_item_group_header_clicked_cb), - 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_NAME: - gtk_tool_item_group_set_name (group, g_value_get_string (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_NAME: - g_value_set_string (value, gtk_tool_item_group_get_name (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); - - if (group->priv->children) - { - g_list_free (group->priv->children); - group->priv->children = NULL; - } - - 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); - - if (group->priv->toplevel) - { - /* disconnect focus tracking handler */ - g_signal_handler_disconnect (group->priv->toplevel, - group->priv->focus_set_id); - - group->priv->focus_set_id = 0; - group->priv->toplevel = NULL; - } - - 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) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkOrientation orientation; - GtkRequisition item_size; - gint requested_rows; - - if (group->priv->children && gtk_tool_item_group_get_name (group)) - { - gtk_widget_size_request (group->priv->header, requisition); - gtk_widget_show (group->priv->header); - } - else - { - requisition->width = requisition->height = 0; - gtk_widget_hide (group->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); - - requisition->width += border_width * 2; - requisition->height += border_width * 2; -} - -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_VISIBLE (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) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - - GtkRequisition item_size; - GtkAllocation item_area; - - GtkOrientation orientation; - GtkToolbarStyle style; - - gint min_rows; - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (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_area.width = 0; - item_area.height = 0; - - /* figure out the required columns (n_columns) and rows (n_rows) to place all items */ - if (!group->priv->collapsed || !group->priv->animation || group->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 - 2 * border_width; - n_columns = MAX (item_area.width / item_size.width, 1); - - /* calculate required rows for n_columns columns */ - 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 (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_size_request (GTK_WIDGET (child->item), &req); - - 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 - 2 * border_width; - 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 = group->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_size_request (GTK_WIDGET (child->item), &req); - - 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 = group->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_size_request (GTK_WIDGET (child->item), &req); - - 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_VISIBLE (group->priv->header)) - { - GtkRequisition child_requisition; - - gtk_widget_size_request (group->priv->header, &child_requisition); - - 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 + 2 * border_width; - inquery->height += item_area.height + 2 * border_width; -} - -static void -gtk_tool_item_group_real_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkRequisition child_requisition; - GtkAllocation child_allocation; - - GtkRequisition item_size; - GtkAllocation item_area; - - GtkOrientation orientation; - GtkToolbarStyle style; - - GList *it; - - gint n_columns, n_rows = 1; - gint min_rows; - - GtkTextDirection direction = gtk_widget_get_direction (widget); - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group)); - - /* chain up */ - GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->size_allocate (widget, allocation); - - child_allocation.x = border_width; - child_allocation.y = border_width; - - /* place the header widget */ - if (GTK_WIDGET_VISIBLE (group->priv->header)) - { - gtk_widget_size_request (group->priv->header, &child_requisition); - - 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 - border_width - child_allocation.width; - } - - gtk_widget_size_allocate (group->priv->header, &child_allocation); - - 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 = border_width; - } - 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); - - /* 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 - 2 * border_width; - item_area.height = allocation->height - 2 * border_width - 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 - 2 * border_width - child_requisition.width; - item_area.height = allocation->height - 2 * border_width; - - 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 (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout) - { - gint col = 0, row = 0; - - for (it = group->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_size_request (GTK_WIDGET (child->item), &child_requisition); - 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); - 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 = group->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, - GtkAllocation *allocation) -{ - gtk_tool_item_group_real_size_allocate (widget, allocation); - - if (GTK_WIDGET_MAPPED (widget)) - gdk_window_invalidate_rect (widget->window, NULL, FALSE); -} - -static void -gtk_tool_item_group_set_focus_cb (GtkWidget *window G_GNUC_UNUSED, - GtkWidget *widget, - gpointer user_data) -{ - GtkAdjustment *adjustment; - 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_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p)); - adjustment = gtk_tool_palette_get_vadjustment (GTK_TOOL_PALETTE (p)); - - if (adjustment) - { - int y; - - /* Handle vertical adjustment. */ - if (gtk_widget_translate_coordinates - (widget, p, 0, 0, NULL, &y) && y < 0) - { - y += adjustment->value; - gtk_adjustment_clamp_page (adjustment, y, y + widget->allocation.height); - } - else if (gtk_widget_translate_coordinates - (widget, p, 0, widget->allocation.height, NULL, &y) && - y > p->allocation.height) - { - y += adjustment->value; - gtk_adjustment_clamp_page (adjustment, y - widget->allocation.height, y); - } - } - - adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p)); - - if (adjustment) - { - int x; - - /* Handle horizontal adjustment. */ - if (gtk_widget_translate_coordinates - (widget, p, 0, 0, &x, NULL) && x < 0) - { - x += adjustment->value; - gtk_adjustment_clamp_page (adjustment, x, x + widget->allocation.width); - } - else if (gtk_widget_translate_coordinates - (widget, p, widget->allocation.width, 0, &x, NULL) && - x > p->allocation.width) - { - x += adjustment->value; - gtk_adjustment_clamp_page (adjustment, x - widget->allocation.width, x); - } - - return; - } - } -} - -static void -gtk_tool_item_group_set_toplevel_window (GtkToolItemGroup *group, - GtkWidget *toplevel) -{ - if (toplevel != group->priv->toplevel) - { - if (group->priv->toplevel) - { - /* Disconnect focus tracking handler. */ - g_signal_handler_disconnect (group->priv->toplevel, - group->priv->focus_set_id); - - group->priv->focus_set_id = 0; - group->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. - */ - group->priv->focus_set_id = - g_signal_connect (toplevel, "set-focus", - G_CALLBACK (gtk_tool_item_group_set_focus_cb), - group); - - group->priv->toplevel = toplevel; - } - } -} - -static void -gtk_tool_item_group_realize (GtkWidget *widget) -{ - GtkWidget *toplevel_window; - const gint border_width = GTK_CONTAINER (widget)->border_width; - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - GdkWindowAttr attributes; - GdkDisplay *display; - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x + border_width; - attributes.y = widget->allocation.y + border_width; - attributes.width = widget->allocation.width - border_width * 2; - attributes.height = widget->allocation.height - border_width * 2; - 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 | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_BUTTON_MOTION_MASK; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - - display = gdk_drawable_get_display (widget->window); - - if (gdk_display_supports_composite (display)) - gdk_window_set_composited (widget->window, TRUE); - - gdk_window_set_user_data (widget->window, widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - - gtk_container_forall (GTK_CONTAINER (widget), - (GtkCallback) gtk_widget_set_parent_window, - widget->window); - - gtk_widget_queue_resize_no_redraw (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_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - gtk_tool_item_group_header_adjust_style (GTK_TOOL_ITEM_GROUP (widget)); - GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->style_set (widget, previous_style); -} - -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; - GList *it; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container)); - group = GTK_TOOL_ITEM_GROUP (container); - - for (it = group->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); - group->priv->children = g_list_delete_link (group->priv->children, it); - - gtk_widget_queue_resize (GTK_WIDGET (container)); - break; - } - } -} - -static void -gtk_tool_item_group_forall (GtkContainer *container, - gboolean internals, - GtkCallback callback, - gpointer callback_data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container); - GList *children; - - if (internals && group->priv->header) - callback (group->priv->header, callback_data); - - children = group->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 G_GNUC_UNUSED) -{ - 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_VISIBLE (group) && GTK_WIDGET_VISIBLE (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->size_request = gtk_tool_item_group_size_request; - 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_set = gtk_tool_item_group_style_set; - wclass->screen_changed = gtk_tool_item_group_screen_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_NAME, - g_param_spec_string ("name", - P_("Name"), - P_("The name of this item group"), - DEFAULT_NAME, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_COLLAPSED, - g_param_spec_boolean ("collapsed", - P_("Collapsed"), - P_("Wether the group has been collapsed and items are hidden"), - DEFAULT_COLLAPSED, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_ELLIPSIZE, - g_param_spec_enum ("header-relief", - P_("header-relif"), - P_("Relief of the group header button"), - GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NORMAL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_widget_class_install_style_property (wclass, - g_param_spec_int ("expander-size", - P_("Expander Size"), - P_("Size of the expander arrow"), - 0, - G_MAXINT, - DEFAULT_EXPANDER_SIZE, - G_PARAM_READABLE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_widget_class_install_style_property (wclass, - g_param_spec_int ("header-spacing", - P_("Header Spacing"), - P_("Spacing between expander arrow and caption"), - 0, - G_MAXINT, - DEFAULT_HEADER_SPACING, - G_PARAM_READABLE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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 toolbar grows"), - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_FILL, - g_param_spec_boolean ("fill", - P_("Fill"), - P_("Whether the item should fill the avaiable space"), - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_type_class_add_private (cls, sizeof (GtkToolItemGroupPrivate)); -} - -/** - * gtk_tool_item_group_new: - * @name: the name of the new group. - * - * Creates a new tool item group with name @name. - * - * Returns: a new #GtkToolItemGroup. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_item_group_new (const gchar *name) -{ - return g_object_new (GTK_TYPE_TOOL_ITEM_GROUP, "name", name, NULL); -} - -/** - * gtk_tool_item_group_set_name: - * @group: an #GtkToolItemGroup. - * @name: the new name of of the group. - * - * Sets the name of the tool item group. The name is displayed in the header - * of the group. - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_name (GtkToolItemGroup *group, - const gchar *name) -{ - const gchar *current_name; - GtkWidget *label; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - current_name = gtk_tool_item_group_get_name (group); - - if (current_name != name && (!current_name || !name || strcmp (current_name, name))) - { - label = gtk_tool_item_group_get_label (group); - gtk_label_set_text (GTK_LABEL (label), name); - - if (name && group->priv->children) - gtk_widget_show (group->priv->header); - else - gtk_widget_hide (group->priv->header); - - g_object_notify (G_OBJECT (group), "name"); - } -} - -/** - * gtk_tool_item_group_header_relief: - * @group: an #GtkToolItemGroup. - * @style: The GtkReliefStyle - * - * Set the button relief of the group header. See #gtk_button_set_relief for - * details - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group, - GtkReliefStyle style) -{ - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - gtk_button_set_relief (GTK_BUTTON(group->priv->header), style); -} - -static gint64 -gtk_tool_item_group_get_animation_timestamp (GtkToolItemGroup *group) -{ - GTimeVal now; - g_source_get_current_time (group->priv->animation_timeout, &now); - return (now.tv_sec * G_USEC_PER_SEC + now.tv_usec - group->priv->animation_start) / 1000; -} - -static void -gtk_tool_item_group_force_expose (GtkToolItemGroup *group) -{ - if (GTK_WIDGET_REALIZED (group->priv->header)) - { - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - GdkRectangle area; - - /* Find the header button's arrow area... */ - area.x = alignment->allocation.x; - area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2; - area.height = group->priv->expander_size; - area.width = group->priv->expander_size; - - /* ... and invalidated it to get it animated. */ - gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE); - } - - if (GTK_WIDGET_REALIZED (group)) - { - GtkWidget *widget = GTK_WIDGET (group); - GtkWidget *parent = gtk_widget_get_parent (widget); - int x, y, width, height; - - /* Find the tool item area button's arrow area... */ - width = widget->allocation.width; - height = widget->allocation.height; - - gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y); - - if (GTK_WIDGET_VISIBLE (group->priv->header)) - { - height -= group->priv->header->allocation.height; - y += group->priv->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); - gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group); - - /* Enque this early to reduce number of expose events. */ - gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group)); - - /* Figure out current style of the expander arrow. */ - if (group->priv->collapsed) - { - if (group->priv->expander_style == GTK_EXPANDER_EXPANDED) - group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED; - else - group->priv->expander_style = GTK_EXPANDER_COLLAPSED; - } - else - { - if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED) - group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED; - else - group->priv->expander_style = GTK_EXPANDER_EXPANDED; - } - - gtk_tool_item_group_force_expose (group); - - /* Finish animation when done. */ - if (timestamp >= ANIMATION_DURATION) - group->priv->animation_timeout = NULL; - - /* Ensure that all composited windows and child windows are repainted, before - * the parent widget gets its expose-event. This is needed to avoid heavy - * rendering artifacts. GTK+ should take care about this issue by itself I - * guess, but currently it doesn't. Also I don't understand the parameters - * of this issue well enough yet, to file a bug report. - */ - gdk_window_process_updates (GTK_WIDGET (group)->window, TRUE); - - return (group->priv->animation_timeout != NULL); -} - -/** - * gtk_tool_item_group_set_collapsed: - * @group: an #GtkToolItemGroup. - * @collapsed: whether the @group should be collapsed or expanded. - * - * Sets whether the @group should be collapsed or expanded. - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group, - gboolean collapsed) -{ - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - GtkWidget *parent; - - 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 != group->priv->collapsed) - { - if (group->priv->animation) - { - GTimeVal now; - - g_get_current_time (&now); - - if (group->priv->animation_timeout) - g_source_destroy (group->priv->animation_timeout); - - group->priv->animation_start = (now.tv_sec * G_USEC_PER_SEC + now.tv_usec); - group->priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT); - - g_source_set_callback (group->priv->animation_timeout, - gtk_tool_item_group_animation_cb, - group, NULL); - - g_source_attach (group->priv->animation_timeout, NULL); - } - else - { - group->priv->expander_style = GTK_EXPANDER_COLLAPSED; - gtk_tool_item_group_force_expose (group); - } - group->priv->collapsed = collapsed; - g_object_notify (G_OBJECT (group), "collapsed"); - } -} - -/** - * gtk_tool_item_group_set_ellipsize: - * @group: an #GtkToolItemGroup. - * @ellipsize: the #PangoEllipsizeMode labels in @group should use. - * - * Sets the ellipsization mode which should be used by labels in @group. - * - * Since: 2.18 - */ -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"); -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - _gtk_tool_item_group_palette_reconfigured (group); -#endif - } -} - -/** - * gtk_tool_item_group_get_name: - * @group: an #GtkToolItemGroup. - * - * Gets the name of @group. - * - * Returns: the name of @group. The name is an internal string of @group and must not be modified. - * - * Since: 2.18 - */ -G_CONST_RETURN gchar* -gtk_tool_item_group_get_name (GtkToolItemGroup *group) -{ - GtkWidget *label; - - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_NAME); - - label = gtk_tool_item_group_get_label (group); - return gtk_label_get_text (GTK_LABEL (label)); -} - -/** - * gtk_tool_item_group_get_collapsed: - * @group: an GtkToolItemGroup. - * - * Gets whether @group is collapsed or expanded. - * - * Returns: %TRUE if @group is collapsed, %FALSE if it is expanded. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the ellipsization mode of @group. - * - * Returns: the #PangoEllipsizeMode of @group. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the relief mode of the header button of @group. - * - * Returns: the #GtkReliefStyle - * - * Since: 2.18 - */ -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: an #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.18 - */ -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)); - - if (GTK_IS_BUTTON (child_widget)) - gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), TRUE); - - gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group)); -} - -/** - * gtk_tool_item_group_set_item_position: - * @group: an #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.18 - */ -void -gtk_tool_item_group_set_item_position (GtkToolItemGroup *group, - GtkToolItem *item, - gint position) -{ - gint old_position; - GList *link; - 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); - - child = gtk_tool_item_group_get_child (group, item, &old_position, &link); - - g_return_if_fail (child != NULL); - - if (position == old_position) - return; - - group->priv->children = g_list_delete_link (group->priv->children, link); - group->priv->children = g_list_insert (group->priv->children, child, position); - - gtk_widget_child_notify (GTK_WIDGET (item), "position"); - if (GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item)) - gtk_widget_queue_resize (GTK_WIDGET (group)); -} - -/** - * gtk_tool_item_group_get_item_position: - * @group: an #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.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the number of tool items in group. - * - * Returns: the number of tool items in group. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * @index: the index. - * - * Gets the tool item at index in group. - * - * Returns: the #GtkToolItem at index. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * @x: the x position. - * @y: the y position. - * - * Gets the tool item at position (x, y). - * - * Returns: the #GtkToolItem at position (x, y). - * - * Since: 2.18 - */ -GtkToolItem* -gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group, - gint x, - gint y) -{ - GtkAllocation *allocation; - GtkOrientation orientation; - GList *it; - - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL); - - allocation = >K_WIDGET (group)->allocation; - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - - 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; - - allocation = >K_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; - GtkOrientation orientation; - GtkToolbarStyle style; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - g_return_if_fail (NULL != item_size); - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group)); - - 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_size_request (GTK_WIDGET (child->item), &child_requisition); - - 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; -} - -void -_gtk_tool_item_group_paint (GtkToolItemGroup *group, - cairo_t *cr) -{ - GtkWidget *widget = GTK_WIDGET (group); - - gdk_cairo_set_source_pixmap (cr, widget->window, - widget->allocation.x, - widget->allocation.y); - - if (group->priv->animation_timeout) - { - GtkOrientation orientation = gtk_tool_item_group_get_orientation (GTK_TOOL_SHELL (group)); - cairo_pattern_t *mask; - gdouble v0, v1; - - if (GTK_ORIENTATION_VERTICAL == orientation) - v1 = widget->allocation.height; - else - v1 = widget->allocation.width; - - v0 = v1 - 256; - - if (!GTK_WIDGET_VISIBLE (group->priv->header)) - v0 = MAX (v0, 0); - else if (GTK_ORIENTATION_VERTICAL == orientation) - v0 = MAX (v0, group->priv->header->allocation.height); - else - v0 = MAX (v0, group->priv->header->allocation.width); - - v1 = MIN (v0 + 256, v1); - - if (GTK_ORIENTATION_VERTICAL == orientation) - { - v0 += widget->allocation.y; - v1 += widget->allocation.y; - - mask = cairo_pattern_create_linear (0.0, v0, 0.0, v1); - } - else - { - v0 += widget->allocation.x; - v1 += widget->allocation.x; - - mask = cairo_pattern_create_linear (v0, 0.0, v1, 0.0); - } - - cairo_pattern_add_color_stop_rgba (mask, 0.00, 0.0, 0.0, 0.0, 1.00); - cairo_pattern_add_color_stop_rgba (mask, 0.25, 0.0, 0.0, 0.0, 0.25); - cairo_pattern_add_color_stop_rgba (mask, 0.50, 0.0, 0.0, 0.0, 0.10); - cairo_pattern_add_color_stop_rgba (mask, 0.75, 0.0, 0.0, 0.0, 0.01); - cairo_pattern_add_color_stop_rgba (mask, 1.00, 0.0, 0.0, 0.0, 0.00); - - cairo_mask (cr, mask); - cairo_pattern_destroy (mask); - } - else - cairo_paint (cr); -} - -gint -_gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group, - gint limit, - gboolean vertical, - gboolean animation) -{ - GtkRequisition requisition; - - gtk_widget_size_request (GTK_WIDGET (group), &requisition); - - if (!group->priv->collapsed || group->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 (group->priv->animation_timeout && animation) - { - gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group); - - timestamp = MIN (timestamp, ANIMATION_DURATION); - - if (group->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 G_GNUC_UNUSED) -{ - 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); -} -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - * Jan Arne Petersen - */ - -#include "gtktoolpaletteprivate.h" - -#include -#include -#include - -#define P_(msgid) (msgid) - -#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_NAME NULL -#define DEFAULT_COLLAPSED FALSE -#define DEFAULT_ELLIPSIZE PANGO_ELLIPSIZE_NONE - -/** - * SECTION:GtkToolItemGroup - * @short_description: A sub container used in a tool palette - * @include: gtktoolitemgroup.h - * - * An #GtkToolItemGroup is used together with #GtkToolPalette to add #GtkToolItems to a palette like container - * with different categories and drag and drop support. - * - * Since: 2.18 - */ - -enum -{ - PROP_NONE, - PROP_NAME, - 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; - - GList *children; - - gboolean animation; - gint64 animation_start; - GSource *animation_timeout; - GtkExpanderStyle expander_style; - gint expander_size; - gint header_spacing; - PangoEllipsizeMode ellipsize; - - gulong focus_set_id; - GtkWidget *toplevel; - - GtkSettings *settings; - gulong settings_connection; - - 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_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL, gtk_tool_item_group_tool_shell_init)); - -static GtkWidget* -gtk_tool_item_group_get_alignment (GtkToolItemGroup *group) -{ - return gtk_bin_get_child (GTK_BIN (group->priv->header)); -} - -static GtkWidget* -gtk_tool_item_group_get_label (GtkToolItemGroup *group) -{ - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - return gtk_bin_get_child (GTK_BIN (alignment)); -} - -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_tool_palette_get_orientation (GTK_TOOL_PALETTE (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 GtkIconSize -gtk_tool_item_group_get_icon_size (GtkToolShell *shell) -{ - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell)); - - if (GTK_IS_TOOL_PALETTE (parent)) - return gtk_tool_palette_get_icon_size (GTK_TOOL_PALETTE (parent)); - - return GTK_ICON_SIZE_SMALL_TOOLBAR; -} - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - -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) -{ - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell)); - - if (GTK_IS_TOOL_PALETTE (parent)) - { - GtkOrientation orientation = gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent)); - if (GTK_ORIENTATION_HORIZONTAL == orientation && - (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell)/* || - GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell)*/)) - return GTK_ORIENTATION_VERTICAL; - } - - 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; -} - -#endif - -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")) - { - animation_change_notify (group); - } -} - -static void -gtk_tool_item_group_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkToolItemGroupPrivate* priv = group->priv; - GtkSettings *old_settings = priv->settings; - GtkSettings *settings; - - if (gtk_widget_has_screen (GTK_WIDGET (group))) - settings = gtk_widget_get_settings (GTK_WIDGET (group)); - else - settings = NULL; - - if (settings == old_settings) - return; - - if (old_settings) - { - g_signal_handler_disconnect (old_settings, priv->settings_connection); - 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_icon_size = gtk_tool_item_group_get_icon_size; - iface->get_orientation = gtk_tool_item_group_get_orientation; - iface->get_style = gtk_tool_item_group_get_style; -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - 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; -#endif -} - -static gboolean -gtk_tool_item_group_header_expose_event_cb (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - GtkExpanderStyle expander_style; - GtkOrientation orientation; - gint x, y; - GtkTextDirection direction; - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - expander_style = group->priv->expander_style; - direction = gtk_widget_get_direction (widget); - - if (GTK_ORIENTATION_VERTICAL == orientation) - { - if (GTK_TEXT_DIR_RTL == direction) - x = widget->allocation.x + widget->allocation.width - group->priv->expander_size / 2; - else - x = widget->allocation.x + group->priv->expander_size / 2; - y = widget->allocation.y + widget->allocation.height / 2; - } - else - { - x = widget->allocation.x + widget->allocation.width / 2; - y = widget->allocation.y + group->priv->expander_size / 2; - - /* Unfortunatly gtk_paint_expander() doesn't support rotated drawing - * modes. Luckily the following shady arithmetics produce the desired - * result. */ - expander_style = GTK_EXPANDER_EXPANDED - expander_style; /* XXX */ - } - - gtk_paint_expander (widget->style, widget->window, - group->priv->header->state, - &event->area, GTK_WIDGET (group), - "tool-palette-header", x, y, - expander_style); - - return FALSE; -} - -static void -gtk_tool_item_group_header_size_request_cb (GtkWidget *widget G_GNUC_UNUSED, - GtkRequisition *requisition, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - requisition->height = MAX (requisition->height, group->priv->expander_size); -} - -static void -gtk_tool_item_group_header_clicked_cb (GtkButton *button G_GNUC_UNUSED, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - GtkWidget *parent = gtk_widget_get_parent (data); - - if (group->priv->collapsed || - !GTK_IS_TOOL_PALETTE (parent) || - !gtk_tool_palette_get_exclusive (GTK_TOOL_PALETTE (parent), data)) - gtk_tool_item_group_set_collapsed (group, !group->priv->collapsed); -} - -static void -gtk_tool_item_group_header_adjust_style (GtkToolItemGroup *group) -{ - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - GtkWidget *label = gtk_bin_get_child (GTK_BIN (alignment)); - GtkWidget *widget = GTK_WIDGET (group); - gint dx = 0, dy = 0; - GtkTextDirection direction = gtk_widget_get_direction (widget); - - gtk_widget_style_get (widget, - "header-spacing", &group->priv->header_spacing, - "expander-size", &group->priv->expander_size, - NULL); - - switch (gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group))) - { - case GTK_ORIENTATION_HORIZONTAL: - dy = group->priv->header_spacing + group->priv->expander_size; - gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE); - if (GTK_TEXT_DIR_RTL == direction) - gtk_label_set_angle (GTK_LABEL (label), -90); - else - gtk_label_set_angle (GTK_LABEL (label), 90); - break; - - case GTK_ORIENTATION_VERTICAL: - dx = group->priv->header_spacing + group->priv->expander_size; - gtk_label_set_ellipsize (GTK_LABEL (label), group->priv->ellipsize); - gtk_label_set_angle (GTK_LABEL (label), 0); - break; - } - - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), dy, 0, dx, 0); -} - -static void -gtk_tool_item_group_init (GtkToolItemGroup *group) -{ - GtkWidget *alignment; - GtkWidget *label; - - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (group), FALSE); - - group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group, - GTK_TYPE_TOOL_ITEM_GROUP, - GtkToolItemGroupPrivate); - - group->priv->children = NULL; - group->priv->header_spacing = DEFAULT_HEADER_SPACING; - group->priv->expander_size = DEFAULT_EXPANDER_SIZE; - group->priv->expander_style = GTK_EXPANDER_EXPANDED; - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); - gtk_container_add (GTK_CONTAINER (alignment), label); - gtk_widget_show_all (alignment); - - gtk_widget_push_composite_child (); - group->priv->header = gtk_button_new (); - gtk_widget_set_composite_name (group->priv->header, "header"); - gtk_widget_pop_composite_child (); - - g_object_ref_sink (group->priv->header); - gtk_button_set_focus_on_click (GTK_BUTTON (group->priv->header), FALSE); - gtk_container_add (GTK_CONTAINER (group->priv->header), alignment); - gtk_widget_set_parent (group->priv->header, GTK_WIDGET (group)); - - gtk_tool_item_group_header_adjust_style (group); - - g_signal_connect_after (alignment, "expose-event", - G_CALLBACK (gtk_tool_item_group_header_expose_event_cb), - group); - g_signal_connect_after (alignment, "size-request", - G_CALLBACK (gtk_tool_item_group_header_size_request_cb), - group); - - g_signal_connect (group->priv->header, "clicked", - G_CALLBACK (gtk_tool_item_group_header_clicked_cb), - 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_NAME: - gtk_tool_item_group_set_name (group, g_value_get_string (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_NAME: - g_value_set_string (value, gtk_tool_item_group_get_name (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); - - if (group->priv->children) - { - g_list_free (group->priv->children); - group->priv->children = NULL; - } - - 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); - - if (group->priv->toplevel) - { - /* disconnect focus tracking handler */ - g_signal_handler_disconnect (group->priv->toplevel, - group->priv->focus_set_id); - - group->priv->focus_set_id = 0; - group->priv->toplevel = NULL; - } - - 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) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkOrientation orientation; - GtkRequisition item_size; - gint requested_rows; - - if (group->priv->children && gtk_tool_item_group_get_name (group)) - { - gtk_widget_size_request (group->priv->header, requisition); - gtk_widget_show (group->priv->header); - } - else - { - requisition->width = requisition->height = 0; - gtk_widget_hide (group->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); - - requisition->width += border_width * 2; - requisition->height += border_width * 2; -} - -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_VISIBLE (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) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - - GtkRequisition item_size; - GtkAllocation item_area; - - GtkOrientation orientation; - GtkToolbarStyle style; - - gint min_rows; - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (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_area.width = 0; - item_area.height = 0; - - /* figure out the required columns (n_columns) and rows (n_rows) to place all items */ - if (!group->priv->collapsed || !group->priv->animation || group->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 - 2 * border_width; - n_columns = MAX (item_area.width / item_size.width, 1); - - /* calculate required rows for n_columns columns */ - 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 (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_size_request (GTK_WIDGET (child->item), &req); - - 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 - 2 * border_width; - 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 = group->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_size_request (GTK_WIDGET (child->item), &req); - - 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 = group->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_size_request (GTK_WIDGET (child->item), &req); - - 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_VISIBLE (group->priv->header)) - { - GtkRequisition child_requisition; - - gtk_widget_size_request (group->priv->header, &child_requisition); - - 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 + 2 * border_width; - inquery->height += item_area.height + 2 * border_width; -} - -static void -gtk_tool_item_group_real_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkRequisition child_requisition; - GtkAllocation child_allocation; - - GtkRequisition item_size; - GtkAllocation item_area; - - GtkOrientation orientation; - GtkToolbarStyle style; - - GList *it; - - gint n_columns, n_rows = 1; - gint min_rows; - - GtkTextDirection direction = gtk_widget_get_direction (widget); - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group)); - - /* chain up */ - GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->size_allocate (widget, allocation); - - child_allocation.x = border_width; - child_allocation.y = border_width; - - /* place the header widget */ - if (GTK_WIDGET_VISIBLE (group->priv->header)) - { - gtk_widget_size_request (group->priv->header, &child_requisition); - - 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 - border_width - child_allocation.width; - } - - gtk_widget_size_allocate (group->priv->header, &child_allocation); - - 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 = border_width; - } - 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); - - /* 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 - 2 * border_width; - item_area.height = allocation->height - 2 * border_width - 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 - 2 * border_width - child_requisition.width; - item_area.height = allocation->height - 2 * border_width; - - 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 (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout) - { - gint col = 0, row = 0; - - for (it = group->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_size_request (GTK_WIDGET (child->item), &child_requisition); - 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); - 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 = group->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, - GtkAllocation *allocation) -{ - gtk_tool_item_group_real_size_allocate (widget, allocation); - - if (GTK_WIDGET_MAPPED (widget)) - gdk_window_invalidate_rect (widget->window, NULL, FALSE); -} - -static void -gtk_tool_item_group_set_focus_cb (GtkWidget *window G_GNUC_UNUSED, - GtkWidget *widget, - gpointer user_data) -{ - GtkAdjustment *adjustment; - 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_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p)); - adjustment = gtk_tool_palette_get_vadjustment (GTK_TOOL_PALETTE (p)); - - if (adjustment) - { - int y; - - /* Handle vertical adjustment. */ - if (gtk_widget_translate_coordinates - (widget, p, 0, 0, NULL, &y) && y < 0) - { - y += adjustment->value; - gtk_adjustment_clamp_page (adjustment, y, y + widget->allocation.height); - } - else if (gtk_widget_translate_coordinates - (widget, p, 0, widget->allocation.height, NULL, &y) && - y > p->allocation.height) - { - y += adjustment->value; - gtk_adjustment_clamp_page (adjustment, y - widget->allocation.height, y); - } - } - - adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p)); - - if (adjustment) - { - int x; - - /* Handle horizontal adjustment. */ - if (gtk_widget_translate_coordinates - (widget, p, 0, 0, &x, NULL) && x < 0) - { - x += adjustment->value; - gtk_adjustment_clamp_page (adjustment, x, x + widget->allocation.width); - } - else if (gtk_widget_translate_coordinates - (widget, p, widget->allocation.width, 0, &x, NULL) && - x > p->allocation.width) - { - x += adjustment->value; - gtk_adjustment_clamp_page (adjustment, x - widget->allocation.width, x); - } - - return; - } - } -} - -static void -gtk_tool_item_group_set_toplevel_window (GtkToolItemGroup *group, - GtkWidget *toplevel) -{ - if (toplevel != group->priv->toplevel) - { - if (group->priv->toplevel) - { - /* Disconnect focus tracking handler. */ - g_signal_handler_disconnect (group->priv->toplevel, - group->priv->focus_set_id); - - group->priv->focus_set_id = 0; - group->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. - */ - group->priv->focus_set_id = - g_signal_connect (toplevel, "set-focus", - G_CALLBACK (gtk_tool_item_group_set_focus_cb), - group); - - group->priv->toplevel = toplevel; - } - } -} - -static void -gtk_tool_item_group_realize (GtkWidget *widget) -{ - GtkWidget *toplevel_window; - const gint border_width = GTK_CONTAINER (widget)->border_width; - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - GdkWindowAttr attributes; - GdkDisplay *display; - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x + border_width; - attributes.y = widget->allocation.y + border_width; - attributes.width = widget->allocation.width - border_width * 2; - attributes.height = widget->allocation.height - border_width * 2; - 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 | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_BUTTON_MOTION_MASK; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - - display = gdk_drawable_get_display (widget->window); - - if (gdk_display_supports_composite (display)) - gdk_window_set_composited (widget->window, TRUE); - - gdk_window_set_user_data (widget->window, widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - - gtk_container_forall (GTK_CONTAINER (widget), - (GtkCallback) gtk_widget_set_parent_window, - widget->window); - - gtk_widget_queue_resize_no_redraw (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_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - gtk_tool_item_group_header_adjust_style (GTK_TOOL_ITEM_GROUP (widget)); - GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->style_set (widget, previous_style); -} - -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; - GList *it; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container)); - group = GTK_TOOL_ITEM_GROUP (container); - - for (it = group->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); - group->priv->children = g_list_delete_link (group->priv->children, it); - - gtk_widget_queue_resize (GTK_WIDGET (container)); - break; - } - } -} - -static void -gtk_tool_item_group_forall (GtkContainer *container, - gboolean internals, - GtkCallback callback, - gpointer callback_data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container); - GList *children; - - if (internals && group->priv->header) - callback (group->priv->header, callback_data); - - children = group->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 G_GNUC_UNUSED) -{ - 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_VISIBLE (group) && GTK_WIDGET_VISIBLE (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->size_request = gtk_tool_item_group_size_request; - 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_set = gtk_tool_item_group_style_set; - wclass->screen_changed = gtk_tool_item_group_screen_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_NAME, - g_param_spec_string ("name", - P_("Name"), - P_("The name of this item group"), - DEFAULT_NAME, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_COLLAPSED, - g_param_spec_boolean ("collapsed", - P_("Collapsed"), - P_("Wether the group has been collapsed and items are hidden"), - DEFAULT_COLLAPSED, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_ELLIPSIZE, - g_param_spec_enum ("header-relief", - P_("header-relif"), - P_("Relief of the group header button"), - GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NORMAL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_widget_class_install_style_property (wclass, - g_param_spec_int ("expander-size", - P_("Expander Size"), - P_("Size of the expander arrow"), - 0, - G_MAXINT, - DEFAULT_EXPANDER_SIZE, - G_PARAM_READABLE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_widget_class_install_style_property (wclass, - g_param_spec_int ("header-spacing", - P_("Header Spacing"), - P_("Spacing between expander arrow and caption"), - 0, - G_MAXINT, - DEFAULT_HEADER_SPACING, - G_PARAM_READABLE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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 toolbar grows"), - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_FILL, - g_param_spec_boolean ("fill", - P_("Fill"), - P_("Whether the item should fill the avaiable space"), - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_type_class_add_private (cls, sizeof (GtkToolItemGroupPrivate)); -} - -/** - * gtk_tool_item_group_new: - * @name: the name of the new group. - * - * Creates a new tool item group with name @name. - * - * Returns: a new #GtkToolItemGroup. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_item_group_new (const gchar *name) -{ - return g_object_new (GTK_TYPE_TOOL_ITEM_GROUP, "name", name, NULL); -} - -/** - * gtk_tool_item_group_set_name: - * @group: an #GtkToolItemGroup. - * @name: the new name of of the group. - * - * Sets the name of the tool item group. The name is displayed in the header - * of the group. - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_name (GtkToolItemGroup *group, - const gchar *name) -{ - const gchar *current_name; - GtkWidget *label; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - current_name = gtk_tool_item_group_get_name (group); - - if (current_name != name && (!current_name || !name || strcmp (current_name, name))) - { - label = gtk_tool_item_group_get_label (group); - gtk_label_set_text (GTK_LABEL (label), name); - - if (name && group->priv->children) - gtk_widget_show (group->priv->header); - else - gtk_widget_hide (group->priv->header); - - g_object_notify (G_OBJECT (group), "name"); - } -} - -/** - * gtk_tool_item_group_header_relief: - * @group: an #GtkToolItemGroup. - * @style: The GtkReliefStyle - * - * Set the button relief of the group header. See #gtk_button_set_relief for - * details - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group, - GtkReliefStyle style) -{ - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - gtk_button_set_relief (GTK_BUTTON(group->priv->header), style); -} - -static gint64 -gtk_tool_item_group_get_animation_timestamp (GtkToolItemGroup *group) -{ - GTimeVal now; - g_source_get_current_time (group->priv->animation_timeout, &now); - return (now.tv_sec * G_USEC_PER_SEC + now.tv_usec - group->priv->animation_start) / 1000; -} - -static void -gtk_tool_item_group_force_expose (GtkToolItemGroup *group) -{ - if (GTK_WIDGET_REALIZED (group->priv->header)) - { - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - GdkRectangle area; - - /* Find the header button's arrow area... */ - area.x = alignment->allocation.x; - area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2; - area.height = group->priv->expander_size; - area.width = group->priv->expander_size; - - /* ... and invalidated it to get it animated. */ - gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE); - } - - if (GTK_WIDGET_REALIZED (group)) - { - GtkWidget *widget = GTK_WIDGET (group); - GtkWidget *parent = gtk_widget_get_parent (widget); - int x, y, width, height; - - /* Find the tool item area button's arrow area... */ - width = widget->allocation.width; - height = widget->allocation.height; - - gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y); - - if (GTK_WIDGET_VISIBLE (group->priv->header)) - { - height -= group->priv->header->allocation.height; - y += group->priv->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); - gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group); - - /* Enque this early to reduce number of expose events. */ - gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group)); - - /* Figure out current style of the expander arrow. */ - if (group->priv->collapsed) - { - if (group->priv->expander_style == GTK_EXPANDER_EXPANDED) - group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED; - else - group->priv->expander_style = GTK_EXPANDER_COLLAPSED; - } - else - { - if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED) - group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED; - else - group->priv->expander_style = GTK_EXPANDER_EXPANDED; - } - - gtk_tool_item_group_force_expose (group); - - /* Finish animation when done. */ - if (timestamp >= ANIMATION_DURATION) - group->priv->animation_timeout = NULL; - - /* Ensure that all composited windows and child windows are repainted, before - * the parent widget gets its expose-event. This is needed to avoid heavy - * rendering artifacts. GTK+ should take care about this issue by itself I - * guess, but currently it doesn't. Also I don't understand the parameters - * of this issue well enough yet, to file a bug report. - */ - gdk_window_process_updates (GTK_WIDGET (group)->window, TRUE); - - return (group->priv->animation_timeout != NULL); -} - -/** - * gtk_tool_item_group_set_collapsed: - * @group: an #GtkToolItemGroup. - * @collapsed: whether the @group should be collapsed or expanded. - * - * Sets whether the @group should be collapsed or expanded. - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group, - gboolean collapsed) -{ - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - GtkWidget *parent; - - 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 != group->priv->collapsed) - { - if (group->priv->animation) - { - GTimeVal now; - - g_get_current_time (&now); - - if (group->priv->animation_timeout) - g_source_destroy (group->priv->animation_timeout); - - group->priv->animation_start = (now.tv_sec * G_USEC_PER_SEC + now.tv_usec); - group->priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT); - - g_source_set_callback (group->priv->animation_timeout, - gtk_tool_item_group_animation_cb, - group, NULL); - - g_source_attach (group->priv->animation_timeout, NULL); - } - else - { - group->priv->expander_style = GTK_EXPANDER_COLLAPSED; - gtk_tool_item_group_force_expose (group); - } - group->priv->collapsed = collapsed; - g_object_notify (G_OBJECT (group), "collapsed"); - } -} - -/** - * gtk_tool_item_group_set_ellipsize: - * @group: an #GtkToolItemGroup. - * @ellipsize: the #PangoEllipsizeMode labels in @group should use. - * - * Sets the ellipsization mode which should be used by labels in @group. - * - * Since: 2.18 - */ -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"); -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - _gtk_tool_item_group_palette_reconfigured (group); -#endif - } -} - -/** - * gtk_tool_item_group_get_name: - * @group: an #GtkToolItemGroup. - * - * Gets the name of @group. - * - * Returns: the name of @group. The name is an internal string of @group and must not be modified. - * - * Since: 2.18 - */ -G_CONST_RETURN gchar* -gtk_tool_item_group_get_name (GtkToolItemGroup *group) -{ - GtkWidget *label; - - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_NAME); - - label = gtk_tool_item_group_get_label (group); - return gtk_label_get_text (GTK_LABEL (label)); -} - -/** - * gtk_tool_item_group_get_collapsed: - * @group: an GtkToolItemGroup. - * - * Gets whether @group is collapsed or expanded. - * - * Returns: %TRUE if @group is collapsed, %FALSE if it is expanded. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the ellipsization mode of @group. - * - * Returns: the #PangoEllipsizeMode of @group. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the relief mode of the header button of @group. - * - * Returns: the #GtkReliefStyle - * - * Since: 2.18 - */ -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: an #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.18 - */ -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)); - - if (GTK_IS_BUTTON (child_widget)) - gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), TRUE); - - gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group)); -} - -/** - * gtk_tool_item_group_set_item_position: - * @group: an #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.18 - */ -void -gtk_tool_item_group_set_item_position (GtkToolItemGroup *group, - GtkToolItem *item, - gint position) -{ - gint old_position; - GList *link; - 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); - - child = gtk_tool_item_group_get_child (group, item, &old_position, &link); - - g_return_if_fail (child != NULL); - - if (position == old_position) - return; - - group->priv->children = g_list_delete_link (group->priv->children, link); - group->priv->children = g_list_insert (group->priv->children, child, position); - - gtk_widget_child_notify (GTK_WIDGET (item), "position"); - if (GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item)) - gtk_widget_queue_resize (GTK_WIDGET (group)); -} - -/** - * gtk_tool_item_group_get_item_position: - * @group: an #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.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the number of tool items in group. - * - * Returns: the number of tool items in group. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * @index: the index. - * - * Gets the tool item at index in group. - * - * Returns: the #GtkToolItem at index. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * @x: the x position. - * @y: the y position. - * - * Gets the tool item at position (x, y). - * - * Returns: the #GtkToolItem at position (x, y). - * - * Since: 2.18 - */ -GtkToolItem* -gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group, - gint x, - gint y) -{ - GtkAllocation *allocation; - GtkOrientation orientation; - GList *it; - - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL); - - allocation = >K_WIDGET (group)->allocation; - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - - 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; - - allocation = >K_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; - GtkOrientation orientation; - GtkToolbarStyle style; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - g_return_if_fail (NULL != item_size); - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group)); - - 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_size_request (GTK_WIDGET (child->item), &child_requisition); - - 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; -} - -void -_gtk_tool_item_group_paint (GtkToolItemGroup *group, - cairo_t *cr) -{ - GtkWidget *widget = GTK_WIDGET (group); - - gdk_cairo_set_source_pixmap (cr, widget->window, - widget->allocation.x, - widget->allocation.y); - - if (group->priv->animation_timeout) - { - GtkOrientation orientation = gtk_tool_item_group_get_orientation (GTK_TOOL_SHELL (group)); - cairo_pattern_t *mask; - gdouble v0, v1; - - if (GTK_ORIENTATION_VERTICAL == orientation) - v1 = widget->allocation.height; - else - v1 = widget->allocation.width; - - v0 = v1 - 256; - - if (!GTK_WIDGET_VISIBLE (group->priv->header)) - v0 = MAX (v0, 0); - else if (GTK_ORIENTATION_VERTICAL == orientation) - v0 = MAX (v0, group->priv->header->allocation.height); - else - v0 = MAX (v0, group->priv->header->allocation.width); - - v1 = MIN (v0 + 256, v1); - - if (GTK_ORIENTATION_VERTICAL == orientation) - { - v0 += widget->allocation.y; - v1 += widget->allocation.y; - - mask = cairo_pattern_create_linear (0.0, v0, 0.0, v1); - } - else - { - v0 += widget->allocation.x; - v1 += widget->allocation.x; - - mask = cairo_pattern_create_linear (v0, 0.0, v1, 0.0); - } - - cairo_pattern_add_color_stop_rgba (mask, 0.00, 0.0, 0.0, 0.0, 1.00); - cairo_pattern_add_color_stop_rgba (mask, 0.25, 0.0, 0.0, 0.0, 0.25); - cairo_pattern_add_color_stop_rgba (mask, 0.50, 0.0, 0.0, 0.0, 0.10); - cairo_pattern_add_color_stop_rgba (mask, 0.75, 0.0, 0.0, 0.0, 0.01); - cairo_pattern_add_color_stop_rgba (mask, 1.00, 0.0, 0.0, 0.0, 0.00); - - cairo_mask (cr, mask); - cairo_pattern_destroy (mask); - } - else - cairo_paint (cr); -} - -gint -_gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group, - gint limit, - gboolean vertical, - gboolean animation) -{ - GtkRequisition requisition; - - gtk_widget_size_request (GTK_WIDGET (group), &requisition); - - if (!group->priv->collapsed || group->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 (group->priv->animation_timeout && animation) - { - gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group); - - timestamp = MIN (timestamp, ANIMATION_DURATION); - - if (group->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 G_GNUC_UNUSED) -{ - 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); -} -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - * Jan Arne Petersen - */ - -#include "gtktoolpaletteprivate.h" - -#include -#include -#include - -#define P_(msgid) (msgid) - -#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_NAME NULL -#define DEFAULT_COLLAPSED FALSE -#define DEFAULT_ELLIPSIZE PANGO_ELLIPSIZE_NONE - -/** - * SECTION:GtkToolItemGroup - * @short_description: A sub container used in a tool palette - * @include: gtktoolitemgroup.h - * - * An #GtkToolItemGroup is used together with #GtkToolPalette to add #GtkToolItems to a palette like container - * with different categories and drag and drop support. - * - * Since: 2.18 - */ - -enum -{ - PROP_NONE, - PROP_NAME, - 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; - - GList *children; - - gboolean animation; - gint64 animation_start; - GSource *animation_timeout; - GtkExpanderStyle expander_style; - gint expander_size; - gint header_spacing; - PangoEllipsizeMode ellipsize; - - gulong focus_set_id; - GtkWidget *toplevel; - - GtkSettings *settings; - gulong settings_connection; - - 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_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL, gtk_tool_item_group_tool_shell_init)); - -static GtkWidget* -gtk_tool_item_group_get_alignment (GtkToolItemGroup *group) -{ - return gtk_bin_get_child (GTK_BIN (group->priv->header)); -} - -static GtkWidget* -gtk_tool_item_group_get_label (GtkToolItemGroup *group) -{ - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - return gtk_bin_get_child (GTK_BIN (alignment)); -} - -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_tool_palette_get_orientation (GTK_TOOL_PALETTE (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 GtkIconSize -gtk_tool_item_group_get_icon_size (GtkToolShell *shell) -{ - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell)); - - if (GTK_IS_TOOL_PALETTE (parent)) - return gtk_tool_palette_get_icon_size (GTK_TOOL_PALETTE (parent)); - - return GTK_ICON_SIZE_SMALL_TOOLBAR; -} - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - -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) -{ - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell)); - - if (GTK_IS_TOOL_PALETTE (parent)) - { - GtkOrientation orientation = gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent)); - if (GTK_ORIENTATION_HORIZONTAL == orientation && - (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell)/* || - GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell)*/)) - return GTK_ORIENTATION_VERTICAL; - } - - 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; -} - -#endif - -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")) - { - animation_change_notify (group); - } -} - -static void -gtk_tool_item_group_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkToolItemGroupPrivate* priv = group->priv; - GtkSettings *old_settings = priv->settings; - GtkSettings *settings; - - if (gtk_widget_has_screen (GTK_WIDGET (group))) - settings = gtk_widget_get_settings (GTK_WIDGET (group)); - else - settings = NULL; - - if (settings == old_settings) - return; - - if (old_settings) - { - g_signal_handler_disconnect (old_settings, priv->settings_connection); - 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_icon_size = gtk_tool_item_group_get_icon_size; - iface->get_orientation = gtk_tool_item_group_get_orientation; - iface->get_style = gtk_tool_item_group_get_style; -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - 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; -#endif -} - -static gboolean -gtk_tool_item_group_header_expose_event_cb (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - GtkExpanderStyle expander_style; - GtkOrientation orientation; - gint x, y; - GtkTextDirection direction; - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - expander_style = group->priv->expander_style; - direction = gtk_widget_get_direction (widget); - - if (GTK_ORIENTATION_VERTICAL == orientation) - { - if (GTK_TEXT_DIR_RTL == direction) - x = widget->allocation.x + widget->allocation.width - group->priv->expander_size / 2; - else - x = widget->allocation.x + group->priv->expander_size / 2; - y = widget->allocation.y + widget->allocation.height / 2; - } - else - { - x = widget->allocation.x + widget->allocation.width / 2; - y = widget->allocation.y + group->priv->expander_size / 2; - - /* Unfortunatly gtk_paint_expander() doesn't support rotated drawing - * modes. Luckily the following shady arithmetics produce the desired - * result. */ - expander_style = GTK_EXPANDER_EXPANDED - expander_style; /* XXX */ - } - - gtk_paint_expander (widget->style, widget->window, - group->priv->header->state, - &event->area, GTK_WIDGET (group), - "tool-palette-header", x, y, - expander_style); - - return FALSE; -} - -static void -gtk_tool_item_group_header_size_request_cb (GtkWidget *widget G_GNUC_UNUSED, - GtkRequisition *requisition, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - requisition->height = MAX (requisition->height, group->priv->expander_size); -} - -static void -gtk_tool_item_group_header_clicked_cb (GtkButton *button G_GNUC_UNUSED, - gpointer data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data); - GtkWidget *parent = gtk_widget_get_parent (data); - - if (group->priv->collapsed || - !GTK_IS_TOOL_PALETTE (parent) || - !gtk_tool_palette_get_exclusive (GTK_TOOL_PALETTE (parent), data)) - gtk_tool_item_group_set_collapsed (group, !group->priv->collapsed); -} - -static void -gtk_tool_item_group_header_adjust_style (GtkToolItemGroup *group) -{ - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - GtkWidget *label = gtk_bin_get_child (GTK_BIN (alignment)); - GtkWidget *widget = GTK_WIDGET (group); - gint dx = 0, dy = 0; - GtkTextDirection direction = gtk_widget_get_direction (widget); - - gtk_widget_style_get (widget, - "header-spacing", &group->priv->header_spacing, - "expander-size", &group->priv->expander_size, - NULL); - - switch (gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group))) - { - case GTK_ORIENTATION_HORIZONTAL: - dy = group->priv->header_spacing + group->priv->expander_size; - gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE); - if (GTK_TEXT_DIR_RTL == direction) - gtk_label_set_angle (GTK_LABEL (label), -90); - else - gtk_label_set_angle (GTK_LABEL (label), 90); - break; - - case GTK_ORIENTATION_VERTICAL: - dx = group->priv->header_spacing + group->priv->expander_size; - gtk_label_set_ellipsize (GTK_LABEL (label), group->priv->ellipsize); - gtk_label_set_angle (GTK_LABEL (label), 0); - break; - } - - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), dy, 0, dx, 0); -} - -static void -gtk_tool_item_group_init (GtkToolItemGroup *group) -{ - GtkWidget *alignment; - GtkWidget *label; - - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (group), FALSE); - - group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group, - GTK_TYPE_TOOL_ITEM_GROUP, - GtkToolItemGroupPrivate); - - group->priv->children = NULL; - group->priv->header_spacing = DEFAULT_HEADER_SPACING; - group->priv->expander_size = DEFAULT_EXPANDER_SIZE; - group->priv->expander_style = GTK_EXPANDER_EXPANDED; - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); - gtk_container_add (GTK_CONTAINER (alignment), label); - gtk_widget_show_all (alignment); - - gtk_widget_push_composite_child (); - group->priv->header = gtk_button_new (); - gtk_widget_set_composite_name (group->priv->header, "header"); - gtk_widget_pop_composite_child (); - - g_object_ref_sink (group->priv->header); - gtk_button_set_focus_on_click (GTK_BUTTON (group->priv->header), FALSE); - gtk_container_add (GTK_CONTAINER (group->priv->header), alignment); - gtk_widget_set_parent (group->priv->header, GTK_WIDGET (group)); - - gtk_tool_item_group_header_adjust_style (group); - - g_signal_connect_after (alignment, "expose-event", - G_CALLBACK (gtk_tool_item_group_header_expose_event_cb), - group); - g_signal_connect_after (alignment, "size-request", - G_CALLBACK (gtk_tool_item_group_header_size_request_cb), - group); - - g_signal_connect (group->priv->header, "clicked", - G_CALLBACK (gtk_tool_item_group_header_clicked_cb), - 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_NAME: - gtk_tool_item_group_set_name (group, g_value_get_string (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_NAME: - g_value_set_string (value, gtk_tool_item_group_get_name (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); - - if (group->priv->children) - { - g_list_free (group->priv->children); - group->priv->children = NULL; - } - - 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); - - if (group->priv->toplevel) - { - /* disconnect focus tracking handler */ - g_signal_handler_disconnect (group->priv->toplevel, - group->priv->focus_set_id); - - group->priv->focus_set_id = 0; - group->priv->toplevel = NULL; - } - - 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) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkOrientation orientation; - GtkRequisition item_size; - gint requested_rows; - - if (group->priv->children && gtk_tool_item_group_get_name (group)) - { - gtk_widget_size_request (group->priv->header, requisition); - gtk_widget_show (group->priv->header); - } - else - { - requisition->width = requisition->height = 0; - gtk_widget_hide (group->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); - - requisition->width += border_width * 2; - requisition->height += border_width * 2; -} - -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_VISIBLE (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) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - - GtkRequisition item_size; - GtkAllocation item_area; - - GtkOrientation orientation; - GtkToolbarStyle style; - - gint min_rows; - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (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_area.width = 0; - item_area.height = 0; - - /* figure out the required columns (n_columns) and rows (n_rows) to place all items */ - if (!group->priv->collapsed || !group->priv->animation || group->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 - 2 * border_width; - n_columns = MAX (item_area.width / item_size.width, 1); - - /* calculate required rows for n_columns columns */ - 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 (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_size_request (GTK_WIDGET (child->item), &req); - - 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 - 2 * border_width; - 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 = group->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_size_request (GTK_WIDGET (child->item), &req); - - 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 = group->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_size_request (GTK_WIDGET (child->item), &req); - - 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_VISIBLE (group->priv->header)) - { - GtkRequisition child_requisition; - - gtk_widget_size_request (group->priv->header, &child_requisition); - - 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 + 2 * border_width; - inquery->height += item_area.height + 2 * border_width; -} - -static void -gtk_tool_item_group_real_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget); - GtkRequisition child_requisition; - GtkAllocation child_allocation; - - GtkRequisition item_size; - GtkAllocation item_area; - - GtkOrientation orientation; - GtkToolbarStyle style; - - GList *it; - - gint n_columns, n_rows = 1; - gint min_rows; - - GtkTextDirection direction = gtk_widget_get_direction (widget); - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group)); - - /* chain up */ - GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->size_allocate (widget, allocation); - - child_allocation.x = border_width; - child_allocation.y = border_width; - - /* place the header widget */ - if (GTK_WIDGET_VISIBLE (group->priv->header)) - { - gtk_widget_size_request (group->priv->header, &child_requisition); - - 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 - border_width - child_allocation.width; - } - - gtk_widget_size_allocate (group->priv->header, &child_allocation); - - 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 = border_width; - } - 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); - - /* 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 - 2 * border_width; - item_area.height = allocation->height - 2 * border_width - 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 - 2 * border_width - child_requisition.width; - item_area.height = allocation->height - 2 * border_width; - - 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 (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout) - { - gint col = 0, row = 0; - - for (it = group->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_size_request (GTK_WIDGET (child->item), &child_requisition); - 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); - 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 = group->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, - GtkAllocation *allocation) -{ - gtk_tool_item_group_real_size_allocate (widget, allocation); - - if (GTK_WIDGET_MAPPED (widget)) - gdk_window_invalidate_rect (widget->window, NULL, FALSE); -} - -static void -gtk_tool_item_group_set_focus_cb (GtkWidget *window G_GNUC_UNUSED, - GtkWidget *widget, - gpointer user_data) -{ - GtkAdjustment *adjustment; - 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_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p)); - adjustment = gtk_tool_palette_get_vadjustment (GTK_TOOL_PALETTE (p)); - - if (adjustment) - { - int y; - - /* Handle vertical adjustment. */ - if (gtk_widget_translate_coordinates - (widget, p, 0, 0, NULL, &y) && y < 0) - { - y += adjustment->value; - gtk_adjustment_clamp_page (adjustment, y, y + widget->allocation.height); - } - else if (gtk_widget_translate_coordinates - (widget, p, 0, widget->allocation.height, NULL, &y) && - y > p->allocation.height) - { - y += adjustment->value; - gtk_adjustment_clamp_page (adjustment, y - widget->allocation.height, y); - } - } - - adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p)); - - if (adjustment) - { - int x; - - /* Handle horizontal adjustment. */ - if (gtk_widget_translate_coordinates - (widget, p, 0, 0, &x, NULL) && x < 0) - { - x += adjustment->value; - gtk_adjustment_clamp_page (adjustment, x, x + widget->allocation.width); - } - else if (gtk_widget_translate_coordinates - (widget, p, widget->allocation.width, 0, &x, NULL) && - x > p->allocation.width) - { - x += adjustment->value; - gtk_adjustment_clamp_page (adjustment, x - widget->allocation.width, x); - } - - return; - } - } -} - -static void -gtk_tool_item_group_set_toplevel_window (GtkToolItemGroup *group, - GtkWidget *toplevel) -{ - if (toplevel != group->priv->toplevel) - { - if (group->priv->toplevel) - { - /* Disconnect focus tracking handler. */ - g_signal_handler_disconnect (group->priv->toplevel, - group->priv->focus_set_id); - - group->priv->focus_set_id = 0; - group->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. - */ - group->priv->focus_set_id = - g_signal_connect (toplevel, "set-focus", - G_CALLBACK (gtk_tool_item_group_set_focus_cb), - group); - - group->priv->toplevel = toplevel; - } - } -} - -static void -gtk_tool_item_group_realize (GtkWidget *widget) -{ - GtkWidget *toplevel_window; - const gint border_width = GTK_CONTAINER (widget)->border_width; - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - GdkWindowAttr attributes; - GdkDisplay *display; - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x + border_width; - attributes.y = widget->allocation.y + border_width; - attributes.width = widget->allocation.width - border_width * 2; - attributes.height = widget->allocation.height - border_width * 2; - 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 | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_BUTTON_MOTION_MASK; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - - display = gdk_drawable_get_display (widget->window); - - if (gdk_display_supports_composite (display)) - gdk_window_set_composited (widget->window, TRUE); - - gdk_window_set_user_data (widget->window, widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - - gtk_container_forall (GTK_CONTAINER (widget), - (GtkCallback) gtk_widget_set_parent_window, - widget->window); - - gtk_widget_queue_resize_no_redraw (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_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - gtk_tool_item_group_header_adjust_style (GTK_TOOL_ITEM_GROUP (widget)); - GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->style_set (widget, previous_style); -} - -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; - GList *it; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container)); - group = GTK_TOOL_ITEM_GROUP (container); - - for (it = group->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); - group->priv->children = g_list_delete_link (group->priv->children, it); - - gtk_widget_queue_resize (GTK_WIDGET (container)); - break; - } - } -} - -static void -gtk_tool_item_group_forall (GtkContainer *container, - gboolean internals, - GtkCallback callback, - gpointer callback_data) -{ - GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container); - GList *children; - - if (internals && group->priv->header) - callback (group->priv->header, callback_data); - - children = group->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 G_GNUC_UNUSED) -{ - 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_VISIBLE (group) && GTK_WIDGET_VISIBLE (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->size_request = gtk_tool_item_group_size_request; - 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_set = gtk_tool_item_group_style_set; - wclass->screen_changed = gtk_tool_item_group_screen_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_NAME, - g_param_spec_string ("name", - P_("Name"), - P_("The name of this item group"), - DEFAULT_NAME, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_COLLAPSED, - g_param_spec_boolean ("collapsed", - P_("Collapsed"), - P_("Wether the group has been collapsed and items are hidden"), - DEFAULT_COLLAPSED, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_ELLIPSIZE, - g_param_spec_enum ("header-relief", - P_("header-relif"), - P_("Relief of the group header button"), - GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NORMAL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_widget_class_install_style_property (wclass, - g_param_spec_int ("expander-size", - P_("Expander Size"), - P_("Size of the expander arrow"), - 0, - G_MAXINT, - DEFAULT_EXPANDER_SIZE, - G_PARAM_READABLE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_widget_class_install_style_property (wclass, - g_param_spec_int ("header-spacing", - P_("Header Spacing"), - P_("Spacing between expander arrow and caption"), - 0, - G_MAXINT, - DEFAULT_HEADER_SPACING, - G_PARAM_READABLE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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 toolbar grows"), - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_FILL, - g_param_spec_boolean ("fill", - P_("Fill"), - P_("Whether the item should fill the avaiable space"), - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - 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, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_type_class_add_private (cls, sizeof (GtkToolItemGroupPrivate)); -} - -/** - * gtk_tool_item_group_new: - * @name: the name of the new group. - * - * Creates a new tool item group with name @name. - * - * Returns: a new #GtkToolItemGroup. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_item_group_new (const gchar *name) -{ - return g_object_new (GTK_TYPE_TOOL_ITEM_GROUP, "name", name, NULL); -} - -/** - * gtk_tool_item_group_set_name: - * @group: an #GtkToolItemGroup. - * @name: the new name of of the group. - * - * Sets the name of the tool item group. The name is displayed in the header - * of the group. - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_name (GtkToolItemGroup *group, - const gchar *name) -{ - const gchar *current_name; - GtkWidget *label; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - current_name = gtk_tool_item_group_get_name (group); - - if (current_name != name && (!current_name || !name || strcmp (current_name, name))) - { - label = gtk_tool_item_group_get_label (group); - gtk_label_set_text (GTK_LABEL (label), name); - - if (name && group->priv->children) - gtk_widget_show (group->priv->header); - else - gtk_widget_hide (group->priv->header); - - g_object_notify (G_OBJECT (group), "name"); - } -} - -/** - * gtk_tool_item_group_header_relief: - * @group: an #GtkToolItemGroup. - * @style: The GtkReliefStyle - * - * Set the button relief of the group header. See #gtk_button_set_relief for - * details - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group, - GtkReliefStyle style) -{ - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - gtk_button_set_relief (GTK_BUTTON(group->priv->header), style); -} - -static gint64 -gtk_tool_item_group_get_animation_timestamp (GtkToolItemGroup *group) -{ - GTimeVal now; - g_source_get_current_time (group->priv->animation_timeout, &now); - return (now.tv_sec * G_USEC_PER_SEC + now.tv_usec - group->priv->animation_start) / 1000; -} - -static void -gtk_tool_item_group_force_expose (GtkToolItemGroup *group) -{ - if (GTK_WIDGET_REALIZED (group->priv->header)) - { - GtkWidget *alignment = gtk_tool_item_group_get_alignment (group); - GdkRectangle area; - - /* Find the header button's arrow area... */ - area.x = alignment->allocation.x; - area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2; - area.height = group->priv->expander_size; - area.width = group->priv->expander_size; - - /* ... and invalidated it to get it animated. */ - gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE); - } - - if (GTK_WIDGET_REALIZED (group)) - { - GtkWidget *widget = GTK_WIDGET (group); - GtkWidget *parent = gtk_widget_get_parent (widget); - int x, y, width, height; - - /* Find the tool item area button's arrow area... */ - width = widget->allocation.width; - height = widget->allocation.height; - - gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y); - - if (GTK_WIDGET_VISIBLE (group->priv->header)) - { - height -= group->priv->header->allocation.height; - y += group->priv->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); - gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group); - - /* Enque this early to reduce number of expose events. */ - gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group)); - - /* Figure out current style of the expander arrow. */ - if (group->priv->collapsed) - { - if (group->priv->expander_style == GTK_EXPANDER_EXPANDED) - group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED; - else - group->priv->expander_style = GTK_EXPANDER_COLLAPSED; - } - else - { - if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED) - group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED; - else - group->priv->expander_style = GTK_EXPANDER_EXPANDED; - } - - gtk_tool_item_group_force_expose (group); - - /* Finish animation when done. */ - if (timestamp >= ANIMATION_DURATION) - group->priv->animation_timeout = NULL; - - /* Ensure that all composited windows and child windows are repainted, before - * the parent widget gets its expose-event. This is needed to avoid heavy - * rendering artifacts. GTK+ should take care about this issue by itself I - * guess, but currently it doesn't. Also I don't understand the parameters - * of this issue well enough yet, to file a bug report. - */ - gdk_window_process_updates (GTK_WIDGET (group)->window, TRUE); - - return (group->priv->animation_timeout != NULL); -} - -/** - * gtk_tool_item_group_set_collapsed: - * @group: an #GtkToolItemGroup. - * @collapsed: whether the @group should be collapsed or expanded. - * - * Sets whether the @group should be collapsed or expanded. - * - * Since: 2.18 - */ -void -gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group, - gboolean collapsed) -{ - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - GtkWidget *parent; - - 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 != group->priv->collapsed) - { - if (group->priv->animation) - { - GTimeVal now; - - g_get_current_time (&now); - - if (group->priv->animation_timeout) - g_source_destroy (group->priv->animation_timeout); - - group->priv->animation_start = (now.tv_sec * G_USEC_PER_SEC + now.tv_usec); - group->priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT); - - g_source_set_callback (group->priv->animation_timeout, - gtk_tool_item_group_animation_cb, - group, NULL); - - g_source_attach (group->priv->animation_timeout, NULL); - } - else - { - group->priv->expander_style = GTK_EXPANDER_COLLAPSED; - gtk_tool_item_group_force_expose (group); - } - group->priv->collapsed = collapsed; - g_object_notify (G_OBJECT (group), "collapsed"); - } -} - -/** - * gtk_tool_item_group_set_ellipsize: - * @group: an #GtkToolItemGroup. - * @ellipsize: the #PangoEllipsizeMode labels in @group should use. - * - * Sets the ellipsization mode which should be used by labels in @group. - * - * Since: 2.18 - */ -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"); -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - _gtk_tool_item_group_palette_reconfigured (group); -#endif - } -} - -/** - * gtk_tool_item_group_get_name: - * @group: an #GtkToolItemGroup. - * - * Gets the name of @group. - * - * Returns: the name of @group. The name is an internal string of @group and must not be modified. - * - * Since: 2.18 - */ -G_CONST_RETURN gchar* -gtk_tool_item_group_get_name (GtkToolItemGroup *group) -{ - GtkWidget *label; - - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_NAME); - - label = gtk_tool_item_group_get_label (group); - return gtk_label_get_text (GTK_LABEL (label)); -} - -/** - * gtk_tool_item_group_get_collapsed: - * @group: an GtkToolItemGroup. - * - * Gets whether @group is collapsed or expanded. - * - * Returns: %TRUE if @group is collapsed, %FALSE if it is expanded. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the ellipsization mode of @group. - * - * Returns: the #PangoEllipsizeMode of @group. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the relief mode of the header button of @group. - * - * Returns: the #GtkReliefStyle - * - * Since: 2.18 - */ -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: an #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.18 - */ -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)); - - if (GTK_IS_BUTTON (child_widget)) - gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), TRUE); - - gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group)); -} - -/** - * gtk_tool_item_group_set_item_position: - * @group: an #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.18 - */ -void -gtk_tool_item_group_set_item_position (GtkToolItemGroup *group, - GtkToolItem *item, - gint position) -{ - gint old_position; - GList *link; - 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); - - child = gtk_tool_item_group_get_child (group, item, &old_position, &link); - - g_return_if_fail (child != NULL); - - if (position == old_position) - return; - - group->priv->children = g_list_delete_link (group->priv->children, link); - group->priv->children = g_list_insert (group->priv->children, child, position); - - gtk_widget_child_notify (GTK_WIDGET (item), "position"); - if (GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item)) - gtk_widget_queue_resize (GTK_WIDGET (group)); -} - -/** - * gtk_tool_item_group_get_item_position: - * @group: an #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.18 - */ -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: an #GtkToolItemGroup. - * - * Gets the number of tool items in group. - * - * Returns: the number of tool items in group. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * @index: the index. - * - * Gets the tool item at index in group. - * - * Returns: the #GtkToolItem at index. - * - * Since: 2.18 - */ -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: an #GtkToolItemGroup. - * @x: the x position. - * @y: the y position. - * - * Gets the tool item at position (x, y). - * - * Returns: the #GtkToolItem at position (x, y). - * - * Since: 2.18 - */ -GtkToolItem* -gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group, - gint x, - gint y) -{ - GtkAllocation *allocation; - GtkOrientation orientation; - GList *it; - - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL); - - allocation = >K_WIDGET (group)->allocation; - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - - 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; - - allocation = >K_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; - GtkOrientation orientation; - GtkToolbarStyle style; - - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - g_return_if_fail (NULL != item_size); - - orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)); - style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group)); - - 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_size_request (GTK_WIDGET (child->item), &child_requisition); - - 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; -} - -void -_gtk_tool_item_group_paint (GtkToolItemGroup *group, - cairo_t *cr) -{ - GtkWidget *widget = GTK_WIDGET (group); - - gdk_cairo_set_source_pixmap (cr, widget->window, - widget->allocation.x, - widget->allocation.y); - - if (group->priv->animation_timeout) - { - GtkOrientation orientation = gtk_tool_item_group_get_orientation (GTK_TOOL_SHELL (group)); - cairo_pattern_t *mask; - gdouble v0, v1; - - if (GTK_ORIENTATION_VERTICAL == orientation) - v1 = widget->allocation.height; - else - v1 = widget->allocation.width; - - v0 = v1 - 256; - - if (!GTK_WIDGET_VISIBLE (group->priv->header)) - v0 = MAX (v0, 0); - else if (GTK_ORIENTATION_VERTICAL == orientation) - v0 = MAX (v0, group->priv->header->allocation.height); - else - v0 = MAX (v0, group->priv->header->allocation.width); - - v1 = MIN (v0 + 256, v1); - - if (GTK_ORIENTATION_VERTICAL == orientation) - { - v0 += widget->allocation.y; - v1 += widget->allocation.y; - - mask = cairo_pattern_create_linear (0.0, v0, 0.0, v1); - } - else - { - v0 += widget->allocation.x; - v1 += widget->allocation.x; - - mask = cairo_pattern_create_linear (v0, 0.0, v1, 0.0); - } - - cairo_pattern_add_color_stop_rgba (mask, 0.00, 0.0, 0.0, 0.0, 1.00); - cairo_pattern_add_color_stop_rgba (mask, 0.25, 0.0, 0.0, 0.0, 0.25); - cairo_pattern_add_color_stop_rgba (mask, 0.50, 0.0, 0.0, 0.0, 0.10); - cairo_pattern_add_color_stop_rgba (mask, 0.75, 0.0, 0.0, 0.0, 0.01); - cairo_pattern_add_color_stop_rgba (mask, 1.00, 0.0, 0.0, 0.0, 0.00); - - cairo_mask (cr, mask); - cairo_pattern_destroy (mask); - } - else - cairo_paint (cr); -} - -gint -_gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group, - gint limit, - gboolean vertical, - gboolean animation) -{ - GtkRequisition requisition; - - gtk_widget_size_request (GTK_WIDGET (group), &requisition); - - if (!group->priv->collapsed || group->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 (group->priv->animation_timeout && animation) - { - gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group); - - timestamp = MIN (timestamp, ANIMATION_DURATION); - - if (group->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 G_GNUC_UNUSED) -{ - 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); -} diff --git a/gtktoolitemgroup.h b/gtktoolitemgroup.h deleted file mode 100644 index c91f504a97..0000000000 --- a/gtktoolitemgroup.h +++ /dev/null @@ -1,276 +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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#ifndef __GTK_TOOL_ITEM_GROUP_H__ -#define __GTK_TOOL_ITEM_GROUP_H__ - -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_TOOL_ITEM_GROUP (gtk_tool_item_group_get_type()) -#define GTK_TOOL_ITEM_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroup)) -#define GTK_TOOL_ITEM_GROUP_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroupClass)) -#define GTK_IS_TOOL_ITEM_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_TOOL_ITEM_GROUP)) -#define GTK_IS_TOOL_ITEM_GROUP_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE(obj, GTK_TYPE_TOOL_ITEM_GROUP)) -#define GTK_TOOL_ITEM_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroupClass)) - -typedef struct _GtkToolItemGroup GtkToolItemGroup; -typedef struct _GtkToolItemGroupClass GtkToolItemGroupClass; -typedef struct _GtkToolItemGroupPrivate GtkToolItemGroupPrivate; - -/** - * GtkToolItemGroup: - * - * This should not be accessed directly. Use the accessor functions below. - */ -struct _GtkToolItemGroup -{ - GtkContainer parent_instance; - GtkToolItemGroupPrivate *priv; -}; - -struct _GtkToolItemGroupClass -{ - GtkContainerClass parent_class; -}; - -GType gtk_tool_item_group_get_type (void) G_GNUC_CONST; -GtkWidget* gtk_tool_item_group_new (const gchar *name); - -void gtk_tool_item_group_set_name (GtkToolItemGroup *group, - const gchar *name); -void gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group, - gboolean collapsed); -void gtk_tool_item_group_set_ellipsize (GtkToolItemGroup *group, - PangoEllipsizeMode ellipsize); -void gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group, - GtkReliefStyle style); - -G_CONST_RETURN gchar* gtk_tool_item_group_get_name (GtkToolItemGroup *group); -gboolean gtk_tool_item_group_get_collapsed (GtkToolItemGroup *group); -PangoEllipsizeMode gtk_tool_item_group_get_ellipsize (GtkToolItemGroup *group); -GtkReliefStyle gtk_tool_item_group_get_header_relief (GtkToolItemGroup *group); - -void gtk_tool_item_group_insert (GtkToolItemGroup *group, - GtkToolItem *item, - gint position); -void gtk_tool_item_group_set_item_position (GtkToolItemGroup *group, - GtkToolItem *item, - gint position); -gint gtk_tool_item_group_get_item_position (GtkToolItemGroup *group, - GtkToolItem *item); - -guint gtk_tool_item_group_get_n_items (GtkToolItemGroup *group); -GtkToolItem* gtk_tool_item_group_get_nth_item (GtkToolItemGroup *group, - guint index); -GtkToolItem* gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group, - gint x, - gint y); - -G_END_DECLS - -#endif /* __GTK_TOOL_ITEM_GROUP_H__ */ -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#ifndef __GTK_TOOL_ITEM_GROUP_H__ -#define __GTK_TOOL_ITEM_GROUP_H__ - -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_TOOL_ITEM_GROUP (gtk_tool_item_group_get_type()) -#define GTK_TOOL_ITEM_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroup)) -#define GTK_TOOL_ITEM_GROUP_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroupClass)) -#define GTK_IS_TOOL_ITEM_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_TOOL_ITEM_GROUP)) -#define GTK_IS_TOOL_ITEM_GROUP_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE(obj, GTK_TYPE_TOOL_ITEM_GROUP)) -#define GTK_TOOL_ITEM_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroupClass)) - -typedef struct _GtkToolItemGroup GtkToolItemGroup; -typedef struct _GtkToolItemGroupClass GtkToolItemGroupClass; -typedef struct _GtkToolItemGroupPrivate GtkToolItemGroupPrivate; - -/** - * GtkToolItemGroup: - * - * This should not be accessed directly. Use the accessor functions below. - */ -struct _GtkToolItemGroup -{ - GtkContainer parent_instance; - GtkToolItemGroupPrivate *priv; -}; - -struct _GtkToolItemGroupClass -{ - GtkContainerClass parent_class; -}; - -GType gtk_tool_item_group_get_type (void) G_GNUC_CONST; -GtkWidget* gtk_tool_item_group_new (const gchar *name); - -void gtk_tool_item_group_set_name (GtkToolItemGroup *group, - const gchar *name); -void gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group, - gboolean collapsed); -void gtk_tool_item_group_set_ellipsize (GtkToolItemGroup *group, - PangoEllipsizeMode ellipsize); -void gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group, - GtkReliefStyle style); - -G_CONST_RETURN gchar* gtk_tool_item_group_get_name (GtkToolItemGroup *group); -gboolean gtk_tool_item_group_get_collapsed (GtkToolItemGroup *group); -PangoEllipsizeMode gtk_tool_item_group_get_ellipsize (GtkToolItemGroup *group); -GtkReliefStyle gtk_tool_item_group_get_header_relief (GtkToolItemGroup *group); - -void gtk_tool_item_group_insert (GtkToolItemGroup *group, - GtkToolItem *item, - gint position); -void gtk_tool_item_group_set_item_position (GtkToolItemGroup *group, - GtkToolItem *item, - gint position); -gint gtk_tool_item_group_get_item_position (GtkToolItemGroup *group, - GtkToolItem *item); - -guint gtk_tool_item_group_get_n_items (GtkToolItemGroup *group); -GtkToolItem* gtk_tool_item_group_get_nth_item (GtkToolItemGroup *group, - guint index); -GtkToolItem* gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group, - gint x, - gint y); - -G_END_DECLS - -#endif /* __GTK_TOOL_ITEM_GROUP_H__ */ -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#ifndef __GTK_TOOL_ITEM_GROUP_H__ -#define __GTK_TOOL_ITEM_GROUP_H__ - -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_TOOL_ITEM_GROUP (gtk_tool_item_group_get_type()) -#define GTK_TOOL_ITEM_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroup)) -#define GTK_TOOL_ITEM_GROUP_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroupClass)) -#define GTK_IS_TOOL_ITEM_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_TOOL_ITEM_GROUP)) -#define GTK_IS_TOOL_ITEM_GROUP_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE(obj, GTK_TYPE_TOOL_ITEM_GROUP)) -#define GTK_TOOL_ITEM_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TOOL_ITEM_GROUP, GtkToolItemGroupClass)) - -typedef struct _GtkToolItemGroup GtkToolItemGroup; -typedef struct _GtkToolItemGroupClass GtkToolItemGroupClass; -typedef struct _GtkToolItemGroupPrivate GtkToolItemGroupPrivate; - -/** - * GtkToolItemGroup: - * - * This should not be accessed directly. Use the accessor functions below. - */ -struct _GtkToolItemGroup -{ - GtkContainer parent_instance; - GtkToolItemGroupPrivate *priv; -}; - -struct _GtkToolItemGroupClass -{ - GtkContainerClass parent_class; -}; - -GType gtk_tool_item_group_get_type (void) G_GNUC_CONST; -GtkWidget* gtk_tool_item_group_new (const gchar *name); - -void gtk_tool_item_group_set_name (GtkToolItemGroup *group, - const gchar *name); -void gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group, - gboolean collapsed); -void gtk_tool_item_group_set_ellipsize (GtkToolItemGroup *group, - PangoEllipsizeMode ellipsize); -void gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group, - GtkReliefStyle style); - -G_CONST_RETURN gchar* gtk_tool_item_group_get_name (GtkToolItemGroup *group); -gboolean gtk_tool_item_group_get_collapsed (GtkToolItemGroup *group); -PangoEllipsizeMode gtk_tool_item_group_get_ellipsize (GtkToolItemGroup *group); -GtkReliefStyle gtk_tool_item_group_get_header_relief (GtkToolItemGroup *group); - -void gtk_tool_item_group_insert (GtkToolItemGroup *group, - GtkToolItem *item, - gint position); -void gtk_tool_item_group_set_item_position (GtkToolItemGroup *group, - GtkToolItem *item, - gint position); -gint gtk_tool_item_group_get_item_position (GtkToolItemGroup *group, - GtkToolItem *item); - -guint gtk_tool_item_group_get_n_items (GtkToolItemGroup *group); -GtkToolItem* gtk_tool_item_group_get_nth_item (GtkToolItemGroup *group, - guint index); -GtkToolItem* gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group, - gint x, - gint y); - -G_END_DECLS - -#endif /* __GTK_TOOL_ITEM_GROUP_H__ */ diff --git a/gtktoolpalette.c b/gtktoolpalette.c deleted file mode 100644 index 4574b6f03d..0000000000 --- a/gtktoolpalette.c +++ /dev/null @@ -1,5055 +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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#include "gtktoolpaletteprivate.h" -#include "gtkmarshalers.h" - -#include -#include - -#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR -#define DEFAULT_ORIENTATION GTK_ORIENTATION_VERTICAL -#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_ICONS - -#define DEFAULT_CHILD_EXCLUSIVE FALSE -#define DEFAULT_CHILD_EXPAND FALSE - -#define P_(msgid) (msgid) - -/** - * SECTION:GtkToolPalette - * @short_description: A tool palette with categories - * @include: gtktoolpalette.h - * - * An #GtkToolPalette allows it to add #GtkToolItems to a palette like container - * with different categories and drag and drop support. - * - * An #GtkToolPalette is created with a call to gtk_tool_palette_new(). - * - * #GtkToolItems cannot be added directly to an #GtkToolPalette, instead they - * are added to an #GtkToolItemGroup which can than be added to an #GtkToolPalette. To add - * an #GtkToolItemGroup to an #GtkToolPalette use gtk_container_add(). - * - * |[ - * GtkWidget *palette, *group; - * GtkToolItem *item; - * - * palette = gtk_tool_palette_new (); - * group = gtk_tool_item_group_new (_("Test Category")); - * gtk_container_add (GTK_CONTAINER (palette), group); - * - * item = gtk_tool_button_new_from_stock (GTK_STOCK_OK); - * gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1); - * ]| - * - * The easiest way to use drag and drop with GtkToolPalette is to call gtk_tool_palette_add_drag_dest() - * with the desired drag source @palette and the desired drag target @widget. Than gtk_tool_palette_get_drag_item() - * can be used to get the dragged item in the #GtkWidget::drag-data-received signal handler of the drag target. - * - * |[ - * static void - * passive_canvas_drag_data_received (GtkWidget *widget, - * GdkDragContext *context, - * gint x, - * gint y, - * GtkSelectionData *selection, - * guint info, - * guint time, - * gpointer data) - * { - * GtkWidget *palette; - * GtkWidget *item; - * - * /* Get the dragged item */ - * palette = gtk_widget_get_ancestor (gtk_drag_get_source_widget (context), GTK_TYPE_TOOL_PALETTE); - * if (palette != NULL) - * item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette), selection); - * - * /* Do something with item */ - * } - * - * GtkWidget *target, palette; - * - * palette = gtk_tool_palette_new (); - * target = gtk_drawing_area_new (); - * - * g_signal_connect (G_OBJECT (target), "drag-data-received", - * G_CALLBACK (passive_canvas_drag_data_received), NULL); - * gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette), target, - * GTK_DEST_DEFAULT_ALL, - * GTK_TOOL_PALETTE_DRAG_ITEMS, - * GDK_ACTION_COPY); - * ]| - * - * Since: 2.18 - */ - -typedef struct _GtkToolItemGroupInfo GtkToolItemGroupInfo; -typedef struct _GtkToolPaletteDragData GtkToolPaletteDragData; - -enum -{ - PROP_NONE, - PROP_ICON_SIZE, - PROP_ORIENTATION, - PROP_TOOLBAR_STYLE, -}; - -enum -{ - CHILD_PROP_NONE, - CHILD_PROP_EXCLUSIVE, - CHILD_PROP_EXPAND, -}; - -struct _GtkToolItemGroupInfo -{ - GtkToolItemGroup *widget; - - guint notify_collapsed; - guint exclusive : 1; - guint expand : 1; -}; - -struct _GtkToolPalettePrivate -{ - GtkToolItemGroupInfo *groups; - gsize groups_size; - gsize groups_length; - - GtkAdjustment *hadjustment; - GtkAdjustment *vadjustment; - - GtkIconSize icon_size; - GtkOrientation orientation; - GtkToolbarStyle style; - - GtkWidget *expanding_child; - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - GtkSizeGroup *text_size_group; -#endif - - guint sparse_groups : 1; - guint drag_source : 2; -}; - -struct _GtkToolPaletteDragData -{ - GtkToolPalette *palette; - GtkWidget *item; -}; - -static GdkAtom dnd_target_atom_item = GDK_NONE; -static GdkAtom dnd_target_atom_group = GDK_NONE; - -static const GtkTargetEntry dnd_targets[] = -{ - { "application/x-GTK-tool-palette-item", GTK_TARGET_SAME_APP, 0 }, - { "application/x-GTK-tool-palette-group", GTK_TARGET_SAME_APP, 0 }, -}; - -G_DEFINE_TYPE (GtkToolPalette, - gtk_tool_palette, - GTK_TYPE_CONTAINER); - -static void -gtk_tool_palette_init (GtkToolPalette *palette) -{ - palette->priv = G_TYPE_INSTANCE_GET_PRIVATE (palette, - GTK_TYPE_TOOL_PALETTE, - GtkToolPalettePrivate); - - palette->priv->groups_size = 4; - palette->priv->groups_length = 0; - palette->priv->groups = g_new0 (GtkToolItemGroupInfo, palette->priv->groups_size); - - palette->priv->icon_size = DEFAULT_ICON_SIZE; - palette->priv->orientation = DEFAULT_ORIENTATION; - palette->priv->style = DEFAULT_TOOLBAR_STYLE; - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - palette->priv->text_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH); -#endif -} - -static void -gtk_tool_palette_reconfigured (GtkToolPalette *palette) -{ - guint i; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - if (palette->priv->groups[i].widget) - _gtk_tool_item_group_palette_reconfigured (palette->priv->groups[i].widget); - } - - gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - switch (prop_id) - { - case PROP_ICON_SIZE: - if ((guint) g_value_get_enum (value) != palette->priv->icon_size) - { - palette->priv->icon_size = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - case PROP_ORIENTATION: - if ((guint) g_value_get_enum (value) != palette->priv->orientation) - { - palette->priv->orientation = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - case PROP_TOOLBAR_STYLE: - if ((guint) g_value_get_enum (value) != palette->priv->style) - { - palette->priv->style = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - switch (prop_id) - { - case PROP_ICON_SIZE: - g_value_set_enum (value, gtk_tool_palette_get_icon_size (palette)); - break; - - case PROP_ORIENTATION: - g_value_set_enum (value, gtk_tool_palette_get_orientation (palette)); - break; - - case PROP_TOOLBAR_STYLE: - g_value_set_enum (value, gtk_tool_palette_get_style (palette)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_dispose (GObject *object) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - guint i; - - if (palette->priv->hadjustment) - { - g_object_unref (palette->priv->hadjustment); - palette->priv->hadjustment = NULL; - } - - if (palette->priv->vadjustment) - { - g_object_unref (palette->priv->vadjustment); - palette->priv->vadjustment = NULL; - } - - for (i = 0; i < palette->priv->groups_size; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (group->notify_collapsed) - { - g_signal_handler_disconnect (group->widget, group->notify_collapsed); - group->notify_collapsed = 0; - } - } - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - if (palette->priv->text_size_group) - { - g_object_unref (palette->priv->text_size_group); - palette->priv->text_size_group = NULL; - } -#endif - - G_OBJECT_CLASS (gtk_tool_palette_parent_class)->dispose (object); -} - -static void -gtk_tool_palette_finalize (GObject *object) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - if (palette->priv->groups) - { - palette->priv->groups_length = 0; - g_free (palette->priv->groups); - palette->priv->groups = NULL; - } - - G_OBJECT_CLASS (gtk_tool_palette_parent_class)->finalize (object); -} - -static void -gtk_tool_palette_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GtkRequisition child_requisition; - guint i; - - requisition->width = 0; - requisition->height = 0; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (!group->widget) - continue; - - gtk_widget_size_request (GTK_WIDGET (group->widget), &child_requisition); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - requisition->width = MAX (requisition->width, child_requisition.width); - requisition->height += child_requisition.height; - } - else - { - requisition->width += child_requisition.width; - requisition->height = MAX (requisition->height, child_requisition.height); - } - } - - requisition->width += border_width * 2; - requisition->height += border_width * 2; -} - -static void -gtk_tool_palette_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GtkAdjustment *adjustment = NULL; - GtkAllocation child_allocation; - - gint n_expand_groups = 0; - gint remaining_space = 0; - gint expand_space = 0; - - gint page_start, page_size = 0; - gint offset = 0; - guint i; - - gint min_offset = -1, max_offset = -1; - - gint x; - - gint *group_sizes = g_newa(gint, palette->priv->groups_length); - - GtkTextDirection direction = gtk_widget_get_direction (widget); - - GTK_WIDGET_CLASS (gtk_tool_palette_parent_class)->size_allocate (widget, allocation); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - adjustment = palette->priv->vadjustment; - page_size = allocation->height; - } - else - { - adjustment = palette->priv->hadjustment; - page_size = allocation->width; - } - - if (adjustment) - offset = gtk_adjustment_get_value (adjustment); - if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation && - GTK_TEXT_DIR_RTL == direction) - offset = -offset; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.width = allocation->width - border_width * 2; - else - child_allocation.height = allocation->height - border_width * 2; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - remaining_space = allocation->height; - else - remaining_space = allocation->width; - - /* figure out the required size of all groups to be able to distribute the - * remaining space on allocation */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - gint size; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - if (gtk_tool_item_group_get_n_items (group->widget)) - { - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - size = _gtk_tool_item_group_get_height_for_width (group->widget, child_allocation.width); - else - size = _gtk_tool_item_group_get_width_for_height (group->widget, child_allocation.height); - - if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget)) - n_expand_groups += 1; - } - else - size = 0; - - remaining_space -= size; - group_sizes[i] = size; - - /* if the widget is currently expanding an offset which allows to display as much of the - * widget as possible is calculated */ - if (widget == palette->priv->expanding_child) - { - gint limit = - GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? - child_allocation.width : child_allocation.height; - - gint real_size; - guint j; - - min_offset = 0; - - for (j = 0; j < i; ++j) - min_offset += group_sizes[j]; - - max_offset = min_offset + group_sizes[i]; - - real_size = _gtk_tool_item_group_get_size_for_limit - (GTK_TOOL_ITEM_GROUP (widget), limit, - GTK_ORIENTATION_VERTICAL == palette->priv->orientation, - FALSE); - - if (size == real_size) - palette->priv->expanding_child = NULL; - } - } - - if (n_expand_groups > 0) - { - remaining_space = MAX (0, remaining_space); - expand_space = remaining_space / n_expand_groups; - } - - if (max_offset != -1) - { - gint limit = - GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? - allocation->height : allocation->width; - - offset = MIN (MAX (offset, max_offset - limit), min_offset); - } - - if (remaining_space > 0) - offset = 0; - - x = border_width; - child_allocation.y = border_width; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.y -= offset; - else - x -= offset; - - /* allocate all groups at the calculated positions */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - GtkWidget *widget; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - if (gtk_tool_item_group_get_n_items (group->widget)) - { - gint size = group_sizes[i]; - - if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget)) - { - size += MIN (expand_space, remaining_space); - remaining_space -= expand_space; - } - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.height = size; - else - child_allocation.width = size; - - if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation && - GTK_TEXT_DIR_RTL == direction) - child_allocation.x = allocation->width - x - child_allocation.width; - else - child_allocation.x = x; - - gtk_widget_size_allocate (widget, &child_allocation); - gtk_widget_show (widget); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.y += child_allocation.height; - else - x += child_allocation.width; - } - else - gtk_widget_hide (widget); - } - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - child_allocation.y += border_width; - child_allocation.y += offset; - - page_start = child_allocation.y; - } - else - { - x += border_width; - x += offset; - - page_start = x; - } - - /* update the scrollbar to match the displayed adjustment */ - if (adjustment) - { - gdouble value; - - adjustment->page_increment = page_size * 0.9; - adjustment->step_increment = page_size * 0.1; - adjustment->page_size = page_size; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation || - GTK_TEXT_DIR_LTR == direction) - { - adjustment->lower = 0; - adjustment->upper = MAX (0, page_start); - - value = MIN (offset, adjustment->upper - adjustment->page_size); - gtk_adjustment_clamp_page (adjustment, value, offset + page_size); - } - else - { - adjustment->lower = page_size - MAX (0, page_start); - adjustment->upper = page_size; - - offset = -offset; - - value = MAX (offset, adjustment->lower); - gtk_adjustment_clamp_page (adjustment, offset, value + page_size); - } - - gtk_adjustment_changed (adjustment); - } -} - -static gboolean -gtk_tool_palette_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GdkDisplay *display; - cairo_t *cr; - guint i; - - display = gdk_drawable_get_display (widget->window); - - if (!gdk_display_supports_composite (display)) - return FALSE; - - cr = gdk_cairo_create (widget->window); - gdk_cairo_region (cr, event->region); - cairo_clip (cr); - - cairo_push_group (cr); - - for (i = 0; i < palette->priv->groups_length; ++i) - if (palette->priv->groups[i].widget) - _gtk_tool_item_group_paint (palette->priv->groups[i].widget, cr); - - cairo_pop_group_to_source (cr); - - cairo_paint (cr); - cairo_destroy (cr); - - return FALSE; -} - -static void -gtk_tool_palette_realize (GtkWidget *widget) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - GdkWindowAttr attributes; - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x + border_width; - attributes.y = widget->allocation.y + border_width; - attributes.width = widget->allocation.width - border_width * 2; - attributes.height = widget->allocation.height - border_width * 2; - 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 | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_BUTTON_MOTION_MASK; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - - gdk_window_set_user_data (widget->window, widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - - gtk_container_forall (GTK_CONTAINER (widget), - (GtkCallback) gtk_widget_set_parent_window, - widget->window); - - gtk_widget_queue_resize_no_redraw (widget); -} - -static void -gtk_tool_palette_adjustment_value_changed (GtkAdjustment *adjustment G_GNUC_UNUSED, - gpointer data) -{ - GtkWidget *widget = GTK_WIDGET (data); - gtk_tool_palette_size_allocate (widget, &widget->allocation); -} - -static void -gtk_tool_palette_set_scroll_adjustments (GtkWidget *widget, - GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - - if (palette->priv->hadjustment) - g_object_unref (palette->priv->hadjustment); - if (palette->priv->vadjustment) - g_object_unref (palette->priv->vadjustment); - - if (hadjustment) - g_object_ref_sink (hadjustment); - if (vadjustment) - g_object_ref_sink (vadjustment); - - palette->priv->hadjustment = hadjustment; - palette->priv->vadjustment = vadjustment; - - if (palette->priv->hadjustment) - g_signal_connect (palette->priv->hadjustment, "value-changed", - G_CALLBACK (gtk_tool_palette_adjustment_value_changed), - palette); - if (palette->priv->vadjustment) - g_signal_connect (palette->priv->vadjustment, "value-changed", - G_CALLBACK (gtk_tool_palette_adjustment_value_changed), - palette); -} - -static void -gtk_tool_palette_repack (GtkToolPalette *palette) -{ - guint si, di; - - for (si = di = 0; di < palette->priv->groups_length; ++si) - { - if (palette->priv->groups[si].widget) - { - palette->priv->groups[di] = palette->priv->groups[si]; - ++di; - } - else - --palette->priv->groups_length; - } - - palette->priv->sparse_groups = FALSE; -} - -static void -gtk_tool_palette_add (GtkContainer *container, - GtkWidget *child) -{ - GtkToolPalette *palette; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (container)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (child)); - - palette = GTK_TOOL_PALETTE (container); - - if (palette->priv->groups_length == palette->priv->groups_size) - gtk_tool_palette_repack (palette); - - if (palette->priv->groups_length == palette->priv->groups_size) - { - gsize old_size = palette->priv->groups_size; - gsize new_size = old_size * 2; - - palette->priv->groups = g_renew (GtkToolItemGroupInfo, - palette->priv->groups, - new_size); - - memset (palette->priv->groups + old_size, 0, - sizeof (GtkToolItemGroupInfo) * old_size); - - palette->priv->groups_size = new_size; - } - - palette->priv->groups[palette->priv->groups_length].widget = g_object_ref_sink (child); - palette->priv->groups_length += 1; - - gtk_widget_set_parent (child, GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_remove (GtkContainer *container, - GtkWidget *child) -{ - GtkToolPalette *palette; - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (container)); - palette = GTK_TOOL_PALETTE (container); - - for (i = 0; i < palette->priv->groups_length; ++i) - if ((GtkWidget*) palette->priv->groups[i].widget == child) - { - g_object_unref (child); - gtk_widget_unparent (child); - - memset (&palette->priv->groups[i], 0, sizeof (GtkToolItemGroupInfo)); - palette->priv->sparse_groups = TRUE; - } -} - -static void -gtk_tool_palette_forall (GtkContainer *container, - gboolean internals G_GNUC_UNUSED, - GtkCallback callback, - gpointer callback_data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - guint i; - - if (palette->priv->groups) - { - for (i = 0; i < palette->priv->groups_length; ++i) - if (palette->priv->groups[i].widget) - callback (GTK_WIDGET (palette->priv->groups[i].widget), - callback_data); - } -} - -static GType -gtk_tool_palette_child_type (GtkContainer *container G_GNUC_UNUSED) -{ - return GTK_TYPE_TOOL_ITEM_GROUP; -} - -static void -gtk_tool_palette_set_child_property (GtkContainer *container, - GtkWidget *child, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - - switch (prop_id) - { - case CHILD_PROP_EXCLUSIVE: - gtk_tool_palette_set_exclusive (palette, child, g_value_get_boolean (value)); - break; - - case CHILD_PROP_EXPAND: - gtk_tool_palette_set_expand (palette, child, g_value_get_boolean (value)); - break; - - default: - GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_get_child_property (GtkContainer *container, - GtkWidget *child, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - - switch (prop_id) - { - case CHILD_PROP_EXCLUSIVE: - g_value_set_boolean (value, gtk_tool_palette_get_exclusive (palette, child)); - break; - - case CHILD_PROP_EXPAND: - g_value_set_boolean (value, gtk_tool_palette_get_expand (palette, child)); - break; - - default: - GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_class_init (GtkToolPaletteClass *cls) -{ - GObjectClass *oclass = G_OBJECT_CLASS (cls); - GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls); - GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls); - - oclass->set_property = gtk_tool_palette_set_property; - oclass->get_property = gtk_tool_palette_get_property; - oclass->dispose = gtk_tool_palette_dispose; - oclass->finalize = gtk_tool_palette_finalize; - - wclass->size_request = gtk_tool_palette_size_request; - wclass->size_allocate = gtk_tool_palette_size_allocate; - wclass->expose_event = gtk_tool_palette_expose_event; - wclass->realize = gtk_tool_palette_realize; - - cclass->add = gtk_tool_palette_add; - cclass->remove = gtk_tool_palette_remove; - cclass->forall = gtk_tool_palette_forall; - cclass->child_type = gtk_tool_palette_child_type; - cclass->set_child_property = gtk_tool_palette_set_child_property; - cclass->get_child_property = gtk_tool_palette_get_child_property; - - cls->set_scroll_adjustments = gtk_tool_palette_set_scroll_adjustments; - /** - * GtkToolPalette::set-scroll-adjustments: - * @widget: the GtkToolPalette that received the signal - * @hadjustment: The horizontal adjustment - * @vadjustment: The vertical adjustment - * - * The ::set-scroll-adjustments when FIXME - * - * Since: 2.18 - */ - wclass->set_scroll_adjustments_signal = - g_signal_new ("set-scroll-adjustments", - G_TYPE_FROM_CLASS (oclass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkToolPaletteClass, set_scroll_adjustments), - NULL, NULL, - _gtk_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, - GTK_TYPE_ADJUSTMENT, - GTK_TYPE_ADJUSTMENT); - - g_object_class_install_property (oclass, PROP_ICON_SIZE, - g_param_spec_enum ("icon-size", - P_("Icon Size"), - P_("The size of palette icons"), - GTK_TYPE_ICON_SIZE, - DEFAULT_ICON_SIZE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_ORIENTATION, - g_param_spec_enum ("orientation", - P_("Orientation"), - P_("Orientation of the tool palette"), - GTK_TYPE_ORIENTATION, - DEFAULT_ORIENTATION, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_TOOLBAR_STYLE, - g_param_spec_enum ("toolbar-style", - P_("Toolbar Style"), - P_("Style of items in the tool palette"), - GTK_TYPE_TOOLBAR_STYLE, - DEFAULT_TOOLBAR_STYLE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_EXCLUSIVE, - g_param_spec_boolean ("exclusive", - P_("Exclusive"), - P_("Whether the item group should be the only expanded at a given time"), - DEFAULT_CHILD_EXCLUSIVE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND, - g_param_spec_boolean ("expand", - P_("Expand"), - P_("Whether the item group should receive extra space when the palette grows"), - DEFAULT_CHILD_EXPAND, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_type_class_add_private (cls, sizeof (GtkToolPalettePrivate)); - - dnd_target_atom_item = gdk_atom_intern_static_string (dnd_targets[0].target); - dnd_target_atom_group = gdk_atom_intern_static_string (dnd_targets[1].target); -} - -/** - * gtk_tool_palette_new: - * - * Creates a new tool palette. - * - * Returns: a new #GtkToolPalette. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_new (void) -{ - return g_object_new (GTK_TYPE_TOOL_PALETTE, NULL); -} - -/** - * gtk_tool_palette_set_icon_size: - * @palette: an #GtkToolPalette. - * @icon_size: the #GtkIconSize that icons in the tool palette shall have. - * - * Sets the size of icons in the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_icon_size (GtkToolPalette *palette, - GtkIconSize icon_size) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (icon_size != palette->priv->icon_size) - g_object_set (palette, "icon-size", icon_size, NULL); -} - -/** - * gtk_tool_palette_set_orientation: - * @palette: an #GtkToolPalette. - * @orientation: the #GtkOrientation that the tool palette shall have. - * - * Sets the orientation (horizontal or vertical) of the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_orientation (GtkToolPalette *palette, - GtkOrientation orientation) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (orientation != palette->priv->orientation) - g_object_set (palette, "orientation", orientation, NULL); -} - -/** - * gtk_tool_palette_set_style: - * @palette: an #GtkToolPalette. - * @style: the #GtkToolbarStyle that items in the tool palette shall have. - * - * Sets the style (text, icons or both) of items in the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_style (GtkToolPalette *palette, - GtkToolbarStyle style) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (style != palette->priv->style) - g_object_set (palette, "toolbar-style", style, NULL); -} - -/** - * gtk_tool_palette_get_icon_size: - * @palette: an #GtkToolPalette. - * - * Gets the size of icons in the tool palette. See gtk_tool_palette_set_icon_size(). - * - * Returns: the #GtkIconSize of icons in the tool palette. - * - * Since: 2.18 - */ -GtkIconSize -gtk_tool_palette_get_icon_size (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ICON_SIZE); - return palette->priv->icon_size; -} - -/** - * gtk_tool_palette_get_orientation: - * @palette: an #GtkToolPalette. - * - * Gets the orientation (horizontal or vertical) of the tool palette. See gtk_tool_palette_set_orientation(). - * - * Returns the #GtkOrientation of the tool palette. - */ -GtkOrientation -gtk_tool_palette_get_orientation (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ORIENTATION); - return palette->priv->orientation; -} - -/** - * gtk_tool_palette_get_style: - * @palette: an #GtkToolPalette. - * - * Gets the style (icons, text or both) of items in the tool palette. - * - * Returns: the #GtkToolbarStyle of items in the tool palette. - * - * Since: 2.18 - */ -GtkToolbarStyle -gtk_tool_palette_get_style (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_TOOLBAR_STYLE); - return palette->priv->style; -} - -/** - * gtk_tool_palette_set_group_position: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @position: a new index for group. - * - * Sets the position of the group as an index of the tool palette. - * If position is 0 the group will become the first child, if position is - * -1 it will become the last child. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_group_position (GtkToolPalette *palette, - GtkWidget *group, - gint position) -{ - GtkToolItemGroupInfo group_info; - gint old_position; - gpointer src, dst; - gsize len; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - gtk_tool_palette_repack (palette); - - g_return_if_fail (position >= -1); - - if (-1 == position) - position = palette->priv->groups_length - 1; - - g_return_if_fail ((guint) position < palette->priv->groups_length); - - if (GTK_TOOL_ITEM_GROUP (group) == palette->priv->groups[position].widget) - return; - - old_position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (old_position >= 0); - - group_info = palette->priv->groups[old_position]; - - if (position < old_position) - { - dst = palette->priv->groups + position + 1; - src = palette->priv->groups + position; - len = old_position - position; - } - else - { - dst = palette->priv->groups + old_position; - src = palette->priv->groups + old_position + 1; - len = position - old_position; - } - - memmove (dst, src, len * sizeof (*palette->priv->groups)); - palette->priv->groups[position] = group_info; - - gtk_widget_queue_resize (GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_group_notify_collapsed (GtkToolItemGroup *group, - GParamSpec *pspec G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (data); - guint i; - - if (gtk_tool_item_group_get_collapsed (group)) - return; - - for (i = 0; i < palette->priv->groups_size; ++i) - { - GtkToolItemGroup *current_group = palette->priv->groups[i].widget; - - if (current_group && current_group != group) - gtk_tool_item_group_set_collapsed (palette->priv->groups[i].widget, TRUE); - } -} - -/** - * gtk_tool_palette_set_exclusive: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @exclusive: whether the group should be exclusive or not. - * - * Sets whether the group should be exclusive or not. If an exclusive group is expanded - * all other groups are collapsed. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_exclusive (GtkToolPalette *palette, - GtkWidget *group, - gboolean exclusive) -{ - GtkToolItemGroupInfo *group_info; - gint position; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (position >= 0); - - group_info = &palette->priv->groups[position]; - - if (exclusive == group_info->exclusive) - return; - - group_info->exclusive = exclusive; - - if (group_info->exclusive != (0 != group_info->notify_collapsed)) - { - if (group_info->exclusive) - { - group_info->notify_collapsed = - g_signal_connect (group, "notify::collapsed", - G_CALLBACK (gtk_tool_palette_group_notify_collapsed), - palette); - } - else - { - g_signal_handler_disconnect (group, group_info->notify_collapsed); - group_info->notify_collapsed = 0; - } - } - - gtk_tool_palette_group_notify_collapsed (group_info->widget, NULL, palette); - gtk_widget_child_notify (group, "exclusive"); -} - -/** - * gtk_tool_palette_set_expand: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @expand: whether the group should be given extra space. - * - * Sets whether the group should be given extra space. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_expand (GtkToolPalette *palette, - GtkWidget *group, - gboolean expand) -{ - GtkToolItemGroupInfo *group_info; - gint position; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (position >= 0); - - group_info = &palette->priv->groups[position]; - - if (expand != group_info->expand) - { - group_info->expand = expand; - gtk_widget_queue_resize (GTK_WIDGET (palette)); - gtk_widget_child_notify (group, "expand"); - } -} - -/** - * gtk_tool_palette_get_group_position: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup. - * - * Gets the position of @group in @palette as index. see gtk_tool_palette_set_group_position(). - * - * Returns: the index of group or -1 if @group is not a child of @palette. - * - * Since: 2.18 - */ -gint -gtk_tool_palette_get_group_position (GtkToolPalette *palette, - GtkWidget *group) -{ - guint i; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), -1); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1); - - for (i = 0; i < palette->priv->groups_length; ++i) - if ((gpointer) group == palette->priv->groups[i].widget) - return i; - - return -1; -} - -/** - * gtk_tool_palette_get_exclusive: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * - * Gets whether group is exclusive or not. See gtk_tool_palette_set_exclusive(). - * - * Returns: %TRUE if group is exclusive. - * - * Since: 2.18 - */ -gboolean -gtk_tool_palette_get_exclusive (GtkToolPalette *palette, - GtkWidget *group) -{ - gint position; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXCLUSIVE); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXCLUSIVE); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXCLUSIVE); - - return palette->priv->groups[position].exclusive; -} - -/** - * gtk_tool_palette_get_expand: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * - * Gets whether group should be given extra space. See gtk_tool_palette_set_expand(). - * - * Returns: %TRUE if group should be given extra space, %FALSE otherwise. - * - * Since: 2.18 - */ -gboolean -gtk_tool_palette_get_expand (GtkToolPalette *palette, - GtkWidget *group) -{ - gint position; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXPAND); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXPAND); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXPAND); - - return palette->priv->groups[position].expand; -} - -/** - * gtk_tool_palette_get_drop_item: - * @palette: an #GtkToolPalette. - * @x: the x position. - * @y: the y position. - * - * Gets the item at position (x, y). See gtk_tool_palette_get_drop_group(). - * - * Returns: the #GtkToolItem at position or %NULL if there is no such item. - * - * Since: 2.18 - */ -GtkToolItem* -gtk_tool_palette_get_drop_item (GtkToolPalette *palette, - gint x, - gint y) -{ - GtkWidget *group = gtk_tool_palette_get_drop_group (palette, x, y); - - if (group) - return gtk_tool_item_group_get_drop_item (GTK_TOOL_ITEM_GROUP (group), - x - group->allocation.x, - y - group->allocation.y); - - return NULL; -} - -/** - * gtk_tool_palette_get_drop_group: - * @palette: an #GtkToolPalette. - * @x: the x position. - * @y: the y position. - * - * Gets the group at position (x, y). - * - * Returns: the #GtkToolItemGroup at position or %NULL if there is no such group. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_get_drop_group (GtkToolPalette *palette, - gint x, - gint y) -{ - GtkAllocation *allocation; - guint i; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - - allocation = >K_WIDGET (palette)->allocation; - - g_return_val_if_fail (x >= 0 && x < allocation->width, NULL); - g_return_val_if_fail (y >= 0 && y < allocation->height, NULL); - - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - GtkWidget *widget; - gint x0, y0; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - x0 = x - widget->allocation.x; - y0 = y - widget->allocation.y; - - if (x0 >= 0 && x0 < widget->allocation.width && - y0 >= 0 && y0 < widget->allocation.height) - return widget; - } - - return NULL; -} - -/** - * gtk_tool_palette_get_drag_item: - * @palette: an #GtkToolPalette. - * @selection: a #GtkSelectionData. - * - * Get the dragged item from the selection. This could be a #GtkToolItem or - * an #GtkToolItemGroup. - * - * Returns: the dragged item in selection. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_get_drag_item (GtkToolPalette *palette, - const GtkSelectionData *selection) -{ - GtkToolPaletteDragData *data; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - g_return_val_if_fail (NULL != selection, NULL); - - g_return_val_if_fail (selection->format == 8, NULL); - g_return_val_if_fail (selection->length == sizeof (GtkToolPaletteDragData), NULL); - g_return_val_if_fail (selection->target == dnd_target_atom_item || - selection->target == dnd_target_atom_group, - NULL); - - data = (GtkToolPaletteDragData*) selection->data; - - g_return_val_if_fail (data->palette == palette, NULL); - - if (dnd_target_atom_item == selection->target) - g_return_val_if_fail (GTK_IS_TOOL_ITEM (data->item), NULL); - else if (dnd_target_atom_group == selection->target) - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (data->item), NULL); - - return data->item; -} - -/** - * gtk_tool_palette_set_drag_source: - * @palette: an #GtkToolPalette. - * @targets: the #GtkToolPaletteDragTargets which the widget should support. - * - * Sets the tool palette as a drag source. Enables all groups and items in - * the tool palette as drag sources on button 1 and button 3 press with copy - * and move actions. - * - * See gtk_drag_source_set(). - * - * Since: 2.18 - * - */ -void -gtk_tool_palette_set_drag_source (GtkToolPalette *palette, - GtkToolPaletteDragTargets targets) -{ - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if ((palette->priv->drag_source & targets) == targets) - return; - - palette->priv->drag_source |= targets; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - if (palette->priv->groups[i].widget) - gtk_container_forall (GTK_CONTAINER (palette->priv->groups[i].widget), - _gtk_tool_palette_child_set_drag_source, - palette); - } -} - -/** - * gtk_tool_palette_add_drag_dest: - * @palette: an #GtkToolPalette. - * @widget: a #GtkWidget which should be a drag destination for palette. - * @flags: the flags that specify what actions GTK+ should take for drops on that widget. - * @targets: the #GtkToolPaletteDragTargets which the widget should support. - * @actions: the #GdkDragActions which the widget should suppport. - * - * Sets the tool palette as drag source (see gtk_tool_palette_set_drag_source) and - * sets widget as a drag destination for drags from palette. With flags the actions - * (like highlighting and target checking) which should be performed by GTK+ for - * drops on widget can be specified. With targets the supported drag targets - * (groups and/or items) can be specified. With actions the supported drag actions - * (copy and move) can be specified. - * - * See gtk_drag_dest_set(). - * - * Since: 2.18 - */ -void -gtk_tool_palette_add_drag_dest (GtkToolPalette *palette, - GtkWidget *widget, - GtkDestDefaults flags, - GtkToolPaletteDragTargets targets, - GdkDragAction actions) -{ - GtkTargetEntry entries[G_N_ELEMENTS (dnd_targets)]; - gint n_entries = 0; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_WIDGET (widget)); - - gtk_tool_palette_set_drag_source (palette, - targets); - - if (targets & GTK_TOOL_PALETTE_DRAG_ITEMS) - entries[n_entries++] = dnd_targets[0]; - if (targets & GTK_TOOL_PALETTE_DRAG_GROUPS) - entries[n_entries++] = dnd_targets[1]; - - gtk_drag_dest_set (widget, flags, entries, n_entries, actions); -} - -void -_gtk_tool_palette_get_item_size (GtkToolPalette *palette, - GtkRequisition *item_size, - gboolean homogeneous_only, - gint *requested_rows) -{ - GtkRequisition max_requisition; - gint max_rows; - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (NULL != item_size); - - max_requisition.width = 0; - max_requisition.height = 0; - max_rows = 0; - - /* iterate over all groups and calculate the max item_size and max row request */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkRequisition requisition; - gint rows; - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (!group->widget) - continue; - - _gtk_tool_item_group_item_size_request (group->widget, &requisition, homogeneous_only, &rows); - - max_requisition.width = MAX (max_requisition.width, requisition.width); - max_requisition.height = MAX (max_requisition.height, requisition.height); - max_rows = MAX (max_rows, rows); - } - - *item_size = max_requisition; - if (requested_rows) - *requested_rows = max_rows; -} - -static void -gtk_tool_palette_item_drag_data_get (GtkWidget *widget, - GdkDragContext *context G_GNUC_UNUSED, - GtkSelectionData *selection, - guint info G_GNUC_UNUSED, - guint time G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL }; - - if (selection->target == dnd_target_atom_item) - drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); - - if (drag_data.item) - gtk_selection_data_set (selection, selection->target, 8, - (guchar*) &drag_data, sizeof (drag_data)); -} - -static void -gtk_tool_palette_child_drag_data_get (GtkWidget *widget, - GdkDragContext *context G_GNUC_UNUSED, - GtkSelectionData *selection, - guint info G_GNUC_UNUSED, - guint time G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL }; - - if (selection->target == dnd_target_atom_group) - drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM_GROUP); - - if (drag_data.item) - gtk_selection_data_set (selection, selection->target, 8, - (guchar*) &drag_data, sizeof (drag_data)); -} - -void -_gtk_tool_palette_child_set_drag_source (GtkWidget *child, - gpointer data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (data); - - /* Check drag_source, - * to work properly when called from gtk_tool_item_group_insert(). - */ - if (!palette->priv->drag_source) - return; - - if (GTK_IS_TOOL_ITEM (child) && - (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_ITEMS)) - { - /* Connect to child instead of the item itself, - * to work arround bug 510377. - */ - if (GTK_IS_TOOL_BUTTON (child)) - child = gtk_bin_get_child (GTK_BIN (child)); - - if (!child) - return; - - gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, - &dnd_targets[0], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); - - g_signal_connect (child, "drag-data-get", - G_CALLBACK (gtk_tool_palette_item_drag_data_get), - palette); - } - else if (GTK_IS_BUTTON (child) && - (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_GROUPS)) - { - gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, - &dnd_targets[1], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); - - g_signal_connect (child, "drag-data-get", - G_CALLBACK (gtk_tool_palette_child_drag_data_get), - palette); - } -} - -/** - * gtk_tool_palette_get_drag_target_item: - * - * Get the target entry for a dragged #GtkToolItem. - * - * Returns: the #GtkTargetEntry for a dragged item. - * - * Since: 2.18 - */ -G_CONST_RETURN GtkTargetEntry* -gtk_tool_palette_get_drag_target_item (void) -{ - return &dnd_targets[0]; -} - -/** - * gtk_tool_palette_get_drag_target_group: - * - * Get the target entry for a dragged #GtkToolItemGroup. - * - * Returns: the #GtkTargetEntry for a dragged group. - * - * Since: 2.18 - */ -G_CONST_RETURN GtkTargetEntry* -gtk_tool_palette_get_drag_target_group (void) -{ - return &dnd_targets[1]; -} - -void -_gtk_tool_palette_set_expanding_child (GtkToolPalette *palette, - GtkWidget *widget) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - palette->priv->expanding_child = widget; -} - -GtkAdjustment* -gtk_tool_palette_get_hadjustment (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - return palette->priv->hadjustment; -} - -GtkAdjustment* -gtk_tool_palette_get_vadjustment (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - return palette->priv->vadjustment; -} - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - -GtkSizeGroup * -_gtk_tool_palette_get_size_group (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - - return palette->priv->text_size_group; -} - -#endif -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#include "gtktoolpaletteprivate.h" -#include "gtkmarshalers.h" - -#include -#include - -#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR -#define DEFAULT_ORIENTATION GTK_ORIENTATION_VERTICAL -#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_ICONS - -#define DEFAULT_CHILD_EXCLUSIVE FALSE -#define DEFAULT_CHILD_EXPAND FALSE - -#define P_(msgid) (msgid) - -/** - * SECTION:GtkToolPalette - * @short_description: A tool palette with categories - * @include: gtktoolpalette.h - * - * An #GtkToolPalette allows it to add #GtkToolItems to a palette like container - * with different categories and drag and drop support. - * - * An #GtkToolPalette is created with a call to gtk_tool_palette_new(). - * - * #GtkToolItems cannot be added directly to an #GtkToolPalette, instead they - * are added to an #GtkToolItemGroup which can than be added to an #GtkToolPalette. To add - * an #GtkToolItemGroup to an #GtkToolPalette use gtk_container_add(). - * - * |[ - * GtkWidget *palette, *group; - * GtkToolItem *item; - * - * palette = gtk_tool_palette_new (); - * group = gtk_tool_item_group_new (_("Test Category")); - * gtk_container_add (GTK_CONTAINER (palette), group); - * - * item = gtk_tool_button_new_from_stock (GTK_STOCK_OK); - * gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1); - * ]| - * - * The easiest way to use drag and drop with GtkToolPalette is to call gtk_tool_palette_add_drag_dest() - * with the desired drag source @palette and the desired drag target @widget. Than gtk_tool_palette_get_drag_item() - * can be used to get the dragged item in the #GtkWidget::drag-data-received signal handler of the drag target. - * - * |[ - * static void - * passive_canvas_drag_data_received (GtkWidget *widget, - * GdkDragContext *context, - * gint x, - * gint y, - * GtkSelectionData *selection, - * guint info, - * guint time, - * gpointer data) - * { - * GtkWidget *palette; - * GtkWidget *item; - * - * /* Get the dragged item */ - * palette = gtk_widget_get_ancestor (gtk_drag_get_source_widget (context), GTK_TYPE_TOOL_PALETTE); - * if (palette != NULL) - * item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette), selection); - * - * /* Do something with item */ - * } - * - * GtkWidget *target, palette; - * - * palette = gtk_tool_palette_new (); - * target = gtk_drawing_area_new (); - * - * g_signal_connect (G_OBJECT (target), "drag-data-received", - * G_CALLBACK (passive_canvas_drag_data_received), NULL); - * gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette), target, - * GTK_DEST_DEFAULT_ALL, - * GTK_TOOL_PALETTE_DRAG_ITEMS, - * GDK_ACTION_COPY); - * ]| - * - * Since: 2.18 - */ - -typedef struct _GtkToolItemGroupInfo GtkToolItemGroupInfo; -typedef struct _GtkToolPaletteDragData GtkToolPaletteDragData; - -enum -{ - PROP_NONE, - PROP_ICON_SIZE, - PROP_ORIENTATION, - PROP_TOOLBAR_STYLE, -}; - -enum -{ - CHILD_PROP_NONE, - CHILD_PROP_EXCLUSIVE, - CHILD_PROP_EXPAND, -}; - -struct _GtkToolItemGroupInfo -{ - GtkToolItemGroup *widget; - - guint notify_collapsed; - guint exclusive : 1; - guint expand : 1; -}; - -struct _GtkToolPalettePrivate -{ - GtkToolItemGroupInfo *groups; - gsize groups_size; - gsize groups_length; - - GtkAdjustment *hadjustment; - GtkAdjustment *vadjustment; - - GtkIconSize icon_size; - GtkOrientation orientation; - GtkToolbarStyle style; - - GtkWidget *expanding_child; - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - GtkSizeGroup *text_size_group; -#endif - - guint sparse_groups : 1; - guint drag_source : 2; -}; - -struct _GtkToolPaletteDragData -{ - GtkToolPalette *palette; - GtkWidget *item; -}; - -static GdkAtom dnd_target_atom_item = GDK_NONE; -static GdkAtom dnd_target_atom_group = GDK_NONE; - -static const GtkTargetEntry dnd_targets[] = -{ - { "application/x-GTK-tool-palette-item", GTK_TARGET_SAME_APP, 0 }, - { "application/x-GTK-tool-palette-group", GTK_TARGET_SAME_APP, 0 }, -}; - -G_DEFINE_TYPE (GtkToolPalette, - gtk_tool_palette, - GTK_TYPE_CONTAINER); - -static void -gtk_tool_palette_init (GtkToolPalette *palette) -{ - palette->priv = G_TYPE_INSTANCE_GET_PRIVATE (palette, - GTK_TYPE_TOOL_PALETTE, - GtkToolPalettePrivate); - - palette->priv->groups_size = 4; - palette->priv->groups_length = 0; - palette->priv->groups = g_new0 (GtkToolItemGroupInfo, palette->priv->groups_size); - - palette->priv->icon_size = DEFAULT_ICON_SIZE; - palette->priv->orientation = DEFAULT_ORIENTATION; - palette->priv->style = DEFAULT_TOOLBAR_STYLE; - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - palette->priv->text_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH); -#endif -} - -static void -gtk_tool_palette_reconfigured (GtkToolPalette *palette) -{ - guint i; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - if (palette->priv->groups[i].widget) - _gtk_tool_item_group_palette_reconfigured (palette->priv->groups[i].widget); - } - - gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - switch (prop_id) - { - case PROP_ICON_SIZE: - if ((guint) g_value_get_enum (value) != palette->priv->icon_size) - { - palette->priv->icon_size = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - case PROP_ORIENTATION: - if ((guint) g_value_get_enum (value) != palette->priv->orientation) - { - palette->priv->orientation = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - case PROP_TOOLBAR_STYLE: - if ((guint) g_value_get_enum (value) != palette->priv->style) - { - palette->priv->style = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - switch (prop_id) - { - case PROP_ICON_SIZE: - g_value_set_enum (value, gtk_tool_palette_get_icon_size (palette)); - break; - - case PROP_ORIENTATION: - g_value_set_enum (value, gtk_tool_palette_get_orientation (palette)); - break; - - case PROP_TOOLBAR_STYLE: - g_value_set_enum (value, gtk_tool_palette_get_style (palette)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_dispose (GObject *object) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - guint i; - - if (palette->priv->hadjustment) - { - g_object_unref (palette->priv->hadjustment); - palette->priv->hadjustment = NULL; - } - - if (palette->priv->vadjustment) - { - g_object_unref (palette->priv->vadjustment); - palette->priv->vadjustment = NULL; - } - - for (i = 0; i < palette->priv->groups_size; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (group->notify_collapsed) - { - g_signal_handler_disconnect (group->widget, group->notify_collapsed); - group->notify_collapsed = 0; - } - } - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - if (palette->priv->text_size_group) - { - g_object_unref (palette->priv->text_size_group); - palette->priv->text_size_group = NULL; - } -#endif - - G_OBJECT_CLASS (gtk_tool_palette_parent_class)->dispose (object); -} - -static void -gtk_tool_palette_finalize (GObject *object) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - if (palette->priv->groups) - { - palette->priv->groups_length = 0; - g_free (palette->priv->groups); - palette->priv->groups = NULL; - } - - G_OBJECT_CLASS (gtk_tool_palette_parent_class)->finalize (object); -} - -static void -gtk_tool_palette_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GtkRequisition child_requisition; - guint i; - - requisition->width = 0; - requisition->height = 0; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (!group->widget) - continue; - - gtk_widget_size_request (GTK_WIDGET (group->widget), &child_requisition); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - requisition->width = MAX (requisition->width, child_requisition.width); - requisition->height += child_requisition.height; - } - else - { - requisition->width += child_requisition.width; - requisition->height = MAX (requisition->height, child_requisition.height); - } - } - - requisition->width += border_width * 2; - requisition->height += border_width * 2; -} - -static void -gtk_tool_palette_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GtkAdjustment *adjustment = NULL; - GtkAllocation child_allocation; - - gint n_expand_groups = 0; - gint remaining_space = 0; - gint expand_space = 0; - - gint page_start, page_size = 0; - gint offset = 0; - guint i; - - gint min_offset = -1, max_offset = -1; - - gint x; - - gint *group_sizes = g_newa(gint, palette->priv->groups_length); - - GtkTextDirection direction = gtk_widget_get_direction (widget); - - GTK_WIDGET_CLASS (gtk_tool_palette_parent_class)->size_allocate (widget, allocation); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - adjustment = palette->priv->vadjustment; - page_size = allocation->height; - } - else - { - adjustment = palette->priv->hadjustment; - page_size = allocation->width; - } - - if (adjustment) - offset = gtk_adjustment_get_value (adjustment); - if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation && - GTK_TEXT_DIR_RTL == direction) - offset = -offset; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.width = allocation->width - border_width * 2; - else - child_allocation.height = allocation->height - border_width * 2; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - remaining_space = allocation->height; - else - remaining_space = allocation->width; - - /* figure out the required size of all groups to be able to distribute the - * remaining space on allocation */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - gint size; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - if (gtk_tool_item_group_get_n_items (group->widget)) - { - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - size = _gtk_tool_item_group_get_height_for_width (group->widget, child_allocation.width); - else - size = _gtk_tool_item_group_get_width_for_height (group->widget, child_allocation.height); - - if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget)) - n_expand_groups += 1; - } - else - size = 0; - - remaining_space -= size; - group_sizes[i] = size; - - /* if the widget is currently expanding an offset which allows to display as much of the - * widget as possible is calculated */ - if (widget == palette->priv->expanding_child) - { - gint limit = - GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? - child_allocation.width : child_allocation.height; - - gint real_size; - guint j; - - min_offset = 0; - - for (j = 0; j < i; ++j) - min_offset += group_sizes[j]; - - max_offset = min_offset + group_sizes[i]; - - real_size = _gtk_tool_item_group_get_size_for_limit - (GTK_TOOL_ITEM_GROUP (widget), limit, - GTK_ORIENTATION_VERTICAL == palette->priv->orientation, - FALSE); - - if (size == real_size) - palette->priv->expanding_child = NULL; - } - } - - if (n_expand_groups > 0) - { - remaining_space = MAX (0, remaining_space); - expand_space = remaining_space / n_expand_groups; - } - - if (max_offset != -1) - { - gint limit = - GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? - allocation->height : allocation->width; - - offset = MIN (MAX (offset, max_offset - limit), min_offset); - } - - if (remaining_space > 0) - offset = 0; - - x = border_width; - child_allocation.y = border_width; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.y -= offset; - else - x -= offset; - - /* allocate all groups at the calculated positions */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - GtkWidget *widget; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - if (gtk_tool_item_group_get_n_items (group->widget)) - { - gint size = group_sizes[i]; - - if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget)) - { - size += MIN (expand_space, remaining_space); - remaining_space -= expand_space; - } - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.height = size; - else - child_allocation.width = size; - - if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation && - GTK_TEXT_DIR_RTL == direction) - child_allocation.x = allocation->width - x - child_allocation.width; - else - child_allocation.x = x; - - gtk_widget_size_allocate (widget, &child_allocation); - gtk_widget_show (widget); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.y += child_allocation.height; - else - x += child_allocation.width; - } - else - gtk_widget_hide (widget); - } - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - child_allocation.y += border_width; - child_allocation.y += offset; - - page_start = child_allocation.y; - } - else - { - x += border_width; - x += offset; - - page_start = x; - } - - /* update the scrollbar to match the displayed adjustment */ - if (adjustment) - { - gdouble value; - - adjustment->page_increment = page_size * 0.9; - adjustment->step_increment = page_size * 0.1; - adjustment->page_size = page_size; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation || - GTK_TEXT_DIR_LTR == direction) - { - adjustment->lower = 0; - adjustment->upper = MAX (0, page_start); - - value = MIN (offset, adjustment->upper - adjustment->page_size); - gtk_adjustment_clamp_page (adjustment, value, offset + page_size); - } - else - { - adjustment->lower = page_size - MAX (0, page_start); - adjustment->upper = page_size; - - offset = -offset; - - value = MAX (offset, adjustment->lower); - gtk_adjustment_clamp_page (adjustment, offset, value + page_size); - } - - gtk_adjustment_changed (adjustment); - } -} - -static gboolean -gtk_tool_palette_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GdkDisplay *display; - cairo_t *cr; - guint i; - - display = gdk_drawable_get_display (widget->window); - - if (!gdk_display_supports_composite (display)) - return FALSE; - - cr = gdk_cairo_create (widget->window); - gdk_cairo_region (cr, event->region); - cairo_clip (cr); - - cairo_push_group (cr); - - for (i = 0; i < palette->priv->groups_length; ++i) - if (palette->priv->groups[i].widget) - _gtk_tool_item_group_paint (palette->priv->groups[i].widget, cr); - - cairo_pop_group_to_source (cr); - - cairo_paint (cr); - cairo_destroy (cr); - - return FALSE; -} - -static void -gtk_tool_palette_realize (GtkWidget *widget) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - GdkWindowAttr attributes; - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x + border_width; - attributes.y = widget->allocation.y + border_width; - attributes.width = widget->allocation.width - border_width * 2; - attributes.height = widget->allocation.height - border_width * 2; - 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 | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_BUTTON_MOTION_MASK; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - - gdk_window_set_user_data (widget->window, widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - - gtk_container_forall (GTK_CONTAINER (widget), - (GtkCallback) gtk_widget_set_parent_window, - widget->window); - - gtk_widget_queue_resize_no_redraw (widget); -} - -static void -gtk_tool_palette_adjustment_value_changed (GtkAdjustment *adjustment G_GNUC_UNUSED, - gpointer data) -{ - GtkWidget *widget = GTK_WIDGET (data); - gtk_tool_palette_size_allocate (widget, &widget->allocation); -} - -static void -gtk_tool_palette_set_scroll_adjustments (GtkWidget *widget, - GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - - if (palette->priv->hadjustment) - g_object_unref (palette->priv->hadjustment); - if (palette->priv->vadjustment) - g_object_unref (palette->priv->vadjustment); - - if (hadjustment) - g_object_ref_sink (hadjustment); - if (vadjustment) - g_object_ref_sink (vadjustment); - - palette->priv->hadjustment = hadjustment; - palette->priv->vadjustment = vadjustment; - - if (palette->priv->hadjustment) - g_signal_connect (palette->priv->hadjustment, "value-changed", - G_CALLBACK (gtk_tool_palette_adjustment_value_changed), - palette); - if (palette->priv->vadjustment) - g_signal_connect (palette->priv->vadjustment, "value-changed", - G_CALLBACK (gtk_tool_palette_adjustment_value_changed), - palette); -} - -static void -gtk_tool_palette_repack (GtkToolPalette *palette) -{ - guint si, di; - - for (si = di = 0; di < palette->priv->groups_length; ++si) - { - if (palette->priv->groups[si].widget) - { - palette->priv->groups[di] = palette->priv->groups[si]; - ++di; - } - else - --palette->priv->groups_length; - } - - palette->priv->sparse_groups = FALSE; -} - -static void -gtk_tool_palette_add (GtkContainer *container, - GtkWidget *child) -{ - GtkToolPalette *palette; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (container)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (child)); - - palette = GTK_TOOL_PALETTE (container); - - if (palette->priv->groups_length == palette->priv->groups_size) - gtk_tool_palette_repack (palette); - - if (palette->priv->groups_length == palette->priv->groups_size) - { - gsize old_size = palette->priv->groups_size; - gsize new_size = old_size * 2; - - palette->priv->groups = g_renew (GtkToolItemGroupInfo, - palette->priv->groups, - new_size); - - memset (palette->priv->groups + old_size, 0, - sizeof (GtkToolItemGroupInfo) * old_size); - - palette->priv->groups_size = new_size; - } - - palette->priv->groups[palette->priv->groups_length].widget = g_object_ref_sink (child); - palette->priv->groups_length += 1; - - gtk_widget_set_parent (child, GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_remove (GtkContainer *container, - GtkWidget *child) -{ - GtkToolPalette *palette; - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (container)); - palette = GTK_TOOL_PALETTE (container); - - for (i = 0; i < palette->priv->groups_length; ++i) - if ((GtkWidget*) palette->priv->groups[i].widget == child) - { - g_object_unref (child); - gtk_widget_unparent (child); - - memset (&palette->priv->groups[i], 0, sizeof (GtkToolItemGroupInfo)); - palette->priv->sparse_groups = TRUE; - } -} - -static void -gtk_tool_palette_forall (GtkContainer *container, - gboolean internals G_GNUC_UNUSED, - GtkCallback callback, - gpointer callback_data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - guint i; - - if (palette->priv->groups) - { - for (i = 0; i < palette->priv->groups_length; ++i) - if (palette->priv->groups[i].widget) - callback (GTK_WIDGET (palette->priv->groups[i].widget), - callback_data); - } -} - -static GType -gtk_tool_palette_child_type (GtkContainer *container G_GNUC_UNUSED) -{ - return GTK_TYPE_TOOL_ITEM_GROUP; -} - -static void -gtk_tool_palette_set_child_property (GtkContainer *container, - GtkWidget *child, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - - switch (prop_id) - { - case CHILD_PROP_EXCLUSIVE: - gtk_tool_palette_set_exclusive (palette, child, g_value_get_boolean (value)); - break; - - case CHILD_PROP_EXPAND: - gtk_tool_palette_set_expand (palette, child, g_value_get_boolean (value)); - break; - - default: - GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_get_child_property (GtkContainer *container, - GtkWidget *child, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - - switch (prop_id) - { - case CHILD_PROP_EXCLUSIVE: - g_value_set_boolean (value, gtk_tool_palette_get_exclusive (palette, child)); - break; - - case CHILD_PROP_EXPAND: - g_value_set_boolean (value, gtk_tool_palette_get_expand (palette, child)); - break; - - default: - GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_class_init (GtkToolPaletteClass *cls) -{ - GObjectClass *oclass = G_OBJECT_CLASS (cls); - GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls); - GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls); - - oclass->set_property = gtk_tool_palette_set_property; - oclass->get_property = gtk_tool_palette_get_property; - oclass->dispose = gtk_tool_palette_dispose; - oclass->finalize = gtk_tool_palette_finalize; - - wclass->size_request = gtk_tool_palette_size_request; - wclass->size_allocate = gtk_tool_palette_size_allocate; - wclass->expose_event = gtk_tool_palette_expose_event; - wclass->realize = gtk_tool_palette_realize; - - cclass->add = gtk_tool_palette_add; - cclass->remove = gtk_tool_palette_remove; - cclass->forall = gtk_tool_palette_forall; - cclass->child_type = gtk_tool_palette_child_type; - cclass->set_child_property = gtk_tool_palette_set_child_property; - cclass->get_child_property = gtk_tool_palette_get_child_property; - - cls->set_scroll_adjustments = gtk_tool_palette_set_scroll_adjustments; - /** - * GtkToolPalette::set-scroll-adjustments: - * @widget: the GtkToolPalette that received the signal - * @hadjustment: The horizontal adjustment - * @vadjustment: The vertical adjustment - * - * The ::set-scroll-adjustments when FIXME - * - * Since: 2.18 - */ - wclass->set_scroll_adjustments_signal = - g_signal_new ("set-scroll-adjustments", - G_TYPE_FROM_CLASS (oclass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkToolPaletteClass, set_scroll_adjustments), - NULL, NULL, - _gtk_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, - GTK_TYPE_ADJUSTMENT, - GTK_TYPE_ADJUSTMENT); - - g_object_class_install_property (oclass, PROP_ICON_SIZE, - g_param_spec_enum ("icon-size", - P_("Icon Size"), - P_("The size of palette icons"), - GTK_TYPE_ICON_SIZE, - DEFAULT_ICON_SIZE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_ORIENTATION, - g_param_spec_enum ("orientation", - P_("Orientation"), - P_("Orientation of the tool palette"), - GTK_TYPE_ORIENTATION, - DEFAULT_ORIENTATION, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_TOOLBAR_STYLE, - g_param_spec_enum ("toolbar-style", - P_("Toolbar Style"), - P_("Style of items in the tool palette"), - GTK_TYPE_TOOLBAR_STYLE, - DEFAULT_TOOLBAR_STYLE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_EXCLUSIVE, - g_param_spec_boolean ("exclusive", - P_("Exclusive"), - P_("Whether the item group should be the only expanded at a given time"), - DEFAULT_CHILD_EXCLUSIVE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND, - g_param_spec_boolean ("expand", - P_("Expand"), - P_("Whether the item group should receive extra space when the palette grows"), - DEFAULT_CHILD_EXPAND, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_type_class_add_private (cls, sizeof (GtkToolPalettePrivate)); - - dnd_target_atom_item = gdk_atom_intern_static_string (dnd_targets[0].target); - dnd_target_atom_group = gdk_atom_intern_static_string (dnd_targets[1].target); -} - -/** - * gtk_tool_palette_new: - * - * Creates a new tool palette. - * - * Returns: a new #GtkToolPalette. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_new (void) -{ - return g_object_new (GTK_TYPE_TOOL_PALETTE, NULL); -} - -/** - * gtk_tool_palette_set_icon_size: - * @palette: an #GtkToolPalette. - * @icon_size: the #GtkIconSize that icons in the tool palette shall have. - * - * Sets the size of icons in the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_icon_size (GtkToolPalette *palette, - GtkIconSize icon_size) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (icon_size != palette->priv->icon_size) - g_object_set (palette, "icon-size", icon_size, NULL); -} - -/** - * gtk_tool_palette_set_orientation: - * @palette: an #GtkToolPalette. - * @orientation: the #GtkOrientation that the tool palette shall have. - * - * Sets the orientation (horizontal or vertical) of the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_orientation (GtkToolPalette *palette, - GtkOrientation orientation) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (orientation != palette->priv->orientation) - g_object_set (palette, "orientation", orientation, NULL); -} - -/** - * gtk_tool_palette_set_style: - * @palette: an #GtkToolPalette. - * @style: the #GtkToolbarStyle that items in the tool palette shall have. - * - * Sets the style (text, icons or both) of items in the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_style (GtkToolPalette *palette, - GtkToolbarStyle style) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (style != palette->priv->style) - g_object_set (palette, "toolbar-style", style, NULL); -} - -/** - * gtk_tool_palette_get_icon_size: - * @palette: an #GtkToolPalette. - * - * Gets the size of icons in the tool palette. See gtk_tool_palette_set_icon_size(). - * - * Returns: the #GtkIconSize of icons in the tool palette. - * - * Since: 2.18 - */ -GtkIconSize -gtk_tool_palette_get_icon_size (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ICON_SIZE); - return palette->priv->icon_size; -} - -/** - * gtk_tool_palette_get_orientation: - * @palette: an #GtkToolPalette. - * - * Gets the orientation (horizontal or vertical) of the tool palette. See gtk_tool_palette_set_orientation(). - * - * Returns the #GtkOrientation of the tool palette. - */ -GtkOrientation -gtk_tool_palette_get_orientation (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ORIENTATION); - return palette->priv->orientation; -} - -/** - * gtk_tool_palette_get_style: - * @palette: an #GtkToolPalette. - * - * Gets the style (icons, text or both) of items in the tool palette. - * - * Returns: the #GtkToolbarStyle of items in the tool palette. - * - * Since: 2.18 - */ -GtkToolbarStyle -gtk_tool_palette_get_style (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_TOOLBAR_STYLE); - return palette->priv->style; -} - -/** - * gtk_tool_palette_set_group_position: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @position: a new index for group. - * - * Sets the position of the group as an index of the tool palette. - * If position is 0 the group will become the first child, if position is - * -1 it will become the last child. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_group_position (GtkToolPalette *palette, - GtkWidget *group, - gint position) -{ - GtkToolItemGroupInfo group_info; - gint old_position; - gpointer src, dst; - gsize len; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - gtk_tool_palette_repack (palette); - - g_return_if_fail (position >= -1); - - if (-1 == position) - position = palette->priv->groups_length - 1; - - g_return_if_fail ((guint) position < palette->priv->groups_length); - - if (GTK_TOOL_ITEM_GROUP (group) == palette->priv->groups[position].widget) - return; - - old_position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (old_position >= 0); - - group_info = palette->priv->groups[old_position]; - - if (position < old_position) - { - dst = palette->priv->groups + position + 1; - src = palette->priv->groups + position; - len = old_position - position; - } - else - { - dst = palette->priv->groups + old_position; - src = palette->priv->groups + old_position + 1; - len = position - old_position; - } - - memmove (dst, src, len * sizeof (*palette->priv->groups)); - palette->priv->groups[position] = group_info; - - gtk_widget_queue_resize (GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_group_notify_collapsed (GtkToolItemGroup *group, - GParamSpec *pspec G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (data); - guint i; - - if (gtk_tool_item_group_get_collapsed (group)) - return; - - for (i = 0; i < palette->priv->groups_size; ++i) - { - GtkToolItemGroup *current_group = palette->priv->groups[i].widget; - - if (current_group && current_group != group) - gtk_tool_item_group_set_collapsed (palette->priv->groups[i].widget, TRUE); - } -} - -/** - * gtk_tool_palette_set_exclusive: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @exclusive: whether the group should be exclusive or not. - * - * Sets whether the group should be exclusive or not. If an exclusive group is expanded - * all other groups are collapsed. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_exclusive (GtkToolPalette *palette, - GtkWidget *group, - gboolean exclusive) -{ - GtkToolItemGroupInfo *group_info; - gint position; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (position >= 0); - - group_info = &palette->priv->groups[position]; - - if (exclusive == group_info->exclusive) - return; - - group_info->exclusive = exclusive; - - if (group_info->exclusive != (0 != group_info->notify_collapsed)) - { - if (group_info->exclusive) - { - group_info->notify_collapsed = - g_signal_connect (group, "notify::collapsed", - G_CALLBACK (gtk_tool_palette_group_notify_collapsed), - palette); - } - else - { - g_signal_handler_disconnect (group, group_info->notify_collapsed); - group_info->notify_collapsed = 0; - } - } - - gtk_tool_palette_group_notify_collapsed (group_info->widget, NULL, palette); - gtk_widget_child_notify (group, "exclusive"); -} - -/** - * gtk_tool_palette_set_expand: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @expand: whether the group should be given extra space. - * - * Sets whether the group should be given extra space. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_expand (GtkToolPalette *palette, - GtkWidget *group, - gboolean expand) -{ - GtkToolItemGroupInfo *group_info; - gint position; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (position >= 0); - - group_info = &palette->priv->groups[position]; - - if (expand != group_info->expand) - { - group_info->expand = expand; - gtk_widget_queue_resize (GTK_WIDGET (palette)); - gtk_widget_child_notify (group, "expand"); - } -} - -/** - * gtk_tool_palette_get_group_position: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup. - * - * Gets the position of @group in @palette as index. see gtk_tool_palette_set_group_position(). - * - * Returns: the index of group or -1 if @group is not a child of @palette. - * - * Since: 2.18 - */ -gint -gtk_tool_palette_get_group_position (GtkToolPalette *palette, - GtkWidget *group) -{ - guint i; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), -1); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1); - - for (i = 0; i < palette->priv->groups_length; ++i) - if ((gpointer) group == palette->priv->groups[i].widget) - return i; - - return -1; -} - -/** - * gtk_tool_palette_get_exclusive: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * - * Gets whether group is exclusive or not. See gtk_tool_palette_set_exclusive(). - * - * Returns: %TRUE if group is exclusive. - * - * Since: 2.18 - */ -gboolean -gtk_tool_palette_get_exclusive (GtkToolPalette *palette, - GtkWidget *group) -{ - gint position; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXCLUSIVE); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXCLUSIVE); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXCLUSIVE); - - return palette->priv->groups[position].exclusive; -} - -/** - * gtk_tool_palette_get_expand: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * - * Gets whether group should be given extra space. See gtk_tool_palette_set_expand(). - * - * Returns: %TRUE if group should be given extra space, %FALSE otherwise. - * - * Since: 2.18 - */ -gboolean -gtk_tool_palette_get_expand (GtkToolPalette *palette, - GtkWidget *group) -{ - gint position; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXPAND); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXPAND); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXPAND); - - return palette->priv->groups[position].expand; -} - -/** - * gtk_tool_palette_get_drop_item: - * @palette: an #GtkToolPalette. - * @x: the x position. - * @y: the y position. - * - * Gets the item at position (x, y). See gtk_tool_palette_get_drop_group(). - * - * Returns: the #GtkToolItem at position or %NULL if there is no such item. - * - * Since: 2.18 - */ -GtkToolItem* -gtk_tool_palette_get_drop_item (GtkToolPalette *palette, - gint x, - gint y) -{ - GtkWidget *group = gtk_tool_palette_get_drop_group (palette, x, y); - - if (group) - return gtk_tool_item_group_get_drop_item (GTK_TOOL_ITEM_GROUP (group), - x - group->allocation.x, - y - group->allocation.y); - - return NULL; -} - -/** - * gtk_tool_palette_get_drop_group: - * @palette: an #GtkToolPalette. - * @x: the x position. - * @y: the y position. - * - * Gets the group at position (x, y). - * - * Returns: the #GtkToolItemGroup at position or %NULL if there is no such group. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_get_drop_group (GtkToolPalette *palette, - gint x, - gint y) -{ - GtkAllocation *allocation; - guint i; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - - allocation = >K_WIDGET (palette)->allocation; - - g_return_val_if_fail (x >= 0 && x < allocation->width, NULL); - g_return_val_if_fail (y >= 0 && y < allocation->height, NULL); - - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - GtkWidget *widget; - gint x0, y0; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - x0 = x - widget->allocation.x; - y0 = y - widget->allocation.y; - - if (x0 >= 0 && x0 < widget->allocation.width && - y0 >= 0 && y0 < widget->allocation.height) - return widget; - } - - return NULL; -} - -/** - * gtk_tool_palette_get_drag_item: - * @palette: an #GtkToolPalette. - * @selection: a #GtkSelectionData. - * - * Get the dragged item from the selection. This could be a #GtkToolItem or - * an #GtkToolItemGroup. - * - * Returns: the dragged item in selection. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_get_drag_item (GtkToolPalette *palette, - const GtkSelectionData *selection) -{ - GtkToolPaletteDragData *data; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - g_return_val_if_fail (NULL != selection, NULL); - - g_return_val_if_fail (selection->format == 8, NULL); - g_return_val_if_fail (selection->length == sizeof (GtkToolPaletteDragData), NULL); - g_return_val_if_fail (selection->target == dnd_target_atom_item || - selection->target == dnd_target_atom_group, - NULL); - - data = (GtkToolPaletteDragData*) selection->data; - - g_return_val_if_fail (data->palette == palette, NULL); - - if (dnd_target_atom_item == selection->target) - g_return_val_if_fail (GTK_IS_TOOL_ITEM (data->item), NULL); - else if (dnd_target_atom_group == selection->target) - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (data->item), NULL); - - return data->item; -} - -/** - * gtk_tool_palette_set_drag_source: - * @palette: an #GtkToolPalette. - * @targets: the #GtkToolPaletteDragTargets which the widget should support. - * - * Sets the tool palette as a drag source. Enables all groups and items in - * the tool palette as drag sources on button 1 and button 3 press with copy - * and move actions. - * - * See gtk_drag_source_set(). - * - * Since: 2.18 - * - */ -void -gtk_tool_palette_set_drag_source (GtkToolPalette *palette, - GtkToolPaletteDragTargets targets) -{ - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if ((palette->priv->drag_source & targets) == targets) - return; - - palette->priv->drag_source |= targets; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - if (palette->priv->groups[i].widget) - gtk_container_forall (GTK_CONTAINER (palette->priv->groups[i].widget), - _gtk_tool_palette_child_set_drag_source, - palette); - } -} - -/** - * gtk_tool_palette_add_drag_dest: - * @palette: an #GtkToolPalette. - * @widget: a #GtkWidget which should be a drag destination for palette. - * @flags: the flags that specify what actions GTK+ should take for drops on that widget. - * @targets: the #GtkToolPaletteDragTargets which the widget should support. - * @actions: the #GdkDragActions which the widget should suppport. - * - * Sets the tool palette as drag source (see gtk_tool_palette_set_drag_source) and - * sets widget as a drag destination for drags from palette. With flags the actions - * (like highlighting and target checking) which should be performed by GTK+ for - * drops on widget can be specified. With targets the supported drag targets - * (groups and/or items) can be specified. With actions the supported drag actions - * (copy and move) can be specified. - * - * See gtk_drag_dest_set(). - * - * Since: 2.18 - */ -void -gtk_tool_palette_add_drag_dest (GtkToolPalette *palette, - GtkWidget *widget, - GtkDestDefaults flags, - GtkToolPaletteDragTargets targets, - GdkDragAction actions) -{ - GtkTargetEntry entries[G_N_ELEMENTS (dnd_targets)]; - gint n_entries = 0; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_WIDGET (widget)); - - gtk_tool_palette_set_drag_source (palette, - targets); - - if (targets & GTK_TOOL_PALETTE_DRAG_ITEMS) - entries[n_entries++] = dnd_targets[0]; - if (targets & GTK_TOOL_PALETTE_DRAG_GROUPS) - entries[n_entries++] = dnd_targets[1]; - - gtk_drag_dest_set (widget, flags, entries, n_entries, actions); -} - -void -_gtk_tool_palette_get_item_size (GtkToolPalette *palette, - GtkRequisition *item_size, - gboolean homogeneous_only, - gint *requested_rows) -{ - GtkRequisition max_requisition; - gint max_rows; - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (NULL != item_size); - - max_requisition.width = 0; - max_requisition.height = 0; - max_rows = 0; - - /* iterate over all groups and calculate the max item_size and max row request */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkRequisition requisition; - gint rows; - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (!group->widget) - continue; - - _gtk_tool_item_group_item_size_request (group->widget, &requisition, homogeneous_only, &rows); - - max_requisition.width = MAX (max_requisition.width, requisition.width); - max_requisition.height = MAX (max_requisition.height, requisition.height); - max_rows = MAX (max_rows, rows); - } - - *item_size = max_requisition; - if (requested_rows) - *requested_rows = max_rows; -} - -static void -gtk_tool_palette_item_drag_data_get (GtkWidget *widget, - GdkDragContext *context G_GNUC_UNUSED, - GtkSelectionData *selection, - guint info G_GNUC_UNUSED, - guint time G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL }; - - if (selection->target == dnd_target_atom_item) - drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); - - if (drag_data.item) - gtk_selection_data_set (selection, selection->target, 8, - (guchar*) &drag_data, sizeof (drag_data)); -} - -static void -gtk_tool_palette_child_drag_data_get (GtkWidget *widget, - GdkDragContext *context G_GNUC_UNUSED, - GtkSelectionData *selection, - guint info G_GNUC_UNUSED, - guint time G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL }; - - if (selection->target == dnd_target_atom_group) - drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM_GROUP); - - if (drag_data.item) - gtk_selection_data_set (selection, selection->target, 8, - (guchar*) &drag_data, sizeof (drag_data)); -} - -void -_gtk_tool_palette_child_set_drag_source (GtkWidget *child, - gpointer data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (data); - - /* Check drag_source, - * to work properly when called from gtk_tool_item_group_insert(). - */ - if (!palette->priv->drag_source) - return; - - if (GTK_IS_TOOL_ITEM (child) && - (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_ITEMS)) - { - /* Connect to child instead of the item itself, - * to work arround bug 510377. - */ - if (GTK_IS_TOOL_BUTTON (child)) - child = gtk_bin_get_child (GTK_BIN (child)); - - if (!child) - return; - - gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, - &dnd_targets[0], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); - - g_signal_connect (child, "drag-data-get", - G_CALLBACK (gtk_tool_palette_item_drag_data_get), - palette); - } - else if (GTK_IS_BUTTON (child) && - (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_GROUPS)) - { - gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, - &dnd_targets[1], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); - - g_signal_connect (child, "drag-data-get", - G_CALLBACK (gtk_tool_palette_child_drag_data_get), - palette); - } -} - -/** - * gtk_tool_palette_get_drag_target_item: - * - * Get the target entry for a dragged #GtkToolItem. - * - * Returns: the #GtkTargetEntry for a dragged item. - * - * Since: 2.18 - */ -G_CONST_RETURN GtkTargetEntry* -gtk_tool_palette_get_drag_target_item (void) -{ - return &dnd_targets[0]; -} - -/** - * gtk_tool_palette_get_drag_target_group: - * - * Get the target entry for a dragged #GtkToolItemGroup. - * - * Returns: the #GtkTargetEntry for a dragged group. - * - * Since: 2.18 - */ -G_CONST_RETURN GtkTargetEntry* -gtk_tool_palette_get_drag_target_group (void) -{ - return &dnd_targets[1]; -} - -void -_gtk_tool_palette_set_expanding_child (GtkToolPalette *palette, - GtkWidget *widget) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - palette->priv->expanding_child = widget; -} - -GtkAdjustment* -gtk_tool_palette_get_hadjustment (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - return palette->priv->hadjustment; -} - -GtkAdjustment* -gtk_tool_palette_get_vadjustment (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - return palette->priv->vadjustment; -} - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - -GtkSizeGroup * -_gtk_tool_palette_get_size_group (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - - return palette->priv->text_size_group; -} - -#endif -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#include "gtktoolpaletteprivate.h" -#include "gtkmarshalers.h" - -#include -#include - -#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR -#define DEFAULT_ORIENTATION GTK_ORIENTATION_VERTICAL -#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_ICONS - -#define DEFAULT_CHILD_EXCLUSIVE FALSE -#define DEFAULT_CHILD_EXPAND FALSE - -#define P_(msgid) (msgid) - -/** - * SECTION:GtkToolPalette - * @short_description: A tool palette with categories - * @include: gtktoolpalette.h - * - * An #GtkToolPalette allows it to add #GtkToolItems to a palette like container - * with different categories and drag and drop support. - * - * An #GtkToolPalette is created with a call to gtk_tool_palette_new(). - * - * #GtkToolItems cannot be added directly to an #GtkToolPalette, instead they - * are added to an #GtkToolItemGroup which can than be added to an #GtkToolPalette. To add - * an #GtkToolItemGroup to an #GtkToolPalette use gtk_container_add(). - * - * |[ - * GtkWidget *palette, *group; - * GtkToolItem *item; - * - * palette = gtk_tool_palette_new (); - * group = gtk_tool_item_group_new (_("Test Category")); - * gtk_container_add (GTK_CONTAINER (palette), group); - * - * item = gtk_tool_button_new_from_stock (GTK_STOCK_OK); - * gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1); - * ]| - * - * The easiest way to use drag and drop with GtkToolPalette is to call gtk_tool_palette_add_drag_dest() - * with the desired drag source @palette and the desired drag target @widget. Than gtk_tool_palette_get_drag_item() - * can be used to get the dragged item in the #GtkWidget::drag-data-received signal handler of the drag target. - * - * |[ - * static void - * passive_canvas_drag_data_received (GtkWidget *widget, - * GdkDragContext *context, - * gint x, - * gint y, - * GtkSelectionData *selection, - * guint info, - * guint time, - * gpointer data) - * { - * GtkWidget *palette; - * GtkWidget *item; - * - * /* Get the dragged item */ - * palette = gtk_widget_get_ancestor (gtk_drag_get_source_widget (context), GTK_TYPE_TOOL_PALETTE); - * if (palette != NULL) - * item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette), selection); - * - * /* Do something with item */ - * } - * - * GtkWidget *target, palette; - * - * palette = gtk_tool_palette_new (); - * target = gtk_drawing_area_new (); - * - * g_signal_connect (G_OBJECT (target), "drag-data-received", - * G_CALLBACK (passive_canvas_drag_data_received), NULL); - * gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette), target, - * GTK_DEST_DEFAULT_ALL, - * GTK_TOOL_PALETTE_DRAG_ITEMS, - * GDK_ACTION_COPY); - * ]| - * - * Since: 2.18 - */ - -typedef struct _GtkToolItemGroupInfo GtkToolItemGroupInfo; -typedef struct _GtkToolPaletteDragData GtkToolPaletteDragData; - -enum -{ - PROP_NONE, - PROP_ICON_SIZE, - PROP_ORIENTATION, - PROP_TOOLBAR_STYLE, -}; - -enum -{ - CHILD_PROP_NONE, - CHILD_PROP_EXCLUSIVE, - CHILD_PROP_EXPAND, -}; - -struct _GtkToolItemGroupInfo -{ - GtkToolItemGroup *widget; - - guint notify_collapsed; - guint exclusive : 1; - guint expand : 1; -}; - -struct _GtkToolPalettePrivate -{ - GtkToolItemGroupInfo *groups; - gsize groups_size; - gsize groups_length; - - GtkAdjustment *hadjustment; - GtkAdjustment *vadjustment; - - GtkIconSize icon_size; - GtkOrientation orientation; - GtkToolbarStyle style; - - GtkWidget *expanding_child; - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - GtkSizeGroup *text_size_group; -#endif - - guint sparse_groups : 1; - guint drag_source : 2; -}; - -struct _GtkToolPaletteDragData -{ - GtkToolPalette *palette; - GtkWidget *item; -}; - -static GdkAtom dnd_target_atom_item = GDK_NONE; -static GdkAtom dnd_target_atom_group = GDK_NONE; - -static const GtkTargetEntry dnd_targets[] = -{ - { "application/x-GTK-tool-palette-item", GTK_TARGET_SAME_APP, 0 }, - { "application/x-GTK-tool-palette-group", GTK_TARGET_SAME_APP, 0 }, -}; - -G_DEFINE_TYPE (GtkToolPalette, - gtk_tool_palette, - GTK_TYPE_CONTAINER); - -static void -gtk_tool_palette_init (GtkToolPalette *palette) -{ - palette->priv = G_TYPE_INSTANCE_GET_PRIVATE (palette, - GTK_TYPE_TOOL_PALETTE, - GtkToolPalettePrivate); - - palette->priv->groups_size = 4; - palette->priv->groups_length = 0; - palette->priv->groups = g_new0 (GtkToolItemGroupInfo, palette->priv->groups_size); - - palette->priv->icon_size = DEFAULT_ICON_SIZE; - palette->priv->orientation = DEFAULT_ORIENTATION; - palette->priv->style = DEFAULT_TOOLBAR_STYLE; - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - palette->priv->text_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH); -#endif -} - -static void -gtk_tool_palette_reconfigured (GtkToolPalette *palette) -{ - guint i; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - if (palette->priv->groups[i].widget) - _gtk_tool_item_group_palette_reconfigured (palette->priv->groups[i].widget); - } - - gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - switch (prop_id) - { - case PROP_ICON_SIZE: - if ((guint) g_value_get_enum (value) != palette->priv->icon_size) - { - palette->priv->icon_size = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - case PROP_ORIENTATION: - if ((guint) g_value_get_enum (value) != palette->priv->orientation) - { - palette->priv->orientation = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - case PROP_TOOLBAR_STYLE: - if ((guint) g_value_get_enum (value) != palette->priv->style) - { - palette->priv->style = g_value_get_enum (value); - gtk_tool_palette_reconfigured (palette); - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - switch (prop_id) - { - case PROP_ICON_SIZE: - g_value_set_enum (value, gtk_tool_palette_get_icon_size (palette)); - break; - - case PROP_ORIENTATION: - g_value_set_enum (value, gtk_tool_palette_get_orientation (palette)); - break; - - case PROP_TOOLBAR_STYLE: - g_value_set_enum (value, gtk_tool_palette_get_style (palette)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_dispose (GObject *object) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - guint i; - - if (palette->priv->hadjustment) - { - g_object_unref (palette->priv->hadjustment); - palette->priv->hadjustment = NULL; - } - - if (palette->priv->vadjustment) - { - g_object_unref (palette->priv->vadjustment); - palette->priv->vadjustment = NULL; - } - - for (i = 0; i < palette->priv->groups_size; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (group->notify_collapsed) - { - g_signal_handler_disconnect (group->widget, group->notify_collapsed); - group->notify_collapsed = 0; - } - } - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - if (palette->priv->text_size_group) - { - g_object_unref (palette->priv->text_size_group); - palette->priv->text_size_group = NULL; - } -#endif - - G_OBJECT_CLASS (gtk_tool_palette_parent_class)->dispose (object); -} - -static void -gtk_tool_palette_finalize (GObject *object) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (object); - - if (palette->priv->groups) - { - palette->priv->groups_length = 0; - g_free (palette->priv->groups); - palette->priv->groups = NULL; - } - - G_OBJECT_CLASS (gtk_tool_palette_parent_class)->finalize (object); -} - -static void -gtk_tool_palette_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GtkRequisition child_requisition; - guint i; - - requisition->width = 0; - requisition->height = 0; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (!group->widget) - continue; - - gtk_widget_size_request (GTK_WIDGET (group->widget), &child_requisition); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - requisition->width = MAX (requisition->width, child_requisition.width); - requisition->height += child_requisition.height; - } - else - { - requisition->width += child_requisition.width; - requisition->height = MAX (requisition->height, child_requisition.height); - } - } - - requisition->width += border_width * 2; - requisition->height += border_width * 2; -} - -static void -gtk_tool_palette_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GtkAdjustment *adjustment = NULL; - GtkAllocation child_allocation; - - gint n_expand_groups = 0; - gint remaining_space = 0; - gint expand_space = 0; - - gint page_start, page_size = 0; - gint offset = 0; - guint i; - - gint min_offset = -1, max_offset = -1; - - gint x; - - gint *group_sizes = g_newa(gint, palette->priv->groups_length); - - GtkTextDirection direction = gtk_widget_get_direction (widget); - - GTK_WIDGET_CLASS (gtk_tool_palette_parent_class)->size_allocate (widget, allocation); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - adjustment = palette->priv->vadjustment; - page_size = allocation->height; - } - else - { - adjustment = palette->priv->hadjustment; - page_size = allocation->width; - } - - if (adjustment) - offset = gtk_adjustment_get_value (adjustment); - if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation && - GTK_TEXT_DIR_RTL == direction) - offset = -offset; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.width = allocation->width - border_width * 2; - else - child_allocation.height = allocation->height - border_width * 2; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - remaining_space = allocation->height; - else - remaining_space = allocation->width; - - /* figure out the required size of all groups to be able to distribute the - * remaining space on allocation */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - gint size; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - if (gtk_tool_item_group_get_n_items (group->widget)) - { - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - size = _gtk_tool_item_group_get_height_for_width (group->widget, child_allocation.width); - else - size = _gtk_tool_item_group_get_width_for_height (group->widget, child_allocation.height); - - if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget)) - n_expand_groups += 1; - } - else - size = 0; - - remaining_space -= size; - group_sizes[i] = size; - - /* if the widget is currently expanding an offset which allows to display as much of the - * widget as possible is calculated */ - if (widget == palette->priv->expanding_child) - { - gint limit = - GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? - child_allocation.width : child_allocation.height; - - gint real_size; - guint j; - - min_offset = 0; - - for (j = 0; j < i; ++j) - min_offset += group_sizes[j]; - - max_offset = min_offset + group_sizes[i]; - - real_size = _gtk_tool_item_group_get_size_for_limit - (GTK_TOOL_ITEM_GROUP (widget), limit, - GTK_ORIENTATION_VERTICAL == palette->priv->orientation, - FALSE); - - if (size == real_size) - palette->priv->expanding_child = NULL; - } - } - - if (n_expand_groups > 0) - { - remaining_space = MAX (0, remaining_space); - expand_space = remaining_space / n_expand_groups; - } - - if (max_offset != -1) - { - gint limit = - GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? - allocation->height : allocation->width; - - offset = MIN (MAX (offset, max_offset - limit), min_offset); - } - - if (remaining_space > 0) - offset = 0; - - x = border_width; - child_allocation.y = border_width; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.y -= offset; - else - x -= offset; - - /* allocate all groups at the calculated positions */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - GtkWidget *widget; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - if (gtk_tool_item_group_get_n_items (group->widget)) - { - gint size = group_sizes[i]; - - if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget)) - { - size += MIN (expand_space, remaining_space); - remaining_space -= expand_space; - } - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.height = size; - else - child_allocation.width = size; - - if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation && - GTK_TEXT_DIR_RTL == direction) - child_allocation.x = allocation->width - x - child_allocation.width; - else - child_allocation.x = x; - - gtk_widget_size_allocate (widget, &child_allocation); - gtk_widget_show (widget); - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - child_allocation.y += child_allocation.height; - else - x += child_allocation.width; - } - else - gtk_widget_hide (widget); - } - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation) - { - child_allocation.y += border_width; - child_allocation.y += offset; - - page_start = child_allocation.y; - } - else - { - x += border_width; - x += offset; - - page_start = x; - } - - /* update the scrollbar to match the displayed adjustment */ - if (adjustment) - { - gdouble value; - - adjustment->page_increment = page_size * 0.9; - adjustment->step_increment = page_size * 0.1; - adjustment->page_size = page_size; - - if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation || - GTK_TEXT_DIR_LTR == direction) - { - adjustment->lower = 0; - adjustment->upper = MAX (0, page_start); - - value = MIN (offset, adjustment->upper - adjustment->page_size); - gtk_adjustment_clamp_page (adjustment, value, offset + page_size); - } - else - { - adjustment->lower = page_size - MAX (0, page_start); - adjustment->upper = page_size; - - offset = -offset; - - value = MAX (offset, adjustment->lower); - gtk_adjustment_clamp_page (adjustment, offset, value + page_size); - } - - gtk_adjustment_changed (adjustment); - } -} - -static gboolean -gtk_tool_palette_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - GdkDisplay *display; - cairo_t *cr; - guint i; - - display = gdk_drawable_get_display (widget->window); - - if (!gdk_display_supports_composite (display)) - return FALSE; - - cr = gdk_cairo_create (widget->window); - gdk_cairo_region (cr, event->region); - cairo_clip (cr); - - cairo_push_group (cr); - - for (i = 0; i < palette->priv->groups_length; ++i) - if (palette->priv->groups[i].widget) - _gtk_tool_item_group_paint (palette->priv->groups[i].widget, cr); - - cairo_pop_group_to_source (cr); - - cairo_paint (cr); - cairo_destroy (cr); - - return FALSE; -} - -static void -gtk_tool_palette_realize (GtkWidget *widget) -{ - const gint border_width = GTK_CONTAINER (widget)->border_width; - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - GdkWindowAttr attributes; - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x + border_width; - attributes.y = widget->allocation.y + border_width; - attributes.width = widget->allocation.width - border_width * 2; - attributes.height = widget->allocation.height - border_width * 2; - 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 | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_BUTTON_MOTION_MASK; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - - gdk_window_set_user_data (widget->window, widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - - gtk_container_forall (GTK_CONTAINER (widget), - (GtkCallback) gtk_widget_set_parent_window, - widget->window); - - gtk_widget_queue_resize_no_redraw (widget); -} - -static void -gtk_tool_palette_adjustment_value_changed (GtkAdjustment *adjustment G_GNUC_UNUSED, - gpointer data) -{ - GtkWidget *widget = GTK_WIDGET (data); - gtk_tool_palette_size_allocate (widget, &widget->allocation); -} - -static void -gtk_tool_palette_set_scroll_adjustments (GtkWidget *widget, - GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (widget); - - if (palette->priv->hadjustment) - g_object_unref (palette->priv->hadjustment); - if (palette->priv->vadjustment) - g_object_unref (palette->priv->vadjustment); - - if (hadjustment) - g_object_ref_sink (hadjustment); - if (vadjustment) - g_object_ref_sink (vadjustment); - - palette->priv->hadjustment = hadjustment; - palette->priv->vadjustment = vadjustment; - - if (palette->priv->hadjustment) - g_signal_connect (palette->priv->hadjustment, "value-changed", - G_CALLBACK (gtk_tool_palette_adjustment_value_changed), - palette); - if (palette->priv->vadjustment) - g_signal_connect (palette->priv->vadjustment, "value-changed", - G_CALLBACK (gtk_tool_palette_adjustment_value_changed), - palette); -} - -static void -gtk_tool_palette_repack (GtkToolPalette *palette) -{ - guint si, di; - - for (si = di = 0; di < palette->priv->groups_length; ++si) - { - if (palette->priv->groups[si].widget) - { - palette->priv->groups[di] = palette->priv->groups[si]; - ++di; - } - else - --palette->priv->groups_length; - } - - palette->priv->sparse_groups = FALSE; -} - -static void -gtk_tool_palette_add (GtkContainer *container, - GtkWidget *child) -{ - GtkToolPalette *palette; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (container)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (child)); - - palette = GTK_TOOL_PALETTE (container); - - if (palette->priv->groups_length == palette->priv->groups_size) - gtk_tool_palette_repack (palette); - - if (palette->priv->groups_length == palette->priv->groups_size) - { - gsize old_size = palette->priv->groups_size; - gsize new_size = old_size * 2; - - palette->priv->groups = g_renew (GtkToolItemGroupInfo, - palette->priv->groups, - new_size); - - memset (palette->priv->groups + old_size, 0, - sizeof (GtkToolItemGroupInfo) * old_size); - - palette->priv->groups_size = new_size; - } - - palette->priv->groups[palette->priv->groups_length].widget = g_object_ref_sink (child); - palette->priv->groups_length += 1; - - gtk_widget_set_parent (child, GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_remove (GtkContainer *container, - GtkWidget *child) -{ - GtkToolPalette *palette; - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (container)); - palette = GTK_TOOL_PALETTE (container); - - for (i = 0; i < palette->priv->groups_length; ++i) - if ((GtkWidget*) palette->priv->groups[i].widget == child) - { - g_object_unref (child); - gtk_widget_unparent (child); - - memset (&palette->priv->groups[i], 0, sizeof (GtkToolItemGroupInfo)); - palette->priv->sparse_groups = TRUE; - } -} - -static void -gtk_tool_palette_forall (GtkContainer *container, - gboolean internals G_GNUC_UNUSED, - GtkCallback callback, - gpointer callback_data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - guint i; - - if (palette->priv->groups) - { - for (i = 0; i < palette->priv->groups_length; ++i) - if (palette->priv->groups[i].widget) - callback (GTK_WIDGET (palette->priv->groups[i].widget), - callback_data); - } -} - -static GType -gtk_tool_palette_child_type (GtkContainer *container G_GNUC_UNUSED) -{ - return GTK_TYPE_TOOL_ITEM_GROUP; -} - -static void -gtk_tool_palette_set_child_property (GtkContainer *container, - GtkWidget *child, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - - switch (prop_id) - { - case CHILD_PROP_EXCLUSIVE: - gtk_tool_palette_set_exclusive (palette, child, g_value_get_boolean (value)); - break; - - case CHILD_PROP_EXPAND: - gtk_tool_palette_set_expand (palette, child, g_value_get_boolean (value)); - break; - - default: - GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_get_child_property (GtkContainer *container, - GtkWidget *child, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (container); - - switch (prop_id) - { - case CHILD_PROP_EXCLUSIVE: - g_value_set_boolean (value, gtk_tool_palette_get_exclusive (palette, child)); - break; - - case CHILD_PROP_EXPAND: - g_value_set_boolean (value, gtk_tool_palette_get_expand (palette, child)); - break; - - default: - GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec); - break; - } -} - -static void -gtk_tool_palette_class_init (GtkToolPaletteClass *cls) -{ - GObjectClass *oclass = G_OBJECT_CLASS (cls); - GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls); - GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls); - - oclass->set_property = gtk_tool_palette_set_property; - oclass->get_property = gtk_tool_palette_get_property; - oclass->dispose = gtk_tool_palette_dispose; - oclass->finalize = gtk_tool_palette_finalize; - - wclass->size_request = gtk_tool_palette_size_request; - wclass->size_allocate = gtk_tool_palette_size_allocate; - wclass->expose_event = gtk_tool_palette_expose_event; - wclass->realize = gtk_tool_palette_realize; - - cclass->add = gtk_tool_palette_add; - cclass->remove = gtk_tool_palette_remove; - cclass->forall = gtk_tool_palette_forall; - cclass->child_type = gtk_tool_palette_child_type; - cclass->set_child_property = gtk_tool_palette_set_child_property; - cclass->get_child_property = gtk_tool_palette_get_child_property; - - cls->set_scroll_adjustments = gtk_tool_palette_set_scroll_adjustments; - /** - * GtkToolPalette::set-scroll-adjustments: - * @widget: the GtkToolPalette that received the signal - * @hadjustment: The horizontal adjustment - * @vadjustment: The vertical adjustment - * - * The ::set-scroll-adjustments when FIXME - * - * Since: 2.18 - */ - wclass->set_scroll_adjustments_signal = - g_signal_new ("set-scroll-adjustments", - G_TYPE_FROM_CLASS (oclass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkToolPaletteClass, set_scroll_adjustments), - NULL, NULL, - _gtk_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, - GTK_TYPE_ADJUSTMENT, - GTK_TYPE_ADJUSTMENT); - - g_object_class_install_property (oclass, PROP_ICON_SIZE, - g_param_spec_enum ("icon-size", - P_("Icon Size"), - P_("The size of palette icons"), - GTK_TYPE_ICON_SIZE, - DEFAULT_ICON_SIZE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_ORIENTATION, - g_param_spec_enum ("orientation", - P_("Orientation"), - P_("Orientation of the tool palette"), - GTK_TYPE_ORIENTATION, - DEFAULT_ORIENTATION, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (oclass, PROP_TOOLBAR_STYLE, - g_param_spec_enum ("toolbar-style", - P_("Toolbar Style"), - P_("Style of items in the tool palette"), - GTK_TYPE_TOOLBAR_STYLE, - DEFAULT_TOOLBAR_STYLE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_EXCLUSIVE, - g_param_spec_boolean ("exclusive", - P_("Exclusive"), - P_("Whether the item group should be the only expanded at a given time"), - DEFAULT_CHILD_EXCLUSIVE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND, - g_param_spec_boolean ("expand", - P_("Expand"), - P_("Whether the item group should receive extra space when the palette grows"), - DEFAULT_CHILD_EXPAND, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_type_class_add_private (cls, sizeof (GtkToolPalettePrivate)); - - dnd_target_atom_item = gdk_atom_intern_static_string (dnd_targets[0].target); - dnd_target_atom_group = gdk_atom_intern_static_string (dnd_targets[1].target); -} - -/** - * gtk_tool_palette_new: - * - * Creates a new tool palette. - * - * Returns: a new #GtkToolPalette. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_new (void) -{ - return g_object_new (GTK_TYPE_TOOL_PALETTE, NULL); -} - -/** - * gtk_tool_palette_set_icon_size: - * @palette: an #GtkToolPalette. - * @icon_size: the #GtkIconSize that icons in the tool palette shall have. - * - * Sets the size of icons in the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_icon_size (GtkToolPalette *palette, - GtkIconSize icon_size) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (icon_size != palette->priv->icon_size) - g_object_set (palette, "icon-size", icon_size, NULL); -} - -/** - * gtk_tool_palette_set_orientation: - * @palette: an #GtkToolPalette. - * @orientation: the #GtkOrientation that the tool palette shall have. - * - * Sets the orientation (horizontal or vertical) of the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_orientation (GtkToolPalette *palette, - GtkOrientation orientation) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (orientation != palette->priv->orientation) - g_object_set (palette, "orientation", orientation, NULL); -} - -/** - * gtk_tool_palette_set_style: - * @palette: an #GtkToolPalette. - * @style: the #GtkToolbarStyle that items in the tool palette shall have. - * - * Sets the style (text, icons or both) of items in the tool palette. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_style (GtkToolPalette *palette, - GtkToolbarStyle style) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if (style != palette->priv->style) - g_object_set (palette, "toolbar-style", style, NULL); -} - -/** - * gtk_tool_palette_get_icon_size: - * @palette: an #GtkToolPalette. - * - * Gets the size of icons in the tool palette. See gtk_tool_palette_set_icon_size(). - * - * Returns: the #GtkIconSize of icons in the tool palette. - * - * Since: 2.18 - */ -GtkIconSize -gtk_tool_palette_get_icon_size (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ICON_SIZE); - return palette->priv->icon_size; -} - -/** - * gtk_tool_palette_get_orientation: - * @palette: an #GtkToolPalette. - * - * Gets the orientation (horizontal or vertical) of the tool palette. See gtk_tool_palette_set_orientation(). - * - * Returns the #GtkOrientation of the tool palette. - */ -GtkOrientation -gtk_tool_palette_get_orientation (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ORIENTATION); - return palette->priv->orientation; -} - -/** - * gtk_tool_palette_get_style: - * @palette: an #GtkToolPalette. - * - * Gets the style (icons, text or both) of items in the tool palette. - * - * Returns: the #GtkToolbarStyle of items in the tool palette. - * - * Since: 2.18 - */ -GtkToolbarStyle -gtk_tool_palette_get_style (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_TOOLBAR_STYLE); - return palette->priv->style; -} - -/** - * gtk_tool_palette_set_group_position: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @position: a new index for group. - * - * Sets the position of the group as an index of the tool palette. - * If position is 0 the group will become the first child, if position is - * -1 it will become the last child. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_group_position (GtkToolPalette *palette, - GtkWidget *group, - gint position) -{ - GtkToolItemGroupInfo group_info; - gint old_position; - gpointer src, dst; - gsize len; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - gtk_tool_palette_repack (palette); - - g_return_if_fail (position >= -1); - - if (-1 == position) - position = palette->priv->groups_length - 1; - - g_return_if_fail ((guint) position < palette->priv->groups_length); - - if (GTK_TOOL_ITEM_GROUP (group) == palette->priv->groups[position].widget) - return; - - old_position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (old_position >= 0); - - group_info = palette->priv->groups[old_position]; - - if (position < old_position) - { - dst = palette->priv->groups + position + 1; - src = palette->priv->groups + position; - len = old_position - position; - } - else - { - dst = palette->priv->groups + old_position; - src = palette->priv->groups + old_position + 1; - len = position - old_position; - } - - memmove (dst, src, len * sizeof (*palette->priv->groups)); - palette->priv->groups[position] = group_info; - - gtk_widget_queue_resize (GTK_WIDGET (palette)); -} - -static void -gtk_tool_palette_group_notify_collapsed (GtkToolItemGroup *group, - GParamSpec *pspec G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (data); - guint i; - - if (gtk_tool_item_group_get_collapsed (group)) - return; - - for (i = 0; i < palette->priv->groups_size; ++i) - { - GtkToolItemGroup *current_group = palette->priv->groups[i].widget; - - if (current_group && current_group != group) - gtk_tool_item_group_set_collapsed (palette->priv->groups[i].widget, TRUE); - } -} - -/** - * gtk_tool_palette_set_exclusive: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @exclusive: whether the group should be exclusive or not. - * - * Sets whether the group should be exclusive or not. If an exclusive group is expanded - * all other groups are collapsed. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_exclusive (GtkToolPalette *palette, - GtkWidget *group, - gboolean exclusive) -{ - GtkToolItemGroupInfo *group_info; - gint position; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (position >= 0); - - group_info = &palette->priv->groups[position]; - - if (exclusive == group_info->exclusive) - return; - - group_info->exclusive = exclusive; - - if (group_info->exclusive != (0 != group_info->notify_collapsed)) - { - if (group_info->exclusive) - { - group_info->notify_collapsed = - g_signal_connect (group, "notify::collapsed", - G_CALLBACK (gtk_tool_palette_group_notify_collapsed), - palette); - } - else - { - g_signal_handler_disconnect (group, group_info->notify_collapsed); - group_info->notify_collapsed = 0; - } - } - - gtk_tool_palette_group_notify_collapsed (group_info->widget, NULL, palette); - gtk_widget_child_notify (group, "exclusive"); -} - -/** - * gtk_tool_palette_set_expand: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * @expand: whether the group should be given extra space. - * - * Sets whether the group should be given extra space. - * - * Since: 2.18 - */ -void -gtk_tool_palette_set_expand (GtkToolPalette *palette, - GtkWidget *group, - gboolean expand) -{ - GtkToolItemGroupInfo *group_info; - gint position; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group)); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_if_fail (position >= 0); - - group_info = &palette->priv->groups[position]; - - if (expand != group_info->expand) - { - group_info->expand = expand; - gtk_widget_queue_resize (GTK_WIDGET (palette)); - gtk_widget_child_notify (group, "expand"); - } -} - -/** - * gtk_tool_palette_get_group_position: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup. - * - * Gets the position of @group in @palette as index. see gtk_tool_palette_set_group_position(). - * - * Returns: the index of group or -1 if @group is not a child of @palette. - * - * Since: 2.18 - */ -gint -gtk_tool_palette_get_group_position (GtkToolPalette *palette, - GtkWidget *group) -{ - guint i; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), -1); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1); - - for (i = 0; i < palette->priv->groups_length; ++i) - if ((gpointer) group == palette->priv->groups[i].widget) - return i; - - return -1; -} - -/** - * gtk_tool_palette_get_exclusive: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * - * Gets whether group is exclusive or not. See gtk_tool_palette_set_exclusive(). - * - * Returns: %TRUE if group is exclusive. - * - * Since: 2.18 - */ -gboolean -gtk_tool_palette_get_exclusive (GtkToolPalette *palette, - GtkWidget *group) -{ - gint position; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXCLUSIVE); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXCLUSIVE); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXCLUSIVE); - - return palette->priv->groups[position].exclusive; -} - -/** - * gtk_tool_palette_get_expand: - * @palette: an #GtkToolPalette. - * @group: an #GtkToolItemGroup which is a child of palette. - * - * Gets whether group should be given extra space. See gtk_tool_palette_set_expand(). - * - * Returns: %TRUE if group should be given extra space, %FALSE otherwise. - * - * Since: 2.18 - */ -gboolean -gtk_tool_palette_get_expand (GtkToolPalette *palette, - GtkWidget *group) -{ - gint position; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXPAND); - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXPAND); - - position = gtk_tool_palette_get_group_position (palette, group); - g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXPAND); - - return palette->priv->groups[position].expand; -} - -/** - * gtk_tool_palette_get_drop_item: - * @palette: an #GtkToolPalette. - * @x: the x position. - * @y: the y position. - * - * Gets the item at position (x, y). See gtk_tool_palette_get_drop_group(). - * - * Returns: the #GtkToolItem at position or %NULL if there is no such item. - * - * Since: 2.18 - */ -GtkToolItem* -gtk_tool_palette_get_drop_item (GtkToolPalette *palette, - gint x, - gint y) -{ - GtkWidget *group = gtk_tool_palette_get_drop_group (palette, x, y); - - if (group) - return gtk_tool_item_group_get_drop_item (GTK_TOOL_ITEM_GROUP (group), - x - group->allocation.x, - y - group->allocation.y); - - return NULL; -} - -/** - * gtk_tool_palette_get_drop_group: - * @palette: an #GtkToolPalette. - * @x: the x position. - * @y: the y position. - * - * Gets the group at position (x, y). - * - * Returns: the #GtkToolItemGroup at position or %NULL if there is no such group. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_get_drop_group (GtkToolPalette *palette, - gint x, - gint y) -{ - GtkAllocation *allocation; - guint i; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - - allocation = >K_WIDGET (palette)->allocation; - - g_return_val_if_fail (x >= 0 && x < allocation->width, NULL); - g_return_val_if_fail (y >= 0 && y < allocation->height, NULL); - - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - GtkWidget *widget; - gint x0, y0; - - if (!group->widget) - continue; - - widget = GTK_WIDGET (group->widget); - - x0 = x - widget->allocation.x; - y0 = y - widget->allocation.y; - - if (x0 >= 0 && x0 < widget->allocation.width && - y0 >= 0 && y0 < widget->allocation.height) - return widget; - } - - return NULL; -} - -/** - * gtk_tool_palette_get_drag_item: - * @palette: an #GtkToolPalette. - * @selection: a #GtkSelectionData. - * - * Get the dragged item from the selection. This could be a #GtkToolItem or - * an #GtkToolItemGroup. - * - * Returns: the dragged item in selection. - * - * Since: 2.18 - */ -GtkWidget* -gtk_tool_palette_get_drag_item (GtkToolPalette *palette, - const GtkSelectionData *selection) -{ - GtkToolPaletteDragData *data; - - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - g_return_val_if_fail (NULL != selection, NULL); - - g_return_val_if_fail (selection->format == 8, NULL); - g_return_val_if_fail (selection->length == sizeof (GtkToolPaletteDragData), NULL); - g_return_val_if_fail (selection->target == dnd_target_atom_item || - selection->target == dnd_target_atom_group, - NULL); - - data = (GtkToolPaletteDragData*) selection->data; - - g_return_val_if_fail (data->palette == palette, NULL); - - if (dnd_target_atom_item == selection->target) - g_return_val_if_fail (GTK_IS_TOOL_ITEM (data->item), NULL); - else if (dnd_target_atom_group == selection->target) - g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (data->item), NULL); - - return data->item; -} - -/** - * gtk_tool_palette_set_drag_source: - * @palette: an #GtkToolPalette. - * @targets: the #GtkToolPaletteDragTargets which the widget should support. - * - * Sets the tool palette as a drag source. Enables all groups and items in - * the tool palette as drag sources on button 1 and button 3 press with copy - * and move actions. - * - * See gtk_drag_source_set(). - * - * Since: 2.18 - * - */ -void -gtk_tool_palette_set_drag_source (GtkToolPalette *palette, - GtkToolPaletteDragTargets targets) -{ - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - - if ((palette->priv->drag_source & targets) == targets) - return; - - palette->priv->drag_source |= targets; - - for (i = 0; i < palette->priv->groups_length; ++i) - { - if (palette->priv->groups[i].widget) - gtk_container_forall (GTK_CONTAINER (palette->priv->groups[i].widget), - _gtk_tool_palette_child_set_drag_source, - palette); - } -} - -/** - * gtk_tool_palette_add_drag_dest: - * @palette: an #GtkToolPalette. - * @widget: a #GtkWidget which should be a drag destination for palette. - * @flags: the flags that specify what actions GTK+ should take for drops on that widget. - * @targets: the #GtkToolPaletteDragTargets which the widget should support. - * @actions: the #GdkDragActions which the widget should suppport. - * - * Sets the tool palette as drag source (see gtk_tool_palette_set_drag_source) and - * sets widget as a drag destination for drags from palette. With flags the actions - * (like highlighting and target checking) which should be performed by GTK+ for - * drops on widget can be specified. With targets the supported drag targets - * (groups and/or items) can be specified. With actions the supported drag actions - * (copy and move) can be specified. - * - * See gtk_drag_dest_set(). - * - * Since: 2.18 - */ -void -gtk_tool_palette_add_drag_dest (GtkToolPalette *palette, - GtkWidget *widget, - GtkDestDefaults flags, - GtkToolPaletteDragTargets targets, - GdkDragAction actions) -{ - GtkTargetEntry entries[G_N_ELEMENTS (dnd_targets)]; - gint n_entries = 0; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (GTK_IS_WIDGET (widget)); - - gtk_tool_palette_set_drag_source (palette, - targets); - - if (targets & GTK_TOOL_PALETTE_DRAG_ITEMS) - entries[n_entries++] = dnd_targets[0]; - if (targets & GTK_TOOL_PALETTE_DRAG_GROUPS) - entries[n_entries++] = dnd_targets[1]; - - gtk_drag_dest_set (widget, flags, entries, n_entries, actions); -} - -void -_gtk_tool_palette_get_item_size (GtkToolPalette *palette, - GtkRequisition *item_size, - gboolean homogeneous_only, - gint *requested_rows) -{ - GtkRequisition max_requisition; - gint max_rows; - guint i; - - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - g_return_if_fail (NULL != item_size); - - max_requisition.width = 0; - max_requisition.height = 0; - max_rows = 0; - - /* iterate over all groups and calculate the max item_size and max row request */ - for (i = 0; i < palette->priv->groups_length; ++i) - { - GtkRequisition requisition; - gint rows; - GtkToolItemGroupInfo *group = &palette->priv->groups[i]; - - if (!group->widget) - continue; - - _gtk_tool_item_group_item_size_request (group->widget, &requisition, homogeneous_only, &rows); - - max_requisition.width = MAX (max_requisition.width, requisition.width); - max_requisition.height = MAX (max_requisition.height, requisition.height); - max_rows = MAX (max_rows, rows); - } - - *item_size = max_requisition; - if (requested_rows) - *requested_rows = max_rows; -} - -static void -gtk_tool_palette_item_drag_data_get (GtkWidget *widget, - GdkDragContext *context G_GNUC_UNUSED, - GtkSelectionData *selection, - guint info G_GNUC_UNUSED, - guint time G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL }; - - if (selection->target == dnd_target_atom_item) - drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); - - if (drag_data.item) - gtk_selection_data_set (selection, selection->target, 8, - (guchar*) &drag_data, sizeof (drag_data)); -} - -static void -gtk_tool_palette_child_drag_data_get (GtkWidget *widget, - GdkDragContext *context G_GNUC_UNUSED, - GtkSelectionData *selection, - guint info G_GNUC_UNUSED, - guint time G_GNUC_UNUSED, - gpointer data) -{ - GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL }; - - if (selection->target == dnd_target_atom_group) - drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM_GROUP); - - if (drag_data.item) - gtk_selection_data_set (selection, selection->target, 8, - (guchar*) &drag_data, sizeof (drag_data)); -} - -void -_gtk_tool_palette_child_set_drag_source (GtkWidget *child, - gpointer data) -{ - GtkToolPalette *palette = GTK_TOOL_PALETTE (data); - - /* Check drag_source, - * to work properly when called from gtk_tool_item_group_insert(). - */ - if (!palette->priv->drag_source) - return; - - if (GTK_IS_TOOL_ITEM (child) && - (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_ITEMS)) - { - /* Connect to child instead of the item itself, - * to work arround bug 510377. - */ - if (GTK_IS_TOOL_BUTTON (child)) - child = gtk_bin_get_child (GTK_BIN (child)); - - if (!child) - return; - - gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, - &dnd_targets[0], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); - - g_signal_connect (child, "drag-data-get", - G_CALLBACK (gtk_tool_palette_item_drag_data_get), - palette); - } - else if (GTK_IS_BUTTON (child) && - (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_GROUPS)) - { - gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, - &dnd_targets[1], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); - - g_signal_connect (child, "drag-data-get", - G_CALLBACK (gtk_tool_palette_child_drag_data_get), - palette); - } -} - -/** - * gtk_tool_palette_get_drag_target_item: - * - * Get the target entry for a dragged #GtkToolItem. - * - * Returns: the #GtkTargetEntry for a dragged item. - * - * Since: 2.18 - */ -G_CONST_RETURN GtkTargetEntry* -gtk_tool_palette_get_drag_target_item (void) -{ - return &dnd_targets[0]; -} - -/** - * gtk_tool_palette_get_drag_target_group: - * - * Get the target entry for a dragged #GtkToolItemGroup. - * - * Returns: the #GtkTargetEntry for a dragged group. - * - * Since: 2.18 - */ -G_CONST_RETURN GtkTargetEntry* -gtk_tool_palette_get_drag_target_group (void) -{ - return &dnd_targets[1]; -} - -void -_gtk_tool_palette_set_expanding_child (GtkToolPalette *palette, - GtkWidget *widget) -{ - g_return_if_fail (GTK_IS_TOOL_PALETTE (palette)); - palette->priv->expanding_child = widget; -} - -GtkAdjustment* -gtk_tool_palette_get_hadjustment (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - return palette->priv->hadjustment; -} - -GtkAdjustment* -gtk_tool_palette_get_vadjustment (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - return palette->priv->vadjustment; -} - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 - -GtkSizeGroup * -_gtk_tool_palette_get_size_group (GtkToolPalette *palette) -{ - g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL); - - return palette->priv->text_size_group; -} - -#endif diff --git a/gtktoolpalette.h b/gtktoolpalette.h deleted file mode 100644 index 13dfafbb6b..0000000000 --- a/gtktoolpalette.h +++ /dev/null @@ -1,399 +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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#ifndef __GTK_TOOL_PALETTE_H__ -#define __GTK_TOOL_PALETTE_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_TOOL_PALETTE (gtk_tool_palette_get_type()) -#define GTK_TOOL_PALETTE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_TOOL_PALETTE, GtkToolPalette)) -#define GTK_TOOL_PALETTE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_TOOL_PALETTE, GtkToolPaletteClass)) -#define GTK_IS_TOOL_PALETTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_TOOL_PALETTE)) -#define GTK_IS_TOOL_PALETTE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE(obj, GTK_TYPE_TOOL_PALETTE)) -#define GTK_TOOL_PALETTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TOOL_PALETTE, GtkToolPaletteClass)) - -typedef struct _GtkToolPalette GtkToolPalette; -typedef struct _GtkToolPaletteClass GtkToolPaletteClass; -typedef struct _GtkToolPalettePrivate GtkToolPalettePrivate; - -/** - * GtkToolPaletteDragTargets: - * @GTK_TOOL_PALETTE_DRAG_ITEMS: Support drag of items. - * @GTK_TOOL_PALETTE_DRAG_GROUPS: Support drag of groups. - * - * Flags used to specify the supported drag targets. - */ -typedef enum /*< flags >*/ -{ - GTK_TOOL_PALETTE_DRAG_ITEMS = (1 << 0), - GTK_TOOL_PALETTE_DRAG_GROUPS = (1 << 1) -} -GtkToolPaletteDragTargets; - -/** - * GtkToolPalette: - * - * This should not be accessed directly. Use the accessor functions below. - */ -struct _GtkToolPalette -{ - GtkContainer parent_instance; - GtkToolPalettePrivate *priv; -}; - -struct _GtkToolPaletteClass -{ - GtkContainerClass parent_class; - - void (*set_scroll_adjustments) (GtkWidget *widget, - GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -}; - -GType gtk_tool_palette_get_type (void) G_GNUC_CONST; -GtkWidget* gtk_tool_palette_new (void); - -void gtk_tool_palette_set_group_position (GtkToolPalette *palette, - GtkWidget *group, - gint position); -void gtk_tool_palette_set_exclusive (GtkToolPalette *palette, - GtkWidget *group, - gboolean exclusive); -void gtk_tool_palette_set_expand (GtkToolPalette *palette, - GtkWidget *group, - gboolean expand); - -gint gtk_tool_palette_get_group_position (GtkToolPalette *palette, - GtkWidget *group); -gboolean gtk_tool_palette_get_exclusive (GtkToolPalette *palette, - GtkWidget *group); -gboolean gtk_tool_palette_get_expand (GtkToolPalette *palette, - GtkWidget *group); - -void gtk_tool_palette_set_icon_size (GtkToolPalette *palette, - GtkIconSize icon_size); -void gtk_tool_palette_set_orientation (GtkToolPalette *palette, - GtkOrientation orientation); -void gtk_tool_palette_set_style (GtkToolPalette *palette, - GtkToolbarStyle style); - -GtkIconSize gtk_tool_palette_get_icon_size (GtkToolPalette *palette); -GtkOrientation gtk_tool_palette_get_orientation (GtkToolPalette *palette); -GtkToolbarStyle gtk_tool_palette_get_style (GtkToolPalette *palette); - -GtkToolItem* gtk_tool_palette_get_drop_item (GtkToolPalette *palette, - gint x, - gint y); -GtkWidget* gtk_tool_palette_get_drop_group (GtkToolPalette *palette, - gint x, - gint y); -GtkWidget* gtk_tool_palette_get_drag_item (GtkToolPalette *palette, - const GtkSelectionData *selection); - -void gtk_tool_palette_set_drag_source (GtkToolPalette *palette, - GtkToolPaletteDragTargets targets); -void gtk_tool_palette_add_drag_dest (GtkToolPalette *palette, - GtkWidget *widget, - GtkDestDefaults flags, - GtkToolPaletteDragTargets targets, - GdkDragAction actions); - -GtkAdjustment* gtk_tool_palette_get_hadjustment (GtkToolPalette *palette); -GtkAdjustment* gtk_tool_palette_get_vadjustment (GtkToolPalette *palette); - -G_CONST_RETURN GtkTargetEntry* gtk_tool_palette_get_drag_target_item (void) G_GNUC_CONST; -G_CONST_RETURN GtkTargetEntry* gtk_tool_palette_get_drag_target_group (void) G_GNUC_CONST; - - -G_END_DECLS - -#endif /* __GTK_TOOL_PALETTE_H__ */ -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#ifndef __GTK_TOOL_PALETTE_H__ -#define __GTK_TOOL_PALETTE_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_TOOL_PALETTE (gtk_tool_palette_get_type()) -#define GTK_TOOL_PALETTE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_TOOL_PALETTE, GtkToolPalette)) -#define GTK_TOOL_PALETTE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_TOOL_PALETTE, GtkToolPaletteClass)) -#define GTK_IS_TOOL_PALETTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_TOOL_PALETTE)) -#define GTK_IS_TOOL_PALETTE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE(obj, GTK_TYPE_TOOL_PALETTE)) -#define GTK_TOOL_PALETTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TOOL_PALETTE, GtkToolPaletteClass)) - -typedef struct _GtkToolPalette GtkToolPalette; -typedef struct _GtkToolPaletteClass GtkToolPaletteClass; -typedef struct _GtkToolPalettePrivate GtkToolPalettePrivate; - -/** - * GtkToolPaletteDragTargets: - * @GTK_TOOL_PALETTE_DRAG_ITEMS: Support drag of items. - * @GTK_TOOL_PALETTE_DRAG_GROUPS: Support drag of groups. - * - * Flags used to specify the supported drag targets. - */ -typedef enum /*< flags >*/ -{ - GTK_TOOL_PALETTE_DRAG_ITEMS = (1 << 0), - GTK_TOOL_PALETTE_DRAG_GROUPS = (1 << 1) -} -GtkToolPaletteDragTargets; - -/** - * GtkToolPalette: - * - * This should not be accessed directly. Use the accessor functions below. - */ -struct _GtkToolPalette -{ - GtkContainer parent_instance; - GtkToolPalettePrivate *priv; -}; - -struct _GtkToolPaletteClass -{ - GtkContainerClass parent_class; - - void (*set_scroll_adjustments) (GtkWidget *widget, - GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -}; - -GType gtk_tool_palette_get_type (void) G_GNUC_CONST; -GtkWidget* gtk_tool_palette_new (void); - -void gtk_tool_palette_set_group_position (GtkToolPalette *palette, - GtkWidget *group, - gint position); -void gtk_tool_palette_set_exclusive (GtkToolPalette *palette, - GtkWidget *group, - gboolean exclusive); -void gtk_tool_palette_set_expand (GtkToolPalette *palette, - GtkWidget *group, - gboolean expand); - -gint gtk_tool_palette_get_group_position (GtkToolPalette *palette, - GtkWidget *group); -gboolean gtk_tool_palette_get_exclusive (GtkToolPalette *palette, - GtkWidget *group); -gboolean gtk_tool_palette_get_expand (GtkToolPalette *palette, - GtkWidget *group); - -void gtk_tool_palette_set_icon_size (GtkToolPalette *palette, - GtkIconSize icon_size); -void gtk_tool_palette_set_orientation (GtkToolPalette *palette, - GtkOrientation orientation); -void gtk_tool_palette_set_style (GtkToolPalette *palette, - GtkToolbarStyle style); - -GtkIconSize gtk_tool_palette_get_icon_size (GtkToolPalette *palette); -GtkOrientation gtk_tool_palette_get_orientation (GtkToolPalette *palette); -GtkToolbarStyle gtk_tool_palette_get_style (GtkToolPalette *palette); - -GtkToolItem* gtk_tool_palette_get_drop_item (GtkToolPalette *palette, - gint x, - gint y); -GtkWidget* gtk_tool_palette_get_drop_group (GtkToolPalette *palette, - gint x, - gint y); -GtkWidget* gtk_tool_palette_get_drag_item (GtkToolPalette *palette, - const GtkSelectionData *selection); - -void gtk_tool_palette_set_drag_source (GtkToolPalette *palette, - GtkToolPaletteDragTargets targets); -void gtk_tool_palette_add_drag_dest (GtkToolPalette *palette, - GtkWidget *widget, - GtkDestDefaults flags, - GtkToolPaletteDragTargets targets, - GdkDragAction actions); - -GtkAdjustment* gtk_tool_palette_get_hadjustment (GtkToolPalette *palette); -GtkAdjustment* gtk_tool_palette_get_vadjustment (GtkToolPalette *palette); - -G_CONST_RETURN GtkTargetEntry* gtk_tool_palette_get_drag_target_item (void) G_GNUC_CONST; -G_CONST_RETURN GtkTargetEntry* gtk_tool_palette_get_drag_target_group (void) G_GNUC_CONST; - - -G_END_DECLS - -#endif /* __GTK_TOOL_PALETTE_H__ */ -/* 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#ifndef __GTK_TOOL_PALETTE_H__ -#define __GTK_TOOL_PALETTE_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_TOOL_PALETTE (gtk_tool_palette_get_type()) -#define GTK_TOOL_PALETTE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_TOOL_PALETTE, GtkToolPalette)) -#define GTK_TOOL_PALETTE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_TOOL_PALETTE, GtkToolPaletteClass)) -#define GTK_IS_TOOL_PALETTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_TOOL_PALETTE)) -#define GTK_IS_TOOL_PALETTE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE(obj, GTK_TYPE_TOOL_PALETTE)) -#define GTK_TOOL_PALETTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TOOL_PALETTE, GtkToolPaletteClass)) - -typedef struct _GtkToolPalette GtkToolPalette; -typedef struct _GtkToolPaletteClass GtkToolPaletteClass; -typedef struct _GtkToolPalettePrivate GtkToolPalettePrivate; - -/** - * GtkToolPaletteDragTargets: - * @GTK_TOOL_PALETTE_DRAG_ITEMS: Support drag of items. - * @GTK_TOOL_PALETTE_DRAG_GROUPS: Support drag of groups. - * - * Flags used to specify the supported drag targets. - */ -typedef enum /*< flags >*/ -{ - GTK_TOOL_PALETTE_DRAG_ITEMS = (1 << 0), - GTK_TOOL_PALETTE_DRAG_GROUPS = (1 << 1) -} -GtkToolPaletteDragTargets; - -/** - * GtkToolPalette: - * - * This should not be accessed directly. Use the accessor functions below. - */ -struct _GtkToolPalette -{ - GtkContainer parent_instance; - GtkToolPalettePrivate *priv; -}; - -struct _GtkToolPaletteClass -{ - GtkContainerClass parent_class; - - void (*set_scroll_adjustments) (GtkWidget *widget, - GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -}; - -GType gtk_tool_palette_get_type (void) G_GNUC_CONST; -GtkWidget* gtk_tool_palette_new (void); - -void gtk_tool_palette_set_group_position (GtkToolPalette *palette, - GtkWidget *group, - gint position); -void gtk_tool_palette_set_exclusive (GtkToolPalette *palette, - GtkWidget *group, - gboolean exclusive); -void gtk_tool_palette_set_expand (GtkToolPalette *palette, - GtkWidget *group, - gboolean expand); - -gint gtk_tool_palette_get_group_position (GtkToolPalette *palette, - GtkWidget *group); -gboolean gtk_tool_palette_get_exclusive (GtkToolPalette *palette, - GtkWidget *group); -gboolean gtk_tool_palette_get_expand (GtkToolPalette *palette, - GtkWidget *group); - -void gtk_tool_palette_set_icon_size (GtkToolPalette *palette, - GtkIconSize icon_size); -void gtk_tool_palette_set_orientation (GtkToolPalette *palette, - GtkOrientation orientation); -void gtk_tool_palette_set_style (GtkToolPalette *palette, - GtkToolbarStyle style); - -GtkIconSize gtk_tool_palette_get_icon_size (GtkToolPalette *palette); -GtkOrientation gtk_tool_palette_get_orientation (GtkToolPalette *palette); -GtkToolbarStyle gtk_tool_palette_get_style (GtkToolPalette *palette); - -GtkToolItem* gtk_tool_palette_get_drop_item (GtkToolPalette *palette, - gint x, - gint y); -GtkWidget* gtk_tool_palette_get_drop_group (GtkToolPalette *palette, - gint x, - gint y); -GtkWidget* gtk_tool_palette_get_drag_item (GtkToolPalette *palette, - const GtkSelectionData *selection); - -void gtk_tool_palette_set_drag_source (GtkToolPalette *palette, - GtkToolPaletteDragTargets targets); -void gtk_tool_palette_add_drag_dest (GtkToolPalette *palette, - GtkWidget *widget, - GtkDestDefaults flags, - GtkToolPaletteDragTargets targets, - GdkDragAction actions); - -GtkAdjustment* gtk_tool_palette_get_hadjustment (GtkToolPalette *palette); -GtkAdjustment* gtk_tool_palette_get_vadjustment (GtkToolPalette *palette); - -G_CONST_RETURN GtkTargetEntry* gtk_tool_palette_get_drag_target_item (void) G_GNUC_CONST; -G_CONST_RETURN GtkTargetEntry* gtk_tool_palette_get_drag_target_group (void) G_GNUC_CONST; - - -G_END_DECLS - -#endif /* __GTK_TOOL_PALETTE_H__ */ diff --git a/gtktoolpaletteprivate.h b/gtktoolpaletteprivate.h deleted file mode 100644 index c1477f9e73..0000000000 --- a/gtktoolpaletteprivate.h +++ /dev/null @@ -1,59 +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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Mathias Hasselmann - */ - -#ifndef __GTK_TOOL_PALETTE_PRIVATE_H__ -#define __GTK_TOOL_PALETTE_PRIVATE_H__ - -#include - -void _gtk_tool_palette_get_item_size (GtkToolPalette *palette, - GtkRequisition *item_size, - gboolean homogeneous_only, - gint *requested_rows); -void _gtk_tool_palette_child_set_drag_source (GtkWidget *widget, - gpointer data); -void _gtk_tool_palette_set_expanding_child (GtkToolPalette *palette, - GtkWidget *widget); - -void _gtk_tool_item_group_palette_reconfigured (GtkToolItemGroup *group); -void _gtk_tool_item_group_item_size_request (GtkToolItemGroup *group, - GtkRequisition *item_size, - gboolean homogeneous_only, - gint *requested_rows); -gint _gtk_tool_item_group_get_height_for_width (GtkToolItemGroup *group, - gint width); -gint _gtk_tool_item_group_get_width_for_height (GtkToolItemGroup *group, - gint height); -void _gtk_tool_item_group_paint (GtkToolItemGroup *group, - cairo_t *cr); -gint _gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group, - gint limit, - gboolean vertical, - gboolean animation); - -#undef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 -/* #define HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 */ - -#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090 -GtkSizeGroup *_gtk_tool_palette_get_size_group (GtkToolPalette *palette); -#endif - -#endif /* __GTK_TOOL_PALETTE_PRIVATE_H__ */