Commit de59f05c authored by Tristan Van Berkom's avatar Tristan Van Berkom

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).
parent 3a56f881
......@@ -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,
......
......@@ -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,
......
......@@ -271,6 +271,13 @@ submenu_headers_toggled (GtkToggleButton *toggle,
gtk_tree_menu_set_header_func (menu, NULL, NULL, NULL);
}
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)
{
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment