Getting closer to updating the treemenu view properly from the model signals

This commit is contained in:
Tristan Van Berkom 2010-11-24 20:00:10 +09:00
parent 39cf1576d7
commit 4a5be7c74e
2 changed files with 152 additions and 53 deletions

View File

@ -78,6 +78,9 @@ static void gtk_tree_menu_populate (GtkTreeMenu
static GtkWidget *gtk_tree_menu_create_item (GtkTreeMenu *menu,
GtkTreeIter *iter,
gboolean header_item);
static void gtk_tree_menu_create_submenu (GtkTreeMenu *menu,
GtkWidget *item,
GtkTreePath *path);
static void gtk_tree_menu_set_area (GtkTreeMenu *menu,
GtkCellArea *area);
static GtkWidget *gtk_tree_menu_get_path_item (GtkTreeMenu *menu,
@ -618,8 +621,17 @@ gtk_tree_menu_get_path_item (GtkTreeMenu *menu,
GtkTreeRowReference *row =
g_object_get_qdata (G_OBJECT (child), tree_menu_path_quark);
if (row && gtk_tree_row_reference_valid (row))
path = gtk_tree_row_reference_get_path (row);
if (row)
{
path = gtk_tree_row_reference_get_path (row);
if (!path)
/* Return any first child where it's row-reference became invalid,
* this is because row-references get null paths before we recieve
* the "row-deleted" signal.
*/
item = child;
}
}
else
{
@ -628,6 +640,13 @@ gtk_tree_menu_get_path_item (GtkTreeMenu *menu,
/* It's always a cellview */
if (GTK_IS_CELL_VIEW (view))
path = gtk_cell_view_get_displayed_row (GTK_CELL_VIEW (view));
if (!path)
/* Return any first child where it's row-reference became invalid,
* this is because row-references get null paths before we recieve
* the "row-deleted" signal.
*/
item = child;
}
if (path)
@ -650,43 +669,97 @@ gtk_tree_menu_path_in_menu (GtkTreeMenu *menu,
gboolean *header_item)
{
GtkTreeMenuPrivate *priv = menu->priv;
GtkTreePath *parent_path = gtk_tree_path_copy (path);
gboolean in_menu = FALSE;
gboolean is_header = FALSE;
/* Check if the is in root of the model */
if (gtk_tree_path_get_depth (parent_path) == 1)
if (gtk_tree_path_get_depth (path) == 1)
{
if (!priv->root)
in_menu = TRUE;
{
g_print ("gtk_tree_menu_path_in_menu: Found in root menu !\n");
in_menu = TRUE;
}
}
/* If we are a submenu, compare the parent path */
else if (priv->root && gtk_tree_path_up (parent_path))
else if (priv->root && gtk_tree_path_get_depth (path) > 1)
{
GtkTreePath *root_path =
gtk_tree_row_reference_get_path (priv->root);
GtkTreePath *root_path = gtk_tree_row_reference_get_path (priv->root);
GtkTreePath *parent_path = gtk_tree_path_copy (path);
gtk_tree_path_up (parent_path);
if (gtk_tree_path_compare (root_path, parent_path) == 0)
in_menu = TRUE;
{
in_menu = TRUE;
g_print ("gtk_tree_menu_path_in_menu: Found in this menu !\n");
}
if (!in_menu && priv->menu_with_header &&
gtk_tree_path_compare (root_path, path) == 0)
{
g_print ("gtk_tree_menu_path_in_menu: Found as menu header !\n");
in_menu = TRUE;
is_header = TRUE;
}
gtk_tree_path_free (root_path);
gtk_tree_path_free (parent_path);
}
gtk_tree_path_free (parent_path);
if (header_item)
*header_item = is_header;
return in_menu;
}
static GtkWidget *
gtk_tree_menu_path_needs_submenu (GtkTreeMenu *menu,
GtkTreePath *search)
{
GtkWidget *item = NULL;
GList *children, *l;
GtkTreePath *parent_path;
if (gtk_tree_path_get_depth (search) <= 1)
return NULL;
parent_path = gtk_tree_path_copy (search);
gtk_tree_path_up (parent_path);
children = gtk_container_get_children (GTK_CONTAINER (menu));
for (l = children; item == NULL && l != NULL; l = l->next)
{
GtkWidget *child = l->data;
GtkTreePath *path = NULL;
/* Separators dont get submenus, if it already has a submenu then let
* the submenu handle inserted rows */
if (!GTK_IS_SEPARATOR_MENU_ITEM (child) &&
!gtk_menu_item_get_submenu (GTK_MENU_ITEM (child)))
{
GtkWidget *view = gtk_bin_get_child (GTK_BIN (child));
/* It's always a cellview */
if (GTK_IS_CELL_VIEW (view))
path = gtk_cell_view_get_displayed_row (GTK_CELL_VIEW (view));
}
if (path)
{
if (gtk_tree_path_compare (parent_path, path) == 0)
item = child;
gtk_tree_path_free (path);
}
}
g_list_free (children);
gtk_tree_path_free (parent_path);
return item;
}
static void
row_inserted_cb (GtkTreeModel *model,
GtkTreePath *path,
@ -695,11 +768,11 @@ row_inserted_cb (GtkTreeModel *model,
{
GtkTreeMenuPrivate *priv = menu->priv;
gint *indices, index, depth;
GtkWidget *item;
/* If the iter should be in this menu then go ahead and insert it */
if (gtk_tree_menu_path_in_menu (menu, path, NULL))
{
GtkWidget *item;
if (priv->wrap_width > 0)
rebuild_menu (menu);
@ -728,6 +801,19 @@ row_inserted_cb (GtkTreeModel *model,
gtk_cell_area_context_flush (menu->priv->context);
}
}
else
{
/* Create submenus for iters if we need to */
item = gtk_tree_menu_path_needs_submenu (menu, path);
if (item)
{
GtkTreePath *item_path = gtk_tree_path_copy (path);
gtk_tree_path_up (item_path);
gtk_tree_menu_create_submenu (menu, item, item_path);
gtk_tree_path_free (item_path);
}
}
}
static void
@ -737,29 +823,25 @@ row_deleted_cb (GtkTreeModel *model,
{
GtkTreeMenuPrivate *priv = menu->priv;
GtkWidget *item;
gboolean header_item;
gboolean in_menu;
in_menu = gtk_tree_menu_path_in_menu (menu, path, &header_item);
/* If it's the header item we leave it to the parent menu
* to remove us from its menu
*/
if (!header_item && in_menu)
item = gtk_tree_menu_get_path_item (menu, path);
g_print ("Deleting item %p\n", item);
if (item)
{
item = gtk_tree_menu_get_path_item (menu, path);
if (item)
if (priv->wrap_width > 0)
rebuild_menu (menu);
else
{
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);
}
/* Get rid of the deleted item */
gtk_widget_destroy (item);
/* Resize everything */
gtk_cell_area_context_flush (menu->priv->context);
}
}
}
@ -1082,6 +1164,41 @@ relayout_item (GtkTreeMenu *menu,
current_row, current_row + rows);
}
static void
gtk_tree_menu_create_submenu (GtkTreeMenu *menu,
GtkWidget *item,
GtkTreePath *path)
{
GtkTreeMenuPrivate *priv = menu->priv;
GtkWidget *view;
GtkWidget *submenu;
view = gtk_bin_get_child (GTK_BIN (item));
gtk_cell_view_set_draw_sensitive (GTK_CELL_VIEW (view), TRUE);
submenu = gtk_tree_menu_new_with_area (priv->area);
gtk_tree_menu_set_row_separator_func (GTK_TREE_MENU (submenu),
priv->row_separator_func,
priv->row_separator_data,
priv->row_separator_destroy);
gtk_tree_menu_set_header_func (GTK_TREE_MENU (submenu),
priv->header_func,
priv->header_data,
priv->header_destroy);
gtk_tree_menu_set_wrap_width (GTK_TREE_MENU (submenu), priv->wrap_width);
gtk_tree_menu_set_row_span_column (GTK_TREE_MENU (submenu), priv->row_span_col);
gtk_tree_menu_set_column_span_column (GTK_TREE_MENU (submenu), priv->col_span_col);
gtk_tree_menu_set_model_internal (GTK_TREE_MENU (submenu), priv->model);
gtk_tree_menu_set_root (GTK_TREE_MENU (submenu), path);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
g_signal_connect (submenu, "menu-activate",
G_CALLBACK (submenu_activated_cb), menu);
}
static GtkWidget *
gtk_tree_menu_create_item (GtkTreeMenu *menu,
GtkTreeIter *iter,
@ -1127,27 +1244,7 @@ gtk_tree_menu_create_item (GtkTreeMenu *menu,
/* Add a GtkTreeMenu submenu to render the children of this row */
if (header_item == FALSE &&
gtk_tree_model_iter_has_child (priv->model, iter))
{
GtkWidget *submenu;
submenu = gtk_tree_menu_new_with_area (priv->area);
gtk_tree_menu_set_row_separator_func (GTK_TREE_MENU (submenu),
priv->row_separator_func,
priv->row_separator_data,
priv->row_separator_destroy);
gtk_tree_menu_set_header_func (GTK_TREE_MENU (submenu),
priv->header_func,
priv->header_data,
priv->header_destroy);
gtk_tree_menu_set_model_internal (GTK_TREE_MENU (submenu), priv->model);
gtk_tree_menu_set_root (GTK_TREE_MENU (submenu), path);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
g_signal_connect (submenu, "menu-activate",
G_CALLBACK (submenu_activated_cb), menu);
}
gtk_tree_menu_create_submenu (menu, item, path);
}
gtk_tree_path_free (path);

View File

@ -1092,6 +1092,7 @@ main (int argc, char **argv)
g_object_set (renderer, "text", "la la la", NULL);
gtk_container_add (GTK_CONTAINER (boom), cellview);
#if 0
/* GtkComboBox list */
tmp = gtk_frame_new ("GtkComboBox (list)");
gtk_box_pack_start (GTK_BOX (mainbox), tmp, FALSE, FALSE, 0);
@ -1333,7 +1334,7 @@ main (int argc, char **argv)
NULL);
gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0);
#endif
/* Capitals */
tmp = gtk_frame_new ("Where are you ?");
@ -1368,6 +1369,7 @@ main (int argc, char **argv)
gdk_threads_add_timeout (1000, (GSourceFunc) capital_animation, model);
#endif
#if 0
/* Ellipsizing growing combos */
tmp = gtk_frame_new ("Unconstrained Menu");
gtk_box_pack_start (GTK_BOX (mainbox), tmp, FALSE, FALSE, 0);
@ -1388,7 +1390,7 @@ main (int argc, char **argv)
"text", 0, NULL);
gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0);
gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox), FALSE);
#endif
gtk_widget_show_all (window);
gtk_main ();