summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk/gtktreemenu.c199
-rw-r--r--tests/testcombo.c6
2 files changed, 152 insertions, 53 deletions
diff --git a/gtk/gtktreemenu.c b/gtk/gtktreemenu.c
index db970c99ff..e9d63514e8 100644
--- a/gtk/gtktreemenu.c
+++ b/gtk/gtktreemenu.c
@@ -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);
diff --git a/tests/testcombo.c b/tests/testcombo.c
index f321fb0a55..1de03fc79d 100644
--- a/tests/testcombo.c
+++ b/tests/testcombo.c
@@ -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 ();