Support grid mode in GtkTreeMenu
Added properties "wrap-width", "row-span-column" and "column-span-column" to allow grid style menus from treemodels. Handling row data changes appropriately.
This commit is contained in:
@ -64,6 +64,16 @@ static GtkCellArea *gtk_tree_menu_cell_layout_get_area (GtkCellLayout
|
||||
|
||||
|
||||
/* TreeModel/DrawingArea callbacks and building menus/submenus */
|
||||
static inline void rebuild_menu (GtkTreeMenu *menu);
|
||||
static gboolean menu_occupied (GtkTreeMenu *menu,
|
||||
guint left_attach,
|
||||
guint right_attach,
|
||||
guint top_attach,
|
||||
guint bottom_attach);
|
||||
static void relayout_item (GtkTreeMenu *menu,
|
||||
GtkWidget *item,
|
||||
GtkTreeIter *iter,
|
||||
GtkWidget *prev);
|
||||
static void gtk_tree_menu_populate (GtkTreeMenu *menu);
|
||||
static GtkWidget *gtk_tree_menu_create_item (GtkTreeMenu *menu,
|
||||
GtkTreeIter *iter,
|
||||
@ -72,6 +82,22 @@ static void gtk_tree_menu_set_area (GtkTreeMenu
|
||||
GtkCellArea *area);
|
||||
static GtkWidget *gtk_tree_menu_get_path_item (GtkTreeMenu *menu,
|
||||
GtkTreePath *path);
|
||||
static void row_inserted_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
GtkTreeMenu *menu);
|
||||
static void row_deleted_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeMenu *menu);
|
||||
static void row_reordered_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gint *new_order,
|
||||
GtkTreeMenu *menu);
|
||||
static void row_changed_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
GtkTreeMenu *menu);
|
||||
|
||||
static void context_size_changed_cb (GtkCellAreaContext *context,
|
||||
GParamSpec *pspec,
|
||||
@ -82,6 +108,8 @@ static void submenu_activated_cb (GtkTreeMenu
|
||||
const gchar *path,
|
||||
GtkTreeMenu *menu);
|
||||
|
||||
|
||||
|
||||
struct _GtkTreeMenuPrivate
|
||||
{
|
||||
/* TreeModel and parent for this menu */
|
||||
@ -97,6 +125,16 @@ struct _GtkTreeMenuPrivate
|
||||
gulong row_inserted_id;
|
||||
gulong row_deleted_id;
|
||||
gulong row_reordered_id;
|
||||
gulong row_changed_id;
|
||||
|
||||
/* Grid menu mode */
|
||||
gint wrap_width;
|
||||
gint row_span_col;
|
||||
gint col_span_col;
|
||||
|
||||
/* Flags */
|
||||
guint32 menu_with_header : 1;
|
||||
guint32 tearoff : 1;
|
||||
|
||||
/* Row separators */
|
||||
GtkTreeViewRowSeparatorFunc row_separator_func;
|
||||
@ -107,9 +145,6 @@ struct _GtkTreeMenuPrivate
|
||||
GtkTreeMenuHeaderFunc header_func;
|
||||
gpointer header_data;
|
||||
GDestroyNotify header_destroy;
|
||||
|
||||
guint32 menu_with_header : 1;
|
||||
guint32 tearoff : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -117,7 +152,10 @@ enum {
|
||||
PROP_MODEL,
|
||||
PROP_ROOT,
|
||||
PROP_CELL_AREA,
|
||||
PROP_TEAROFF
|
||||
PROP_TEAROFF,
|
||||
PROP_WRAP_WIDTH,
|
||||
PROP_ROW_SPAN_COL,
|
||||
PROP_COL_SPAN_COL
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -142,6 +180,32 @@ gtk_tree_menu_init (GtkTreeMenu *menu)
|
||||
GtkTreeMenuPrivate);
|
||||
priv = menu->priv;
|
||||
|
||||
priv->model = NULL;
|
||||
priv->root = NULL;
|
||||
priv->area = NULL;
|
||||
priv->context = NULL;
|
||||
|
||||
priv->size_changed_id = 0;
|
||||
priv->row_inserted_id = 0;
|
||||
priv->row_deleted_id = 0;
|
||||
priv->row_reordered_id = 0;
|
||||
priv->row_changed_id = 0;
|
||||
|
||||
priv->wrap_width = 0;
|
||||
priv->row_span_col = -1;
|
||||
priv->col_span_col = -1;
|
||||
|
||||
priv->menu_with_header = FALSE;
|
||||
priv->tearoff = FALSE;
|
||||
|
||||
priv->row_separator_func = NULL;
|
||||
priv->row_separator_data = NULL;
|
||||
priv->row_separator_destroy = NULL;
|
||||
|
||||
priv->header_func = NULL;
|
||||
priv->header_data = NULL;
|
||||
priv->header_destroy = NULL;
|
||||
|
||||
gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
|
||||
}
|
||||
|
||||
@ -188,24 +252,85 @@ gtk_tree_menu_class_init (GtkTreeMenuClass *class)
|
||||
GTK_TYPE_TREE_PATH,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_CELL_AREA,
|
||||
g_param_spec_object ("cell-area",
|
||||
P_("Cell Area"),
|
||||
P_("The GtkCellArea used to layout cells"),
|
||||
GTK_TYPE_CELL_AREA,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_CELL_AREA,
|
||||
g_param_spec_object ("cell-area",
|
||||
P_("Cell Area"),
|
||||
P_("The GtkCellArea used to layout cells"),
|
||||
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_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));
|
||||
|
||||
/**
|
||||
* GtkTreeMenu:wrap-width:
|
||||
*
|
||||
* If wrap-width is set to a positive value, the list will be
|
||||
* displayed in multiple columns, the number of columns is
|
||||
* determined by wrap-width.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WRAP_WIDTH,
|
||||
g_param_spec_int ("wrap-width",
|
||||
P_("Wrap Width"),
|
||||
P_("Wrap width for laying out items in a grid"),
|
||||
0,
|
||||
G_MAXINT,
|
||||
0,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GtkTreeMenuPrivate));
|
||||
/**
|
||||
* GtkTreeMenu:row-span-column:
|
||||
*
|
||||
* If this is set to a non-negative value, it must be the index of a column
|
||||
* of type %G_TYPE_INT in the model.
|
||||
*
|
||||
* The values of that column are used to determine how many rows a value in
|
||||
* the list will span. Therefore, the values in the model column pointed to
|
||||
* by this property must be greater than zero and not larger than wrap-width.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ROW_SPAN_COL,
|
||||
g_param_spec_int ("row-span-column",
|
||||
P_("Row span column"),
|
||||
P_("TreeModel column containing the row span values"),
|
||||
-1,
|
||||
G_MAXINT,
|
||||
-1,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GtkTreeMenu:column-span-column:
|
||||
*
|
||||
* If this is set to a non-negative value, it must be the index of a column
|
||||
* of type %G_TYPE_INT in the model.
|
||||
*
|
||||
* The values of that column are used to determine how many columns a value
|
||||
* in the list will span.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_COL_SPAN_COL,
|
||||
g_param_spec_int ("column-span-column",
|
||||
P_("Column span column"),
|
||||
P_("TreeModel column containing the column span values"),
|
||||
-1,
|
||||
G_MAXINT,
|
||||
-1,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (GtkTreeMenuPrivate));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
@ -312,6 +437,18 @@ gtk_tree_menu_set_property (GObject *object,
|
||||
gtk_tree_menu_set_tearoff (menu, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_WRAP_WIDTH:
|
||||
gtk_tree_menu_set_wrap_width (menu, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_ROW_SPAN_COL:
|
||||
gtk_tree_menu_set_row_span_column (menu, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_COL_SPAN_COL:
|
||||
gtk_tree_menu_set_column_span_column (menu, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -510,7 +647,7 @@ row_inserted_cb (GtkTreeModel *model,
|
||||
parent_path = gtk_tree_path_copy (path);
|
||||
|
||||
/* Check if the menu and the added iter are in root of the model */
|
||||
if (!gtk_tree_path_up (parent_path))
|
||||
if (gtk_tree_path_get_depth (parent_path) <= 1)
|
||||
{
|
||||
if (!priv->root)
|
||||
this_menu = TRUE;
|
||||
@ -534,27 +671,32 @@ row_inserted_cb (GtkTreeModel *model,
|
||||
{
|
||||
GtkWidget *item;
|
||||
|
||||
/* Get the index of the path for this depth */
|
||||
indices = gtk_tree_path_get_indices (path);
|
||||
depth = gtk_tree_path_get_depth (path);
|
||||
index = indices[depth -1];
|
||||
|
||||
/* Menus with a header include a menuitem for it's root node
|
||||
* and a separator menu item */
|
||||
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);
|
||||
|
||||
/* Resize everything */
|
||||
gtk_cell_area_context_flush (menu->priv->context);
|
||||
if (priv->wrap_width > 0)
|
||||
rebuild_menu (menu);
|
||||
else
|
||||
{
|
||||
/* Get the index of the path for this depth */
|
||||
indices = gtk_tree_path_get_indices (path);
|
||||
depth = gtk_tree_path_get_depth (path);
|
||||
index = indices[depth -1];
|
||||
|
||||
/* Menus with a header include a menuitem for it's root node
|
||||
* and a separator menu item */
|
||||
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);
|
||||
|
||||
/* Resize everything */
|
||||
gtk_cell_area_context_flush (menu->priv->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -580,14 +722,19 @@ row_deleted_cb (GtkTreeModel *model,
|
||||
}
|
||||
}
|
||||
|
||||
/* Get rid of the deleted item */
|
||||
item = gtk_tree_menu_get_path_item (menu, path);
|
||||
if (item)
|
||||
{
|
||||
gtk_widget_destroy (item);
|
||||
|
||||
/* Resize everything */
|
||||
gtk_cell_area_context_flush (menu->priv->context);
|
||||
if (priv->wrap_width > 0)
|
||||
rebuild_menu (menu);
|
||||
else
|
||||
{
|
||||
/* Get rid of the deleted item */
|
||||
gtk_widget_destroy (item);
|
||||
|
||||
/* Resize everything */
|
||||
gtk_cell_area_context_flush (menu->priv->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -615,15 +762,102 @@ row_reordered_cb (GtkTreeModel *model,
|
||||
}
|
||||
|
||||
if (this_menu)
|
||||
rebuild_menu (menu);
|
||||
}
|
||||
|
||||
static gint
|
||||
menu_item_position (GtkTreeMenu *menu,
|
||||
GtkWidget *item)
|
||||
{
|
||||
GList *children, *l;
|
||||
gint position;
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (menu));
|
||||
for (position = 0, l = children; l; position++, l = l->next)
|
||||
{
|
||||
/* Destroy and repopulate the menu at the level where the order changed */
|
||||
gtk_container_foreach (GTK_CONTAINER (menu),
|
||||
(GtkCallback) gtk_widget_destroy, NULL);
|
||||
GtkWidget *iitem = l->data;
|
||||
|
||||
gtk_tree_menu_populate (menu);
|
||||
if (item == iitem)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Resize everything */
|
||||
gtk_cell_area_context_flush (menu->priv->context);
|
||||
g_list_free (children);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
static void
|
||||
row_changed_cb (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv = menu->priv;
|
||||
gboolean is_separator = FALSE;
|
||||
gboolean has_header = FALSE;
|
||||
GtkWidget *item;
|
||||
|
||||
item = gtk_tree_menu_get_path_item (menu, path);
|
||||
|
||||
if (priv->root)
|
||||
{
|
||||
GtkTreePath *root_path =
|
||||
gtk_tree_row_reference_get_path (priv->root);
|
||||
|
||||
if (gtk_tree_path_compare (root_path, path) == 0)
|
||||
{
|
||||
if (priv->header_func)
|
||||
has_header =
|
||||
priv->header_func (priv->model, iter, priv->header_data);
|
||||
|
||||
if (has_header && !item)
|
||||
{
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_widget_show (item);
|
||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_tree_menu_create_item (menu, iter, TRUE);
|
||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
priv->menu_with_header = TRUE;
|
||||
}
|
||||
else if (!has_header && item)
|
||||
{
|
||||
/* Destroy the header item and the following separator */
|
||||
gtk_widget_destroy (item);
|
||||
gtk_widget_destroy (GTK_MENU_SHELL (menu)->children->data);
|
||||
|
||||
priv->menu_with_header = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_tree_path_free (root_path);
|
||||
}
|
||||
|
||||
if (item)
|
||||
{
|
||||
if (priv->wrap_width > 0)
|
||||
/* Ugly, we need to rebuild the menu here if
|
||||
* the row-span/row-column values change
|
||||
*/
|
||||
rebuild_menu (menu);
|
||||
else
|
||||
{
|
||||
if (priv->row_separator_func)
|
||||
is_separator =
|
||||
priv->row_separator_func (model, iter,
|
||||
priv->row_separator_data);
|
||||
|
||||
|
||||
if (is_separator != GTK_IS_SEPARATOR_MENU_ITEM (item))
|
||||
{
|
||||
gint position = menu_item_position (menu, item);
|
||||
|
||||
gtk_widget_destroy (item);
|
||||
item = gtk_tree_menu_create_item (menu, iter, FALSE);
|
||||
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), item, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -654,6 +888,93 @@ gtk_tree_menu_set_area (GtkTreeMenu *menu,
|
||||
g_object_ref_sink (priv->area);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
menu_occupied (GtkTreeMenu *menu,
|
||||
guint left_attach,
|
||||
guint right_attach,
|
||||
guint top_attach,
|
||||
guint bottom_attach)
|
||||
{
|
||||
GList *i;
|
||||
|
||||
for (i = GTK_MENU_SHELL (menu)->children; i; i = i->next)
|
||||
{
|
||||
guint l, r, b, t;
|
||||
|
||||
gtk_container_child_get (GTK_CONTAINER (menu),
|
||||
i->data,
|
||||
"left-attach", &l,
|
||||
"right-attach", &r,
|
||||
"bottom-attach", &b,
|
||||
"top-attach", &t,
|
||||
NULL);
|
||||
|
||||
/* look if this item intersects with the given coordinates */
|
||||
if (right_attach > l && left_attach < r && bottom_attach > t && top_attach < b)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
relayout_item (GtkTreeMenu *menu,
|
||||
GtkWidget *item,
|
||||
GtkTreeIter *iter,
|
||||
GtkWidget *prev)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv = menu->priv;
|
||||
gint current_col = 0, current_row = 0;
|
||||
gint rows = 1, cols = 1;
|
||||
|
||||
if (priv->col_span_col == -1 &&
|
||||
priv->row_span_col == -1 &&
|
||||
prev)
|
||||
{
|
||||
gtk_container_child_get (GTK_CONTAINER (menu), prev,
|
||||
"right-attach", ¤t_col,
|
||||
"top-attach", ¤t_row,
|
||||
NULL);
|
||||
if (current_col + cols > priv->wrap_width)
|
||||
{
|
||||
current_col = 0;
|
||||
current_row++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->col_span_col != -1)
|
||||
gtk_tree_model_get (priv->model, iter,
|
||||
priv->col_span_col, &cols,
|
||||
-1);
|
||||
if (priv->row_span_col != -1)
|
||||
gtk_tree_model_get (priv->model, iter,
|
||||
priv->row_span_col, &rows,
|
||||
-1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (current_col + cols > priv->wrap_width)
|
||||
{
|
||||
current_col = 0;
|
||||
current_row++;
|
||||
}
|
||||
|
||||
if (!menu_occupied (menu,
|
||||
current_col, current_col + cols,
|
||||
current_row, current_row + rows))
|
||||
break;
|
||||
|
||||
current_col++;
|
||||
}
|
||||
}
|
||||
|
||||
/* set attach props */
|
||||
gtk_menu_attach (GTK_MENU (menu), item,
|
||||
current_col, current_col + cols,
|
||||
current_row, current_row + rows);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
gtk_tree_menu_create_item (GtkTreeMenu *menu,
|
||||
GtkTreeIter *iter,
|
||||
@ -727,6 +1048,21 @@ gtk_tree_menu_create_item (GtkTreeMenu *menu,
|
||||
return item;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rebuild_menu (GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv = menu->priv;
|
||||
|
||||
/* Destroy all the menu items */
|
||||
gtk_container_foreach (GTK_CONTAINER (menu),
|
||||
(GtkCallback) gtk_widget_destroy, NULL);
|
||||
|
||||
/* Populate */
|
||||
if (priv->model)
|
||||
gtk_tree_menu_populate (menu);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_tree_menu_populate (GtkTreeMenu *menu)
|
||||
{
|
||||
@ -735,7 +1071,7 @@ gtk_tree_menu_populate (GtkTreeMenu *menu)
|
||||
GtkTreeIter parent;
|
||||
GtkTreeIter iter;
|
||||
gboolean valid = FALSE;
|
||||
GtkWidget *menu_item;
|
||||
GtkWidget *menu_item, *prev = NULL;
|
||||
|
||||
if (!priv->model)
|
||||
return;
|
||||
@ -762,6 +1098,7 @@ gtk_tree_menu_populate (GtkTreeMenu *menu)
|
||||
gtk_widget_show (menu_item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
||||
|
||||
prev = menu_item;
|
||||
priv->menu_with_header = TRUE;
|
||||
}
|
||||
}
|
||||
@ -775,11 +1112,13 @@ gtk_tree_menu_populate (GtkTreeMenu *menu)
|
||||
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);
|
||||
}
|
||||
if (priv->wrap_width > 0)
|
||||
gtk_menu_attach (GTK_MENU (menu), menu_item, 0, priv->wrap_width, 0, 1);
|
||||
else
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
||||
|
||||
prev = menu_item;
|
||||
}
|
||||
|
||||
valid = gtk_tree_model_iter_children (priv->model, &iter, NULL);
|
||||
}
|
||||
@ -789,8 +1128,13 @@ gtk_tree_menu_populate (GtkTreeMenu *menu)
|
||||
while (valid)
|
||||
{
|
||||
menu_item = gtk_tree_menu_create_item (menu, &iter, FALSE);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
||||
|
||||
if (priv->wrap_width > 0)
|
||||
relayout_item (menu, menu_item, &iter, prev);
|
||||
|
||||
prev = menu_item;
|
||||
valid = gtk_tree_model_iter_next (priv->model, &iter);
|
||||
}
|
||||
}
|
||||
@ -876,9 +1220,12 @@ gtk_tree_menu_set_model (GtkTreeMenu *menu,
|
||||
priv->row_deleted_id);
|
||||
g_signal_handler_disconnect (priv->model,
|
||||
priv->row_reordered_id);
|
||||
g_signal_handler_disconnect (priv->model,
|
||||
priv->row_changed_id);
|
||||
priv->row_inserted_id = 0;
|
||||
priv->row_deleted_id = 0;
|
||||
priv->row_reordered_id = 0;
|
||||
priv->row_changed_id = 0;
|
||||
|
||||
g_object_unref (priv->model);
|
||||
}
|
||||
@ -896,6 +1243,8 @@ gtk_tree_menu_set_model (GtkTreeMenu *menu,
|
||||
G_CALLBACK (row_deleted_cb), menu);
|
||||
priv->row_reordered_id = g_signal_connect (priv->model, "rows-reordered",
|
||||
G_CALLBACK (row_reordered_cb), menu);
|
||||
priv->row_changed_id = g_signal_connect (priv->model, "row-changed",
|
||||
G_CALLBACK (row_changed_cb), menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -931,13 +1280,7 @@ gtk_tree_menu_set_root (GtkTreeMenu *menu,
|
||||
else
|
||||
priv->root = NULL;
|
||||
|
||||
/* Destroy all the menu items for the previous root */
|
||||
gtk_container_foreach (GTK_CONTAINER (menu),
|
||||
(GtkCallback) gtk_widget_destroy, NULL);
|
||||
|
||||
/* Populate for the new root */
|
||||
if (priv->model)
|
||||
gtk_tree_menu_populate (menu);
|
||||
rebuild_menu (menu);
|
||||
}
|
||||
|
||||
GtkTreePath *
|
||||
@ -981,18 +1324,122 @@ gtk_tree_menu_set_tearoff (GtkTreeMenu *menu,
|
||||
{
|
||||
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);
|
||||
rebuild_menu (menu);
|
||||
|
||||
g_object_notify (G_OBJECT (menu), "tearoff");
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
gtk_tree_menu_get_wrap_width (GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_MENU (menu), FALSE);
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
return priv->wrap_width;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_menu_set_wrap_width (GtkTreeMenu *menu,
|
||||
gint width)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_TREE_MENU (menu));
|
||||
g_return_if_fail (width >= 0);
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
if (priv->wrap_width != width)
|
||||
{
|
||||
priv->wrap_width = width;
|
||||
|
||||
rebuild_menu (menu);
|
||||
|
||||
g_object_notify (G_OBJECT (menu), "wrap-width");
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
gtk_tree_menu_get_row_span_column (GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_MENU (menu), FALSE);
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
return priv->row_span_col;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_menu_set_row_span_column (GtkTreeMenu *menu,
|
||||
gint row_span)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_TREE_MENU (menu));
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
if (priv->row_span_col != row_span)
|
||||
{
|
||||
priv->row_span_col = row_span;
|
||||
|
||||
if (priv->wrap_width > 0)
|
||||
rebuild_menu (menu);
|
||||
|
||||
g_object_notify (G_OBJECT (menu), "row-span-column");
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
gtk_tree_menu_get_column_span_column (GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_MENU (menu), FALSE);
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
return priv->col_span_col;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_menu_set_column_span_column (GtkTreeMenu *menu,
|
||||
gint column_span)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_TREE_MENU (menu));
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
if (priv->col_span_col != column_span)
|
||||
{
|
||||
priv->col_span_col = column_span;
|
||||
|
||||
if (priv->wrap_width > 0)
|
||||
rebuild_menu (menu);
|
||||
|
||||
g_object_notify (G_OBJECT (menu), "column-span-column");
|
||||
}
|
||||
}
|
||||
|
||||
GtkTreeViewRowSeparatorFunc
|
||||
gtk_tree_menu_get_row_separator_func (GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_MENU (menu), NULL);
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
return priv->row_separator_func;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_menu_set_row_separator_func (GtkTreeMenu *menu,
|
||||
@ -1013,17 +1460,11 @@ gtk_tree_menu_set_row_separator_func (GtkTreeMenu *menu,
|
||||
priv->row_separator_data = data;
|
||||
priv->row_separator_destroy = destroy;
|
||||
|
||||
/* 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);
|
||||
rebuild_menu (menu);
|
||||
}
|
||||
|
||||
GtkTreeViewRowSeparatorFunc
|
||||
gtk_tree_menu_get_row_separator_func (GtkTreeMenu *menu)
|
||||
GtkTreeMenuHeaderFunc
|
||||
gtk_tree_menu_get_header_func (GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
@ -1031,7 +1472,7 @@ gtk_tree_menu_get_row_separator_func (GtkTreeMenu *menu)
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
return priv->row_separator_func;
|
||||
return priv->header_func;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1053,23 +1494,5 @@ gtk_tree_menu_set_header_func (GtkTreeMenu *menu,
|
||||
priv->header_data = data;
|
||||
priv->header_destroy = destroy;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
GtkTreeMenuHeaderFunc
|
||||
gtk_tree_menu_get_header_func (GtkTreeMenu *menu)
|
||||
{
|
||||
GtkTreeMenuPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_TREE_MENU (menu), NULL);
|
||||
|
||||
priv = menu->priv;
|
||||
|
||||
return priv->header_func;
|
||||
rebuild_menu (menu);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user