[gtk+/combo-refactor: 18/48] Added gtk_tree_menu_set/get_tearoff to allow the root menu to have a tearoff item
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/combo-refactor: 18/48] Added gtk_tree_menu_set/get_tearoff to allow the root menu to have a tearoff item
- Date: Tue, 7 Dec 2010 06:22:17 +0000 (UTC)
commit 14ce0ef0e450896765072b749a9d8fcf0b369e19
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Tue Nov 23 12:11:52 2010 +0900
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).
gtk/gtktreemenu.c | 129 ++++++++++++++++++++++++++++++++++++--------------
gtk/gtktreemenu.h | 3 +
tests/testtreemenu.c | 15 ++++++
3 files changed, 111 insertions(+), 36 deletions(-)
---
diff --git a/gtk/gtktreemenu.c b/gtk/gtktreemenu.c
index c1ad3cd..278bdc4 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 539613f..472c7ce 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 e514f47..7445147 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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]