diff options
author | Jonathan Blandford <jrb@redhat.com> | 2001-09-25 16:44:39 +0000 |
---|---|---|
committer | Jonathan Blandford <jrb@src.gnome.org> | 2001-09-25 16:44:39 +0000 |
commit | 92841cb95add212c35b2ef58129f043c33676c52 (patch) | |
tree | a58a60c4bc75ea3f716bfd59d3c193cf417fc5f4 | |
parent | 8a2d408daed1b616ab760cdfeec050cb6e54c1de (diff) | |
download | gtk+-92841cb95add212c35b2ef58129f043c33676c52.tar.gz |
Make a GtkCellEditable (get_widget_window_size): Change to let it honor
Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkentry.c: Make a GtkCellEditable
(get_widget_window_size): Change to let it honor size_allocate
when a CellEditable.
* gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and
editable changes.
(gtk_tree_view_set_cursor): Now you can set the cursor
horizontally, as well as start editing.
* gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing
code to look more like the other check buttons.
* gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size):
Change the way we calculate cell size.
* gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller.
* demos/gtk-demo/sizegroup.c: Add mnemonics.
* gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs.
Fix logic.
* gtk/gtkcellrenderertext.c: Change to be editable.
* gtk/gtkcellrenderertoggle.c: Change to be activatable.
* test/testtreesort.c: Fix misspelling
* test/testreecolumns.c: Add mnemonics.
* test/testreeedit.c: New test program.
-rw-r--r-- | ChangeLog | 34 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 34 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 34 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 34 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 34 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 34 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 34 | ||||
-rw-r--r-- | demos/gtk-demo/appwindow.c | 10 | ||||
-rw-r--r-- | demos/gtk-demo/sizegroup.c | 13 | ||||
-rw-r--r-- | docs/tree-column-sizing.txt | 2 | ||||
-rw-r--r-- | gtk/gtkcellrenderer.c | 56 | ||||
-rw-r--r-- | gtk/gtkcellrenderertext.c | 96 | ||||
-rw-r--r-- | gtk/gtkcellrenderertext.h | 4 | ||||
-rw-r--r-- | gtk/gtkcellrenderertoggle.c | 63 | ||||
-rw-r--r-- | gtk/gtkcellrenderertoggle.h | 3 | ||||
-rw-r--r-- | gtk/gtkentry.c | 80 | ||||
-rw-r--r-- | gtk/gtkentry.h | 4 | ||||
-rw-r--r-- | gtk/gtkmarshal.list | 1 | ||||
-rw-r--r-- | gtk/gtkmarshalers.list | 1 | ||||
-rw-r--r-- | gtk/gtkstyle.c | 15 | ||||
-rw-r--r-- | gtk/gtktreeprivate.h | 1 | ||||
-rw-r--r-- | gtk/gtktreeview.c | 787 | ||||
-rw-r--r-- | gtk/gtktreeview.h | 5 | ||||
-rw-r--r-- | gtk/gtktreeviewcolumn.c | 197 | ||||
-rw-r--r-- | gtk/gtktreeviewcolumn.h | 3 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/testtreecolumns.c | 8 | ||||
-rw-r--r-- | tests/testtreeedit.c | 140 | ||||
-rw-r--r-- | tests/testtreefocus.c | 4 | ||||
-rw-r--r-- | tests/testtreesort.c | 2 |
30 files changed, 1233 insertions, 506 deletions
@@ -1,3 +1,37 @@ +Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com> + + * gtk/gtkentry.c: Make a GtkCellEditable + (get_widget_window_size): Change to let it honor size_allocate + when a CellEditable. + + * gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and + editable changes. + (gtk_tree_view_set_cursor): Now you can set the cursor + horizontally, as well as start editing. + + * gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing + code to look more like the other check buttons. + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size): + Change the way we calculate cell size. + + * gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller. + + * demos/gtk-demo/sizegroup.c: Add mnemonics. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs. + Fix logic. + + * gtk/gtkcellrenderertext.c: Change to be editable. + + * gtk/gtkcellrenderertoggle.c: Change to be activatable. + + * test/testtreesort.c: Fix misspelling + + * test/testreecolumns.c: Add mnemonics. + + * test/testreeedit.c: New test program. + 2001-09-25 Havoc Pennington <hp@pobox.com> * gtk/gtkwindow.c: Put notes in gtk_window_set_has_frame(), diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index bb81bc4b98..b3dc1a4731 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,37 @@ +Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com> + + * gtk/gtkentry.c: Make a GtkCellEditable + (get_widget_window_size): Change to let it honor size_allocate + when a CellEditable. + + * gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and + editable changes. + (gtk_tree_view_set_cursor): Now you can set the cursor + horizontally, as well as start editing. + + * gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing + code to look more like the other check buttons. + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size): + Change the way we calculate cell size. + + * gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller. + + * demos/gtk-demo/sizegroup.c: Add mnemonics. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs. + Fix logic. + + * gtk/gtkcellrenderertext.c: Change to be editable. + + * gtk/gtkcellrenderertoggle.c: Change to be activatable. + + * test/testtreesort.c: Fix misspelling + + * test/testreecolumns.c: Add mnemonics. + + * test/testreeedit.c: New test program. + 2001-09-25 Havoc Pennington <hp@pobox.com> * gtk/gtkwindow.c: Put notes in gtk_window_set_has_frame(), diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index bb81bc4b98..b3dc1a4731 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,37 @@ +Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com> + + * gtk/gtkentry.c: Make a GtkCellEditable + (get_widget_window_size): Change to let it honor size_allocate + when a CellEditable. + + * gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and + editable changes. + (gtk_tree_view_set_cursor): Now you can set the cursor + horizontally, as well as start editing. + + * gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing + code to look more like the other check buttons. + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size): + Change the way we calculate cell size. + + * gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller. + + * demos/gtk-demo/sizegroup.c: Add mnemonics. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs. + Fix logic. + + * gtk/gtkcellrenderertext.c: Change to be editable. + + * gtk/gtkcellrenderertoggle.c: Change to be activatable. + + * test/testtreesort.c: Fix misspelling + + * test/testreecolumns.c: Add mnemonics. + + * test/testreeedit.c: New test program. + 2001-09-25 Havoc Pennington <hp@pobox.com> * gtk/gtkwindow.c: Put notes in gtk_window_set_has_frame(), diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index bb81bc4b98..b3dc1a4731 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,37 @@ +Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com> + + * gtk/gtkentry.c: Make a GtkCellEditable + (get_widget_window_size): Change to let it honor size_allocate + when a CellEditable. + + * gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and + editable changes. + (gtk_tree_view_set_cursor): Now you can set the cursor + horizontally, as well as start editing. + + * gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing + code to look more like the other check buttons. + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size): + Change the way we calculate cell size. + + * gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller. + + * demos/gtk-demo/sizegroup.c: Add mnemonics. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs. + Fix logic. + + * gtk/gtkcellrenderertext.c: Change to be editable. + + * gtk/gtkcellrenderertoggle.c: Change to be activatable. + + * test/testtreesort.c: Fix misspelling + + * test/testreecolumns.c: Add mnemonics. + + * test/testreeedit.c: New test program. + 2001-09-25 Havoc Pennington <hp@pobox.com> * gtk/gtkwindow.c: Put notes in gtk_window_set_has_frame(), diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index bb81bc4b98..b3dc1a4731 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,37 @@ +Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com> + + * gtk/gtkentry.c: Make a GtkCellEditable + (get_widget_window_size): Change to let it honor size_allocate + when a CellEditable. + + * gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and + editable changes. + (gtk_tree_view_set_cursor): Now you can set the cursor + horizontally, as well as start editing. + + * gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing + code to look more like the other check buttons. + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size): + Change the way we calculate cell size. + + * gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller. + + * demos/gtk-demo/sizegroup.c: Add mnemonics. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs. + Fix logic. + + * gtk/gtkcellrenderertext.c: Change to be editable. + + * gtk/gtkcellrenderertoggle.c: Change to be activatable. + + * test/testtreesort.c: Fix misspelling + + * test/testreecolumns.c: Add mnemonics. + + * test/testreeedit.c: New test program. + 2001-09-25 Havoc Pennington <hp@pobox.com> * gtk/gtkwindow.c: Put notes in gtk_window_set_has_frame(), diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index bb81bc4b98..b3dc1a4731 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,37 @@ +Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com> + + * gtk/gtkentry.c: Make a GtkCellEditable + (get_widget_window_size): Change to let it honor size_allocate + when a CellEditable. + + * gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and + editable changes. + (gtk_tree_view_set_cursor): Now you can set the cursor + horizontally, as well as start editing. + + * gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing + code to look more like the other check buttons. + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size): + Change the way we calculate cell size. + + * gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller. + + * demos/gtk-demo/sizegroup.c: Add mnemonics. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs. + Fix logic. + + * gtk/gtkcellrenderertext.c: Change to be editable. + + * gtk/gtkcellrenderertoggle.c: Change to be activatable. + + * test/testtreesort.c: Fix misspelling + + * test/testreecolumns.c: Add mnemonics. + + * test/testreeedit.c: New test program. + 2001-09-25 Havoc Pennington <hp@pobox.com> * gtk/gtkwindow.c: Put notes in gtk_window_set_has_frame(), diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index bb81bc4b98..b3dc1a4731 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,37 @@ +Tue Sep 25 12:34:42 2001 Jonathan Blandford <jrb@redhat.com> + + * gtk/gtkentry.c: Make a GtkCellEditable + (get_widget_window_size): Change to let it honor size_allocate + when a CellEditable. + + * gtk/gtktreeview.c: M-x clean-line-ends. Lots of focus and + editable changes. + (gtk_tree_view_set_cursor): Now you can set the cursor + horizontally, as well as start editing. + + * gtk/gtkstyle.c (gtk_default_draw_check): changing toggle drawing + code to look more like the other check buttons. + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_get_size): + Change the way we calculate cell size. + + * gtk/gtkmarshal.list (VOID:STRING,STRING): new marshaller. + + * demos/gtk-demo/sizegroup.c: Add mnemonics. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_get_size): Fix docs. + Fix logic. + + * gtk/gtkcellrenderertext.c: Change to be editable. + + * gtk/gtkcellrenderertoggle.c: Change to be activatable. + + * test/testtreesort.c: Fix misspelling + + * test/testreecolumns.c: Add mnemonics. + + * test/testreeedit.c: New test program. + 2001-09-25 Havoc Pennington <hp@pobox.com> * gtk/gtkwindow.c: Put notes in gtk_window_set_has_frame(), diff --git a/demos/gtk-demo/appwindow.c b/demos/gtk-demo/appwindow.c index fd86d8dd9c..cb88dc7fe8 100644 --- a/demos/gtk-demo/appwindow.c +++ b/demos/gtk-demo/appwindow.c @@ -43,12 +43,12 @@ static GtkItemFactoryEntry menu_items[] = { "/File/sep1", NULL, menuitem_cb, 0, "<Separator>" }, { "/File/_Quit", "<control>Q", menuitem_cb, 0, "<StockItem>", GTK_STOCK_QUIT }, - { "/_Preferences", NULL, 0, 0, "<Branch>" }, - { "/_Preferences/_Color", NULL, 0, 0, "<Branch>" }, - { "/_Preferences/Color/_Red", NULL, menuitem_cb, 0, "<RadioItem>" }, - { "/_Preferences/Color/_Green", NULL, menuitem_cb, 0, "/Preferences/Color/Red" }, + { "/_Preferences", NULL, 0, 0, "<Branch>" }, + { "/_Preferences/_Color", NULL, 0, 0, "<Branch>" }, + { "/_Preferences/Color/_Red", NULL, menuitem_cb, 0, "<RadioItem>" }, + { "/_Preferences/Color/_Green", NULL, menuitem_cb, 0, "/Preferences/Color/Red" }, { "/_Preferences/Color/_Blue", NULL, menuitem_cb, 0, "/Preferences/Color/Red" }, - { "/_Preferences/_Shape", NULL, 0, 0, "<Branch>" }, + { "/_Preferences/_Shape", NULL, 0, 0, "<Branch>" }, { "/_Preferences/Shape/_Square", NULL, menuitem_cb, 0, "<RadioItem>" }, { "/_Preferences/Shape/_Rectangle", NULL, menuitem_cb, 0, "/Preferences/Shape/Square" }, { "/_Preferences/Shape/_Oval", NULL, menuitem_cb, 0, "/Preferences/Shape/Rectangle" }, diff --git a/demos/gtk-demo/sizegroup.c b/demos/gtk-demo/sizegroup.c index fe87feff50..536dd74532 100644 --- a/demos/gtk-demo/sizegroup.c +++ b/demos/gtk-demo/sizegroup.c @@ -52,7 +52,7 @@ add_row (GtkTable *table, GtkWidget *option_menu; GtkWidget *label; - label = gtk_label_new (label_text); + label = gtk_label_new_with_mnemonic (label_text); gtk_misc_set_alignment (GTK_MISC (label), 0, 1); gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1, @@ -60,6 +60,7 @@ add_row (GtkTable *table, 0, 0); option_menu = create_option_menu (options); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), option_menu); gtk_size_group_add_widget (size_group, option_menu); gtk_table_attach (GTK_TABLE (table), option_menu, 1, 2, row, row + 1, @@ -137,8 +138,8 @@ do_sizegroup (void) gtk_table_set_col_spacings (GTK_TABLE (table), 10); gtk_container_add (GTK_CONTAINER (frame), table); - add_row (GTK_TABLE (table), 0, size_group, "Foreground", color_options); - add_row (GTK_TABLE (table), 1, size_group, "Background", color_options); + add_row (GTK_TABLE (table), 0, size_group, "_Foreground", color_options); + add_row (GTK_TABLE (table), 1, size_group, "_Background", color_options); /* And another frame holding line style options */ @@ -151,11 +152,11 @@ do_sizegroup (void) gtk_table_set_col_spacings (GTK_TABLE (table), 10); gtk_container_add (GTK_CONTAINER (frame), table); - add_row (GTK_TABLE (table), 0, size_group, "Dashing", dash_options); - add_row (GTK_TABLE (table), 1, size_group, "Line ends", end_options); + add_row (GTK_TABLE (table), 0, size_group, "_Dashing", dash_options); + add_row (GTK_TABLE (table), 1, size_group, "_Line ends", end_options); /* And a check button to turn grouping on and off */ - check_button = gtk_check_button_new_with_label ("Enable grouping"); + check_button = gtk_check_button_new_with_mnemonic ("_Enable grouping"); gtk_box_pack_start (GTK_BOX (vbox), check_button, FALSE, FALSE, 0); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE); diff --git a/docs/tree-column-sizing.txt b/docs/tree-column-sizing.txt index 367755fe53..09e872434a 100644 --- a/docs/tree-column-sizing.txt +++ b/docs/tree-column-sizing.txt @@ -30,7 +30,7 @@ HOW THE GTKTREEVIEWCOLUMN STORES SIZE: ====================================== There are a number of size related fields in the GtkTreeViewColumn -structure: +structure. These are all valid after realization: sizing The sizing method to use when calculating the size of the column. Can be grow_only, resizable, auto, and fixed. diff --git a/gtk/gtkcellrenderer.c b/gtk/gtkcellrenderer.c index 4cd5ae493a..651dc7f7a8 100644 --- a/gtk/gtkcellrenderer.c +++ b/gtk/gtkcellrenderer.c @@ -318,7 +318,9 @@ gtk_cell_renderer_set_property (GObject *object, * Obtains the width and height needed to render the cell. Used by view widgets * to determine the appropriate size for the cell_area passed to * gtk_cell_renderer_render(). If @cell_area is not %NULL, fills in the x and y - * offsets (if set) of the cell relative to this location. + * offsets (if set) of the cell relative to this location. Please note that the + * values set in @width and @height, as well as those in @x_offset and @y_offset + * are inclusive of the xpad and ypad properties. **/ void gtk_cell_renderer_get_size (GtkCellRenderer *cell, @@ -329,29 +331,24 @@ gtk_cell_renderer_get_size (GtkCellRenderer *cell, gint *width, gint *height) { - gint *real_width = NULL; - gint *real_height = NULL; + gint *real_width = width; + gint *real_height = height; g_return_if_fail (GTK_IS_CELL_RENDERER (cell)); g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->get_size != NULL); - if (width) + if (width && cell->width != -1) { - if (cell->width == -1) - real_width = width; - else - *width = cell->width; + real_width = NULL; + *width = cell->width; } - if (height) + if (height && cell->height != -1) { - if (cell->height == -1) - real_height = height; - else - *height = cell->height; + real_height = NULL; + *height = cell->height; } - if (real_width || real_height) - GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (cell, widget, cell_area, x_offset, y_offset, real_width, real_height); + GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (cell, widget, cell_area, x_offset, y_offset, real_width, real_height); } /** @@ -364,15 +361,13 @@ gtk_cell_renderer_get_size (GtkCellRenderer *cell, * @expose_area: area that actually needs updating * @flags: flags that affect rendering * - * Invokes the virtual render function of the #GtkCellRenderer. The - * three passed-in rectangles are areas of @window. Most renderers - * will draw to @cell_area; the xalign, yalign, xpad, and ypad fields - * of the #GtkCellRenderer should be honored with respect to - * @cell_area. @background_area includes the blank space around the - * cell, and also the area containing the tree expander; so the - * @background_area rectangles for all cells tile to cover the entire - * @window. Cell renderers can use the @background_area to draw custom expanders, for - * example. @expose_area is a clip rectangle. + * Invokes the virtual render function of the #GtkCellRenderer. The three + * passed-in rectangles are areas of @window. Most renderers will draw within + * @cell_area; the xalign, yalign, xpad, and ypad fields of the #GtkCellRenderer + * should be honored with respect to @cell_area. @background_area includes the + * blank space around the cell, and also the area containing the tree expander; + * so the @background_area rectangles for all cells tile to cover the entire + * @window. @expose_area is a clip rectangle. * **/ void @@ -384,11 +379,6 @@ gtk_cell_renderer_render (GtkCellRenderer *cell, GdkRectangle *expose_area, GtkCellRendererState flags) { - /* It's actually okay to pass in a NULL cell, as we run into that - * a lot - */ - if (cell == NULL) - return; g_return_if_fail (GTK_IS_CELL_RENDERER (cell)); g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->render != NULL); @@ -407,8 +397,8 @@ gtk_cell_renderer_render (GtkCellRenderer *cell, * @event: a #GdkEvent * @widget: widget that received the event * @path: widget-dependent string representation of the event location; e.g. for #GtkTreeView, a string representation of #GtkTreePath - * @background_area: background area as passed to gtk_cell_renderer_render() - * @cell_area: cell area as passed to gtk_cell_renderer_render() + * @background_area: background area as passed to @gtk_cell_renderer_render + * @cell_area: cell area as passed to @gtk_cell_renderer_render * @flags: render flags * * Passes an activate event to the cell renderer for possible processing. Some @@ -449,8 +439,8 @@ gtk_cell_renderer_activate (GtkCellRenderer *cell, * @event: a #GdkEvent * @widget: widget that received the event * @path: widget-dependent string representation of the event location; e.g. for #GtkTreeView, a string representation of #GtkTreePath - * @background_area: background area as passed to gtk_cell_renderer_render() - * @cell_area: cell area as passed to gtk_cell_renderer_render() + * @background_area: background area as passed to @gtk_cell_renderer_render + * @cell_area: cell area as passed to @gtk_cell_renderer_render * @flags: render flags * * Passes an activate event to the cell renderer for possible processing. diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index 0055dff58b..bced2d8c14 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -19,6 +19,9 @@ #include <stdlib.h> #include "gtkcellrenderertext.h" +#include "gtkeditable.h" +#include "gtkentry.h" +#include "gtksignal.h" #include "gtkintl.h" static void gtk_cell_renderer_text_init (GtkCellRendererText *celltext); @@ -48,7 +51,18 @@ static void gtk_cell_renderer_text_render (GtkCellRenderer *cell, GdkRectangle *expose_area, guint flags); +static GtkCellEditable *gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags); +enum { + EDITED, + LAST_SIGNAL +}; enum { PROP_0, @@ -94,6 +108,9 @@ enum { }; static gpointer parent_class; +static guint text_cell_renderer_signals [LAST_SIGNAL]; + +#define GTK_CELL_RENDERER_TEXT_PATH "gtk-cell-renderer-text-path" GtkType gtk_cell_renderer_text_get_type (void) @@ -128,7 +145,7 @@ gtk_cell_renderer_text_init (GtkCellRendererText *celltext) GTK_CELL_RENDERER (celltext)->yalign = 0.5; GTK_CELL_RENDERER (celltext)->xpad = 2; GTK_CELL_RENDERER (celltext)->ypad = 2; - + GTK_CELL_RENDERER (celltext)->mode = GTK_CELL_RENDERER_MODE_EDITABLE; celltext->fixed_height_rows = -1; celltext->font = pango_font_description_new (); } @@ -148,7 +165,8 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) cell_class->get_size = gtk_cell_renderer_text_get_size; cell_class->render = gtk_cell_renderer_text_render; - + cell_class->start_editing = gtk_cell_renderer_text_start_editing; + g_object_class_install_property (object_class, PROP_TEXT, g_param_spec_string ("text", @@ -390,6 +408,17 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET, _("Underline set"), _("Whether this tag affects underlining")); + + text_cell_renderer_signals [EDITED] = + gtk_signal_new ("edited", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkCellRendererTextClass, edited), + gtk_marshal_VOID__STRING_STRING, + GTK_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); + } static void @@ -1135,12 +1164,12 @@ gtk_cell_renderer_text_get_size (GtkCellRenderer *cell, if (x_offset) { *x_offset = cell->xalign * (cell_area->width - rect.width - (2 * cell->xpad)); - *x_offset = MAX (*x_offset, 0) + cell->xpad; + *x_offset = MAX (*x_offset, 0); } if (y_offset) { *y_offset = cell->yalign * (cell_area->height - rect.height - (2 * cell->ypad)); - *y_offset = MAX (*y_offset, 0) + cell->ypad; + *y_offset = MAX (*y_offset, 0); } } @@ -1202,7 +1231,7 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell, g_object_unref (G_OBJECT (gc)); } - + gtk_paint_layout (widget->style, window, state, @@ -1210,12 +1239,60 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell, cell_area, widget, "cellrenderertext", - cell_area->x + x_offset, - cell_area->y + y_offset, + cell_area->x + x_offset + cell->xpad, + cell_area->y + y_offset + cell->ypad, layout); g_object_unref (G_OBJECT (layout)); } +static void +gtk_cell_renderer_text_editing_done (GtkCellEditable *entry, + gpointer data) +{ + gchar *path; + gchar *new_text; + + path = g_object_get_data (G_OBJECT (entry), GTK_CELL_RENDERER_TEXT_PATH); + new_text = gtk_entry_get_text (GTK_ENTRY (entry)); + + gtk_signal_emit (GTK_OBJECT (data), text_cell_renderer_signals[EDITED], path, new_text); +} + +static GtkCellEditable * +gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + GtkCellRendererText *celltext; + GtkWidget *entry; + + celltext = GTK_CELL_RENDERER_TEXT (cell); + + /* If the cell isn't editable we return NULL. */ + if (celltext->editable == FALSE) + return NULL; + + entry = g_object_new (GTK_TYPE_ENTRY, + "has_frame", FALSE, + NULL); + + gtk_entry_set_text (GTK_ENTRY (entry), celltext->text); + g_object_set_data_full (G_OBJECT (entry), GTK_CELL_RENDERER_TEXT_PATH, g_strdup (path), g_free); + + gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); + + gtk_widget_show (entry); + gtk_signal_connect (GTK_OBJECT (entry), + "editing_done", + G_CALLBACK (gtk_cell_renderer_text_editing_done), + celltext); + return GTK_CELL_EDITABLE (entry); + +} /** * gtk_cell_renderer_text_set_fixed_height_from_font: @@ -1226,8 +1303,9 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell, * "y_pad" property set on it. Further changes in these properties do not * affect the height, so they must be accompanied by a subsequent call to this * function. Using this function is unflexible, and should really only be used - * if calculating the size of a cell is too slow. If @no_rows is -1, then the - * fixed height is unset, and the height is determined by the properties again. + * if calculating the size of a cell is too slow (ie, a massive number of cells + * displayed). If @number_of_rows is -1, then the fixed height is unset, and + * the height is determined by the properties again. **/ void gtk_cell_renderer_text_set_fixed_height_from_font (GtkCellRendererText *renderer, diff --git a/gtk/gtkcellrenderertext.h b/gtk/gtkcellrenderertext.h index 41a8fcb7e4..dfc4f8b3db 100644 --- a/gtk/gtkcellrenderertext.h +++ b/gtk/gtkcellrenderertext.h @@ -79,6 +79,10 @@ struct _GtkCellRendererText struct _GtkCellRendererTextClass { GtkCellRendererClass parent_class; + + void (* edited) (GtkCellRendererText *cell_renderer_text, + gchar *path, + gchar *new_text); }; GtkType gtk_cell_renderer_text_get_type (void); diff --git a/gtk/gtkcellrenderertoggle.c b/gtk/gtkcellrenderertoggle.c index fac7dd7bd9..845266f6e7 100644 --- a/gtk/gtkcellrenderertoggle.c +++ b/gtk/gtkcellrenderertoggle.c @@ -62,6 +62,7 @@ enum { enum { PROP_ZERO, + PROP_ACTIVATABLE, PROP_ACTIVE, PROP_RADIO }; @@ -101,6 +102,7 @@ gtk_cell_renderer_toggle_get_type (void) static void gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle) { + celltoggle->activatable = TRUE; celltoggle->active = FALSE; celltoggle->radio = FALSE; GTK_CELL_RENDERER (celltoggle)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; @@ -131,6 +133,15 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) G_PARAM_WRITABLE)); g_object_class_install_property (object_class, + PROP_ACTIVATABLE, + g_param_spec_boolean ("activatable", + _("Activatable"), + _("The toggle button can be activated"), + TRUE, + G_PARAM_READABLE | + G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, PROP_RADIO, g_param_spec_boolean ("radio", _("Radio state"), @@ -163,6 +174,9 @@ gtk_cell_renderer_toggle_get_property (GObject *object, case PROP_ACTIVE: g_value_set_boolean (value, celltoggle->active); break; + case PROP_ACTIVATABLE: + g_value_set_boolean (value, celltoggle->activatable); + break; case PROP_RADIO: g_value_set_boolean (value, celltoggle->radio); break; @@ -187,6 +201,10 @@ gtk_cell_renderer_toggle_set_property (GObject *object, celltoggle->active = g_value_get_boolean (value); g_object_notify (G_OBJECT(object), "active"); break; + case PROP_ACTIVATABLE: + celltoggle->activatable = g_value_get_boolean (value); + g_object_notify (G_OBJECT(object), "activatable"); + break; case PROP_RADIO: celltoggle->radio = g_value_get_boolean (value); g_object_notify (G_OBJECT(object), "radio"); @@ -241,13 +259,13 @@ gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, { if (x_offset) { - *x_offset = cell->xalign * (cell_area->width - calc_width - (2 * cell->xpad)); - *x_offset = MAX (*x_offset, 0) + cell->xpad; + *x_offset = cell->xalign * (cell_area->width - calc_width); + *x_offset = MAX (*x_offset, 0); } if (y_offset) { - *y_offset = cell->yalign * (cell_area->height - calc_height - (2 * cell->ypad)); - *y_offset = MAX (*y_offset, 0) + cell->ypad; + *y_offset = cell->yalign * (cell_area->height - calc_height); + *y_offset = MAX (*y_offset, 0); } } } @@ -281,21 +299,17 @@ gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) { if (GTK_WIDGET_HAS_FOCUS (widget)) - { - state = GTK_STATE_SELECTED; - } + state = GTK_STATE_SELECTED; else - { - state = GTK_STATE_ACTIVE; - } + state = GTK_STATE_ACTIVE; } - else if (cell->mode == GTK_CELL_RENDERER_MODE_INERT) + else if (celltoggle->activatable) { - state = GTK_STATE_INSENSITIVE; + state = GTK_STATE_NORMAL; } else { - state = GTK_STATE_NORMAL; + state = GTK_STATE_INSENSITIVE; } if (celltoggle->radio) @@ -306,7 +320,7 @@ gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, cell_area, widget, "cellradio", cell_area->x + x_offset + cell->xpad, cell_area->y + y_offset + cell->ypad, - width, height); + width - 1, height - 1); } else { @@ -316,7 +330,7 @@ gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, cell_area, widget, "cellcheck", cell_area->x + x_offset + cell->xpad, cell_area->y + y_offset + cell->ypad, - width, height); + width - 1, height - 1); } } @@ -330,24 +344,15 @@ gtk_cell_renderer_toggle_activate (GtkCellRenderer *cell, guint flags) { GtkCellRendererToggle *celltoggle; - gboolean retval = FALSE; celltoggle = GTK_CELL_RENDERER_TOGGLE (cell); - - switch (event->type) + if (celltoggle->activatable) { - case GDK_BUTTON_PRESS: - { - gtk_signal_emit (GTK_OBJECT (cell), toggle_cell_signals[TOGGLED], path); - retval = TRUE; - } - break; - - default: - break; + gtk_signal_emit (GTK_OBJECT (cell), toggle_cell_signals[TOGGLED], path); + return TRUE; } - - return retval; + + return FALSE; } /** diff --git a/gtk/gtkcellrenderertoggle.h b/gtk/gtkcellrenderertoggle.h index f1918e1cfa..db166112fb 100644 --- a/gtk/gtkcellrenderertoggle.h +++ b/gtk/gtkcellrenderertoggle.h @@ -43,6 +43,7 @@ struct _GtkCellRendererToggle /*< private >*/ guint active : 1; + guint activatable : 1; guint radio : 1; }; @@ -50,7 +51,7 @@ struct _GtkCellRendererToggleClass { GtkCellRendererClass parent_class; - void (* toggled) (GtkCellRendererToggle *celltoggle, + void (* toggled) (GtkCellRendererToggle *cell_renderer_toggle, gchar *path); }; diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 0715097f2b..c8931e4818 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -30,6 +30,7 @@ #include "gdk/gdkkeysyms.h" #include "gtkbindings.h" +#include "gtkcelleditable.h" #include "gtkclipboard.h" #include "gtkdnd.h" #include "gtkentry.h" @@ -100,8 +101,9 @@ static GtkTargetEntry target_table[] = { /* GObject, GtkObject methods */ -static void gtk_entry_class_init (GtkEntryClass *klass); -static void gtk_entry_editable_init (GtkEditableClass *iface); +static void gtk_entry_class_init (GtkEntryClass *klass); +static void gtk_entry_editable_init (GtkEditableClass *iface); +static void gtk_entry_cell_editable_init (GtkCellEditableIface *iface); static void gtk_entry_init (GtkEntry *entry); static void gtk_entry_set_property (GObject *object, guint prop_id, @@ -189,6 +191,11 @@ static gboolean gtk_entry_get_selection_bounds (GtkEditable *editable, gint *start, gint *end); +/* GtkCellEditable method implementations + */ +static void gtk_entry_start_editing (GtkCellEditable *cell_editable, + GdkEvent *event); + /* Default signal handlers */ static void gtk_entry_real_insert_text (GtkEntry *entry, @@ -298,10 +305,20 @@ gtk_entry_get_type (void) NULL /* interface_data */ }; + static const GInterfaceInfo cell_editable_info = + { + (GInterfaceInitFunc) gtk_entry_cell_editable_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + entry_type = gtk_type_unique (GTK_TYPE_WIDGET, &entry_info); g_type_add_interface_static (entry_type, GTK_TYPE_EDITABLE, &editable_info); + g_type_add_interface_static (entry_type, + GTK_TYPE_CELL_EDITABLE, + &cell_editable_info); } return entry_type; @@ -764,6 +781,12 @@ gtk_entry_editable_init (GtkEditableClass *iface) } static void +gtk_entry_cell_editable_init (GtkCellEditableIface *iface) +{ + iface->start_editing = gtk_entry_start_editing; +} + +static void gtk_entry_set_property (GObject *object, guint prop_id, const GValue *value, @@ -881,7 +904,7 @@ gtk_entry_init (GtkEntry *entry) entry->invisible_char = '*'; entry->dnd_position = -1; entry->width_chars = -1; - + entry->is_cell_renderer = FALSE; entry->has_frame = TRUE; gtk_drag_dest_set (GTK_WIDGET (entry), @@ -1179,13 +1202,23 @@ get_widget_window_size (GtkEntry *entry, *x = widget->allocation.x; if (y) - *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2; + { + if (entry->is_cell_renderer) + *y = widget->allocation.y; + else + *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2; + } if (width) *width = widget->allocation.width; if (height) - *height = requisition.height; + { + if (entry->is_cell_renderer) + *height = widget->allocation.height; + else + *height = requisition.height; + } } static void @@ -1777,6 +1810,43 @@ gtk_entry_style_set (GtkWidget *widget, } } +/* GtkCellEditable method implementations + */ +static void +gtk_cell_editable_entry_activated (GtkEntry *entry, gpointer data) +{ + gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry)); + gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry)); +} + +static gboolean +gtk_cell_editable_key_press_event (GtkEntry *entry, + GdkEventKey *key_event, + gpointer data) +{ + if (key_event->keyval == GDK_Escape) + { + gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry)); + gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry)); + + return TRUE; + } + + return FALSE; +} + +static void +gtk_entry_start_editing (GtkCellEditable *cell_editable, + GdkEvent *event) +{ + GTK_ENTRY (cell_editable)->is_cell_renderer = TRUE; + + g_signal_connect (G_OBJECT (cell_editable), "activate", + G_CALLBACK (gtk_cell_editable_entry_activated), NULL); + g_signal_connect (G_OBJECT (cell_editable), "key_press_event", + G_CALLBACK (gtk_cell_editable_key_press_event), NULL); +} + /* Default signal handlers */ static void diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h index 5ec2049e49..90b7bf5b5a 100644 --- a/gtk/gtkentry.h +++ b/gtk/gtkentry.h @@ -84,7 +84,9 @@ struct _GtkEntry guint cursor_visible : 1; guint in_click : 1; /* Flag so we don't select all when clicking in entry to focus in */ - + + guint is_cell_renderer : 1; + guint button; guint blink_timeout; guint recompute_idle; diff --git a/gtk/gtkmarshal.list b/gtk/gtkmarshal.list index 186140fbaa..23a66260e6 100644 --- a/gtk/gtkmarshal.list +++ b/gtk/gtkmarshal.list @@ -77,6 +77,7 @@ VOID:POINTER,INT VOID:POINTER,POINTER,POINTER VOID:POINTER,UINT VOID:STRING +VOID:STRING,STRING VOID:STRING,INT,POINTER VOID:UINT,BOXED,UINT,FLAGS,FLAGS VOID:UINT,OBJECT,UINT,FLAGS,FLAGS diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list index 186140fbaa..23a66260e6 100644 --- a/gtk/gtkmarshalers.list +++ b/gtk/gtkmarshalers.list @@ -77,6 +77,7 @@ VOID:POINTER,INT VOID:POINTER,POINTER,POINTER VOID:POINTER,UINT VOID:STRING +VOID:STRING,STRING VOID:STRING,INT,POINTER VOID:UINT,BOXED,UINT,FLAGS,FLAGS VOID:UINT,OBJECT,UINT,FLAGS,FLAGS diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index 5a91aab433..d3a7fc7c2e 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -3018,19 +3018,12 @@ gtk_default_draw_check (GtkStyle *style, x, y, width, height); + x -= (1 + INDICATOR_PART_SIZE - width) / 2; + y -= (((1 + INDICATOR_PART_SIZE - height) / 2) - 1); if (shadow_type == GTK_SHADOW_IN) { - gdk_draw_line (window, - widget->style->fg_gc[state_type], - x, y, - x + width, - y + height); - gdk_draw_line (window, - widget->style->fg_gc[state_type], - x + width, - y, - x, - y + height); + draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT); + draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA); } } else diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index 33235b5feb..5ffedf56e2 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -109,7 +109,6 @@ struct _GtkTreeViewPrivate /* Focus code */ GtkTreeViewColumn *focus_column; - GtkTreeViewColumn *scroll_column; /* Selection stuff */ GtkTreeRowReference *anchor; diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 9b6366e3c8..c0a180d6af 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -106,6 +106,7 @@ enum TOGGLE_CURSOR_ROW, EXPAND_COLLAPSE_CURSOR_ROW, SELECT_CURSOR_PARENT, + START_INTERACTIVE_SEARCH, LAST_SIGNAL }; @@ -313,6 +314,8 @@ static void gtk_tree_view_check_dirty_and_clean (GtkTreeView static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view, GtkRBTree *tree, GtkRBNode *node); +static void gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view, + GtkTreeViewColumn *column); static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, GdkEventMotion *event); static void _gtk_tree_view_update_col_width (GtkTreeView *tree_view); @@ -337,8 +340,6 @@ static gboolean gtk_tree_view_real_expand_row (GtkTreeView static void gtk_tree_view_real_set_cursor (GtkTreeView *tree_view, GtkTreePath *path, gboolean clear_and_select); -static void gtk_tree_view_ensure_focus_column (GtkTreeView *tree_view); - /* interactive search */ static void gtk_tree_view_search_dialog_destroy (GtkWidget *search_dialog, @@ -370,25 +371,27 @@ static gboolean gtk_tree_view_search_iter (GtkTreeModel *model gint n); static void gtk_tree_view_search_init (GtkWidget *entry, GtkTreeView *tree_view); -static void gtk_tree_view_interactive_search (GtkTreeView *tree_view, - GdkEventKey *key); static void gtk_tree_view_put (GtkTreeView *tree_view, GtkWidget *child_widget, gint x, gint y, gint width, gint height); -static void gtk_tree_view_start_editing (GtkTreeView *tree_view, - GtkTreeViewColumn *column, - GtkCellEditable *cell_editable, - GdkRectangle *cell_area, - GdkEvent *event, - guint flags); -static void gtk_tree_view_stop_editing (GtkTreeView *tree_view); +static gboolean gtk_tree_view_start_editing (GtkTreeView *tree_view, + GtkTreePath *cursor_path); +static void gtk_tree_view_real_start_editing (GtkTreeView *tree_view, + GtkTreeViewColumn *column, + GtkTreePath *path, + GtkCellEditable *cell_editable, + GdkRectangle *cell_area, + GdkEvent *event, + guint flags); +static void gtk_tree_view_stop_editing (GtkTreeView *tree_view); +static void gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view); static GtkContainerClass *parent_class = NULL; -static guint tree_view_signals[LAST_SIGNAL] = { 0 }; +static guint tree_view_signals [LAST_SIGNAL] = { 0 }; @@ -482,6 +485,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) class->toggle_cursor_row = gtk_tree_view_real_toggle_cursor_row; class->expand_collapse_cursor_row = gtk_tree_view_real_expand_collapse_cursor_row; class->select_cursor_parent = gtk_tree_view_real_select_cursor_parent; + class->start_interactive_search = gtk_tree_view_real_start_interactive_search; /* Properties */ @@ -556,7 +560,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) _("View allows user to search through columns interactively"), TRUE, G_PARAM_READWRITE)); - + g_object_class_install_property (o_class, PROP_SEARCH_COLUMN, g_param_spec_int ("search_column", @@ -566,40 +570,46 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) G_MAXINT, 0, G_PARAM_READWRITE)); - + /* Style properties */ - /* the width of the column resize windows */ #define _TREE_VIEW_EXPANDER_SIZE 10 #define _TREE_VIEW_VERTICAL_SEPARATOR 2 -#define _TREE_VIEW_HORIZONTAL_SEPARATOR 0 +#define _TREE_VIEW_HORIZONTAL_SEPARATOR 2 gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("expander_size", _("Expander Size"), - _("Size of the expander arrow"), + _("Size of the expander arrow."), 0, G_MAXINT, _TREE_VIEW_EXPANDER_SIZE, G_PARAM_READABLE)); - + gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("vertical_separator", _("Vertical Separator Width"), - _("Vertical space between cells"), + _("Vertical space between cells. Must be an even number."), 0, G_MAXINT, _TREE_VIEW_VERTICAL_SEPARATOR, G_PARAM_READABLE)); - + gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("horizontal_separator", _("Horizontal Separator Width"), - _("Horizontal space between cells"), + _("Horizontal space between cells. Must be an even number."), 0, G_MAXINT, _TREE_VIEW_HORIZONTAL_SEPARATOR, G_PARAM_READABLE)); + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("allow_rules", + _("Allow Rules"), + _("Allow drawing of alternating color rows."), + TRUE, + G_PARAM_READABLE)); + /* Signals */ widget_class->set_scroll_adjustments_signal = gtk_signal_new ("set_scroll_adjustments", @@ -718,6 +728,15 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); + tree_view_signals[START_INTERACTIVE_SEARCH] = + g_signal_new ("start_interactive_search", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | GTK_RUN_ACTION, + G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search), + NULL, NULL, + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + /* Key bindings */ gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0, GTK_MOVEMENT_DISPLAY_LINES, -1); @@ -815,6 +834,9 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0); + gtk_binding_entry_add_signal (binding_set, GDK_s, GDK_CONTROL_MASK, "start_interactive_search", 0); + + gtk_binding_entry_add_signal (binding_set, GDK_S, GDK_CONTROL_MASK, "start_interactive_search", 0); } static void @@ -829,7 +851,7 @@ gtk_tree_view_init (GtkTreeView *tree_view) /* We need some padding */ tree_view->priv->tab_offset += EXPANDER_EXTRA_PADDING; - + tree_view->priv->n_columns = 0; tree_view->priv->header_height = 1; tree_view->priv->x_drag = 0; @@ -967,7 +989,9 @@ gtk_tree_view_destroy (GtkObject *object) GtkWidget *search_dialog; GList *list; - if (tree_view->priv->columns != NULL) + gtk_tree_view_stop_editing (tree_view); + + if (tree_view->priv->columns != NULL) { list = tree_view->priv->columns; while (list) @@ -1014,7 +1038,7 @@ gtk_tree_view_destroy (GtkObject *object) tree_view->priv->drag_dest_row = NULL; } - + if (tree_view->priv->column_drop_func_data && tree_view->priv->column_drop_func_data_destroy) { @@ -1236,6 +1260,9 @@ gtk_tree_view_realize (GtkWidget *widget) } tree_view->priv->scroll_to_column = NULL; } + + if (GTK_WIDGET_CLASS (parent_class)->map) + (* GTK_WIDGET_CLASS (parent_class)->map) (widget); } static void @@ -1265,7 +1292,7 @@ gtk_tree_view_unrealize (GtkWidget *widget) gtk_timeout_remove (tree_view->priv->expand_collapse_timeout); tree_view->priv->expand_collapse_timeout = 0; } - + for (list = tree_view->priv->columns; list; list = list->next) _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data)); @@ -1425,12 +1452,11 @@ gtk_tree_view_size_allocate (GtkWidget *widget, GtkTreeViewChild *child = tmp_list->data; tmp_list = tmp_list->next; - /* totally ignore our childs allocation <-: */ + /* totally ignore our childs requisition */ allocation.x = child->x; allocation.y = child->y; allocation.width = child->width; allocation.height = child->height; - gtk_widget_size_allocate (child->widget, &allocation); } @@ -1487,12 +1513,17 @@ gtk_tree_view_button_press (GtkWidget *widget, GdkRectangle background_area; GdkRectangle cell_area; gint vertical_separator; + gint horizontal_separator; g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); tree_view = GTK_TREE_VIEW (widget); - gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL); + gtk_tree_view_stop_editing (tree_view); + gtk_widget_style_get (widget, + "vertical_separator", &vertical_separator, + "horizontal_separator", &horizontal_separator, + NULL); if (event->window == tree_view->priv->bin_window) { @@ -1528,7 +1559,7 @@ gtk_tree_view_button_press (GtkWidget *widget, } /* find the node that was clicked */ - new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y; + new_y = ((gint) event->y < TREE_VIEW_HEADER_HEIGHT (tree_view)) ? TREE_VIEW_HEADER_HEIGHT (tree_view) : (gint)event->y; y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y), &tree, @@ -1541,8 +1572,8 @@ gtk_tree_view_button_press (GtkWidget *widget, /* Get the path and the node */ path = _gtk_tree_view_find_path (tree_view, tree, node); depth = gtk_tree_path_get_depth (path); - background_area.y = y_offset + event->y + vertical_separator; - background_area.height = GTK_RBNODE_GET_HEIGHT (node) - vertical_separator; + background_area.y = y_offset + event->y; + background_area.height = GTK_RBNODE_GET_HEIGHT (node); background_area.x = 0; /* Let the column have a chance at selecting it. */ @@ -1551,7 +1582,7 @@ gtk_tree_view_button_press (GtkWidget *widget, GtkTreeIter iter; GtkCellEditable *cell_editable = NULL; /* FIXME: get the right flags */ - guint flags = 0; + guint flags = 0; column = list->data; @@ -1559,18 +1590,6 @@ gtk_tree_view_button_press (GtkWidget *widget, continue; background_area.width = column->width; - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS(tree_view)) - { - cell_area = background_area; - cell_area.x += depth*tree_view->priv->tab_offset; - cell_area.width -= depth*tree_view->priv->tab_offset; - } - else - { - cell_area = background_area; - } - if ((background_area.x > (gint) event->x) || (background_area.y > (gint) event->y) || (background_area.x + background_area.width <= (gint) event->x) || @@ -1580,6 +1599,18 @@ gtk_tree_view_button_press (GtkWidget *widget, continue; } + cell_area = background_area; + cell_area.width -= horizontal_separator; + 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)) + { + cell_area.x += depth*tree_view->priv->tab_offset; + cell_area.width -= depth*tree_view->priv->tab_offset; + } + gtk_tree_model_get_iter (tree_view->priv->model, &iter, path); gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, @@ -1598,13 +1629,14 @@ gtk_tree_view_button_press (GtkWidget *widget, { if (cell_editable != NULL) { - gtk_tree_view_stop_editing (tree_view); - gtk_tree_view_start_editing (tree_view, - column, - cell_editable, - &cell_area, - (GdkEvent *)event, - flags); + gtk_tree_view_real_start_editing (tree_view, + column, + path, + cell_editable, + &cell_area, + (GdkEvent *)event, + flags); + } g_free (path_string); gtk_tree_path_free (path); @@ -1921,28 +1953,6 @@ ensure_unprelighted (GtkTreeView *tree_view) g_assert (tree_view->priv->prelight_node == NULL); } -static void -gtk_tree_view_ensure_focus_column (GtkTreeView *tree_view) -{ - GList *list; - if (tree_view->priv->focus_column != NULL && - tree_view->priv->focus_column->visible) - return; - - if (tree_view->priv->focus_column) - gtk_tree_view_column_cell_focus (tree_view->priv->focus_column, 0, TRUE); - - for (list = tree_view->priv->columns; list; list = list->next) - { - GtkTreeViewColumn *column = list->data; - - if (column->visible) - { - gtk_tree_view_column_cell_focus (column, 1, FALSE); - return; - } - } -} @@ -2057,7 +2067,7 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view) NULL); width = expander_size; - + /* Get x, y, width, height of arrow */ if (reorder->left_column) { @@ -2132,7 +2142,7 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view) NULL); width = expander_size; - + /* Get x, y, width, height of arrow */ width = width/2; /* remember, the arrow only takes half the available width */ gdk_window_get_origin (widget->window, &x, &y); @@ -2431,17 +2441,23 @@ gtk_tree_view_bin_expose (GtkWidget *widget, GtkTreePath *drag_dest_path; GList *last_column; gint vertical_separator; + gint horizontal_separator; + gboolean allow_rules; g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE); tree_view = GTK_TREE_VIEW (widget); - gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL); + gtk_widget_style_get (widget, + "horizontal_separator", &horizontal_separator, + "vertical_separator", &vertical_separator, + "allow_rules", &allow_rules, + NULL); if (tree_view->priv->tree == NULL) return TRUE; gtk_tree_view_check_dirty_and_clean (GTK_TREE_VIEW (widget)); - gtk_tree_view_ensure_focus_column (GTK_TREE_VIEW (widget)); + /* we want to account for a potential HEADER offset. That is, if the header * exists, we want to offset our event by its height to find the right node. */ @@ -2516,7 +2532,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget, flags |= GTK_CELL_RENDERER_SELECTED; parity = _gtk_rbtree_node_find_parity (tree, node); - + for (list = tree_view->priv->columns; list; list = list->next) { GtkTreeViewColumn *column = list->data; @@ -2550,17 +2566,15 @@ gtk_tree_view_bin_expose (GtkWidget *widget, cell_area = background_area; cell_area.y += vertical_separator / 2; + cell_area.x += horizontal_separator / 2; cell_area.height -= vertical_separator; + cell_area.width -= horizontal_separator; /* Select the detail for drawing the cell. relevant * factors are parity, sortedness, and whether to * display rules. */ - - /* FIXME when we have style properties, clean this up. - */ - - if (tree_view->priv->has_rules) + if (allow_rules && tree_view->priv->has_rules) { if (flags & GTK_CELL_RENDERER_SORTED) { @@ -2653,8 +2667,9 @@ gtk_tree_view_bin_expose (GtkWidget *widget, flags); } if (node == cursor && - GTK_WIDGET_HAS_FOCUS (widget) && - column == tree_view->priv->focus_column) + ((column == tree_view->priv->focus_column && + GTK_WIDGET_HAS_FOCUS (widget)) || + (column == tree_view->priv->edited_column))) { gtk_tree_view_column_cell_draw_focus (column, event->window, @@ -2806,7 +2821,6 @@ gtk_tree_view_key_press (GtkWidget *widget, GdkEventKey *event) { GtkTreeView *tree_view = (GtkTreeView *) widget; - gint retval; if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG)) { @@ -2818,12 +2832,7 @@ gtk_tree_view_key_press (GtkWidget *widget, return TRUE; } - retval = (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event); - - if (! retval) - gtk_tree_view_interactive_search (tree_view, event); - - return retval; + return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event); } /* FIXME Is this function necessary? Can I get an enter_notify event @@ -2892,7 +2901,7 @@ gtk_tree_view_leave_notify (GtkWidget *widget, NULL); ensure_unprelighted (tree_view); - + return TRUE; } @@ -2932,8 +2941,7 @@ gtk_tree_view_focus_out (GtkWidget *widget, /* destroy interactive search dialog */ search_dialog = gtk_object_get_data (GTK_OBJECT (widget), "search-dialog"); if (search_dialog) - gtk_tree_view_search_dialog_destroy (search_dialog, - GTK_TREE_VIEW (widget)); + gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget)); return FALSE; } @@ -3178,7 +3186,7 @@ open_row_timeout (gpointer data) gboolean result = FALSE; GDK_THREADS_ENTER (); - + gtk_tree_view_get_drag_dest_row (tree_view, &dest_path, &pos); @@ -3196,10 +3204,10 @@ open_row_timeout (gpointer data) { if (dest_path) gtk_tree_path_free (dest_path); - + result = TRUE; } - + GDK_THREADS_LEAVE (); return result; @@ -4017,16 +4025,6 @@ gtk_tree_view_header_focus (GtkTreeView *tree_view, return (focus_child != NULL); } -/* We make the assumption that if container->focus_child != NULL, the focus must - * be in the header. For now, this is accurate. It may not be in the future. - */ - -/* The sordid relationship between focus_column and scroll_column: - * - * The focus_column represents the column that currently has keyboard focus, and - * is used when navigating columns by keyboard. scroll_column is used for - * handling scrolling by keyboard, such that in cases. - */ static gint gtk_tree_view_focus (GtkWidget *widget, GtkDirectionType direction) @@ -4046,6 +4044,7 @@ gtk_tree_view_focus (GtkWidget *widget, focus_child = container->focus_child; + gtk_tree_view_stop_editing (GTK_TREE_VIEW (widget)); /* Case 1. Headers currently have focus. */ if (focus_child) { @@ -4194,7 +4193,7 @@ gtk_tree_view_real_move_cursor (GtkTreeView *tree_view, if (tree_view->priv->tree == NULL) return; - + gtk_tree_view_stop_editing (tree_view); GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS); gtk_widget_grab_focus (GTK_WIDGET (tree_view)); @@ -4219,10 +4218,10 @@ gtk_tree_view_real_move_cursor (GtkTreeView *tree_view, } } -static void -gtk_tree_view_put (GtkTreeView *tree_view, - GtkWidget *child_widget, - gint x, +static void +gtk_tree_view_put (GtkTreeView *tree_view, + GtkWidget *child_widget, + gint x, gint y, gint width, gint height) @@ -4231,7 +4230,7 @@ gtk_tree_view_put (GtkTreeView *tree_view, g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); g_return_if_fail (GTK_IS_WIDGET (child_widget)); - + child = g_new (GtkTreeViewChild, 1); child->widget = child_widget; @@ -4241,7 +4240,7 @@ gtk_tree_view_put (GtkTreeView *tree_view, child->height = height; tree_view->priv->children = g_list_append (tree_view->priv->children, child); - + if (GTK_WIDGET_REALIZED (tree_view)) gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window); @@ -4334,6 +4333,7 @@ gtk_tree_view_row_changed (GtkTreeModel *model, { _gtk_rbtree_node_set_height (tree, node, height + vertical_separator); gtk_widget_queue_resize (GTK_WIDGET (data)); + _gtk_tree_view_update_size (tree_view); goto done; } if (dirty_marked) @@ -4542,14 +4542,14 @@ gtk_tree_view_row_deleted (GtkTreeModel *model, g_return_if_fail (path != NULL); + gtk_tree_row_reference_deleted (G_OBJECT (data), path); + if (_gtk_tree_view_find_node (tree_view, path, &tree, &node)) return; if (tree == NULL) return; - gtk_tree_row_reference_deleted (G_OBJECT (data), path); - /* Change the selection */ selection_changed = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED); @@ -4572,7 +4572,7 @@ gtk_tree_view_row_deleted (GtkTreeModel *model, GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED); tree_view->priv->expanded_collapsed_node = NULL; } - + if (tree_view->priv->destroy_count_func) { gint child_count = 0; @@ -4801,9 +4801,9 @@ gtk_tree_view_insert_iter_height (GtkTreeView *tree_view, GList *list; gint max_height = 0; gint vertical_separator; - + gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL); - + /* do stuff with node */ for (list = tree_view->priv->columns; list; list = list->next) { @@ -4890,10 +4890,13 @@ gtk_tree_view_calc_size (GtkTreeView *tree_view, GtkTreeViewColumn *column; gint max_height; gint vertical_separator; - + gint horizontal_separator; TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL); - gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL); + gtk_widget_style_get (GTK_WIDGET (tree_view), + "vertical_separator", &vertical_separator, + "horizontal_separator", &horizontal_separator, + NULL); temp = tree->root; while (temp->left != tree->nil) @@ -4928,9 +4931,9 @@ gtk_tree_view_calc_size (GtkTreeView *tree_view, if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view)) _gtk_tree_view_column_set_width (column, - MAX (column->width, depth * tree_view->priv->tab_offset + width)); + MAX (column->width, depth * tree_view->priv->tab_offset + width + horizontal_separator)); else - _gtk_tree_view_column_set_width (column, MAX (column->width, width)); + _gtk_tree_view_column_set_width (column, MAX (column->width, width + horizontal_separator)); } _gtk_rbtree_node_set_height (tree, temp, max_height); @@ -4954,7 +4957,12 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view, GList *list; gboolean retval = FALSE; gint tmpheight; - + gint horizontal_separator; + + gtk_widget_style_get (GTK_WIDGET (tree_view), + "horizontal_separator", &horizontal_separator, + NULL); + if (height) *height = 0; @@ -4966,12 +4974,11 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view, continue; if (!column->visible) continue; - + gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter, GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT), node->children?TRUE:FALSE); - if (height) { gtk_tree_view_column_cell_get_size (column, @@ -4989,7 +4996,7 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view, if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view)) { - if (depth * tree_view->priv->tab_offset + width > column->width) + if (depth * tree_view->priv->tab_offset + horizontal_separator + width > column->requested_width) { gtk_tree_view_column_cell_set_dirty (column); retval = TRUE; @@ -4997,7 +5004,7 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view, } else { - if (width > column->width) + if (horizontal_separator + width > column->requested_width) { gtk_tree_view_column_cell_set_dirty (column); retval = TRUE; @@ -5045,7 +5052,7 @@ gtk_tree_view_discover_dirty (GtkTreeView *tree_view, gtk_tree_view_discover_dirty_iter (tree_view, iter, depth, - FALSE, + NULL, temp); if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) && temp->children != NULL) @@ -5059,8 +5066,8 @@ gtk_tree_view_discover_dirty (GtkTreeView *tree_view, /** * gtk_tree_view_check_dirty_and_clean: * @tree_view: A #GtkTreeView - * - * Does all the actual sizing for + * + * Does all the actual sizing for **/ static void gtk_tree_view_check_dirty_and_clean (GtkTreeView *tree_view) @@ -5141,10 +5148,24 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view, } -/* This function could be more efficient. - * I'll optimize it if profiling seems to imply that - * it's important - */ +static void +gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view, + GtkTreeViewColumn *column) +{ + if (column == NULL) + return; + if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) < + (column->button->allocation.x + column->button->allocation.width)) + gtk_adjustment_set_value (tree_view->priv->hadjustment, + column->button->allocation.x + column->button->allocation.width - + tree_view->priv->hadjustment->page_size); + else if (tree_view->priv->hadjustment->value > column->button->allocation.x) + gtk_adjustment_set_value (tree_view->priv->hadjustment, + column->button->allocation.x); +} + +/* This function could be more efficient. I'll optimize it if profiling seems + * to imply that it is important */ GtkTreePath * _gtk_tree_view_find_path (GtkTreeView *tree_view, GtkRBTree *tree, @@ -5563,9 +5584,9 @@ gtk_tree_view_queue_draw_arrow (GtkTreeView *tree_view, if (clip_rect) { GdkRectangle new_rect; - + gdk_rectangle_intersect (clip_rect, &rect, &new_rect); - + gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE); } else @@ -5635,7 +5656,7 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view, gint vertical_separator; gint expander_size; GtkExpanderStyle expander_style; - + gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, "expander_size", &expander_size, @@ -5749,6 +5770,18 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view) gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE); } gtk_tree_path_free (cursor_path); + if (tree_view->priv->focus_column == NULL) + { + GList *list; + for (list = tree_view->priv->columns; list; list = list->next) + { + if (GTK_TREE_VIEW_COLUMN (list->data)->visible) + { + tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data); + break; + } + } + } } static void @@ -5829,9 +5862,7 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view, _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node); cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); g_return_if_fail (cursor_path != NULL); - gtk_tree_view_real_set_cursor (tree_view, - cursor_path, - TRUE); + gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE); } static void @@ -5870,19 +5901,19 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view, break; } } - + while (list) { column = list->data; if (column->visible == FALSE) goto loop_end; - gtk_tree_view_column_cell_set_cell_data (column, - tree_view->priv->model, - &iter, - GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT), - cursor_node->children?TRUE:FALSE); - if (gtk_tree_view_column_cell_focus (column, count, FALSE)) + gtk_tree_view_column_cell_set_cell_data (column, + tree_view->priv->model, + &iter, + GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT), + cursor_node->children?TRUE:FALSE); + if (gtk_tree_view_column_cell_focus (column, count)) { tree_view->priv->focus_column = column; found_column = TRUE; @@ -5901,9 +5932,8 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view, cursor_tree, cursor_node, NULL); - return; } - g_print ("scroll now!\n"); + gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column); } static void @@ -5959,8 +5989,8 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view) GtkRBNode *cursor_node = NULL; GtkTreePath *cursor_path = NULL; GdkModifierType state = 0; - cursor_path = NULL; + if (tree_view->priv->cursor) cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); @@ -5969,12 +5999,22 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view) _gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node); + if (cursor_tree == NULL) { gtk_tree_path_free (cursor_path); return; } + if (tree_view->priv->focus_column) + { + if (gtk_tree_view_start_editing (tree_view, cursor_path)) + { + gtk_tree_path_free (cursor_path); + return; + } + } + gtk_get_current_event_state (&state); _gtk_tree_selection_internal_select_node (tree_view->priv->selection, cursor_node, @@ -5985,7 +6025,9 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view) gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node); gtk_widget_grab_focus (GTK_WIDGET (tree_view)); - gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL); + gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL); + gtk_tree_view_row_activated (tree_view, cursor_path, tree_view->priv->focus_column); + gtk_tree_path_free (cursor_path); } @@ -6096,6 +6138,58 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view) gtk_tree_path_free (cursor_path); } +static void +gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view) +{ + GtkWidget *window; + GtkWidget *entry; + + if (tree_view->priv->enable_search == FALSE || + tree_view->priv->search_column < 0) + return; + + /* set up window */ + window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_title (GTK_WINDOW (window), "search dialog"); + gtk_container_set_border_width (GTK_CONTAINER (window), 3); + gtk_window_set_modal (GTK_WINDOW (window), TRUE); + gtk_signal_connect + (GTK_OBJECT (window), "delete_event", + GTK_SIGNAL_FUNC (gtk_tree_view_search_delete_event), + tree_view); + gtk_signal_connect + (GTK_OBJECT (window), "key_press_event", + GTK_SIGNAL_FUNC (gtk_tree_view_search_key_press_event), + tree_view); + gtk_signal_connect + (GTK_OBJECT (window), "button_press_event", + GTK_SIGNAL_FUNC (gtk_tree_view_search_button_press_event), + tree_view); + + /* add entry */ + entry = gtk_entry_new (); + gtk_widget_show (entry); + gtk_signal_connect + (GTK_OBJECT (entry), "changed", + GTK_SIGNAL_FUNC (gtk_tree_view_search_init), + tree_view); + gtk_container_add (GTK_CONTAINER (window), entry); + + /* done, show it */ + tree_view->priv->search_dialog_position_func (tree_view, window); + gtk_widget_show_all (window); + gtk_widget_grab_focus (entry); + + /* position window */ + + gtk_object_set_data (GTK_OBJECT (window), "text", + gtk_entry_get_text (GTK_ENTRY (entry))); + gtk_object_set_data (GTK_OBJECT (tree_view), "search-dialog", window); + + /* search first matching iter */ + gtk_tree_view_search_init (entry, tree_view); +} + void _gtk_tree_view_update_size (GtkTreeView *tree_view) { @@ -6982,7 +7076,7 @@ gtk_tree_view_move_column_after (GtkTreeView *tree_view, * gtk_tree_view_set_expander_column: * @tree_view: A #GtkTreeView * @column: NULL, or the column to draw the expander arrow at. - * + * * Sets the column to draw the expander arrow at. It must be in @tree_view. If * @column is %NULL, then the expander arrow is fixed at the first column. **/ @@ -7204,8 +7298,6 @@ gtk_tree_view_row_activated (GtkTreeView *tree_view, { g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - /* FIXME: Actually activate the path internally, not just emit the signal */ - /* g_warning ("FIXME: Actually activate the path internally, not just emit the signal\n"); */ g_signal_emit (G_OBJECT(tree_view), tree_view_signals[ROW_ACTIVATED], 0, path, column); } @@ -7277,13 +7369,13 @@ expand_collapse_timeout (gpointer data) gboolean redraw; GDK_THREADS_ENTER (); - + redraw = FALSE; expanding = TRUE; node = tree_view->priv->expanded_collapsed_node; tree = tree_view->priv->expanded_collapsed_tree; - + if (node->children == NULL) expanding = FALSE; @@ -7295,7 +7387,7 @@ expand_collapse_timeout (gpointer data) GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED); redraw = TRUE; - + } else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SEMI_EXPANDED)) { @@ -7417,7 +7509,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view, if (tree_view->priv->expand_collapse_timeout) gtk_timeout_remove (tree_view->priv->expand_collapse_timeout); - + if (tree_view->priv->expanded_collapsed_node != NULL) { GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED); @@ -7427,7 +7519,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view, tree_view->priv->expand_collapse_timeout = gtk_timeout_add (50, expand_collapse_timeout, tree_view); tree_view->priv->expanded_collapsed_node = node; tree_view->priv->expanded_collapsed_tree = tree; - + GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED); if (GTK_WIDGET_MAPPED (tree_view)) @@ -7497,7 +7589,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view, /* if the prelighted node is a child of us, we want to unprelight it. We have * a chance to prelight the correct node below */ - + if (tree_view->priv->prelight_tree) { GtkRBTree *parent_tree; @@ -7528,7 +7620,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view, if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE) gtk_tree_view_column_cell_set_dirty (column); } - + if (tree_view->priv->destroy_count_func) { GtkTreePath *child_path; @@ -7559,7 +7651,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view, tree_view->priv->expanded_collapsed_tree = tree; GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED); - + if (GTK_WIDGET_MAPPED (tree_view)) { gtk_widget_queue_draw (GTK_WIDGET (tree_view)); @@ -7713,9 +7805,9 @@ gtk_tree_view_map_expanded_rows (GtkTreeView *tree_view, * gtk_tree_view_row_expanded: * @tree_view: A #GtkTreeView. * @path: A #GtkTreePath to test expansion state. - * + * * Returns TRUE if the node pointed to by @path is expanded in @tree_view. - * + * * Return value: TRUE if #path is expanded. **/ gboolean @@ -7837,21 +7929,45 @@ gtk_tree_view_real_set_cursor (GtkTreeView *tree_view, * gtk_tree_view_set_cursor: * @tree_view: A #GtkTreeView * @path: A #GtkTreePath + * @focus_column: A #GtkTreeViewColumn, or NULL + * @start_editing: %TRUE if the specified cell should start being edited. * * Sets the current keyboard focus to be at @path, and selects it. This is * useful when you want to focus the user's attention on a particular row. If - * you want to give the user keyboard focus in the tree_view, you should use - * this function to set the correct path, and gtk_widget_grab_focus (GTK_WIDGET - * (tree_view)) to actually give focus to the @tree_view. + * @column is not %NULL, then focus is given to the column specified by it. + * Additionally, if @column is specified, and @start_editing is %TRUE, then + * editing should be started in the specified cell. Keyboard focus is given to + * the widget after this is called. **/ void -gtk_tree_view_set_cursor (GtkTreeView *tree_view, - GtkTreePath *path) +gtk_tree_view_set_cursor (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *focus_column, + gboolean start_editing) { g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); g_return_if_fail (path != NULL); + if (focus_column) + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column)); gtk_tree_view_real_set_cursor (tree_view, path, TRUE); + + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); + if (focus_column && focus_column->visible) + { + GList *list; + gboolean column_in_tree = FALSE; + + for (list = tree_view->priv->columns; list; list = list->next) + if (list->data == focus_column) + { + column_in_tree = TRUE; + break; + } + g_return_if_fail (column_in_tree); + if (start_editing) + gtk_tree_view_start_editing (tree_view, path); + } } @@ -7990,12 +8106,13 @@ gtk_tree_view_get_path_at_pos (GtkTreeView *tree_view, * * Fills the bounding rectangle in tree window coordinates for the cell at the * row specified by @path and the column specified by @column. If @path is - * %NULL, the y and height fields of the rectangle will be filled with 0. If - * @column is %NULL, the x and width fields will be filled with 0. The sum of - * all cell rects does not cover the entire tree; there are extra pixels in - * between rows, for example. The returned rectangle is equivalent to the - * @cell_area passed to gtk_cell_renderer_render(). This function is only valid - * if #tree_view is realized. + * %NULL, or points to a path not currently displayed, the y and height fields + * of the rectangle will be filled with 0. If @column is %NULL, the x and width + * fields will be filled with 0. The sum of all cell rects does not cover the + * entire tree; there are extra pixels in between rows, for example. The + * returned rectangle is equivalent to the @cell_area passed to + * gtk_cell_renderer_render(). This function is only valid if #tree_view is + * realized. **/ void gtk_tree_view_get_cell_area (GtkTreeView *tree_view, @@ -8006,6 +8123,7 @@ gtk_tree_view_get_cell_area (GtkTreeView *tree_view, GtkRBTree *tree = NULL; GtkRBNode *node = NULL; gint vertical_separator; + gint horizontal_separator; g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column)); @@ -8013,37 +8131,40 @@ gtk_tree_view_get_cell_area (GtkTreeView *tree_view, g_return_if_fail (!column || column->tree_view == (GtkWidget *) tree_view); g_return_if_fail (GTK_WIDGET_REALIZED (tree_view)); - gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL); + gtk_widget_style_get (GTK_WIDGET (tree_view), + "vertical_separator", &vertical_separator, + "horizontal_separator", &horizontal_separator, + NULL); rect->x = 0; rect->y = 0; rect->width = 0; rect->height = 0; + if (column) + { + rect->x = column->button->allocation.x + horizontal_separator/2; + rect->width = column->button->allocation.width - horizontal_separator; + } + if (path) { /* Get vertical coords */ + if (_gtk_tree_view_find_node (tree_view, path, &tree, &node) && + tree != NULL) + return; - _gtk_tree_view_find_node (tree_view, path, &tree, &node); - - if (tree == NULL) - { - g_warning (G_STRLOC": no row corresponding to path"); - return; - } - - /* Remember that the rbtree stores node height including the vertical - * separator, see comment at top of file. - */ rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator); - rect->height = CELL_HEIGHT (node, vertical_separator); - } - if (column) - { - rect->x = column->button->allocation.x; - rect->width = column->button->allocation.width; + if (gtk_tree_view_is_expander_column (tree_view, column) && + TREE_VIEW_DRAW_EXPANDERS (tree_view)) + { + gint depth = gtk_tree_path_get_depth (path) - 1; + rect->x += depth * tree_view->priv->tab_offset; + rect->width -= depth * tree_view->priv->tab_offset; + rect->width = MAX (rect->width, 0); + } } } @@ -8054,17 +8175,16 @@ gtk_tree_view_get_cell_area (GtkTreeView *tree_view, * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes * @rect: rectangle to fill with cell background rect * - * Fills the bounding rectangle in tree window coordinates for the - * cell at the row specified by @path and the column specified by - * @column. If @path is %NULL, the y and height fields of the - * rectangle will be filled with 0. If @column is %NULL, the x and - * width fields will be filled with 0. The returned rectangle is - * equivalent to the @background_area passed to - * gtk_cell_renderer_render(). These background areas tile to cover - * the entire tree window (except for the area used for header - * buttons). Contrast with the cell_area, returned by - * gtk_tree_view_get_cell_area(), which returns only the cell itself, - * excluding surrounding borders and the tree expander area. + * Fills the bounding rectangle in tree window coordinates for the cell at the + * row specified by @path and the column specified by @column. If @path is + * %NULL, or points to a node not found in the tree, the y and height fields of + * the rectangle will be filled with 0. If @column is %NULL, the x and width + * fields will be filled with 0. The returned rectangle is equivalent to the + * @background_area passed to gtk_cell_renderer_render(). These background + * areas tile to cover the entire tree window (except for the area used for + * header buttons). Contrast with the cell_area, returned by + * gtk_tree_view_get_cell_area(), which returns only the cell itself, excluding + * surrounding borders and the tree expander area. * **/ void @@ -8089,13 +8209,9 @@ gtk_tree_view_get_background_area (GtkTreeView *tree_view, { /* Get vertical coords */ - _gtk_tree_view_find_node (tree_view, path, &tree, &node); - - if (tree == NULL) - { - g_warning (G_STRLOC": no row corresponding to path"); - return; - } + if (_gtk_tree_view_find_node (tree_view, path, &tree, &node) && + tree != NULL) + return; rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node); @@ -8163,14 +8279,9 @@ gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view, g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); if (tx) - { - *tx = wx + tree_view->priv->hadjustment->value; - } - + *tx = wx + tree_view->priv->hadjustment->value; if (ty) - { - *ty = wy + tree_view->priv->vadjustment->value; - } + *ty = wy + tree_view->priv->vadjustment->value; } /** @@ -8195,14 +8306,9 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view, g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); if (wx) - { - *wx = tx - tree_view->priv->hadjustment->value; - } - + *wx = tx - tree_view->priv->hadjustment->value; if (wy) - { - *wy = ty - tree_view->priv->vadjustment->value; - } + *wy = ty - tree_view->priv->vadjustment->value; } @@ -8585,7 +8691,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, * @func: Function to be called when a view row is destroyed, or NULL * @data: User data to be passed to @func, or NULL * @destroy: Destroy notifier for @data, or NULL - * + * * This function should almost never be used. It is meant for private use by * ATK for determining the number of visible children that are removed when the * user collapses a row, or a row is deleted. @@ -8608,7 +8714,7 @@ gtk_tree_view_set_destroy_count_func (GtkTreeView *tree_view, /* - * Interactive search + * Interactive search */ /** @@ -8657,7 +8763,7 @@ gint gtk_tree_view_get_search_column (GtkTreeView *tree_view) { g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0); - + return (tree_view->priv->search_column); } @@ -8680,7 +8786,7 @@ gtk_tree_view_set_search_column (GtkTreeView *tree_view, return; tree_view->priv->search_column = column; - + } /** @@ -8732,7 +8838,7 @@ gtk_tree_view_search_dialog_destroy (GtkWidget *search_dialog, { /* remove data from tree_view */ gtk_object_remove_data (GTK_OBJECT (tree_view), "search-dialog"); - + gtk_widget_destroy (search_dialog); } @@ -8756,84 +8862,6 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view, tree_y + tree_height); } -static void -gtk_tree_view_interactive_search (GtkTreeView *tree_view, - GdkEventKey *event) -{ - GtkWidget *window; - GtkWidget *entry; - - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - switch (event->keyval) - { - case GDK_Shift_L: - case GDK_Shift_R: - case GDK_Control_L: - case GDK_Control_R: - case GDK_Caps_Lock: - case GDK_Shift_Lock: - case GDK_Meta_L: - case GDK_Meta_R: - case GDK_Alt_L: - case GDK_Alt_R: - case GDK_Super_L: - case GDK_Super_R: - case GDK_Hyper_L: - case GDK_Hyper_R: - case GDK_Mode_switch: - return; - default: - break; - } - - if (tree_view->priv->enable_search == FALSE || - tree_view->priv->search_column < 0) - return; - - /* set up window */ - window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_window_set_title (GTK_WINDOW (window), "search dialog"); - gtk_container_set_border_width (GTK_CONTAINER (window), 3); - gtk_window_set_modal (GTK_WINDOW (window), TRUE); - gtk_signal_connect - (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (gtk_tree_view_search_delete_event), - tree_view); - gtk_signal_connect - (GTK_OBJECT (window), "key_press_event", - GTK_SIGNAL_FUNC (gtk_tree_view_search_key_press_event), - tree_view); - gtk_signal_connect - (GTK_OBJECT (window), "button_press_event", - GTK_SIGNAL_FUNC (gtk_tree_view_search_button_press_event), - tree_view); - - /* add entry */ - entry = gtk_entry_new (); - gtk_widget_show (entry); - gtk_signal_connect - (GTK_OBJECT (entry), "changed", - GTK_SIGNAL_FUNC (gtk_tree_view_search_init), - tree_view); - gtk_container_add (GTK_CONTAINER (window), entry); - - /* done, show it */ - tree_view->priv->search_dialog_position_func (tree_view, window); - gtk_widget_show_all (window); - gtk_widget_grab_focus (entry); - - gtk_widget_event (entry, (GdkEvent *) event); - - /* position window */ - - gtk_object_set_data (GTK_OBJECT (window), "text", - gtk_entry_get_text (GTK_ENTRY (entry))); - gtk_object_set_data (GTK_OBJECT (tree_view), "search-dialog", window); - - /* search first matching iter */ - gtk_tree_view_search_init (entry, tree_view); -} - static gboolean gtk_tree_view_search_delete_event (GtkWidget *widget, GdkEventAny *event, @@ -8842,7 +8870,7 @@ gtk_tree_view_search_delete_event (GtkWidget *widget, g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); gtk_tree_view_search_dialog_destroy (widget, tree_view); - + return TRUE; } @@ -8854,7 +8882,7 @@ gtk_tree_view_search_button_press_event (GtkWidget *widget, g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); gtk_tree_view_search_dialog_destroy (widget, tree_view); - + return TRUE; } @@ -8865,10 +8893,11 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget, { g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE); - + /* close window */ - if (event->keyval == GDK_Escape || event->keyval == GDK_Return - || event->keyval == GDK_Tab) + if (event->keyval == GDK_Escape || + event->keyval == GDK_Return || + event->keyval == GDK_Tab) { gtk_tree_view_search_dialog_destroy (widget, tree_view); return TRUE; @@ -8877,20 +8906,17 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget, /* select previous matching iter */ if (event->keyval == GDK_Up) { - gtk_tree_view_search_move (widget, - tree_view, - TRUE); + gtk_tree_view_search_move (widget, tree_view, TRUE); return TRUE; } /* select next matching iter */ if (event->keyval == GDK_Down) { - gtk_tree_view_search_move (widget, - tree_view, - FALSE); + gtk_tree_view_search_move (widget, tree_view, FALSE); return TRUE; } + return FALSE; } @@ -8917,23 +8943,25 @@ gtk_tree_view_search_move (GtkWidget *window, return; len = strlen (text); - + if (len < 1) return; model = gtk_tree_view_get_model (tree_view); selection = gtk_tree_view_get_selection (tree_view); - + /* search */ gtk_tree_selection_unselect_all (selection); gtk_tree_model_get_iter_root (model, &iter); - + ret = gtk_tree_view_search_iter (model, selection, &iter, text, &count, up?((*selected_iter) - 1):((*selected_iter + 1))); - + if (ret) - /* found */ - *selected_iter += up?(-1):(1); + { + /* found */ + *selected_iter += up?(-1):(1); + } else { /* return to old iter */ @@ -8942,7 +8970,6 @@ gtk_tree_view_search_move (GtkWidget *window, gtk_tree_view_search_iter (model, selection, &iter, text, &count, *selected_iter); - } } @@ -8966,12 +8993,12 @@ gtk_tree_view_search_equal_func (GtkTreeModel *model, normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL); case_normalized_string = g_utf8_casefold (normalized_string, -1); case_normalized_key = g_utf8_casefold (normalized_key, -1); - + key_len = strlen (case_normalized_key); if (!strncmp (case_normalized_key, case_normalized_string, key_len)) retval = FALSE; - + g_value_unset (&value); g_free (normalized_key); g_free (normalized_string); @@ -9014,7 +9041,7 @@ gtk_tree_view_search_iter (GtkTreeModel *model, if (path) gtk_tree_path_free (path); - + return TRUE; } } @@ -9029,7 +9056,7 @@ gtk_tree_view_search_iter (GtkTreeModel *model, while (node->left != tree->nil) node = node->left; - + tmp = *iter; has_child = gtk_tree_model_iter_children (model, iter, &tmp); gtk_tree_path_append_index (path, 0); @@ -9044,13 +9071,13 @@ gtk_tree_view_search_iter (GtkTreeModel *model, do { node = _gtk_rbtree_next (tree, node); - + if (node) { gboolean has_next; - + has_next = gtk_tree_model_iter_next (model, iter); - + done = TRUE; gtk_tree_path_next (path); @@ -9090,7 +9117,7 @@ gtk_tree_view_search_iter (GtkTreeModel *model, if (path) gtk_tree_path_free (path); - + return FALSE; } @@ -9107,10 +9134,10 @@ gtk_tree_view_search_init (GtkWidget *entry, GtkTreeIter iter; GtkTreeModel *model; GtkTreeSelection *selection; - + g_return_if_fail (GTK_IS_ENTRY (entry)); g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - + window = gtk_widget_get_parent (entry); text = gtk_entry_get_text (GTK_ENTRY (entry)); len = strlen (text); @@ -9126,14 +9153,14 @@ gtk_tree_view_search_init (GtkWidget *entry, if (len < 1) return; - + gtk_tree_model_get_iter_root (model, &iter); - + ret = gtk_tree_view_search_iter (model, selection, &iter, text, &count, 1); - if (ret) + if (ret) { selected_iter = g_malloc (sizeof (int)); *selected_iter = 1; @@ -9148,20 +9175,85 @@ gtk_tree_view_remove_widget (GtkCellEditable *cell_editable, { g_return_if_fail (tree_view->priv->edited_column != NULL); _gtk_tree_view_column_stop_editing (tree_view->priv->edited_column); + tree_view->priv->edited_column = NULL; + gtk_container_remove (GTK_CONTAINER (tree_view), GTK_WIDGET (cell_editable)); + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); +} + +static gboolean +gtk_tree_view_start_editing (GtkTreeView *tree_view, + GtkTreePath *cursor_path) +{ + GtkTreeIter iter; + GdkRectangle background_area; + GdkRectangle cell_area; + GtkCellEditable *editable_widget = NULL; + gchar *path_string; + guint flags = 0; /* can be 0, as the flags are primarily for rendering */ + gint retval = FALSE; + GtkRBTree *cursor_tree; + GtkRBNode *cursor_node; + + g_assert (tree_view->priv->focus_column); + + if (_gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node) || + cursor_node == NULL) + return FALSE; + + path_string = gtk_tree_path_to_string (cursor_path); + gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path); + gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column, + tree_view->priv->model, + &iter, + GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT), + cursor_node->children?TRUE:FALSE); + gtk_tree_view_get_background_area (tree_view, + cursor_path, + tree_view->priv->focus_column, + &background_area); + gtk_tree_view_get_cell_area (tree_view, + cursor_path, + tree_view->priv->focus_column, + &cell_area); + if (_gtk_tree_view_column_cell_event (tree_view->priv->focus_column, + &editable_widget, + NULL, + path_string, + &background_area, + &cell_area, + flags)) + { + retval = TRUE; + if (editable_widget != NULL) + { + gtk_tree_view_real_start_editing (tree_view, + tree_view->priv->focus_column, + cursor_path, + editable_widget, + &cell_area, + NULL, + flags); + } + + } + g_free (path_string); + return retval; } static void -gtk_tree_view_start_editing (GtkTreeView *tree_view, - GtkTreeViewColumn *column, - GtkCellEditable *cell_editable, - GdkRectangle *cell_area, - GdkEvent *event, - guint flags) +gtk_tree_view_real_start_editing (GtkTreeView *tree_view, + GtkTreeViewColumn *column, + GtkTreePath *path, + GtkCellEditable *cell_editable, + GdkRectangle *cell_area, + GdkEvent *event, + guint flags) { tree_view->priv->edited_column = column; _gtk_tree_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable)); + gtk_tree_view_real_set_cursor (tree_view, path, FALSE); GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS); gtk_tree_view_put (tree_view, GTK_WIDGET (cell_editable), @@ -9177,6 +9269,7 @@ gtk_tree_view_stop_editing (GtkTreeView *tree_view) { if (tree_view->priv->edited_column == NULL) return; + gtk_cell_editable_editing_done (tree_view->priv->edited_column->editable_widget); gtk_cell_editable_remove_widget (tree_view->priv->edited_column->editable_widget); } diff --git a/gtk/gtktreeview.h b/gtk/gtktreeview.h index 2c10f253c9..2ce8aafd83 100644 --- a/gtk/gtktreeview.h +++ b/gtk/gtktreeview.h @@ -96,6 +96,7 @@ struct _GtkTreeViewClass gboolean expand, gboolean open_all); void (* select_cursor_parent) (GtkTreeView *tree_view); + void (* start_interactive_search) (GtkTreeView *tree_view); }; @@ -212,7 +213,9 @@ void gtk_tree_view_set_reorderable (GtkTreeView gboolean reorderable); gboolean gtk_tree_view_get_reorderable (GtkTreeView *tree_view); void gtk_tree_view_set_cursor (GtkTreeView *tree_view, - GtkTreePath *path); + GtkTreePath *path, + GtkTreeViewColumn *focus_column, + gboolean start_editing); /* Layout information */ diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 7d477b0fa5..34e5608e85 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -2129,39 +2129,34 @@ gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column, } } -/** - * gtk_tree_view_column_cell_render: - * @tree_column: A #GtkTreeViewColumn. - * @window: a #GdkDrawable to draw to - * @background_area: entire cell area (including tree expanders and maybe padding on the sides) - * @cell_area: area normally rendered by a cell renderer - * @expose_area: area that actually needs updating - * @flags: flags that affect rendering - * - * Renders the cell contained by #tree_column. This is used primarily by the - * GtkTreeView. - **/ -void -gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column, - GdkWindow *window, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, - guint flags) +/* both rendering and rendering focus are somewhat complicated, and a bit of + * code. Rather than duplicate them, we put them together to keep the code in + * one place + */ +static void +gtk_tree_view_column_cell_render_or_focus (GtkTreeViewColumn *tree_column, + GdkWindow *window, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + guint flags, + gboolean render, + GdkRectangle *focus_rectangle) { GList *list; GdkRectangle real_cell_area; gint expand_cell_count = 0; gint full_requested_width = 0; gint extra_space; + gint min_x, min_y, max_x, max_y; - g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); - g_return_if_fail (background_area != NULL); - g_return_if_fail (cell_area != NULL); - g_return_if_fail (expose_area != NULL); + min_x = G_MAXINT; + min_y = G_MAXINT; + max_x = 0; + max_y = 0; real_cell_area = *cell_area; - + /* Find out how my extra space we have to allocate */ for (list = tree_column->cell_list; list; list = list->next) { @@ -2195,13 +2190,35 @@ gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column, real_cell_area.width = info->requested_width + (info->expand?extra_space:0); - gtk_cell_renderer_render (info->cell, - window, - tree_column->tree_view, - background_area, - &real_cell_area, - expose_area, - flags); + if (render) + { + gtk_cell_renderer_render (info->cell, + window, + tree_column->tree_view, + background_area, + &real_cell_area, + expose_area, + flags); + } + else + { + gint x_offset, y_offset, width, height; + + gtk_cell_renderer_get_size (info->cell, + tree_column->tree_view, + &real_cell_area, + &x_offset, &y_offset, + &width, &height); + + if (min_x > (real_cell_area.x + x_offset)) + min_x = real_cell_area.x + x_offset; + if (max_x < real_cell_area.x + x_offset + width) + max_x = real_cell_area.x + x_offset + width; + if (min_y > (real_cell_area.y + y_offset)) + min_y = real_cell_area.y + y_offset; + if (max_y < real_cell_area.y + y_offset + height) + max_y = real_cell_area.y + y_offset + height; + } real_cell_area.x += (info->requested_width + tree_column->spacing); } for (list = g_list_last (tree_column->cell_list); list; list = list->prev) @@ -2227,6 +2244,59 @@ gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column, flags); real_cell_area.x += (info->requested_width + tree_column->spacing); } + if (! render) + { + if (min_x >= max_x || min_y >= max_y) + { + *focus_rectangle = *cell_area; + focus_rectangle->x -= 1; + focus_rectangle->y -= 1; + focus_rectangle->width += 2; + focus_rectangle->height += 2; + } + else + { + focus_rectangle->x = min_x - 1; + focus_rectangle->y = min_y - 1; + focus_rectangle->width = (max_x - min_x) + 2; + focus_rectangle->height = (max_y - min_y) + 2; + } + } +} + +/** + * gtk_tree_view_column_cell_render: + * @tree_column: A #GtkTreeViewColumn. + * @window: a #GdkDrawable to draw to + * @background_area: entire cell area (including tree expanders and maybe padding on the sides) + * @cell_area: area normally rendered by a cell renderer + * @expose_area: area that actually needs updating + * @flags: flags that affect rendering + * + * Renders the cell contained by #tree_column. This is used primarily by the + * GtkTreeView. + **/ +void +gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column, + GdkWindow *window, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + guint flags) +{ + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); + g_return_if_fail (background_area != NULL); + g_return_if_fail (cell_area != NULL); + g_return_if_fail (expose_area != NULL); + + gtk_tree_view_column_cell_render_or_focus (tree_column, + window, + background_area, + cell_area, + expose_area, + flags, + TRUE, + NULL); } gboolean @@ -2266,7 +2336,13 @@ _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column, background_area, cell_area, flags); - return (*editable_widget != NULL); + + if (*editable_widget != NULL) + { + g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE); + + return TRUE; + } } return FALSE; } @@ -2274,13 +2350,10 @@ _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column, gboolean gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, - gint direction, - gboolean unfocus) + gint direction) { - if (unfocus) - GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column = NULL; - else - GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column = tree_column; + if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column) + return FALSE; return TRUE; } @@ -2292,15 +2365,45 @@ gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn *tree_column, GdkRectangle *expose_area, guint flags) { - gtk_paint_focus (tree_column->tree_view->style, - window, - NULL, - tree_column->tree_view, - "treeview", - cell_area->x, - cell_area->y, - cell_area->width-1, - cell_area->height); + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); + if (tree_column->editable_widget) + { + /* This function is only called on the editable row when editing. + */ + + gtk_paint_focus (tree_column->tree_view->style, + window, + NULL, + tree_column->tree_view, + "treeview", + cell_area->x - 1, + cell_area->y - 1, + cell_area->width + 2 - 1, + cell_area->height + 2 - 1); + + } + else + { + GdkRectangle focus_rectangle; + gtk_tree_view_column_cell_render_or_focus (tree_column, + window, + background_area, + cell_area, + expose_area, + flags, + FALSE, + &focus_rectangle); + + gtk_paint_focus (tree_column->tree_view->style, + window, + NULL, + tree_column->tree_view, + "treeview", + focus_rectangle.x, + focus_rectangle.y, + focus_rectangle.width - 1, + focus_rectangle.height - 1); + } } gboolean diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h index 9bebfb8d67..d8fdd6b0e2 100644 --- a/gtk/gtktreeviewcolumn.h +++ b/gtk/gtktreeviewcolumn.h @@ -217,8 +217,7 @@ gboolean gtk_tree_view_column_cell_event (GtkTreeViewCol GdkRectangle *cell_area, guint flags); gboolean gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, - gint direction, - gboolean unfocus); + gint direction); void gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn *tree_column, GdkWindow *window, GdkRectangle *background_area, diff --git a/tests/Makefile.am b/tests/Makefile.am index ddb04fb83f..44512c0616 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -35,6 +35,7 @@ noinst_PROGRAMS = \ $(testsocket_programs) \ testtext \ testtextbuffer \ + testtreeedit \ testtreeview \ testtreefocus \ testtreecolumns \ @@ -52,6 +53,7 @@ testsocket_DEPENDENCIES = $(DEPS) testsocket_child_DEPENDENCIES = $(DEPS) testtext_DEPENDENCIES = $(TEST_DEPS) testtextbuffer_DEPENDENCIES = $(TEST_DEPS) +testtreeedit_DEPENDENCIS = $(DEPS) testtreeview_DEPENDENCIES = $(DEPS) testtreefocus_DEPENDENCIES = $(DEPS) testtreecolumns_DEPENDENCIES = $(DEPS) @@ -68,6 +70,7 @@ testselection_LDADD = $(LDADDS) testsocket_LDADD = $(LDADDS) testsocket_child_LDADD = $(LDADDS) testtextbuffer_LDADD = $(LDADDS) +testtreeedit_LDADD = $(LDADDS) testtreeview_LDADD = $(LDADDS) testtreefocus_LDADD = $(LDADDS) testtreecolumns_LDADD = $(LDADDS) @@ -79,6 +82,9 @@ testgtk_SOURCES = \ prop-editor.c \ testgtk.c +testtreeedit_SOURCES = \ + testtreeedit.c + testtreeview_SOURCES = \ prop-editor.c \ testtreeview.c diff --git a/tests/testtreecolumns.c b/tests/testtreecolumns.c index f0468ca6a8..c57eb07556 100644 --- a/tests/testtreecolumns.c +++ b/tests/testtreecolumns.c @@ -620,14 +620,14 @@ main (int argc, char *argv[]) gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 0, 0); gtk_box_pack_start (GTK_BOX (vbox2), bbox, TRUE, TRUE, 0); - button = gtk_button_new_with_label ("<<"); + button = gtk_button_new_with_mnemonic ("<< (_Q)"); gtk_widget_set_sensitive (button, FALSE); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_left_clicked), top_right_tree_view); g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (top_right_tree_view))), "changed", GTK_SIGNAL_FUNC (selection_changed), button); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); - button = gtk_button_new_with_label (">>"); + button = gtk_button_new_with_mnemonic (">> (_W)"); gtk_widget_set_sensitive (button, FALSE); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_right_clicked), top_right_tree_view); g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view))), @@ -639,14 +639,14 @@ main (int argc, char *argv[]) gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 0, 0); gtk_box_pack_start (GTK_BOX (vbox2), bbox, TRUE, TRUE, 0); - button = gtk_button_new_with_label ("<<"); + button = gtk_button_new_with_mnemonic ("<< (_E)"); gtk_widget_set_sensitive (button, FALSE); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_left_clicked), bottom_right_tree_view); g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (bottom_right_tree_view))), "changed", GTK_SIGNAL_FUNC (selection_changed), button); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); - button = gtk_button_new_with_label (">>"); + button = gtk_button_new_with_mnemonic (">> (_R)"); gtk_widget_set_sensitive (button, FALSE); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_right_clicked), bottom_right_tree_view); g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view))), diff --git a/tests/testtreeedit.c b/tests/testtreeedit.c new file mode 100644 index 0000000000..c9f5950629 --- /dev/null +++ b/tests/testtreeedit.c @@ -0,0 +1,140 @@ +#include <gtk/gtk.h> + +typedef struct { + const gchar *string; + gboolean is_editable; +} ListEntry; + +enum { + STRING_COLUMN, + IS_EDITABLE_COLUMN, + NUM_COLUMNS +}; + +static ListEntry model_strings[] = +{ + {"A simple string", TRUE }, + {"Another string!", TRUE }, + {"Guess what, a third string. This one can't be edited", FALSE }, + {"And then a fourth string. Neither can this", FALSE }, + {"Multiline\nFun!", TRUE }, + { NULL } +}; + +static GtkTreeModel * +create_model (void) +{ + GtkListStore *model; + GtkTreeIter iter; + gint i; + + model = gtk_list_store_new (NUM_COLUMNS, + G_TYPE_STRING, + G_TYPE_BOOLEAN); + + for (i = 0; model_strings[i].string != NULL; i++) + { + gtk_list_store_append (model, &iter); + + gtk_list_store_set (model, &iter, + STRING_COLUMN, model_strings[i].string, + IS_EDITABLE_COLUMN, model_strings[i].is_editable, + -1); + } + + return GTK_TREE_MODEL (model); +} + +static void +toggled (GtkCellRendererToggle *cell, + gchar *path_string, + gpointer data) +{ + GtkTreeModel *model = GTK_TREE_MODEL (data); + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string (path_string); + gboolean value; + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, IS_EDITABLE_COLUMN, &value, -1); + + value = !value; + gtk_list_store_set (GTK_LIST_STORE (model), &iter, IS_EDITABLE_COLUMN, value, -1); + + gtk_tree_path_free (path); +} + +static void +edited (GtkCellRendererText *cell, + gchar *path_string, + gchar *new_text, + gpointer data) +{ + GtkTreeModel *model = GTK_TREE_MODEL (data); + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string (path_string); + + gtk_tree_model_get_iter (model, &iter, path); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, STRING_COLUMN, new_text, -1); + + gtk_tree_path_free (path); +} + +gint +main (gint argc, gchar **argv) +{ + GtkWidget *window; + GtkWidget *scrolled_window; + GtkWidget *tree_view; + GtkTreeModel *tree_model; + GtkCellRenderer *renderer; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "GtkTreeView editing sample"); + gtk_signal_connect (GTK_OBJECT (window), "destroy", gtk_main_quit, NULL); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_add (GTK_CONTAINER (window), scrolled_window); + + tree_model = create_model (); + tree_view = gtk_tree_view_new_with_model (tree_model); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), + -1, "String", + renderer, + "text", STRING_COLUMN, + "editable", IS_EDITABLE_COLUMN, + NULL); + + g_signal_connect (G_OBJECT (renderer), "edited", + G_CALLBACK (edited), tree_model); + renderer = gtk_cell_renderer_toggle_new (); + g_signal_connect (G_OBJECT (renderer), "toggled", + G_CALLBACK (toggled), tree_model); + + g_object_set (G_OBJECT (renderer), + "xalign", 0.0, + "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, + NULL); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), + -1, "Editable", + renderer, + "active", IS_EDITABLE_COLUMN, + NULL); + gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view); + + gtk_window_set_default_size (GTK_WINDOW (window), + 650, 400); + + gtk_widget_show_all (window); + gtk_main (); + + return 0; +} diff --git a/tests/testtreefocus.c b/tests/testtreefocus.c index 08a3207c4f..ca5afd318a 100644 --- a/tests/testtreefocus.c +++ b/tests/testtreefocus.c @@ -348,7 +348,7 @@ main (int argc, char *argv[]) renderer, "active", ALEX_COLUMN, "visible", VISIBLE_COLUMN, - "can_activate", WORLD_COLUMN, + "activatable", WORLD_COLUMN, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (tree_view), col_offset - 1); gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), GTK_TREE_VIEW_COLUMN_FIXED); @@ -381,7 +381,7 @@ main (int argc, char *argv[]) renderer, "active", TIM_COLUMN, "visible", VISIBLE_COLUMN, - "can_activate", WORLD_COLUMN, + "activatable", WORLD_COLUMN, NULL); column = gtk_tree_view_get_column (GTK_TREE_VIEW (tree_view), col_offset - 1); gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), GTK_TREE_VIEW_COLUMN_FIXED); diff --git a/tests/testtreesort.c b/tests/testtreesort.c index b9f285efa7..0dba6d29c6 100644 --- a/tests/testtreesort.c +++ b/tests/testtreesort.c @@ -12,7 +12,7 @@ struct _ListSort static ListSort data[] = { - { "Apples", "Transmorgrify long word to demonstrate weirdness", "Exculpatory", "Gesundheit"}, + { "Apples", "Transmogrify long word to demonstrate weirdness", "Exculpatory", "Gesundheit"}, { "Oranges", "Wicker", "Adamantine", "Convivial" }, { "Bovine Spongiform Encephilopathy", "Sleazebucket", "Mountaineer", "Pander" }, { "Foot and Mouth", "Lampshade", "Skim Milk\nFull Milk", "Viewless" }, |