diff options
-rw-r--r-- | gtk/gtktreeprivate.h | 3 | ||||
-rw-r--r-- | gtk/gtktreeview.c | 143 | ||||
-rw-r--r-- | tests/Makefile.am | 8 | ||||
-rw-r--r-- | tests/testgrouping.c | 155 |
4 files changed, 277 insertions, 32 deletions
diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index dad8db4121..4861762fa0 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -210,6 +210,7 @@ struct _GtkTreeViewPrivate guint hover_expand : 1; guint imcontext_changed : 1; + /* Auto expand/collapse timeout in hover mode */ guint auto_expand_timeout; @@ -231,6 +232,8 @@ struct _GtkTreeViewPrivate GtkTreeViewRowSeparatorFunc row_separator_func; gpointer row_separator_data; GtkDestroyNotify row_separator_destroy; + + gint level_indentation; }; #ifdef __GNUC__ diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 19c5fffa26..d17034ee19 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -133,7 +133,9 @@ enum { PROP_SEARCH_COLUMN, PROP_FIXED_HEIGHT_MODE, PROP_HOVER_SELECTION, - PROP_HOVER_EXPAND + PROP_HOVER_EXPAND, + PROP_SHOW_EXPANDERS, + PROP_LEVEL_INDENTATION }; static void gtk_tree_view_class_init (GtkTreeViewClass *klass); @@ -708,6 +710,24 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) FALSE, GTK_PARAM_READWRITE)); + g_object_class_install_property (o_class, + PROP_SHOW_EXPANDERS, + g_param_spec_boolean ("show-expanders", + P_("Show Expanders"), + P_("View has expanders"), + TRUE, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (o_class, + PROP_LEVEL_INDENTATION, + g_param_spec_int ("level-indentation", + P_("Level Indentation"), + P_("Extra indentation for each level"), + 0, + G_MAXINT, + 0, + GTK_PARAM_READWRITE)); + /* Style properties */ #define _TREE_VIEW_EXPANDER_SIZE 12 #define _TREE_VIEW_VERTICAL_SEPARATOR 2 @@ -1199,6 +1219,8 @@ gtk_tree_view_init (GtkTreeView *tree_view) tree_view->priv->hover_selection = FALSE; tree_view->priv->hover_expand = FALSE; + + tree_view->priv->level_indentation = 0; } @@ -1257,6 +1279,15 @@ gtk_tree_view_set_property (GObject *object, case PROP_HOVER_EXPAND: tree_view->priv->hover_expand = g_value_get_boolean (value); break; + case PROP_SHOW_EXPANDERS: + if (g_value_get_boolean (value)) + GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS); + else + GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS); + break; + case PROP_LEVEL_INDENTATION: + tree_view->priv->level_indentation = g_value_get_int (value); + break; default: break; } @@ -1313,6 +1344,12 @@ gtk_tree_view_get_property (GObject *object, case PROP_HOVER_EXPAND: g_value_set_boolean (value, tree_view->priv->hover_expand); break; + case PROP_SHOW_EXPANDERS: + g_value_set_boolean (value, GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS)); + break; + case PROP_LEVEL_INDENTATION: + g_value_set_int (value, tree_view->priv->level_indentation); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2257,7 +2294,8 @@ gtk_tree_view_button_press (GtkWidget *widget, /* are we in an arrow? */ if (tree_view->priv->prelight_node && - GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT)) + GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT) && + TREE_VIEW_DRAW_EXPANDERS (tree_view)) { if (event->button == 1) { @@ -2321,11 +2359,16 @@ gtk_tree_view_button_press (GtkWidget *widget, cell_area.height -= vertical_separator; cell_area.x += horizontal_separator/2; cell_area.y += vertical_separator/2; - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS(tree_view)) + if (gtk_tree_view_is_expander_column (tree_view, column)) { - cell_area.x += depth * tree_view->priv->expander_size; - cell_area.width -= depth * tree_view->priv->expander_size; + cell_area.x += (depth - 1) * tree_view->priv->level_indentation; + cell_area.width -= (depth - 1) * tree_view->priv->level_indentation; + + if (TREE_VIEW_DRAW_EXPANDERS(tree_view)) + { + cell_area.x += depth * tree_view->priv->expander_size; + cell_area.width -= depth * tree_view->priv->expander_size; + } } break; } @@ -2835,7 +2878,7 @@ do_prelight (GtkTreeView *tree_view, /* We are still on the same node, but we might need to take care of the arrow */ - if (tree && node) + if (tree && node && TREE_VIEW_DRAW_EXPANDERS (tree_view)) { gboolean over_arrow; gboolean flag_set; @@ -2867,7 +2910,8 @@ do_prelight (GtkTreeView *tree_view, GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT); - if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT)) + if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT) + && TREE_VIEW_DRAW_EXPANDERS (tree_view)) { GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT); @@ -2897,7 +2941,8 @@ do_prelight (GtkTreeView *tree_view, /* Prelight the new node and arrow */ - if (coords_are_over_arrow (tree_view, tree, node, x, y)) + if (TREE_VIEW_DRAW_EXPANDERS (tree_view) + && coords_are_over_arrow (tree_view, tree, node, x, y)) { GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT); @@ -3773,12 +3818,17 @@ gtk_tree_view_bin_expose (GtkWidget *widget, background_area.width, background_area.height); - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS(tree_view)) + if (gtk_tree_view_is_expander_column (tree_view, column)) { - if (!rtl) - cell_area.x += depth * tree_view->priv->expander_size; - cell_area.width -= depth * tree_view->priv->expander_size; + cell_area.x += (depth - 1) * tree_view->priv->level_indentation; + cell_area.width -= (depth - 1) * tree_view->priv->level_indentation; + + if (TREE_VIEW_DRAW_EXPANDERS(tree_view)) + { + if (!rtl) + cell_area.x += depth * tree_view->priv->expander_size; + cell_area.width -= depth * tree_view->priv->expander_size; + } /* If we have an expander column, the highlight underline * starts with that column, so that it indicates which @@ -3804,7 +3854,8 @@ gtk_tree_view_bin_expose (GtkWidget *widget, &cell_area, &event->area, flags); - if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT) + if (TREE_VIEW_DRAW_EXPANDERS(tree_view) + && (node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT) { if (!got_pointer) { @@ -4702,9 +4753,12 @@ validate_row (GtkTreeView *tree_view, else height = 2 + 2 * focus_pad; - if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view)) + if (gtk_tree_view_is_expander_column (tree_view, column)) { - tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size); + tmp_width = tmp_width + horizontal_separator + (depth - 1) * tree_view->priv->level_indentation; + + if (TREE_VIEW_DRAW_EXPANDERS (tree_view)) + tmp_width += depth * tree_view->priv->expander_size; } else tmp_width = tmp_width + horizontal_separator; @@ -7842,10 +7896,15 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view, &width, NULL); } - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS (tree_view)) + if (gtk_tree_view_is_expander_column (tree_view, column)) { - if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width) + int tmp = 0; + + tmp = horizontal_separator + width + (depth - 1) * tree_view->priv->level_indentation; + if (TREE_VIEW_DRAW_EXPANDERS (tree_view)) + tmp += depth * tree_view->priv->expander_size; + + if (tmp > column->requested_width) { _gtk_tree_view_column_cell_set_dirty (column, TRUE); retval = TRUE; @@ -11680,13 +11739,22 @@ gtk_tree_view_get_cell_area (GtkTreeView *tree_view, rect->height = MAX (CELL_HEIGHT (node, vertical_separator), tree_view->priv->expander_size - vertical_separator); if (column && - gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS (tree_view)) + gtk_tree_view_is_expander_column (tree_view, column)) { gint depth = gtk_tree_path_get_depth (path) - 1; - rect->x += depth * tree_view->priv->expander_size; - rect->width -= depth * tree_view->priv->expander_size; + if (depth > 0) + { + rect->x += (depth - 1) * tree_view->priv->level_indentation; + rect->width -= (depth - 1) * tree_view->priv->level_indentation; + } + + if (TREE_VIEW_DRAW_EXPANDERS (tree_view)) + { + rect->x += depth * tree_view->priv->expander_size; + rect->width -= depth * tree_view->priv->expander_size; + } + rect->width = MAX (rect->width, 0); } } @@ -12363,11 +12431,16 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, cell_area.y += vertical_separator / 2; cell_area.height -= vertical_separator; - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS(tree_view)) + if (gtk_tree_view_is_expander_column (tree_view, column)) { - cell_area.x += depth * tree_view->priv->expander_size; - cell_area.width -= depth * tree_view->priv->expander_size; + cell_area.x += (depth - 1) * tree_view->priv->level_indentation; + cell_area.width -= (depth - 1) * tree_view->priv->level_indentation; + + if (TREE_VIEW_DRAW_EXPANDERS(tree_view)) + { + cell_area.x += depth * tree_view->priv->expander_size; + cell_area.width -= depth * tree_view->priv->expander_size; + } } if (gtk_tree_view_column_cell_is_visible (column)) @@ -13295,10 +13368,18 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view, tree_view->priv->focus_column, &cell_area); - if (gtk_tree_view_is_expander_column (tree_view, tree_view->priv->focus_column) && TREE_VIEW_DRAW_EXPANDERS (tree_view)) + if (gtk_tree_view_is_expander_column (tree_view, tree_view->priv->focus_column)) { - cell_area.x += tree_view->priv->expander_size; - cell_area.width -= tree_view->priv->expander_size; + gint depth = gtk_tree_path_get_depth (cursor_path); + + cell_area.x += (depth - 1) * tree_view->priv->level_indentation; + cell_area.width -= (depth - 1) * tree_view->priv->level_indentation; + + if (TREE_VIEW_DRAW_EXPANDERS (tree_view)) + { + cell_area.x += depth * tree_view->priv->expander_size; + cell_area.width -= depth * tree_view->priv->expander_size; + } } if (_gtk_tree_view_column_cell_event (tree_view->priv->focus_column, diff --git a/tests/Makefile.am b/tests/Makefile.am index 94a5980fa2..a900f8d5fb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -78,7 +78,8 @@ noinst_PROGRAMS = \ pixbuf-random \ pixbuf-threads \ testmerge \ - testactions + testactions \ + testgrouping autotestfilechooser_DEPENDENCIES = $(TEST_DEPS) simple_DEPENDENCIES = $(TEST_DEPS) @@ -126,6 +127,7 @@ treestoretest_DEPENDENCIES = $(TEST_DEPS) testxinerama_DEPENDENCIES = $(TEST_DEPS) testmerge_DEPENDENCIES = $(TEST_DEPS) testactions_DEPENDENCIES = $(TEST_DEPS) +testgrouping_DEPENDENCIES = $(TEST_DEPS) autotestfilechooser_LDADD = $(LDADDS) simple_LDADD = $(LDADDS) @@ -180,6 +182,7 @@ pixbuf_random_LDADD = $(LDADDS) pixbuf_threads_LDADD = $(LDADDS) $(GLIB_LIBS) testmerge_LDADD = $(LDADDS) testactions_LDADD = $(LDADDS) +testgrouping_LDADD = $(LDADDS) autotestfilechooser_SOURCES = \ autotestfilechooser.c @@ -246,6 +249,9 @@ testrecentchooser_SOURCES = \ prop-editor.c \ testrecentchooser.c +testgrouping_SOURCES = \ + testgrouping.c + EXTRA_DIST = \ prop-editor.h \ testgtk.1 \ diff --git a/tests/testgrouping.c b/tests/testgrouping.c new file mode 100644 index 0000000000..4b412d01ef --- /dev/null +++ b/tests/testgrouping.c @@ -0,0 +1,155 @@ +#include <gtk/gtk.h> + + +static GtkTreeModel * +create_model (void) +{ + GtkTreeStore *store; + GtkTreeIter iter; + GtkTreeIter parent; + + store = gtk_tree_store_new (1, G_TYPE_STRING); + + gtk_tree_store_insert_with_values (store, &parent, NULL, 0, + 0, "Applications", -1); + + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "File Manager", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "Gossip", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "System Settings", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "The GIMP", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "Terminal", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "Word Processor", -1); + + + gtk_tree_store_insert_with_values (store, &parent, NULL, 1, + 0, "Documents", -1); + + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "blaat.txt", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "sliff.txt", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "test.txt", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "blaat.txt", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "brrrr.txt", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "hohoho.txt", -1); + + + gtk_tree_store_insert_with_values (store, &parent, NULL, 2, + 0, "Images", -1); + + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "image1.png", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "image2.png", -1); + gtk_tree_store_insert_with_values (store, &iter, &parent, 0, + 0, "image3.jpg", -1); + + return GTK_TREE_MODEL (store); +} + +static void +set_color_func (GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + if (gtk_tree_model_iter_has_child (model, iter)) + g_object_set (cell, "cell-background", "Grey", NULL); + else + g_object_set (cell, "cell-background", NULL, NULL); +} + +static void +tree_view_row_activated (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column) +{ + if (gtk_tree_path_get_depth (path) > 1) + return; + + if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (tree_view), path)) + gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path); + else + gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE); +} + +static gboolean +tree_view_select_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer data) +{ + if (gtk_tree_path_get_depth (path) > 1) + return TRUE; + + return FALSE; +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *sw, *tv; + GtkTreeModel *model; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + gtk_init (&argc, &argv); + + model = create_model (); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (window, "delete_event", + G_CALLBACK (gtk_main_quit), NULL); + gtk_window_set_default_size (GTK_WINDOW (window), 320, 480); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_container_add (GTK_CONTAINER (window), sw); + + tv = gtk_tree_view_new_with_model (model); + gtk_container_add (GTK_CONTAINER (sw), tv); + + g_signal_connect (tv, "row-activated", + G_CALLBACK (tree_view_row_activated), tv); + g_object_set (tv, + "show-expanders", FALSE, + "level-indentation", 10, + NULL); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tv), FALSE); + gtk_tree_view_expand_all (GTK_TREE_VIEW (tv)); + + gtk_tree_selection_set_select_function (gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)), + tree_view_select_func, + NULL, + NULL); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("(none)", + renderer, + "text", 0, + NULL); + gtk_tree_view_column_set_cell_data_func (column, + renderer, + set_color_func, + NULL, + NULL); + gtk_tree_view_insert_column (GTK_TREE_VIEW (tv), column, 0); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} |