diff options
author | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2010-11-23 12:11:52 +0900 |
---|---|---|
committer | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2011-01-04 23:37:07 +0900 |
commit | de59f05ccd65e9c34b9152335eb41ab5bea72b55 (patch) | |
tree | 53a96707253622289a2daecdb5f7d313d418f162 | |
parent | 3a56f8814f575cb97f877acc17a09c0f13fc0bb4 (diff) | |
download | gtk+-de59f05ccd65e9c34b9152335eb41ab5bea72b55.tar.gz |
Added gtk_tree_menu_set/get_tearoff to allow the root menu to have a tearoff item
Combo boxes expose an "add-tearoffs" feature to add a tearoff item to the root of the combo menu, added this feature to GtkTreeMenu to achieve this (and updated the testcase).
-rw-r--r-- | gtk/gtktreemenu.c | 129 | ||||
-rw-r--r-- | gtk/gtktreemenu.h | 3 | ||||
-rw-r--r-- | tests/testtreemenu.c | 15 |
3 files changed, 111 insertions, 36 deletions
diff --git a/gtk/gtktreemenu.c b/gtk/gtktreemenu.c index c1ad3cdc4d..278bdc4f78 100644 --- a/gtk/gtktreemenu.c +++ b/gtk/gtktreemenu.c @@ -26,6 +26,7 @@ #include "gtktreemenu.h" #include "gtkmarshalers.h" #include "gtkmenuitem.h" +#include "gtktearoffmenuitem.h" #include "gtkseparatormenuitem.h" #include "gtkcellareabox.h" #include "gtkcellareacontext.h" @@ -56,8 +57,6 @@ static void gtk_tree_menu_get_preferred_width (GtkWidget static void gtk_tree_menu_get_preferred_height (GtkWidget *widget, gint *minimum_size, gint *natural_size); -static void gtk_tree_menu_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); /* GtkCellLayoutIface */ static void gtk_tree_menu_cell_layout_init (GtkCellLayoutIface *iface); @@ -110,13 +109,15 @@ struct _GtkTreeMenuPrivate GDestroyNotify header_destroy; guint32 menu_with_header : 1; + guint32 tearoff : 1; }; enum { PROP_0, PROP_MODEL, PROP_ROOT, - PROP_CELL_AREA + PROP_CELL_AREA, + PROP_TEAROFF }; enum { @@ -160,7 +161,6 @@ gtk_tree_menu_class_init (GtkTreeMenuClass *class) widget_class->get_preferred_width = gtk_tree_menu_get_preferred_width; widget_class->get_preferred_height = gtk_tree_menu_get_preferred_height; - widget_class->size_allocate = gtk_tree_menu_size_allocate; tree_menu_signals[SIGNAL_MENU_ACTIVATE] = g_signal_new (I_("menu-activate"), @@ -196,6 +196,14 @@ gtk_tree_menu_class_init (GtkTreeMenuClass *class) GTK_TYPE_CELL_AREA, GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_TEAROFF, + g_param_spec_boolean ("tearoff", + P_("Tearoff"), + P_("Whether the menu has a tearoff item"), + FALSE, + GTK_PARAM_READWRITE)); + g_type_class_add_private (object_class, sizeof (GtkTreeMenuPrivate)); } @@ -300,6 +308,10 @@ gtk_tree_menu_set_property (GObject *object, gtk_tree_menu_set_area (menu, (GtkCellArea *)g_value_get_object (value)); break; + case PROP_TEAROFF: + gtk_tree_menu_set_tearoff (menu, g_value_get_boolean (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -317,21 +329,25 @@ gtk_tree_menu_get_property (GObject *object, switch (prop_id) { - case PROP_MODEL: - g_value_set_object (value, priv->model); - break; - - case PROP_ROOT: - g_value_set_boxed (value, priv->root); - break; + case PROP_MODEL: + g_value_set_object (value, priv->model); + break; + + case PROP_ROOT: + g_value_set_boxed (value, priv->root); + break; + + case PROP_CELL_AREA: + g_value_set_object (value, priv->area); + break; - case PROP_CELL_AREA: - g_value_set_object (value, priv->area); - break; + case PROP_TEAROFF: + g_value_set_boolean (value, priv->tearoff); + break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } } @@ -390,7 +406,6 @@ gtk_tree_menu_get_preferred_width (GtkWidget *widget, g_signal_handler_block (priv->context, priv->size_changed_id); sync_reserve_submenu_size (menu); - gtk_cell_area_context_flush_preferred_width (priv->context); GTK_WIDGET_CLASS (gtk_tree_menu_parent_class)->get_preferred_width (widget, minimum_size, natural_size); @@ -408,29 +423,12 @@ gtk_tree_menu_get_preferred_height (GtkWidget *widget, g_signal_handler_block (priv->context, priv->size_changed_id); sync_reserve_submenu_size (menu); - gtk_cell_area_context_flush_preferred_height (priv->context); GTK_WIDGET_CLASS (gtk_tree_menu_parent_class)->get_preferred_height (widget, minimum_size, natural_size); g_signal_handler_unblock (priv->context, priv->size_changed_id); } -static void -gtk_tree_menu_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkTreeMenu *menu = GTK_TREE_MENU (widget); - GtkTreeMenuPrivate *priv = menu->priv; - - /* flush the context allocation */ - gtk_cell_area_context_flush_allocation (priv->context); - - /* Leave it to the first cell area to allocate the size of priv->context, since - * we configure the menu to allocate all children the same width this works fine - */ - GTK_WIDGET_CLASS (gtk_tree_menu_parent_class)->size_allocate (widget, allocation); -} - /**************************************************************** * GtkCellLayoutIface * ****************************************************************/ @@ -546,6 +544,12 @@ row_inserted_cb (GtkTreeModel *model, if (priv->menu_with_header) index += 2; + /* Index after the tearoff item for the root menu if + * there is a tearoff item + */ + if (priv->root == NULL && priv->tearoff) + index += 1; + item = gtk_tree_menu_create_item (menu, iter, FALSE); gtk_menu_shell_insert (GTK_MENU_SHELL (menu), item, index); @@ -764,7 +768,21 @@ gtk_tree_menu_populate (GtkTreeMenu *menu) gtk_tree_path_free (path); } else - valid = gtk_tree_model_iter_children (priv->model, &iter, NULL); + { + /* Tearoff menu items only go in the root menu */ + if (priv->tearoff) + { + menu_item = gtk_tearoff_menu_item_new (); + gtk_widget_show (menu_item); + + /* Here if wrap_width > 0 then we need to attach the menu + * item to span the entire first row of the grid menu */ + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + } + + + valid = gtk_tree_model_iter_children (priv->model, &iter, NULL); + } /* Create a menu item for every row at the current depth, add a GtkTreeMenu * submenu for iters/items that have children */ @@ -937,6 +955,45 @@ gtk_tree_menu_get_root (GtkTreeMenu *menu) return NULL; } +gboolean +gtk_tree_menu_get_tearoff (GtkTreeMenu *menu) +{ + GtkTreeMenuPrivate *priv; + + g_return_val_if_fail (GTK_IS_TREE_MENU (menu), FALSE); + + priv = menu->priv; + + return priv->tearoff; +} + +void +gtk_tree_menu_set_tearoff (GtkTreeMenu *menu, + gboolean tearoff) +{ + GtkTreeMenuPrivate *priv; + + g_return_if_fail (GTK_IS_TREE_MENU (menu)); + + priv = menu->priv; + + if (priv->tearoff != tearoff) + { + priv->tearoff = tearoff; + + /* Destroy all the menu items */ + gtk_container_foreach (GTK_CONTAINER (menu), + (GtkCallback) gtk_widget_destroy, NULL); + + /* Populate again */ + if (priv->model) + gtk_tree_menu_populate (menu); + + g_object_notify (G_OBJECT (menu), "tearoff"); + } +} + + void gtk_tree_menu_set_row_separator_func (GtkTreeMenu *menu, GtkTreeViewRowSeparatorFunc func, diff --git a/gtk/gtktreemenu.h b/gtk/gtktreemenu.h index 539613f161..472c7ce18c 100644 --- a/gtk/gtktreemenu.h +++ b/gtk/gtktreemenu.h @@ -85,6 +85,9 @@ GtkTreeModel *gtk_tree_menu_get_model (GtkTreeMenu void gtk_tree_menu_set_root (GtkTreeMenu *menu, GtkTreePath *path); GtkTreePath *gtk_tree_menu_get_root (GtkTreeMenu *menu); +gboolean gtk_tree_menu_get_tearoff (GtkTreeMenu *menu); +void gtk_tree_menu_set_tearoff (GtkTreeMenu *menu, + gboolean tearoff); void gtk_tree_menu_set_row_separator_func (GtkTreeMenu *menu, GtkTreeViewRowSeparatorFunc func, diff --git a/tests/testtreemenu.c b/tests/testtreemenu.c index e514f47522..7445147d3e 100644 --- a/tests/testtreemenu.c +++ b/tests/testtreemenu.c @@ -272,6 +272,13 @@ submenu_headers_toggled (GtkToggleButton *toggle, } static void +tearoff_toggled (GtkToggleButton *toggle, + GtkTreeMenu *menu) +{ + gtk_tree_menu_set_tearoff (menu, gtk_toggle_button_get_active (toggle)); +} + +static void tree_menu (void) { GtkWidget *window, *widget; @@ -347,6 +354,14 @@ tree_menu (void) g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (submenu_headers_toggled), menu); + widget = gtk_check_button_new_with_label ("Tearoff menu"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); + gtk_widget_show (widget); + gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); + + g_signal_connect (G_OBJECT (widget), "toggled", + G_CALLBACK (tearoff_toggled), menu); + gtk_container_add (GTK_CONTAINER (window), vbox); |