From: Havoc Pennington Date: Thu, 8 Feb 2001 23:36:53 +0000 (+0000) Subject: remove validation idle X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=4a3c8a367a012a1e098934585d46db8611e12420;p=~andy%2Fgtk remove validation idle 2001-02-08 Havoc Pennington * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove validation idle * demos/gtk-demo/main.c (create_tree): adjust to changes in text cell renderer * demos/pixbuf-demo.c (timeout): remove deprecated gtk_widget_draw * demos/testpixbuf-save.c (main): remove deprecated gtk_drawing_area_size * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate buttons even if the model isn't setup. gtk_tree_view_check_dirty() at the start of the allocation. (gtk_tree_view_check_dirty): handle column->button == NULL, handle unsetup or NULL model. * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the even/odd/sorted cells in the tree view. * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): bugfixes * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row backgrounds with draw_flat_box using different detail for even/odd rows. * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each row, so we can draw the alternating colors thing * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a property from a synonym property, notify for the synonym. Also, nuke the background_gdk_set and foreground_gdk_set synonyms (gtk_text_tag_get_property): Always return the font, even if all its fields aren't set * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't store the attr list; it leaves us with no way to change attributes in _render according to the render flags, and no way to implement get_property. Instead store all the specific text attributes. Separate whether an attribute is enabled from its value. Sync all properties with GtkTextTag, make them all consistent, etc. * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so renderers can highlight the sort row/column * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use accessor functions to get values; this has the side effect of showing up which accessor functions were missing. Added those. * gtk/gtktreeviewcolumn.h: Replace set_justification with set_alignment, to be consistent with GtkLabel, GtkMisc * gtk/gtktreeviewcolumn.c: Added code to display sort indicator arrow. * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h * gtk/gtktreesortable.h: updates in here --- diff --git a/ChangeLog b/ChangeLog index 3b88af8b9..7404d8f92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,66 @@ +2001-02-08 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove + validation idle + + * demos/gtk-demo/main.c (create_tree): adjust to changes in text + cell renderer + + * demos/pixbuf-demo.c (timeout): remove deprecated + gtk_widget_draw + + * demos/testpixbuf-save.c (main): remove deprecated + gtk_drawing_area_size + + * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate + buttons even if the model isn't setup. gtk_tree_view_check_dirty() + at the start of the allocation. + (gtk_tree_view_check_dirty): handle column->button == NULL, handle + unsetup or NULL model. + + * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the + even/odd/sorted cells in the tree view. + + * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): + bugfixes + + * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row + backgrounds with draw_flat_box using different detail for even/odd + rows. + + * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each + row, so we can draw the alternating colors thing + + * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a + property from a synonym property, notify for the synonym. + Also, nuke the background_gdk_set and foreground_gdk_set synonyms + (gtk_text_tag_get_property): Always return the font, even if + all its fields aren't set + + * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't + store the attr list; it leaves us with no way to change attributes + in _render according to the render flags, and no way to implement + get_property. Instead store all the specific text attributes. + Separate whether an attribute is enabled from its value. Sync all + properties with GtkTextTag, make them all consistent, etc. + + * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so + renderers can highlight the sort row/column + + * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use + accessor functions to get values; this has the side effect of + showing up which accessor functions were missing. Added those. + + * gtk/gtktreeviewcolumn.h: Replace set_justification with + set_alignment, to be consistent with GtkLabel, GtkMisc + + * gtk/gtktreeviewcolumn.c: Added code to display sort indicator + arrow. + + * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h + + * gtk/gtktreesortable.h: updates in here + 2001-02-07 Sven Neumann * gtk/gtkentry.c (gtk_entry_draw_text): convert area_height to diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 3b88af8b9..7404d8f92 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,66 @@ +2001-02-08 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove + validation idle + + * demos/gtk-demo/main.c (create_tree): adjust to changes in text + cell renderer + + * demos/pixbuf-demo.c (timeout): remove deprecated + gtk_widget_draw + + * demos/testpixbuf-save.c (main): remove deprecated + gtk_drawing_area_size + + * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate + buttons even if the model isn't setup. gtk_tree_view_check_dirty() + at the start of the allocation. + (gtk_tree_view_check_dirty): handle column->button == NULL, handle + unsetup or NULL model. + + * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the + even/odd/sorted cells in the tree view. + + * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): + bugfixes + + * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row + backgrounds with draw_flat_box using different detail for even/odd + rows. + + * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each + row, so we can draw the alternating colors thing + + * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a + property from a synonym property, notify for the synonym. + Also, nuke the background_gdk_set and foreground_gdk_set synonyms + (gtk_text_tag_get_property): Always return the font, even if + all its fields aren't set + + * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't + store the attr list; it leaves us with no way to change attributes + in _render according to the render flags, and no way to implement + get_property. Instead store all the specific text attributes. + Separate whether an attribute is enabled from its value. Sync all + properties with GtkTextTag, make them all consistent, etc. + + * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so + renderers can highlight the sort row/column + + * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use + accessor functions to get values; this has the side effect of + showing up which accessor functions were missing. Added those. + + * gtk/gtktreeviewcolumn.h: Replace set_justification with + set_alignment, to be consistent with GtkLabel, GtkMisc + + * gtk/gtktreeviewcolumn.c: Added code to display sort indicator + arrow. + + * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h + + * gtk/gtktreesortable.h: updates in here + 2001-02-07 Sven Neumann * gtk/gtkentry.c (gtk_entry_draw_text): convert area_height to diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 3b88af8b9..7404d8f92 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,66 @@ +2001-02-08 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove + validation idle + + * demos/gtk-demo/main.c (create_tree): adjust to changes in text + cell renderer + + * demos/pixbuf-demo.c (timeout): remove deprecated + gtk_widget_draw + + * demos/testpixbuf-save.c (main): remove deprecated + gtk_drawing_area_size + + * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate + buttons even if the model isn't setup. gtk_tree_view_check_dirty() + at the start of the allocation. + (gtk_tree_view_check_dirty): handle column->button == NULL, handle + unsetup or NULL model. + + * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the + even/odd/sorted cells in the tree view. + + * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): + bugfixes + + * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row + backgrounds with draw_flat_box using different detail for even/odd + rows. + + * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each + row, so we can draw the alternating colors thing + + * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a + property from a synonym property, notify for the synonym. + Also, nuke the background_gdk_set and foreground_gdk_set synonyms + (gtk_text_tag_get_property): Always return the font, even if + all its fields aren't set + + * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't + store the attr list; it leaves us with no way to change attributes + in _render according to the render flags, and no way to implement + get_property. Instead store all the specific text attributes. + Separate whether an attribute is enabled from its value. Sync all + properties with GtkTextTag, make them all consistent, etc. + + * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so + renderers can highlight the sort row/column + + * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use + accessor functions to get values; this has the side effect of + showing up which accessor functions were missing. Added those. + + * gtk/gtktreeviewcolumn.h: Replace set_justification with + set_alignment, to be consistent with GtkLabel, GtkMisc + + * gtk/gtktreeviewcolumn.c: Added code to display sort indicator + arrow. + + * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h + + * gtk/gtktreesortable.h: updates in here + 2001-02-07 Sven Neumann * gtk/gtkentry.c (gtk_entry_draw_text): convert area_height to diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 3b88af8b9..7404d8f92 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,66 @@ +2001-02-08 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove + validation idle + + * demos/gtk-demo/main.c (create_tree): adjust to changes in text + cell renderer + + * demos/pixbuf-demo.c (timeout): remove deprecated + gtk_widget_draw + + * demos/testpixbuf-save.c (main): remove deprecated + gtk_drawing_area_size + + * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate + buttons even if the model isn't setup. gtk_tree_view_check_dirty() + at the start of the allocation. + (gtk_tree_view_check_dirty): handle column->button == NULL, handle + unsetup or NULL model. + + * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the + even/odd/sorted cells in the tree view. + + * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): + bugfixes + + * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row + backgrounds with draw_flat_box using different detail for even/odd + rows. + + * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each + row, so we can draw the alternating colors thing + + * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a + property from a synonym property, notify for the synonym. + Also, nuke the background_gdk_set and foreground_gdk_set synonyms + (gtk_text_tag_get_property): Always return the font, even if + all its fields aren't set + + * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't + store the attr list; it leaves us with no way to change attributes + in _render according to the render flags, and no way to implement + get_property. Instead store all the specific text attributes. + Separate whether an attribute is enabled from its value. Sync all + properties with GtkTextTag, make them all consistent, etc. + + * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so + renderers can highlight the sort row/column + + * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use + accessor functions to get values; this has the side effect of + showing up which accessor functions were missing. Added those. + + * gtk/gtktreeviewcolumn.h: Replace set_justification with + set_alignment, to be consistent with GtkLabel, GtkMisc + + * gtk/gtktreeviewcolumn.c: Added code to display sort indicator + arrow. + + * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h + + * gtk/gtktreesortable.h: updates in here + 2001-02-07 Sven Neumann * gtk/gtkentry.c (gtk_entry_draw_text): convert area_height to diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 3b88af8b9..7404d8f92 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,66 @@ +2001-02-08 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove + validation idle + + * demos/gtk-demo/main.c (create_tree): adjust to changes in text + cell renderer + + * demos/pixbuf-demo.c (timeout): remove deprecated + gtk_widget_draw + + * demos/testpixbuf-save.c (main): remove deprecated + gtk_drawing_area_size + + * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate + buttons even if the model isn't setup. gtk_tree_view_check_dirty() + at the start of the allocation. + (gtk_tree_view_check_dirty): handle column->button == NULL, handle + unsetup or NULL model. + + * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the + even/odd/sorted cells in the tree view. + + * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): + bugfixes + + * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row + backgrounds with draw_flat_box using different detail for even/odd + rows. + + * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each + row, so we can draw the alternating colors thing + + * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a + property from a synonym property, notify for the synonym. + Also, nuke the background_gdk_set and foreground_gdk_set synonyms + (gtk_text_tag_get_property): Always return the font, even if + all its fields aren't set + + * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't + store the attr list; it leaves us with no way to change attributes + in _render according to the render flags, and no way to implement + get_property. Instead store all the specific text attributes. + Separate whether an attribute is enabled from its value. Sync all + properties with GtkTextTag, make them all consistent, etc. + + * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so + renderers can highlight the sort row/column + + * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use + accessor functions to get values; this has the side effect of + showing up which accessor functions were missing. Added those. + + * gtk/gtktreeviewcolumn.h: Replace set_justification with + set_alignment, to be consistent with GtkLabel, GtkMisc + + * gtk/gtktreeviewcolumn.c: Added code to display sort indicator + arrow. + + * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h + + * gtk/gtktreesortable.h: updates in here + 2001-02-07 Sven Neumann * gtk/gtkentry.c (gtk_entry_draw_text): convert area_height to diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 3b88af8b9..7404d8f92 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,66 @@ +2001-02-08 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove + validation idle + + * demos/gtk-demo/main.c (create_tree): adjust to changes in text + cell renderer + + * demos/pixbuf-demo.c (timeout): remove deprecated + gtk_widget_draw + + * demos/testpixbuf-save.c (main): remove deprecated + gtk_drawing_area_size + + * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate + buttons even if the model isn't setup. gtk_tree_view_check_dirty() + at the start of the allocation. + (gtk_tree_view_check_dirty): handle column->button == NULL, handle + unsetup or NULL model. + + * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the + even/odd/sorted cells in the tree view. + + * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): + bugfixes + + * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row + backgrounds with draw_flat_box using different detail for even/odd + rows. + + * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each + row, so we can draw the alternating colors thing + + * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a + property from a synonym property, notify for the synonym. + Also, nuke the background_gdk_set and foreground_gdk_set synonyms + (gtk_text_tag_get_property): Always return the font, even if + all its fields aren't set + + * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't + store the attr list; it leaves us with no way to change attributes + in _render according to the render flags, and no way to implement + get_property. Instead store all the specific text attributes. + Separate whether an attribute is enabled from its value. Sync all + properties with GtkTextTag, make them all consistent, etc. + + * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so + renderers can highlight the sort row/column + + * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use + accessor functions to get values; this has the side effect of + showing up which accessor functions were missing. Added those. + + * gtk/gtktreeviewcolumn.h: Replace set_justification with + set_alignment, to be consistent with GtkLabel, GtkMisc + + * gtk/gtktreeviewcolumn.c: Added code to display sort indicator + arrow. + + * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h + + * gtk/gtktreesortable.h: updates in here + 2001-02-07 Sven Neumann * gtk/gtkentry.c (gtk_entry_draw_text): convert area_height to diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 3b88af8b9..7404d8f92 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,66 @@ +2001-02-08 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove + validation idle + + * demos/gtk-demo/main.c (create_tree): adjust to changes in text + cell renderer + + * demos/pixbuf-demo.c (timeout): remove deprecated + gtk_widget_draw + + * demos/testpixbuf-save.c (main): remove deprecated + gtk_drawing_area_size + + * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate + buttons even if the model isn't setup. gtk_tree_view_check_dirty() + at the start of the allocation. + (gtk_tree_view_check_dirty): handle column->button == NULL, handle + unsetup or NULL model. + + * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the + even/odd/sorted cells in the tree view. + + * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): + bugfixes + + * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row + backgrounds with draw_flat_box using different detail for even/odd + rows. + + * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each + row, so we can draw the alternating colors thing + + * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a + property from a synonym property, notify for the synonym. + Also, nuke the background_gdk_set and foreground_gdk_set synonyms + (gtk_text_tag_get_property): Always return the font, even if + all its fields aren't set + + * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't + store the attr list; it leaves us with no way to change attributes + in _render according to the render flags, and no way to implement + get_property. Instead store all the specific text attributes. + Separate whether an attribute is enabled from its value. Sync all + properties with GtkTextTag, make them all consistent, etc. + + * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so + renderers can highlight the sort row/column + + * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use + accessor functions to get values; this has the side effect of + showing up which accessor functions were missing. Added those. + + * gtk/gtktreeviewcolumn.h: Replace set_justification with + set_alignment, to be consistent with GtkLabel, GtkMisc + + * gtk/gtktreeviewcolumn.c: Added code to display sort indicator + arrow. + + * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h + + * gtk/gtktreesortable.h: updates in here + 2001-02-07 Sven Neumann * gtk/gtkentry.c (gtk_entry_draw_text): convert area_height to diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c index 3d545d70f..e03ad041a 100644 --- a/demos/gtk-demo/main.c +++ b/demos/gtk-demo/main.c @@ -380,11 +380,17 @@ create_tree (void) } cell = gtk_cell_renderer_text_new (); + + g_object_set (G_OBJECT (cell), + "style", PANGO_STYLE_ITALIC, + NULL); + column = gtk_tree_view_column_new_with_attributes ("Widget (double click for demo)", cell, "text", TITLE_COLUMN, - "italic", ITALIC_COLUMN, + "style_set", ITALIC_COLUMN, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column)); diff --git a/demos/pixbuf-demo.c b/demos/pixbuf-demo.c index ae9a0998e..0ee8aca46 100644 --- a/demos/pixbuf-demo.c +++ b/demos/pixbuf-demo.c @@ -175,7 +175,7 @@ timeout (gpointer data) : MAX (127, fabs (255 * cos (f * 2.0 * M_PI))))); } - gtk_widget_draw (da, NULL); + gtk_widget_queue_draw (da); frame_num++; return TRUE; diff --git a/demos/testpixbuf-save.c b/demos/testpixbuf-save.c index 802f98494..a97fd9585 100644 --- a/demos/testpixbuf-save.c +++ b/demos/testpixbuf-save.c @@ -135,9 +135,9 @@ main (int argc, char **argv) gtk_container_add (GTK_CONTAINER (window), vbox); drawing_area = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); + gtk_widget_set_usize (GTK_WIDGET (drawing_area), + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event", GTK_SIGNAL_FUNC (expose_cb), NULL); diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 230f78445..92b76f99a 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -175,6 +175,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \ gtktreemodelsimple.h \ gtktreemodelsort.h \ gtktreeselection.h \ + gtktreesortable.h \ gtktreestore.h \ gtktreeview.h \ gtktreeviewcolumn.h \ diff --git a/gtk/gtkcellrenderer.h b/gtk/gtkcellrenderer.h index bf1855395..27694571d 100644 --- a/gtk/gtkcellrenderer.h +++ b/gtk/gtkcellrenderer.h @@ -32,7 +32,9 @@ typedef enum { GTK_CELL_RENDERER_SELECTED = 1 << 0, GTK_CELL_RENDERER_PRELIT = 1 << 1, - GTK_CELL_RENDERER_INSENSITIVE = 1 << 2 + GTK_CELL_RENDERER_INSENSITIVE = 1 << 2, + /* this flag means the cell is in the sort column/row */ + GTK_CELL_RENDERER_SORTED = 1 << 3 } GtkCellRendererState; #define GTK_TYPE_CELL_RENDERER (gtk_cell_renderer_get_type ()) diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index 751659fc5..7ad67797c 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -23,6 +23,7 @@ static void gtk_cell_renderer_text_init (GtkCellRendererText *celltext); static void gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class); +static void gtk_cell_renderer_text_finalize (GObject *object); static void gtk_cell_renderer_text_get_property (GObject *object, guint param_id, @@ -47,21 +48,48 @@ static void gtk_cell_renderer_text_render (GtkCellRenderer *cell, guint flags); + enum { - PROP_ZERO, + PROP_0, + PROP_TEXT, - PROP_FONT, + + /* Style args */ PROP_BACKGROUND, - PROP_BACKGROUND_GDK, PROP_FOREGROUND, + PROP_BACKGROUND_GDK, PROP_FOREGROUND_GDK, + PROP_FONT, + PROP_FONT_DESC, + PROP_FAMILY, + PROP_STYLE, + PROP_VARIANT, + PROP_WEIGHT, + PROP_STRETCH, + PROP_SIZE, + PROP_SIZE_POINTS, + PROP_EDITABLE, PROP_STRIKETHROUGH, PROP_UNDERLINE, - PROP_EDITABLE, - PROP_ITALIC, - PROP_BOLD + PROP_RISE, + + /* Whether-a-style-arg-is-set args */ + PROP_BACKGROUND_SET, + PROP_FOREGROUND_SET, + PROP_FAMILY_SET, + PROP_STYLE_SET, + PROP_VARIANT_SET, + PROP_WEIGHT_SET, + PROP_STRETCH_SET, + PROP_SIZE_SET, + PROP_EDITABLE_SET, + PROP_STRIKETHROUGH_SET, + PROP_UNDERLINE_SET, + PROP_RISE_SET }; +static gpointer parent_class; + GtkType gtk_cell_renderer_text_get_type (void) { @@ -91,12 +119,10 @@ gtk_cell_renderer_text_get_type (void) static void gtk_cell_renderer_text_init (GtkCellRendererText *celltext) { - celltext->attr_list = pango_attr_list_new (); GTK_CELL_RENDERER (celltext)->xalign = 0.0; GTK_CELL_RENDERER (celltext)->yalign = 0.5; GTK_CELL_RENDERER (celltext)->xpad = 2; GTK_CELL_RENDERER (celltext)->ypad = 2; - celltext->underline = FALSE; } static void @@ -105,87 +131,241 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) GObjectClass *object_class = G_OBJECT_CLASS (class); GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class); + parent_class = g_type_class_peek_parent (class); + + object_class->finalize = gtk_cell_renderer_text_finalize; + object_class->get_property = gtk_cell_renderer_text_get_property; object_class->set_property = gtk_cell_renderer_text_set_property; cell_class->get_size = gtk_cell_renderer_text_get_size; cell_class->render = gtk_cell_renderer_text_render; - + g_object_class_install_property (object_class, - PROP_TEXT, - g_param_spec_string ("text", - _("Text String"), - _("The text of the renderer."), - "", - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + PROP_TEXT, + g_param_spec_string ("text", + _("Text"), + _("Text to render"), + NULL, + G_PARAM_READWRITE)); g_object_class_install_property (object_class, - PROP_FONT, - g_param_spec_string ("font", - _("Font String"), - _("The string of the font."), - "", - G_PARAM_WRITABLE)); - + PROP_BACKGROUND, + g_param_spec_string ("background", + _("Background color name"), + _("Background color as a string"), + NULL, + G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_BACKGROUND_GDK, + g_param_spec_boxed ("background_gdk", + _("Background color"), + _("Background color as a GdkColor"), + GTK_TYPE_GDK_COLOR, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_FOREGROUND, + g_param_spec_string ("foreground", + _("Foreground color name"), + _("Foreground color as a string"), + NULL, + G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_FOREGROUND_GDK, + g_param_spec_boxed ("foreground_gdk", + _("Foreground color"), + _("Foreground color as a GdkColor"), + GTK_TYPE_GDK_COLOR, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + + g_object_class_install_property (object_class, + PROP_EDITABLE, + g_param_spec_boolean ("editable", + _("Editable"), + _("Whether the text can be modified by the user"), + TRUE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_FONT, + g_param_spec_string ("font", + _("Font"), + _("Font description as a string"), + NULL, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (object_class, - PROP_BACKGROUND, - g_param_spec_string ("background", - _("Background Color string"), - _("The color for the background of the text."), - "white", - G_PARAM_WRITABLE)); + PROP_FONT_DESC, + g_param_spec_boxed ("font_desc", + _("Font"), + _("Font description as a PangoFontDescription struct"), + GTK_TYPE_PANGO_FONT_DESCRIPTION, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (object_class, - PROP_FOREGROUND, - g_param_spec_string ("foreground", - _("Foreground Color string"), - _("The color for the background of the text."), - "black", - G_PARAM_WRITABLE)); + PROP_FAMILY, + g_param_spec_string ("family", + _("Font family"), + _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"), + NULL, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_STYLE, + g_param_spec_enum ("style", + _("Font style"), + _("Font style"), + PANGO_TYPE_STYLE, + PANGO_STYLE_NORMAL, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_VARIANT, + g_param_spec_enum ("variant", + _("Font variant"), + _("Font variant"), + PANGO_TYPE_VARIANT, + PANGO_VARIANT_NORMAL, + G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, - PROP_STRIKETHROUGH, - g_param_spec_boolean ("strikethrough", - _("Strikethrough"), - _("Draw a line through the text."), - FALSE, - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + PROP_WEIGHT, + g_param_spec_int ("weight", + _("Font weight"), + _("Font weight"), + 0, + G_MAXINT, + PANGO_WEIGHT_NORMAL, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (object_class, - PROP_UNDERLINE, - g_param_spec_boolean ("underline", - _("Underline"), - _("Underline the text."), - FALSE, - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + PROP_STRETCH, + g_param_spec_enum ("stretch", + _("Font stretch"), + _("Font stretch"), + PANGO_TYPE_STRETCH, + PANGO_STRETCH_NORMAL, + G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, - PROP_EDITABLE, - g_param_spec_boolean ("editable", - _("Editable"), - _("Make the text editable."), - FALSE, - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + PROP_SIZE, + g_param_spec_int ("size", + _("Font size"), + _("Font size"), + 0, + G_MAXINT, + 0, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_SIZE_POINTS, + g_param_spec_double ("size_points", + _("Font points"), + _("Font size in points"), + 0.0, + G_MAXDOUBLE, + 0.0, + G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, - PROP_ITALIC, - g_param_spec_boolean ("italic", - _("Italic"), - _("Make the text italic."), - FALSE, - G_PARAM_WRITABLE)); + PROP_RISE, + g_param_spec_int ("rise", + _("Rise"), + _("Offset of text above the baseline (below the baseline if rise is negative)"), + -G_MAXINT, + G_MAXINT, + 0, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + + g_object_class_install_property (object_class, + PROP_STRIKETHROUGH, + g_param_spec_boolean ("strikethrough", + _("Strikethrough"), + _("Whether to strike through the text"), + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, - PROP_BOLD, - g_param_spec_boolean ("bold", - _("Bold"), - _("Make the text bold."), - FALSE, - G_PARAM_WRITABLE)); + PROP_UNDERLINE, + g_param_spec_enum ("underline", + _("Underline"), + _("Style of underline for this text"), + PANGO_TYPE_UNDERLINE, + PANGO_UNDERLINE_NONE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + /* Style props are set or not */ + +#define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE)) + + ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET, + _("Background set"), + _("Whether this tag affects the background color")); + + ADD_SET_PROP ("foreground_set", PROP_FOREGROUND_SET, + _("Foreground set"), + _("Whether this tag affects the foreground color")); + + ADD_SET_PROP ("editable_set", PROP_EDITABLE_SET, + _("Editability set"), + _("Whether this tag affects text editability")); + + ADD_SET_PROP ("family_set", PROP_FAMILY_SET, + _("Font family set"), + _("Whether this tag affects the font family")); + + ADD_SET_PROP ("style_set", PROP_STYLE_SET, + _("Font style set"), + _("Whether this tag affects the font style")); + + ADD_SET_PROP ("variant_set", PROP_VARIANT_SET, + _("Font variant set"), + _("Whether this tag affects the font variant")); + + ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET, + _("Font weight set"), + _("Whether this tag affects the font weight")); + + ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET, + _("Font stretch set"), + _("Whether this tag affects the font stretch")); + + ADD_SET_PROP ("size_set", PROP_SIZE_SET, + _("Font size set"), + _("Whether this tag affects the font size")); + + ADD_SET_PROP ("rise_set", PROP_RISE_SET, + _("Rise set"), + _("Whether this tag affects the rise")); + + ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET, + _("Strikethrough set"), + _("Whether this tag affects strikethrough")); + + ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET, + _("Underline set"), + _("Whether this tag affects underlining")); +} + +static void +gtk_cell_renderer_text_finalize (GObject *object) +{ + GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object); + + if (celltext->font.family_name) + g_free (celltext->font.family_name); + + if (celltext->text) + g_free (celltext->text); + + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } static void @@ -196,26 +376,146 @@ gtk_cell_renderer_text_get_property (GObject *object, const gchar *trailer) { GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object); - PangoAttrIterator *attr_iter; - PangoAttribute *attr; switch (param_id) { case PROP_TEXT: g_value_set_string (value, celltext->text); break; - case PROP_STRIKETHROUGH: - attr_iter = pango_attr_list_get_iterator (celltext->attr_list); - attr = pango_attr_iterator_get (attr_iter, - PANGO_ATTR_STRIKETHROUGH); - g_value_set_boolean (value, ((PangoAttrInt*) attr)->value); + + case PROP_BACKGROUND_GDK: + { + GdkColor color; + + color.red = celltext->background.red; + color.green = celltext->background.green; + color.blue = celltext->background.blue; + + g_value_set_boxed (value, &color); + } break; - case PROP_UNDERLINE: - g_value_set_boolean (value, celltext->underline); + + case PROP_FOREGROUND_GDK: + { + GdkColor color; + + color.red = celltext->foreground.red; + color.green = celltext->foreground.green; + color.blue = celltext->foreground.blue; + + g_value_set_boxed (value, &color); + } + break; + + case PROP_FONT: + { + /* FIXME GValue imposes a totally gratuitous string copy + * here, we could just hand off string ownership + */ + gchar *str = pango_font_description_to_string (&celltext->font); + g_value_set_string (value, str); + g_free (str); + } break; + + case PROP_FONT_DESC: + g_value_set_boxed (value, &celltext->font); + break; + + case PROP_FAMILY: + g_value_set_string (value, celltext->font.family_name); + break; + + case PROP_STYLE: + g_value_set_enum (value, celltext->font.style); + break; + + case PROP_VARIANT: + g_value_set_enum (value, celltext->font.variant); + break; + + case PROP_WEIGHT: + g_value_set_int (value, celltext->font.weight); + break; + + case PROP_STRETCH: + g_value_set_enum (value, celltext->font.stretch); + break; + + case PROP_SIZE: + g_value_set_int (value, celltext->font.size); + break; + + case PROP_SIZE_POINTS: + g_value_set_double (value, ((double)celltext->font.size) / (double)PANGO_SCALE); + break; + case PROP_EDITABLE: g_value_set_boolean (value, celltext->editable); break; + + case PROP_STRIKETHROUGH: + g_value_set_boolean (value, celltext->strikethrough); + break; + + case PROP_UNDERLINE: + g_value_set_enum (value, celltext->underline_style); + break; + + case PROP_RISE: + g_value_set_int (value, celltext->rise); + break; + + case PROP_BACKGROUND_SET: + g_value_set_boolean (value, celltext->background_set); + break; + + case PROP_FOREGROUND_SET: + g_value_set_boolean (value, celltext->foreground_set); + break; + + case PROP_FAMILY_SET: + g_value_set_boolean (value, celltext->family_set); + break; + + case PROP_STYLE_SET: + g_value_set_boolean (value, celltext->style_set); + break; + + case PROP_VARIANT_SET: + g_value_set_boolean (value, celltext->variant_set); + break; + + case PROP_WEIGHT_SET: + g_value_set_boolean (value, celltext->weight_set); + break; + + case PROP_STRETCH_SET: + g_value_set_boolean (value, celltext->stretch_set); + break; + + case PROP_SIZE_SET: + g_value_set_boolean (value, celltext->size_set); + break; + + case PROP_EDITABLE_SET: + g_value_set_boolean (value, celltext->editable_set); + break; + + case PROP_STRIKETHROUGH_SET: + g_value_set_boolean (value, celltext->strikethrough_set); + break; + + case PROP_UNDERLINE_SET: + g_value_set_boolean (value, celltext->underline_set); + break; + + case PROP_RISE_SET: + g_value_set_boolean (value, celltext->rise_set); + break; + + case PROP_BACKGROUND: + case PROP_FOREGROUND: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -223,6 +523,121 @@ gtk_cell_renderer_text_get_property (GObject *object, } +static void +set_bg_color (GtkCellRendererText *celltext, + GdkColor *color) +{ + if (color) + { + if (!celltext->background_set) + { + celltext->background_set = TRUE; + g_object_notify (G_OBJECT (celltext), "background_set"); + } + + celltext->background.red = color->red; + celltext->background.green = color->green; + celltext->background.blue = color->blue; + } + else + { + if (celltext->background_set) + { + celltext->background_set = FALSE; + g_object_notify (G_OBJECT (celltext), "background_set"); + } + } +} + + +static void +set_fg_color (GtkCellRendererText *celltext, + GdkColor *color) +{ + if (color) + { + if (!celltext->foreground_set) + { + celltext->foreground_set = TRUE; + g_object_notify (G_OBJECT (celltext), "foreground_set"); + } + + celltext->foreground.red = color->red; + celltext->foreground.green = color->green; + celltext->foreground.blue = color->blue; + } + else + { + if (celltext->foreground_set) + { + celltext->foreground_set = FALSE; + g_object_notify (G_OBJECT (celltext), "foreground_set"); + } + } +} + +static void +set_font_description (GtkCellRendererText *celltext, + PangoFontDescription *font_desc) +{ + if (font_desc != NULL) + { + /* pango_font_description_from_string() will sometimes return + * a NULL family or -1 size, so handle those cases. + */ + + if (font_desc->family_name) + g_object_set (G_OBJECT (celltext), + "family", font_desc->family_name, + NULL); + + if (font_desc->size >= 0) + g_object_set (G_OBJECT (celltext), + "size", font_desc->size, + NULL); + + g_object_set (G_OBJECT (celltext), + "style", font_desc->style, + "variant", font_desc->variant, + "weight", font_desc->weight, + "stretch", font_desc->stretch, + NULL); + } + else + { + if (celltext->family_set) + { + celltext->family_set = FALSE; + g_object_notify (G_OBJECT (celltext), "family_set"); + } + if (celltext->style_set) + { + celltext->style_set = FALSE; + g_object_notify (G_OBJECT (celltext), "style_set"); + } + if (celltext->variant_set) + { + celltext->variant_set = FALSE; + g_object_notify (G_OBJECT (celltext), "variant_set"); + } + if (celltext->weight_set) + { + celltext->weight_set = FALSE; + g_object_notify (G_OBJECT (celltext), "weight_set"); + } + if (celltext->stretch_set) + { + celltext->stretch_set = FALSE; + g_object_notify (G_OBJECT (celltext), "stretch_set"); + } + if (celltext->size_set) + { + celltext->size_set = FALSE; + g_object_notify (G_OBJECT (celltext), "size_set"); + } + } +} + static void gtk_cell_renderer_text_set_property (GObject *object, guint param_id, @@ -232,99 +647,206 @@ gtk_cell_renderer_text_set_property (GObject *object, { GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object); - GdkColor color; - PangoFontDescription *font_desc; - gchar *string; - PangoAttribute *attribute; - gchar *font; - switch (param_id) { case PROP_TEXT: - g_free (celltext->text); - celltext->text = g_value_dup_string (value); - break; - case PROP_FONT: - font = g_value_get_string (value); - - if (font) - { - font_desc = pango_font_description_from_string (font); - attribute = pango_attr_font_desc_new (font_desc); - attribute->start_index = 0; - attribute->end_index = G_MAXINT; - pango_font_description_free (font_desc); - pango_attr_list_change (celltext->attr_list, - attribute); - } + if (celltext->text) + g_free (celltext->text); + celltext->text = g_strdup (g_value_get_string (value)); break; + case PROP_BACKGROUND: - string = g_value_get_string (value); - if (string && gdk_color_parse (string, &color)) - { - attribute = pango_attr_background_new (color.red, - color.green, - color.blue); - attribute->start_index = 0; - attribute->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, - attribute); - } - break; - case PROP_BACKGROUND_GDK: + { + GdkColor color; + + if (gdk_color_parse (g_value_get_string (value), &color)) + set_bg_color (celltext, &color); + else + g_warning ("Don't know color `%s'", g_value_get_string (value)); + + g_object_notify (G_OBJECT (celltext), "background_gdk"); + } break; + case PROP_FOREGROUND: - string = g_value_get_string (value); - if (string && gdk_color_parse (string, &color)) - { - attribute = pango_attr_foreground_new (color.red, - color.green, - color.blue); - attribute->start_index = 0; - attribute->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, - attribute); - } + { + GdkColor color; + + if (gdk_color_parse (g_value_get_string (value), &color)) + set_bg_color (celltext, &color); + else + g_warning ("Don't know color `%s'", g_value_get_string (value)); + + g_object_notify (G_OBJECT (celltext), "foreground_gdk"); + } + break; + + case PROP_BACKGROUND_GDK: + set_bg_color (celltext, g_value_get_boxed (value)); break; + case PROP_FOREGROUND_GDK: + set_fg_color (celltext, g_value_get_boxed (value)); + break; + + case PROP_FONT: + { + PangoFontDescription *font_desc = NULL; + const gchar *name; + + name = g_value_get_string (value); + + if (name) + font_desc = pango_font_description_from_string (name); + + set_font_description (celltext, font_desc); + + if (font_desc) + pango_font_description_free (font_desc); + } + break; + + case PROP_FONT_DESC: + set_font_description (celltext, g_value_get_boxed (value)); + break; + + case PROP_FAMILY: + if (celltext->font.family_name) + g_free (celltext->font.family_name); + celltext->font.family_name = g_strdup (g_value_get_string (value)); + + celltext->family_set = TRUE; + g_object_notify (G_OBJECT (celltext), "family_set"); + g_object_notify (G_OBJECT (celltext), "font_desc"); + g_object_notify (G_OBJECT (celltext), "font"); + break; + + case PROP_STYLE: + celltext->font.style = g_value_get_enum (value); + + celltext->style_set = TRUE; + g_object_notify (G_OBJECT (celltext), "style_set"); + g_object_notify (G_OBJECT (celltext), "font_desc"); + g_object_notify (G_OBJECT (celltext), "font"); + break; + + case PROP_VARIANT: + celltext->font.variant = g_value_get_enum (value); + + celltext->variant_set = TRUE; + g_object_notify (G_OBJECT (celltext), "variant_set"); + g_object_notify (G_OBJECT (celltext), "font_desc"); + g_object_notify (G_OBJECT (celltext), "font"); + break; + + case PROP_WEIGHT: + celltext->font.weight = g_value_get_int (value); + + celltext->weight_set = TRUE; + g_object_notify (G_OBJECT (celltext), "weight_set"); + g_object_notify (G_OBJECT (celltext), "font_desc"); + g_object_notify (G_OBJECT (celltext), "font"); + break; + + case PROP_STRETCH: + celltext->font.stretch = g_value_get_enum (value); + + celltext->stretch_set = TRUE; + g_object_notify (G_OBJECT (celltext), "stretch_set"); + g_object_notify (G_OBJECT (celltext), "font_desc"); + g_object_notify (G_OBJECT (celltext), "font"); + break; + + case PROP_SIZE: + celltext->font.size = g_value_get_int (value); + + celltext->size_set = TRUE; + g_object_notify (G_OBJECT (celltext), "size_set"); + g_object_notify (G_OBJECT (celltext), "font_desc"); + g_object_notify (G_OBJECT (celltext), "font"); break; + + case PROP_SIZE_POINTS: + celltext->font.size = g_value_get_double (value) * PANGO_SCALE; + + celltext->size_set = TRUE; + g_object_notify (G_OBJECT (celltext), "size_set"); + g_object_notify (G_OBJECT (celltext), "font_desc"); + g_object_notify (G_OBJECT (celltext), "font"); + break; + + case PROP_EDITABLE: + celltext->editable = g_value_get_boolean (value); + celltext->editable_set = TRUE; + g_object_notify (G_OBJECT (celltext), "editable_set"); + break; + case PROP_STRIKETHROUGH: - attribute = pango_attr_strikethrough_new (g_value_get_boolean (value)); - attribute->start_index = 0; - attribute->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, - attribute); + celltext->strikethrough = g_value_get_boolean (value); + celltext->strikethrough_set = TRUE; + g_object_notify (G_OBJECT (celltext), "strikethrough_set"); break; + case PROP_UNDERLINE: - celltext->underline = g_value_get_boolean (value); - attribute = pango_attr_underline_new (celltext->underline ? - PANGO_UNDERLINE_SINGLE : - PANGO_UNDERLINE_NONE); - attribute->start_index = 0; - attribute->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, - attribute); + celltext->underline_style = g_value_get_enum (value); + celltext->underline_set = TRUE; + g_object_notify (G_OBJECT (celltext), "underline_set"); break; - case PROP_EDITABLE: + + case PROP_RISE: + celltext->rise = g_value_get_int (value); + celltext->rise_set = TRUE; + g_object_notify (G_OBJECT (celltext), "rise_set"); + break; + + case PROP_BACKGROUND_SET: + celltext->background_set = g_value_get_boolean (value); + break; + + case PROP_FOREGROUND_SET: + celltext->foreground_set = g_value_get_boolean (value); + break; + + case PROP_FAMILY_SET: + celltext->family_set = g_value_get_boolean (value); + break; + + case PROP_STYLE_SET: + celltext->style_set = g_value_get_boolean (value); break; - case PROP_ITALIC: - attribute = pango_attr_style_new (g_value_get_boolean (value) ? - PANGO_STYLE_ITALIC : - PANGO_STYLE_NORMAL); - attribute->start_index = 0; - attribute->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, - attribute); - break; - case PROP_BOLD: - attribute = pango_attr_weight_new (g_value_get_boolean (value) ? - PANGO_WEIGHT_BOLD : - PANGO_WEIGHT_NORMAL); - attribute->start_index = 0; - attribute->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, - attribute); + + case PROP_VARIANT_SET: + celltext->variant_set = g_value_get_boolean (value); + break; + + case PROP_WEIGHT_SET: + celltext->weight_set = g_value_get_boolean (value); + break; + + case PROP_STRETCH_SET: + celltext->stretch_set = g_value_get_boolean (value); + break; + + case PROP_SIZE_SET: + celltext->size_set = g_value_get_boolean (value); + break; + + case PROP_EDITABLE_SET: + celltext->editable_set = g_value_get_boolean (value); break; + + case PROP_STRIKETHROUGH_SET: + celltext->strikethrough_set = g_value_get_boolean (value); + break; + + case PROP_UNDERLINE_SET: + celltext->underline_set = g_value_get_boolean (value); + break; + + case PROP_RISE_SET: + celltext->rise_set = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -347,7 +869,108 @@ gtk_cell_renderer_text_set_property (GObject *object, GtkCellRenderer * gtk_cell_renderer_text_new (void) { - return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_text_get_type ())); + return GTK_CELL_RENDERER (g_object_new (gtk_cell_renderer_text_get_type (), NULL)); +} + +static void +add_attr (PangoAttrList *attr_list, + PangoAttribute *attr) +{ + attr->start_index = 0; + attr->end_index = G_MAXINT; + + pango_attr_list_insert (attr_list, attr); +} + +static PangoLayout* +get_layout (GtkCellRendererText *celltext, + GtkWidget *widget, + gboolean will_render, + GtkCellRendererState flags) +{ + PangoAttrList *attr_list; + PangoLayout *layout; + PangoUnderline uline; + + layout = gtk_widget_create_pango_layout (widget, celltext->text); + + attr_list = pango_attr_list_new (); + + if (will_render) + { + /* Add options that affect appearance but not size */ + + /* note that background doesn't go here, since it affects + * background_area not the PangoLayout area + */ + + if (celltext->foreground_set) + { + PangoColor color; + + color = celltext->foreground; + + add_attr (attr_list, + pango_attr_foreground_new (color.red, color.green, color.blue)); + } + + if (celltext->strikethrough_set) + add_attr (attr_list, + pango_attr_strikethrough_new (celltext->strikethrough)); + } + + if (celltext->family_set && + celltext->font.family_name) + add_attr (attr_list, pango_attr_family_new (celltext->font.family_name)); + + if (celltext->style_set) + add_attr (attr_list, pango_attr_style_new (celltext->font.style)); + + if (celltext->variant_set) + add_attr (attr_list, pango_attr_variant_new (celltext->font.variant)); + + if (celltext->weight_set) + add_attr (attr_list, pango_attr_weight_new (celltext->font.weight)); + + if (celltext->stretch_set) + add_attr (attr_list, pango_attr_stretch_new (celltext->font.stretch)); + + if (celltext->size_set && + celltext->font.size >= 0) + add_attr (attr_list, pango_attr_size_new (celltext->font.size)); + + if (celltext->underline_set) + uline = celltext->underline_style; + else + uline = PANGO_UNDERLINE_NONE; + + if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT) + { + switch (uline) + { + case PANGO_UNDERLINE_NONE: + uline = PANGO_UNDERLINE_SINGLE; + break; + + case PANGO_UNDERLINE_SINGLE: + uline = PANGO_UNDERLINE_DOUBLE; + break; + + default: + break; + } + } + + if (uline != PANGO_UNDERLINE_NONE) + add_attr (attr_list, pango_attr_underline_new (celltext->underline_style)); + + if (celltext->rise_set) + add_attr (attr_list, pango_attr_rise_new (celltext->rise)); + + pango_layout_set_attributes (layout, attr_list); + pango_layout_set_width (layout, -1); + + return layout; } static void @@ -359,21 +982,9 @@ gtk_cell_renderer_text_get_size (GtkCellRenderer *cell, GtkCellRendererText *celltext = (GtkCellRendererText *)cell; PangoRectangle rect; PangoLayout *layout; - PangoAttribute *attr; - PangoUnderline underline; - layout = gtk_widget_create_pango_layout (widget, celltext->text); - underline = celltext->underline ? - PANGO_UNDERLINE_DOUBLE : - PANGO_UNDERLINE_NONE; - - attr = pango_attr_underline_new (underline); - attr->start_index = 0; - attr->end_index = G_MAXINT; - - pango_attr_list_change (celltext->attr_list, attr); - pango_layout_set_attributes (layout, celltext->attr_list); - pango_layout_set_width (layout, -1); + layout = get_layout (celltext, widget, FALSE, 0); + pango_layout_get_pixel_extents (layout, NULL, &rect); if (width) @@ -398,40 +1009,15 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell, GtkCellRendererText *celltext = (GtkCellRendererText *) cell; PangoRectangle rect; PangoLayout *layout; - PangoAttribute *attr; - PangoUnderline underline; GtkStateType state; gint real_xoffset; gint real_yoffset; - layout = gtk_widget_create_pango_layout (widget, celltext->text); + layout = get_layout (celltext, widget, TRUE, flags); - if (celltext->underline) - underline = PANGO_UNDERLINE_SINGLE; - else - underline = PANGO_UNDERLINE_NONE; - - attr = pango_attr_underline_new (underline); - attr->start_index = 0; - attr->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, attr); - pango_layout_set_attributes (layout, celltext->attr_list); - - pango_layout_set_width (layout, -1); pango_layout_get_pixel_extents (layout, NULL, &rect); - if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT) - underline = (celltext->underline) ? PANGO_UNDERLINE_DOUBLE:PANGO_UNDERLINE_SINGLE; - else - underline = (celltext->underline) ? PANGO_UNDERLINE_SINGLE:PANGO_UNDERLINE_NONE; - - attr = pango_attr_underline_new (underline); - attr->start_index = 0; - attr->end_index = G_MAXINT; - pango_attr_list_change (celltext->attr_list, attr); - pango_layout_set_attributes (layout, celltext->attr_list); - real_xoffset = cell->xalign * (cell_area->width - rect.width - (2 * cell->xpad)); real_xoffset = MAX (real_xoffset, 0) + cell->xpad; real_yoffset = cell->yalign * (cell_area->height - rect.height - (2 * cell->ypad)); @@ -441,6 +1027,30 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell, state = GTK_STATE_SELECTED; else state = GTK_STATE_NORMAL; + + if (celltext->background_set && state != GTK_STATE_SELECTED) + { + GdkColor color; + GdkGC *gc; + + color.red = celltext->background.red; + color.green = celltext->background.green; + color.blue = celltext->background.blue; + + gc = gdk_gc_new (window); + + gdk_gc_set_rgb_fg_color (gc, &color); + + gdk_draw_rectangle (window, + gc, + TRUE, + background_area->x, + background_area->y, + background_area->width, + background_area->height); + + g_object_unref (G_OBJECT (gc)); + } gtk_paint_layout (widget->style, window, diff --git a/gtk/gtkcellrenderertext.h b/gtk/gtkcellrenderertext.h index 762705413..b2270b3de 100644 --- a/gtk/gtkcellrenderertext.h +++ b/gtk/gtkcellrenderertext.h @@ -43,10 +43,37 @@ struct _GtkCellRendererText /*< private >*/ gchar *text; - PangoAttrList *attr_list; + PangoFontDescription font; + PangoColor foreground; + PangoColor background; + PangoUnderline underline_style; + + gint rise; + + guint strikethrough : 1; + + /* editable feature doesn't work */ guint editable : 1; - guint underline : 1; + + /* font elements set */ + guint family_set : 1; + guint style_set : 1; + guint variant_set : 1; + guint weight_set : 1; + guint stretch_set : 1; + guint size_set : 1; + + guint foreground_set : 1; + guint background_set : 1; + + guint underline_set : 1; + + guint rise_set : 1; + + guint strikethrough_set : 1; + + guint editable_set : 1; }; struct _GtkCellRendererTextClass diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index 619594894..e740dd2bd 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -1250,7 +1250,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, &src_iter, src_path)) { - g_print ("can't get source path as iter\n"); goto out; } @@ -1266,8 +1265,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, &dest_iter); retval = TRUE; - - g_print ("prepending to list\n"); } else { @@ -1280,11 +1277,7 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, &dest_iter, &tmp_iter); retval = TRUE; - - g_print ("inserting into list\n"); } - else - g_print ("can't get iter to insert after\n"); } gtk_tree_path_free (prev); @@ -1304,9 +1297,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, { copy_iter = _gtk_tree_data_list_node_copy (dl, list_store->column_headers[col]); - - g_print ("copied col %d type %s\n", col, - g_type_name (list_store->column_headers[col])); if (copy_head == NULL) copy_head = copy_iter; @@ -1332,7 +1322,6 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, /* FIXME maybe add some data targets eventually, or handle text * targets in the simple case. */ - g_print ("not accepting target\n"); } out: diff --git a/gtk/gtkrbtree.c b/gtk/gtkrbtree.c index e8bbf2d9d..2765599a5 100644 --- a/gtk/gtkrbtree.c +++ b/gtk/gtkrbtree.c @@ -110,6 +110,7 @@ _gtk_rbnode_new (GtkRBTree *tree, node->right = tree->nil; node->parent = tree->nil; node->flags = GTK_RBNODE_RED; + node->parity = 1; node->count = 1; node->children = NULL; node->offset = height; @@ -122,6 +123,17 @@ _gtk_rbnode_free (GtkRBNode *node) G_LOCK (current_allocator); node->left = current_allocator->free_nodes; current_allocator->free_nodes = node; + if (gtk_debug_flags & GTK_DEBUG_TREE) + { + /* unfortunately node->left has to continue to point to + * a node... + */ + node->right = (gpointer) 0xdeadbeef; + node->parent = (gpointer) 0xdeadbeef; + node->offset = 56789; + node->count = 56789; + node->flags = 0; + } G_UNLOCK (current_allocator); } @@ -130,6 +142,7 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree, GtkRBNode *node) { gint node_height, right_height; + guint node_parity, right_parity; GtkRBNode *right = node->right; g_return_if_fail (node != tree->nil); @@ -143,6 +156,15 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree, (right->right?right->right->offset:0) - (right->children?right->children->root->offset:0); + node_parity = node->parity - + (node->left?node->left->parity:0) - + (node->right?node->right->parity:0) - + (node->children?node->children->root->parity:0); + right_parity = right->parity - + (right->left?right->left->parity:0) - + (right->right?right->right->parity:0) - + (right->children?right->children->root->parity:0); + node->right = right->left; if (right->left != tree->nil) right->left->parent = node; @@ -167,6 +189,7 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree, (node->right?node->right->count:0); right->count = 1 + (right->left?right->left->count:0) + (right->right?right->right->count:0); + node->offset = node_height + (node->left?node->left->offset:0) + (node->right?node->right->offset:0) + @@ -175,6 +198,15 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree, (right->left?right->left->offset:0) + (right->right?right->right->offset:0) + (right->children?right->children->root->offset:0); + + node->parity = node_parity + + (node->left?node->left->parity:0) + + (node->right?node->right->parity:0) + + (node->children?node->children->root->parity:0); + right->parity = right_parity + + (right->left?right->left->parity:0) + + (right->right?right->right->parity:0) + + (right->children?right->children->root->parity:0); } static void @@ -182,6 +214,7 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree, GtkRBNode *node) { gint node_height, left_height; + guint node_parity, left_parity; GtkRBNode *left = node->left; g_return_if_fail (node != tree->nil); @@ -195,6 +228,15 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree, (left->right?left->right->offset:0) - (left->children?left->children->root->offset:0); + node_parity = node->parity - + (node->left?node->left->parity:0) - + (node->right?node->right->parity:0) - + (node->children?node->children->root->parity:0); + left_parity = left->parity - + (left->left?left->left->parity:0) - + (left->right?left->right->parity:0) - + (left->children?left->children->root->parity:0); + node->left = left->right; if (left->right != tree->nil) left->right->parent = node; @@ -222,6 +264,7 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree, (node->right?node->right->count:0); left->count = 1 + (left->left?left->left->count:0) + (left->right?left->right->count:0); + node->offset = node_height + (node->left?node->left->offset:0) + (node->right?node->right->offset:0) + @@ -230,6 +273,15 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree, (left->left?left->left->offset:0) + (left->right?left->right->offset:0) + (left->children?left->children->root->offset:0); + + node->parity = node_parity + + (node->left?node->left->parity:0) + + (node->right?node->right->parity:0) + + (node->children?node->children->root->parity:0); + left->parity = left_parity + + (left->left?left->left->parity:0) + + (left->right?left->right->parity:0) + + (left->children?left->children->root->parity:0); } static void @@ -412,6 +464,7 @@ _gtk_rbtree_new (void) retval->nil->flags = GTK_RBNODE_BLACK; retval->nil->count = 0; retval->nil->offset = 0; + retval->nil->parity = 0; retval->root = retval->nil; return retval; @@ -451,12 +504,21 @@ _gtk_rbtree_remove (GtkRBTree *tree) GtkRBNode *tmp_node; gint height = tree->root->offset; + + if (gtk_debug_flags & GTK_DEBUG_TREE) + _gtk_rbtree_test (G_STRLOC, tree); + tmp_tree = tree->parent_tree; tmp_node = tree->parent_node; while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil) { tmp_node->offset -= height; + + /* If the removed tree was odd, flip all parents */ + if (tree->root->parity) + tmp_node->parity = !tmp_node->parity; + tmp_node = tmp_node->parent; if (tmp_node == tmp_tree->nil) { @@ -464,7 +526,13 @@ _gtk_rbtree_remove (GtkRBTree *tree) tmp_tree = tmp_tree->parent_tree; } } + + tmp_tree = tree->parent_tree; + _gtk_rbtree_free (tree); + + if (gtk_debug_flags & GTK_DEBUG_TREE) + _gtk_rbtree_test (G_STRLOC, tmp_tree); } @@ -476,8 +544,11 @@ _gtk_rbtree_insert_after (GtkRBTree *tree, GtkRBNode *node; gboolean right = TRUE; GtkRBNode *tmp_node; - GtkRBTree *tmp_tree; + GtkRBTree *tmp_tree; + if (gtk_debug_flags & GTK_DEBUG_TREE) + _gtk_rbtree_test (G_STRLOC, tree); + if (current != NULL && current->right != tree->nil) { current = current->right; @@ -513,6 +584,8 @@ _gtk_rbtree_insert_after (GtkRBTree *tree, * started in. */ if (tmp_tree == tree) tmp_node->count++; + + tmp_node->parity += 1; tmp_node->offset += height; tmp_node = tmp_node->parent; if (tmp_node == tmp_tree->nil) @@ -524,7 +597,7 @@ _gtk_rbtree_insert_after (GtkRBTree *tree, _gtk_rbtree_insert_fixup (tree, node); if (gtk_debug_flags & GTK_DEBUG_TREE) - _gtk_rbtree_test (tree); + _gtk_rbtree_test (G_STRLOC, tree); return node; } @@ -539,6 +612,9 @@ _gtk_rbtree_insert_before (GtkRBTree *tree, GtkRBNode *tmp_node; GtkRBTree *tmp_tree; + if (gtk_debug_flags & GTK_DEBUG_TREE) + _gtk_rbtree_test (G_STRLOC, tree); + if (current != NULL && current->left != tree->nil) { current = current->left; @@ -574,6 +650,8 @@ _gtk_rbtree_insert_before (GtkRBTree *tree, * started in. */ if (tmp_tree == tree) tmp_node->count++; + + tmp_node->parity += 1; tmp_node->offset += height; tmp_node = tmp_node->parent; if (tmp_node == tmp_tree->nil) @@ -585,7 +663,7 @@ _gtk_rbtree_insert_before (GtkRBTree *tree, _gtk_rbtree_insert_fixup (tree, node); if (gtk_debug_flags & GTK_DEBUG_TREE) - _gtk_rbtree_test (tree); + _gtk_rbtree_test (G_STRLOC, tree); return node; } @@ -670,6 +748,41 @@ _gtk_rbtree_node_find_offset (GtkRBTree *tree, return retval; } +gint +_gtk_rbtree_node_find_parity (GtkRBTree *tree, + GtkRBNode *node) +{ + GtkRBNode *last; + gint retval; + + g_assert (node); + g_assert (node->left); + + retval = node->left->parity; + + while (tree && node && node != tree->nil) + { + last = node; + node = node->parent; + + /* Add left branch, plus children, iff we came from the right */ + if (node->right == last) + retval += node->parity - node->right->parity; + + if (node == tree->nil) + { + node = tree->parent_node; + tree = tree->parent_tree; + + /* Add the parent node, plus the left branch. */ + if (node) + retval += node->left->parity + 1; /* 1 == GTK_RBNODE_GET_PARITY() */ + } + } + + return retval % 2; +} + gint _gtk_rbtree_find_offset (GtkRBTree *tree, gint height, @@ -734,14 +847,20 @@ _gtk_rbtree_remove_node (GtkRBTree *tree, GtkRBNode *node) { GtkRBNode *x, *y; - + GtkRBTree *tmp_tree; + GtkRBNode *tmp_node; + g_return_if_fail (tree != NULL); g_return_if_fail (node != NULL); + /* make sure we're deleting a node that's actually in the tree */ for (x = node; x->parent != tree->nil; x = x->parent) ; g_return_if_fail (x == tree->root); + if (gtk_debug_flags & GTK_DEBUG_TREE) + _gtk_rbtree_test (G_STRLOC, tree); + if (node->left == tree->nil || node->right == tree->nil) { y = node; @@ -753,9 +872,31 @@ _gtk_rbtree_remove_node (GtkRBTree *tree, while (y->left != tree->nil) y = y->left; } + + /* adjust count only beneath tree */ for (x = y; x != tree->nil; x = x->parent) x->count--; - y->count = node->count; + + /* y->count = node->count; */ + + /* offsets and parity adjust all the way up through parent trees */ + + tmp_tree = tree; + tmp_node = y; + + while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil) + { + /* tmp_node->offset -= y->offset; */ + tmp_node->parity -= (guint) 1; /* parity of y is always 1 */ + + tmp_node = tmp_node->parent; + if (tmp_node == tmp_tree->nil) + { + tmp_node = tmp_tree->parent_node; + tmp_tree = tmp_tree->parent_tree; + } + } + /* x is y's only child */ if (y->left != tree->nil) x = y->left; @@ -778,13 +919,10 @@ _gtk_rbtree_remove_node (GtkRBTree *tree, if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK) _gtk_rbtree_remove_node_fixup (tree, x); - G_LOCK (current_allocator); - y->left = current_allocator->free_nodes; - current_allocator->free_nodes = y; - G_UNLOCK (current_allocator); + _gtk_rbnode_free (y); if (gtk_debug_flags & GTK_DEBUG_TREE) - _gtk_rbtree_test (tree); + _gtk_rbtree_test (G_STRLOC, tree); } GtkRBNode * @@ -989,6 +1127,9 @@ _count_nodes (GtkRBTree *tree, if (node == tree->nil) return 0; + g_assert (node->left); + g_assert (node->right); + res = (_count_nodes (tree, node->left) + _count_nodes (tree, node->right) + 1); @@ -997,41 +1138,113 @@ _count_nodes (GtkRBTree *tree, return res; } -void -_gtk_rbtree_test (GtkRBTree *tree) +static guint +get_parity (GtkRBNode *node) { - if ((_count_nodes (tree, tree->root->left) + - _count_nodes (tree, tree->root->right) + 1) == tree->root->count) - g_print ("Tree passed\n"); + guint child_total = 0; + guint rem; + + /* The parity of a node is node->parity minus + * the parity of left, right, and children. + * + * This is equivalent to saying that if left, right, children + * sum to 0 parity, then node->parity is the parity of node, + * and if left, right, children are odd parity, then + * node->parity is the reverse of the node's parity. + */ + + child_total += (guint) node->left->parity; + child_total += (guint) node->right->parity; + + if (node->children) + child_total += (guint) node->children->root->parity; + + rem = child_total % 2; + + if (rem == 0) + return node->parity; else - g_print ("Tree failed\n"); + return !node->parity; +} +static guint +count_parity (GtkRBTree *tree, + GtkRBNode *node) +{ + guint res; + + if (node == tree->nil) + return 0; + + res = + count_parity (tree, node->left) + + count_parity (tree, node->right) + + (guint)1 + + (node->children ? count_parity (node->children, node->children->root) : 0); + + res = res % (guint)2; + + if (res != node->parity) + g_print ("parity incorrect for node\n"); + + if (get_parity (node) != 1) + g_error ("Node has incorrect parity %d", get_parity (node)); + + return res; } static void -_gtk_rbtree_test_height_helper (GtkRBTree *tree, - GtkRBNode *node, - gint height) +_gtk_rbtree_test_height (GtkRBTree *tree, + GtkRBNode *node) { - if (node == tree->nil) - return; + gint computed_offset = 0; - if (node->offset - - (node->left?node->left->offset:0) - - (node->right?node->right->offset:0) - - (node->children?node->children->root->offset:0) != height) - g_error ("tree failed\n"); + /* This whole test is sort of a useless truism. */ + + if (node->left != tree->nil) + computed_offset += node->left->offset; - _gtk_rbtree_test_height_helper (tree, node->left, height); - _gtk_rbtree_test_height_helper (tree, node->right, height); - if (node->children) - _gtk_rbtree_test_height_helper (node->children, node->children->root, height); + if (node->right != tree->nil) + computed_offset += node->right->offset; + + if (node->children && node->children->root != node->children->nil) + computed_offset += node->children->root->offset; + + if (GTK_RBNODE_GET_HEIGHT (node) + computed_offset != node->offset) + g_error ("node has broken offset\n"); + if (node->left != tree->nil) + _gtk_rbtree_test_height (tree, node->left); + + if (node->right != tree->nil) + _gtk_rbtree_test_height (tree, node->right); + + if (node->children && node->children->root != node->children->nil) + _gtk_rbtree_test_height (node->children, node->children->root); } void -_gtk_rbtree_test_height (GtkRBTree *tree, - gint height) +_gtk_rbtree_test (const gchar *where, + GtkRBTree *tree) { - _gtk_rbtree_test_height_helper (tree, tree->root, height); + GtkRBTree *tmp_tree; + + /* Test the entire tree */ + tmp_tree = tree; + while (tmp_tree->parent_tree) + tmp_tree = tmp_tree->parent_tree; + + g_print ("%s: whole tree offset is %d\n", where, tmp_tree->root->offset); + + if (tmp_tree->root != tmp_tree->nil) + { + g_assert ((_count_nodes (tmp_tree, tmp_tree->root->left) + + _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count); + + + _gtk_rbtree_test_height (tmp_tree, tmp_tree->root); + + g_assert (count_parity (tmp_tree, tmp_tree->root) == tmp_tree->root->parity); + } } + diff --git a/gtk/gtkrbtree.h b/gtk/gtkrbtree.h index 40c779320..eea9160b6 100644 --- a/gtk/gtkrbtree.h +++ b/gtk/gtkrbtree.h @@ -33,6 +33,7 @@ typedef enum GTK_RBNODE_IS_SELECTED = 1 << 3, GTK_RBNODE_IS_PRELIT = 1 << 4, GTK_RBNODE_IS_VIEW = 1 << 5 + } GtkRBNodeColor; typedef struct _GtkRBTree GtkRBTree; @@ -53,7 +54,20 @@ struct _GtkRBTree struct _GtkRBNode { - guint flags; + guint flags : 14; + + /* We keep track of whether the aggregate count of children plus 1 + * for the node itself comes to an even number. The parity flag is + * the total count of children mod 2, where the total count of + * children gets computed in the same way that the total offset gets + * computed. i.e. not the same as the "count" field below which + * doesn't include children. We could replace parity with a + * full-size int field here, and then take % 2 to get the parity flag, + * but that would use extra memory. + */ + + guint parity : 1; + GtkRBNode *left; GtkRBNode *right; GtkRBNode *parent; @@ -62,13 +76,15 @@ struct _GtkRBNode * i.e. node->left->count + node->right->count + 1 */ gint count; - + /* this is the total of sizes of * node->left, node->right, our own height, and the height * of all trees in ->children, iff children exists because * the thing is expanded. */ gint offset; + + /* Child trees */ GtkRBTree *children; }; @@ -101,6 +117,8 @@ void _gtk_rbtree_node_set_height (GtkRBTree *tree, gint height); gint _gtk_rbtree_node_find_offset (GtkRBTree *tree, GtkRBNode *node); +gint _gtk_rbtree_node_find_parity (GtkRBTree *tree, + GtkRBNode *node); gint _gtk_rbtree_find_offset (GtkRBTree *tree, gint offset, GtkRBTree **new_tree, @@ -127,7 +145,8 @@ gint _gtk_rbtree_get_depth (GtkRBTree *tree); /* This func just checks the integrity of the tree */ /* It will go away later. */ -void _gtk_rbtree_test (GtkRBTree *tree); +void _gtk_rbtree_test (const gchar *where, + GtkRBTree *tree); #ifdef __cplusplus diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index 30c75cf90..7b6c04e01 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -2416,6 +2416,29 @@ gtk_default_draw_box (GtkStyle *style, x, y, width, height); } +static GdkGC* +get_darkened_gc (GdkWindow *window, + GdkColor *color, + gint darken_count) +{ + GdkColor src = *color; + GdkColor shaded; + GdkGC *gc; + + gc = gdk_gc_new (window); + + while (darken_count) + { + gtk_style_shade (&src, &shaded, 1.3); + src = shaded; + --darken_count; + } + + gdk_gc_set_rgb_fg_color (gc, &shaded); + + return gc; +} + static void gtk_default_draw_flat_box (GtkStyle *style, GdkWindow *window, @@ -2430,6 +2453,7 @@ gtk_default_draw_flat_box (GtkStyle *style, gint height) { GdkGC *gc1; + GdkGC *freeme = NULL; g_return_if_fail (GTK_IS_STYLE (style)); g_return_if_fail (window != NULL); @@ -2443,14 +2467,60 @@ gtk_default_draw_flat_box (GtkStyle *style, if (detail) { - if (!strcmp ("text", detail) && state_type == GTK_STATE_SELECTED) - gc1 = style->bg_gc[GTK_STATE_SELECTED]; - else if (!strcmp ("viewportbin", detail)) - gc1 = style->bg_gc[GTK_STATE_NORMAL]; - else if (!strcmp ("entry_bg", detail)) - gc1 = style->base_gc[state_type]; + if (state_type == GTK_STATE_SELECTED) + { + if (!strcmp ("text", detail)) + gc1 = style->bg_gc[GTK_STATE_SELECTED]; + else if (!strcmp ("cell_even_sorted", detail) || + !strcmp ("cell_odd_sorted", detail) || + !strcmp ("cell_even_ruled_sorted", detail) || + !strcmp ("cell_odd_ruled_sorted", detail)) + { + freeme = get_darkened_gc (window, &style->bg[state_type], 1); + gc1 = freeme; + } + else + { + gc1 = style->bg_gc[state_type]; + } + } else - gc1 = style->bg_gc[state_type]; + { + if (!strcmp ("viewportbin", detail)) + gc1 = style->bg_gc[GTK_STATE_NORMAL]; + else if (!strcmp ("entry_bg", detail)) + gc1 = style->base_gc[state_type]; + + /* For trees: even rows are base color, odd rows are a shade of + * the base color, the sort column is a shade of the original color + * for that row. + */ + + /* FIXME when we have style properties, clean this up. + */ + + else if (!strcmp ("cell_even", detail) || + !strcmp ("cell_odd", detail) || + !strcmp ("cell_even_ruled", detail)) + { + gc1 = style->base_gc[state_type]; + } + else if (!strcmp ("cell_even_sorted", detail) || + !strcmp ("cell_odd_sorted", detail) || + !strcmp ("cell_odd_ruled", detail) || + !strcmp ("cell_even_ruled_sorted", detail)) + { + freeme = get_darkened_gc (window, &style->base[state_type], 1); + gc1 = freeme; + } + else if (!strcmp ("cell_odd_ruled_sorted", detail)) + { + freeme = get_darkened_gc (window, &style->base[state_type], 2); + gc1 = freeme; + } + else + gc1 = style->bg_gc[state_type]; + } } else gc1 = style->bg_gc[state_type]; @@ -2475,6 +2545,10 @@ gtk_default_draw_flat_box (GtkStyle *style, gtk_style_apply_default_background (style, window, widget && !GTK_WIDGET_NO_WINDOW (widget), state_type, area, x, y, width, height); + + + if (freeme) + g_object_unref (G_OBJECT (freeme)); } static void diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index 153f3417e..4340000ff 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -106,8 +106,6 @@ enum { /* Whether-a-style-arg-is-set args */ PROP_BACKGROUND_SET, PROP_FOREGROUND_SET, - PROP_BACKGROUND_GDK_SET, - PROP_FOREGROUND_GDK_SET, PROP_BACKGROUND_STIPPLE_SET, PROP_FOREGROUND_STIPPLE_SET, PROP_FAMILY_SET, @@ -507,10 +505,6 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) _("Background full height set"), _("Whether this tag affects background height")); - ADD_SET_PROP ("background_gdk_set", PROP_BACKGROUND_GDK_SET, - _("Background set"), - _("Whether this tag affects the background color")); - ADD_SET_PROP ("background_stipple_set", PROP_BACKGROUND_STIPPLE_SET, _("Background stipple set"), _("Whether this tag affects the background stipple")); @@ -519,10 +513,6 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) _("Foreground set"), _("Whether this tag affects the foreground color")); - ADD_SET_PROP ("foreground_gdk_set", PROP_FOREGROUND_GDK_SET, - _("Foreground set"), - _("Whether this tag affects the foreground color")); - ADD_SET_PROP ("foreground_stipple_set", PROP_FOREGROUND_STIPPLE_SET, _("Foreground stipple set"), _("Whether this tag affects the foreground stipple")); @@ -814,6 +804,8 @@ gtk_text_tag_set_property (GObject *object, set_bg_color (text_tag, &color); else g_warning ("Don't know color `%s'", g_value_get_string (value)); + + g_object_notify (G_OBJECT (text_tag), "background_gdk"); } break; @@ -825,6 +817,8 @@ gtk_text_tag_set_property (GObject *object, set_fg_color (text_tag, &color); else g_warning ("Don't know color `%s'", g_value_get_string (value)); + + g_object_notify (G_OBJECT (text_tag), "foreground_gdk"); } break; @@ -847,7 +841,7 @@ gtk_text_tag_set_property (GObject *object, GdkBitmap *bitmap = g_value_get_as_pointer (value); text_tag->bg_stipple_set = TRUE; - g_object_notify (G_OBJECT (text_tag), "bg_stipple_set"); + g_object_notify (G_OBJECT (text_tag), "background_stipple_set"); if (text_tag->values->appearance.bg_stipple != bitmap) { @@ -867,7 +861,7 @@ gtk_text_tag_set_property (GObject *object, GdkBitmap *bitmap = g_value_get_as_pointer (value); text_tag->fg_stipple_set = TRUE; - g_object_notify (G_OBJECT (text_tag), "fg_stipple_set"); + g_object_notify (G_OBJECT (text_tag), "foreground_stipple_set"); if (text_tag->values->appearance.fg_stipple != bitmap) { @@ -895,8 +889,8 @@ gtk_text_tag_set_property (GObject *object, set_font_description (text_tag, font_desc); if (font_desc) - pango_font_description_free (font_desc); - + pango_font_description_free (font_desc); + size_changed = TRUE; } break; @@ -919,6 +913,8 @@ gtk_text_tag_set_property (GObject *object, text_tag->values->font.family_name = g_strdup (g_value_get_string (value)); text_tag->family_set = TRUE; g_object_notify (G_OBJECT (text_tag), "family_set"); + g_object_notify (G_OBJECT (text_tag), "font_desc"); + g_object_notify (G_OBJECT (text_tag), "font"); size_changed = TRUE; break; @@ -926,6 +922,8 @@ gtk_text_tag_set_property (GObject *object, text_tag->values->font.style = g_value_get_enum (value); text_tag->style_set = TRUE; g_object_notify (G_OBJECT (text_tag), "style_set"); + g_object_notify (G_OBJECT (text_tag), "font_desc"); + g_object_notify (G_OBJECT (text_tag), "font"); size_changed = TRUE; break; @@ -933,6 +931,8 @@ gtk_text_tag_set_property (GObject *object, text_tag->values->font.variant = g_value_get_enum (value); text_tag->variant_set = TRUE; g_object_notify (G_OBJECT (text_tag), "variant_set"); + g_object_notify (G_OBJECT (text_tag), "font_desc"); + g_object_notify (G_OBJECT (text_tag), "font"); size_changed = TRUE; break; @@ -940,6 +940,8 @@ gtk_text_tag_set_property (GObject *object, text_tag->values->font.weight = g_value_get_int (value); text_tag->weight_set = TRUE; g_object_notify (G_OBJECT (text_tag), "weight_set"); + g_object_notify (G_OBJECT (text_tag), "font_desc"); + g_object_notify (G_OBJECT (text_tag), "font"); size_changed = TRUE; break; @@ -947,20 +949,28 @@ gtk_text_tag_set_property (GObject *object, text_tag->values->font.stretch = g_value_get_enum (value); text_tag->stretch_set = TRUE; g_object_notify (G_OBJECT (text_tag), "stretch_set"); + g_object_notify (G_OBJECT (text_tag), "font_desc"); + g_object_notify (G_OBJECT (text_tag), "font"); size_changed = TRUE; break; case PROP_SIZE: text_tag->values->font.size = g_value_get_int (value); text_tag->size_set = TRUE; + g_object_notify (G_OBJECT (text_tag), "size_points"); g_object_notify (G_OBJECT (text_tag), "size_set"); + g_object_notify (G_OBJECT (text_tag), "font_desc"); + g_object_notify (G_OBJECT (text_tag), "font"); size_changed = TRUE; break; case PROP_SIZE_POINTS: text_tag->values->font.size = g_value_get_double (value) * PANGO_SCALE; text_tag->size_set = TRUE; + g_object_notify (G_OBJECT (text_tag), "size"); g_object_notify (G_OBJECT (text_tag), "size_set"); + g_object_notify (G_OBJECT (text_tag), "font_desc"); + g_object_notify (G_OBJECT (text_tag), "font"); size_changed = TRUE; break; @@ -1086,12 +1096,10 @@ gtk_text_tag_set_property (GObject *object, /* Whether the value should be used... */ case PROP_BACKGROUND_SET: - case PROP_BACKGROUND_GDK_SET: text_tag->bg_color_set = g_value_get_boolean (value); break; case PROP_FOREGROUND_SET: - case PROP_FOREGROUND_GDK_SET: text_tag->fg_color_set = g_value_get_boolean (value); break; @@ -1289,12 +1297,6 @@ gtk_text_tag_get_property (GObject *object, break; case PROP_FONT: - if (tag->family_set && - tag->style_set && - tag->variant_set && - tag->size_set && - tag->stretch_set && - tag->weight_set) { /* FIXME GValue imposes a totally gratuitous string copy * here, we could just hand off string ownership @@ -1306,13 +1308,7 @@ gtk_text_tag_get_property (GObject *object, break; case PROP_FONT_DESC: - if (tag->family_set && - tag->style_set && - tag->variant_set && - tag->size_set && - tag->stretch_set && - tag->weight_set) - g_value_set_boxed (value, &tag->values->font); + g_value_set_boxed (value, &tag->values->font); break; case PROP_FAMILY: @@ -1413,12 +1409,10 @@ gtk_text_tag_get_property (GObject *object, break; case PROP_BACKGROUND_SET: - case PROP_BACKGROUND_GDK_SET: g_value_set_boolean (value, tag->bg_color_set); break; case PROP_FOREGROUND_SET: - case PROP_FOREGROUND_GDK_SET: g_value_set_boolean (value, tag->fg_color_set); break; diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index 76859fdd3..df233806b 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -4176,9 +4176,16 @@ gtk_text_view_destroy_layout (GtkTextView *text_view) { if (text_view->layout) { - /* Remove layout from all anchored children */ GSList *tmp_list; + if (text_view->incremental_validate_idle) + { + g_source_remove (text_view->incremental_validate_idle); + text_view->incremental_validate_idle = 0; + } + + /* Remove layout from all anchored children */ + tmp_list = text_view->children; while (tmp_list != NULL) { diff --git a/gtk/gtktreemodelsort.c b/gtk/gtktreemodelsort.c index 99a704761..17735cec5 100644 --- a/gtk/gtktreemodelsort.c +++ b/gtk/gtktreemodelsort.c @@ -419,7 +419,7 @@ gtk_tree_model_sort_changed (GtkTreeModel *s_model, array, (GtkTreeIter *) elt, TRUE); - g_print ("index is %d\n", index); + gtk_signal_emit_by_name (GTK_OBJECT (data), "changed", path, &iter); gtk_tree_path_free (path); diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index 6b2daa569..63e81c076 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -110,6 +110,9 @@ struct _GtkTreeViewPrivate GtkTreeViewColumn *scroll_to_column; gfloat scroll_to_row_align; gfloat scroll_to_col_align; + + /* hint to display rows in alternating colors */ + guint has_rules : 1; }; #ifdef __GNUC__ diff --git a/gtk/gtktreeselection.c b/gtk/gtktreeselection.c index 509b270d4..baf424a14 100644 --- a/gtk/gtktreeselection.c +++ b/gtk/gtktreeselection.c @@ -707,6 +707,9 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) &node); gtk_tree_path_free (anchor_path); + + if (tree == NULL) + return FALSE; if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) { @@ -976,6 +979,7 @@ gtk_tree_selection_real_select_node (GtkTreeSelection *selection, selected = TRUE; gtk_tree_path_free (path); } + if (selected == TRUE) { node->flags ^= GTK_RBNODE_IS_SELECTED; diff --git a/gtk/gtktreesortable.h b/gtk/gtktreesortable.h index 403073e5b..8c7ed59b9 100644 --- a/gtk/gtktreesortable.h +++ b/gtk/gtktreesortable.h @@ -26,6 +26,12 @@ extern "C" { #endif /* __cplusplus */ +typedef enum +{ + GTK_TREE_SORT_ASCENDING, + GTK_TREE_SORT_DESCENDING +} GtkTreeSortOrder; + #define GTK_TYPE_TREE_SORTABLE (gtk_tree_sortable_get_type ()) #define GTK_TREE_SORTABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TREE_SORTABLE, GtkTreeSortable)) #define GTK_IS_TREE_SORTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TREE_SORTABLE)) @@ -38,14 +44,19 @@ struct _GtkTreeSortableIface { GTypeInterface g_iface; - /* FIXME think about sorting reverse when the column is clicked - * a second time. - */ - gboolean (* column_sortable) (GtkTreeSortable *sortable, - gint column); - gint (* get_sort_column) (GtkTreeSortable *sortable); - void (* set_sort_column) (GtkTreeSortable *sortable, - gint column); + /* This one is a signal */ + void (* sort_column_changed) (GtkTreeSortable *sortable); + + /* virtual methods */ + gboolean (* column_sortable) (GtkTreeSortable *sortable, + gint column, + GtkTreeSortOrder order); + void (* get_sort_column) (GtkTreeSortable *sortable, + gint *column, + GtkTreeSortOrder *order); + void (* set_sort_column) (GtkTreeSortable *sortable, + gint column, + GtkTreeSortOrder order); }; diff --git a/gtk/gtktreestore.c b/gtk/gtktreestore.c index d44c46819..d54bab9d3 100644 --- a/gtk/gtktreestore.c +++ b/gtk/gtktreestore.c @@ -1061,14 +1061,12 @@ gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source, &iter, path)) { - g_print ("data_delete deleting tree row\n"); gtk_tree_store_remove (GTK_TREE_STORE (drag_source), &iter); return TRUE; } else { - g_print ("data_delete path not in tree\n"); return FALSE; } } @@ -1117,9 +1115,6 @@ copy_node_data (GtkTreeStore *tree_store, copy_iter = _gtk_tree_data_list_node_copy (dl, tree_store->column_headers[col]); - g_print ("copied col %d type %s\n", col, - g_type_name (tree_store->column_headers[col])); - if (copy_head == NULL) copy_head = copy_iter; @@ -1205,7 +1200,6 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, &src_iter, src_path)) { - g_print ("can't get source path as iter\n"); goto out; } @@ -1240,8 +1234,6 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, dest_parent_p); retval = TRUE; - - g_print ("prepending to tree\n"); } else { @@ -1256,10 +1248,7 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, &tmp_iter); retval = TRUE; - g_print ("inserting into tree\n"); } - else - g_print ("can't get iter to insert after\n"); } gtk_tree_path_free (prev); @@ -1280,7 +1269,7 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, /* FIXME maybe add some data targets eventually, or handle text * targets in the simple case. */ - g_print ("not accepting target\n"); + } out: diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index db5de4e46..b30eeefb1 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -28,6 +28,8 @@ #include "gtkbutton.h" #include "gtkalignment.h" #include "gtklabel.h" +#include "gtkhbox.h" +#include "gtkarrow.h" #include @@ -437,10 +439,6 @@ gtk_tree_view_realize (GtkWidget *widget) tree_view = GTK_TREE_VIEW (widget); - if (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP) && - tree_view->priv->model) - gtk_tree_view_setup_model (tree_view); - gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); @@ -768,7 +766,9 @@ gtk_tree_view_size_allocate (GtkWidget *widget, widget->allocation = *allocation; tree_view = GTK_TREE_VIEW (widget); - + + gtk_tree_view_check_dirty (tree_view); + tmp_list = tree_view->priv->children; while (tmp_list) @@ -788,28 +788,25 @@ gtk_tree_view_size_allocate (GtkWidget *widget, gtk_widget_size_allocate (child->widget, &allocation); } + gtk_tree_view_size_allocate_buttons (widget); + if (GTK_WIDGET_REALIZED (widget)) { gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); + gdk_window_move_resize (tree_view->priv->header_window, 0, 0, MAX (tree_view->priv->width, allocation->width), tree_view->priv->header_height); } - - /* FIXME I don't think the invariant that the model must be setup - * before touching the buttons is maintained in most of the - * rest of the code, e.g. in realize, so something is wrong - */ - if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP)) - gtk_tree_view_size_allocate_buttons (widget); tree_view->priv->hadjustment->page_size = allocation->width; tree_view->priv->hadjustment->page_increment = allocation->width / 2; tree_view->priv->hadjustment->lower = 0; tree_view->priv->hadjustment->upper = tree_view->priv->width; + if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width) tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0); gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed"); @@ -818,9 +815,11 @@ gtk_tree_view_size_allocate (GtkWidget *widget, tree_view->priv->vadjustment->page_increment = (allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2; tree_view->priv->vadjustment->lower = 0; tree_view->priv->vadjustment->upper = tree_view->priv->height; + if (tree_view->priv->vadjustment->value + allocation->height > tree_view->priv->height) gtk_adjustment_set_value (tree_view->priv->vadjustment, (gfloat) MAX (tree_view->priv->height - allocation->height, 0)); + gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed"); } @@ -879,12 +878,14 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, depth = gtk_tree_path_get_depth (path); - if (_gtk_tree_view_find_node (tree_view, - path, - &tree, - &node)) - return NULL; + _gtk_tree_view_find_node (tree_view, + path, + &tree, + &node); + if (tree == NULL) + return NULL; + if (!gtk_tree_model_get_iter (tree_view->priv->model, &iter, path)) @@ -970,9 +971,9 @@ gtk_tree_view_bin_expose (GtkWidget *widget, GtkTreePath *path; GtkRBTree *tree; GList *list; - GtkRBNode *node, *last_node = NULL; + GtkRBNode *node; GtkRBNode *cursor = NULL; - GtkRBTree *cursor_tree = NULL, *last_tree = NULL; + GtkRBTree *cursor_tree = NULL; GtkRBNode *drag_highlight = NULL; GtkRBTree *drag_highlight_tree = NULL; GtkTreeIter iter; @@ -984,7 +985,6 @@ gtk_tree_view_bin_expose (GtkWidget *widget, GdkRectangle background_area; GdkRectangle cell_area; guint flags; - gboolean last_selected; gint highlight_x; gint bin_window_width; GtkTreePath *cursor_path; @@ -1014,10 +1014,6 @@ gtk_tree_view_bin_expose (GtkWidget *widget, if (node == NULL) return TRUE; - /* See if the last node was selected */ - _gtk_rbtree_prev_full (tree, node, &last_tree, &last_node); - last_selected = (last_node && GTK_RBNODE_FLAG_SET (last_node, GTK_RBNODE_IS_SELECTED)); - /* find the path for the node */ path = _gtk_tree_view_find_path ((GtkTreeView *)widget, tree, @@ -1060,45 +1056,39 @@ gtk_tree_view_bin_expose (GtkWidget *widget, max_height = MAX (TREE_VIEW_EXPANDER_MIN_HEIGHT, GTK_RBNODE_GET_HEIGHT (node)); else */ + gboolean parity; + max_height = BACKGROUND_HEIGHT (node); x_offset = -event->area.x; cell_offset = 0; highlight_x = 0; /* should match x coord of first cell */ - background_area.y = y_offset + event->area.y + TREE_VIEW_VERTICAL_SEPARATOR / 2; - background_area.height = max_height - TREE_VIEW_VERTICAL_SEPARATOR; + background_area.y = y_offset + event->area.y; + background_area.height = max_height; flags = 0; if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT)) flags |= GTK_CELL_RENDERER_PRELIT; + parity = _gtk_rbtree_node_find_parity (tree, node); + if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) - { - flags |= GTK_CELL_RENDERER_SELECTED; - - /* Draw the selection */ - gdk_draw_rectangle (event->window, - GTK_WIDGET (tree_view)->style->bg_gc [GTK_STATE_SELECTED], - TRUE, - event->area.x, - background_area.y - (last_selected?TREE_VIEW_VERTICAL_SEPARATOR:0), - event->area.width, - background_area.height + (last_selected?TREE_VIEW_VERTICAL_SEPARATOR:0)); - last_selected = TRUE; - } - else - { - last_selected = FALSE; - } - + flags |= GTK_CELL_RENDERER_SELECTED; + for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next) { GtkTreeViewColumn *column = list->data; - + const gchar *detail = NULL; + if (!column->visible) - continue; + continue; + if (column->show_sort_indicator) + flags |= GTK_CELL_RENDERER_SORTED; + else + flags &= ~GTK_CELL_RENDERER_SORTED; + cell = column->cell; gtk_tree_view_column_set_cell_data (column, tree_view->priv->model, @@ -1106,10 +1096,75 @@ gtk_tree_view_bin_expose (GtkWidget *widget, background_area.x = cell_offset; background_area.width = TREE_VIEW_COLUMN_WIDTH (column); + + cell_area = background_area; + cell_area.y += TREE_VIEW_VERTICAL_SEPARATOR / 2; + cell_area.height -= TREE_VIEW_VERTICAL_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 1 + if (tree_view->priv->has_rules) + { + if (flags & GTK_CELL_RENDERER_SORTED) + { + if (parity) + detail = "cell_odd_ruled_sorted"; + else + detail = "cell_even_ruled_sorted"; + } + else + { + if (parity) + detail = "cell_odd_ruled"; + else + detail = "cell_even_ruled"; + } + } + else + { + if (flags & GTK_CELL_RENDERER_SORTED) + { + if (parity) + detail = "cell_odd_sorted"; + else + detail = "cell_even_sorted"; + } + else + { + if (parity) + detail = "cell_odd"; + else + detail = "cell_even"; + } + } + + g_assert (detail); +#endif + + /* Draw background */ + gtk_paint_flat_box (widget->style, + event->window, + (flags & GTK_CELL_RENDERER_SELECTED) ? + GTK_STATE_SELECTED : GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + &event->area, + widget, + detail, + background_area.x, + background_area.y, + background_area.width, + background_area.height); + if (i == tree_view->priv->expander_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; @@ -1118,7 +1173,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget, * level of the tree we're dropping at. */ highlight_x = cell_area.x; - + gtk_cell_renderer_render (cell, event->window, widget, @@ -1126,6 +1181,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget, &cell_area, &event->area, flags); + if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT) { gint x, y; @@ -1137,8 +1193,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget, } } else - { - cell_area = background_area; + { gtk_cell_renderer_render (cell, event->window, widget, @@ -1196,6 +1251,9 @@ gtk_tree_view_bin_expose (GtkWidget *widget, tree = node->children; node = tree->root; + + g_assert (node != tree->nil); + while (node->left != tree->nil) node = node->left; has_child = gtk_tree_model_iter_children (tree_view->priv->model, @@ -1246,7 +1304,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget, } } while (y_offset < event->area.height); - + if (cursor_path) gtk_tree_path_free (cursor_path); @@ -1284,6 +1342,9 @@ coords_are_over_arrow (GtkTreeView *tree_view, GdkRectangle arrow; gint x2; + if (!GTK_WIDGET_REALIZED (tree_view)) + return FALSE; + if ((node->flags & GTK_RBNODE_IS_PARENT) == 0) return FALSE; @@ -1351,6 +1412,12 @@ do_prelight (GtkTreeView *tree_view, GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT); } +static void +ensure_unprelighted (GtkTreeView *tree_view) +{ + do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */ +} + static gboolean gtk_tree_view_motion (GtkWidget *widget, GdkEventMotion *event) @@ -1406,7 +1473,7 @@ gtk_tree_view_motion (GtkWidget *widget, &tree, &node); - if (node == NULL) + if (tree == NULL) return TRUE; /* If we are currently pressing down a button, we don't want to prelight anything else. */ @@ -1502,7 +1569,7 @@ gtk_tree_view_leave_notify (GtkWidget *widget, tree_view->priv->prelight_node, NULL); - do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */ + ensure_unprelighted (tree_view); return TRUE; } @@ -1756,14 +1823,14 @@ gtk_tree_view_button_release (GtkWidget *widget, tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree; tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node; gtk_tree_model_get_iter (tree_view->priv->model, &iter, path); - gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter); - - gtk_tree_view_build_tree (tree_view, - tree_view->priv->button_pressed_node->children, - &child, - gtk_tree_path_get_depth (path) + 1, - FALSE, - GTK_WIDGET_REALIZED (widget)); + + if (gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter)) + gtk_tree_view_build_tree (tree_view, + tree_view->priv->button_pressed_node->children, + &child, + gtk_tree_path_get_depth (path) + 1, + FALSE, + GTK_WIDGET_REALIZED (widget)); } else { @@ -2422,6 +2489,9 @@ gtk_tree_view_changed (GtkTreeModel *model, /* We aren't actually showing the node */ return; + if (tree == NULL) + return; + dirty_marked = gtk_tree_view_discover_dirty_iter (tree_view, iter, gtk_tree_path_get_depth (path), @@ -2554,6 +2624,9 @@ gtk_tree_view_child_toggled (GtkTreeModel *model, /* We aren't actually showing the node */ return; + if (tree == NULL) + return; + has_child = gtk_tree_model_iter_has_child (model, &real_iter); /* Sanity check. */ @@ -2596,12 +2669,15 @@ gtk_tree_view_deleted (GtkTreeModel *model, GtkRBTree *tree; GtkRBNode *node; GList *list; - + g_return_if_fail (path != NULL); if (_gtk_tree_view_find_node (tree_view, path, &tree, &node)) return; + if (tree == NULL) + return; + /* next, update the selection */ if (tree_view->priv->anchor) { @@ -2633,11 +2709,20 @@ gtk_tree_view_deleted (GtkTreeModel *model, ((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE) ((GtkTreeViewColumn *)list->data)->dirty = TRUE; + /* Ensure we don't have a dangling pointer to a dead node */ + ensure_unprelighted (tree_view); + + g_assert (tree_view->priv->prelight_node == NULL); + if (tree->root->count == 1) - _gtk_rbtree_remove (tree); + { + _gtk_rbtree_remove (tree); + } else - _gtk_rbtree_remove_node (tree, node); - + { + _gtk_rbtree_remove_node (tree, node); + } + _gtk_tree_view_set_size (GTK_TREE_VIEW (data), -1, -1); } @@ -2905,6 +2990,10 @@ gtk_tree_view_check_dirty (GtkTreeView *tree_view) GtkTreeViewColumn *column; GtkTreeIter iter; + if (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP) && + tree_view->priv->model) + gtk_tree_view_setup_model (tree_view); + for (list = tree_view->priv->columns; list; list = list->next) { column = list->data; @@ -2913,13 +3002,22 @@ gtk_tree_view_check_dirty (GtkTreeView *tree_view) dirty = TRUE; if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE) { - gtk_tree_view_column_set_width (column, MAX (column->button->requisition.width, 1)); + gint w = 1; + + if (column->button) + w = MAX (w, column->button->requisition.width); + + gtk_tree_view_column_set_width (column, w); } } } + if (dirty == FALSE) return; + if (tree_view->priv->model == NULL) + return; + path = gtk_tree_path_new_root (); if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path)) { @@ -2948,8 +3046,8 @@ gtk_tree_view_create_button (GtkTreeView *tree_view, button = column->button = gtk_button_new (); gtk_widget_pop_composite_child (); - gtk_widget_set_parent (button, GTK_WIDGET (tree_view)); - + gtk_widget_set_parent (button, GTK_WIDGET (tree_view));\ + gtk_signal_connect (GTK_OBJECT (button), "clicked", (GtkSignalFunc) gtk_tree_view_button_clicked, (gpointer) tree_view); @@ -2965,7 +3063,13 @@ gtk_tree_view_create_buttons (GtkTreeView *tree_view) GList *list; GtkTreeViewColumn *column; gint i; + GtkWidget *hbox; + GtkWidget *arrow; + /* FIXME this has to be merged with update_button_contents() in + * gtktreeviewcolumn.c + */ + for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++) { column = list->data; @@ -2974,23 +3078,14 @@ gtk_tree_view_create_buttons (GtkTreeView *tree_view) continue; gtk_tree_view_create_button (tree_view, i); - switch (column->justification) - { - case GTK_JUSTIFY_LEFT: - alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0); - break; - case GTK_JUSTIFY_RIGHT: - alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0); - break; - case GTK_JUSTIFY_CENTER: - alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); - break; - case GTK_JUSTIFY_FILL: - default: - alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); - break; - } + alignment = gtk_alignment_new (column->xalign, 0.5, 0.0, 0.0); + hbox = gtk_hbox_new (FALSE, 2); + arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN); + + column->arrow = arrow; + column->alignment = alignment; + if (column->child) label = column->child; else @@ -2999,10 +3094,19 @@ gtk_tree_view_create_buttons (GtkTreeView *tree_view) gtk_widget_show (label); } - gtk_container_add (GTK_CONTAINER (alignment), label); - gtk_container_add (GTK_CONTAINER (column->button), alignment); + if (column->xalign <= 0.5) + gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); + else + gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0); + + gtk_container_add (GTK_CONTAINER (alignment), label); + gtk_container_add (GTK_CONTAINER (column->button), hbox); + + gtk_widget_show (hbox); gtk_widget_show (alignment); + /* don't show the arrow yet */ } gtk_tree_view_size_request_buttons (tree_view); @@ -3104,7 +3208,10 @@ _gtk_tree_view_find_path (GtkTreeView *tree_view, return path; } -/* Returns whether or not it's a parent, or not */ +/* Returns TRUE if we ran out of tree before finding the node, + * so the returned node is the last node we saw and the returned + * tree is NULL + */ gboolean _gtk_tree_view_find_node (GtkTreeView *tree_view, GtkTreePath *path, @@ -3129,7 +3236,8 @@ _gtk_tree_view_find_node (GtkTreeView *tree_view, return TRUE; } tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1); - if (++i >= depth) + ++i; + if (i >= depth) { *node = tmpnode; *tree = tmptree; @@ -3269,6 +3377,7 @@ _gtk_tree_view_set_size (GtkTreeView *tree_view, width += TREE_VIEW_COLUMN_WIDTH (column); } } + if (height == -1) height = tree_view->priv->tree->root->offset + TREE_VIEW_VERTICAL_SEPARATOR; @@ -3292,6 +3401,7 @@ _gtk_tree_view_set_size (GtkTreeView *tree_view, gdk_window_resize (tree_view->priv->bin_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), height + TREE_VIEW_HEADER_HEIGHT (tree_view)); gdk_window_resize (tree_view->priv->header_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), tree_view->priv->header_height); } + gtk_widget_queue_resize (GTK_WIDGET (tree_view)); } @@ -4557,6 +4667,10 @@ gtk_tree_view_collapse_all_helper (GtkRBTree *tree, node->children, &iter, gtk_tree_path_get_depth (path)); + + /* Ensure we don't have a dangling pointer to a dead node */ + ensure_unprelighted (GTK_TREE_VIEW (data)); + _gtk_rbtree_remove (node->children); gtk_tree_path_free (path); } @@ -4620,7 +4734,7 @@ gtk_tree_view_expand_row (GtkTreeView *tree_view, &tree, &node)) return FALSE; - + if (node->children) return TRUE; @@ -4682,6 +4796,12 @@ gtk_tree_view_collapse_row (GtkTreeView *tree_view, node->children, &iter, gtk_tree_path_get_depth (path)); + + /* Ensure we don't have a dangling pointer to a dead node */ + ensure_unprelighted (tree_view); + + g_assert (tree_view->priv->prelight_node == NULL); + _gtk_rbtree_remove (node->children); if (GTK_WIDGET_MAPPED (tree_view)) @@ -4785,6 +4905,56 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view, } } +/** + * gtk_tree_view_set_rules_hint + * @tree_view: a #GtkTreeView + * @setting: %TRUE if the tree requires reading across rows + * + * This function tells GTK+ that the user interface for your + * application requires users to read across tree rows and associate + * cells with one another. By default, GTK+ will then render the tree + * with alternating row colors. DO NOT use it + * just because you prefer the appearance of the ruled tree; that's a + * question for the theme. Some themes will draw tree rows in + * alternating colors even when rules are turned off, and users who + * prefer that appearance all the time can choose those themes. You + * should call this function only as a semantic + * hint to the theme engine that your tree makes alternating colors + * useful from a functional standpoint (since it has lots of columns, + * generally). + * + **/ +void +gtk_tree_view_set_rules_hint (GtkTreeView *tree_view, + gboolean setting) +{ + g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + + setting = setting != FALSE; + + if (tree_view->priv->has_rules != setting) + { + tree_view->priv->has_rules = setting; + gtk_widget_queue_draw (GTK_WIDGET (tree_view)); + } +} + +/** + * gtk_tree_view_get_rules_hint + * @tree_view: a #GtkTreeView + * + * Gets the setting set by gtk_tree_view_set_rules_hint(). + * + * Return value: %TRUE if rules are useful for the user of this tree + **/ +gboolean +gtk_tree_view_get_rules_hint (GtkTreeView *tree_view) +{ + g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE); + + return tree_view->priv->has_rules; +} + /* Drag-and-drop */ static void @@ -5447,8 +5617,6 @@ gtk_tree_view_drag_data_delete (GtkWidget *widget, tree_view = GTK_TREE_VIEW (widget); model = gtk_tree_view_get_model (tree_view); - - g_print ("data_delete\n"); if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete")) return; @@ -5491,7 +5659,6 @@ gtk_tree_view_drag_leave (GtkWidget *widget, di = get_info (GTK_TREE_VIEW (widget)); /* unset any highlight row */ - g_print ("drag leave\n"); gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, GTK_TREE_VIEW_DROP_BEFORE); @@ -5561,7 +5728,6 @@ set_destination_row (GtkTreeView *tree_view, * we return FALSE drag_leave isn't called */ - g_print ("no longer a drag dest\n"); gtk_tree_view_set_drag_dest_row (tree_view, NULL, GTK_TREE_VIEW_DROP_BEFORE); @@ -5575,7 +5741,6 @@ set_destination_row (GtkTreeView *tree_view, *target = gtk_drag_dest_find_target (widget, context, di->dest_target_list); if (*target == GDK_NONE) { - g_print ("bad target, not accepting\n"); return FALSE; } @@ -5587,7 +5752,6 @@ set_destination_row (GtkTreeView *tree_view, /* can't drop here */ remove_open_timeout (tree_view); - g_print ("no drag row here\n"); gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, GTK_TREE_VIEW_DROP_BEFORE); @@ -5631,7 +5795,6 @@ set_destination_row (GtkTreeView *tree_view, *suggested_action = GDK_ACTION_MOVE; } - g_print ("setting drag dest row\n"); gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), path, pos); } @@ -5640,7 +5803,6 @@ set_destination_row (GtkTreeView *tree_view, /* can't drop here */ remove_open_timeout (tree_view); - g_print ("droppable predicate false\n"); gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, GTK_TREE_VIEW_DROP_BEFORE); @@ -5664,8 +5826,6 @@ gtk_tree_view_drag_motion (GtkWidget *widget, tree_view = GTK_TREE_VIEW (widget); - g_print ("motion\n"); - if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target)) return FALSE; @@ -5676,7 +5836,6 @@ gtk_tree_view_drag_motion (GtkWidget *widget, if (path == NULL) { /* Can't drop here. */ - g_print ("not over a dest row\n"); gdk_drag_status (context, 0, time); } else @@ -5695,13 +5854,11 @@ gtk_tree_view_drag_motion (GtkWidget *widget, * determining whether to accept the drop */ set_status_pending (context, suggested_action); - g_print ("motion requesting the drop data\n"); gtk_drag_get_data (widget, context, target, time); } else { set_status_pending (context, 0); - g_print ("motion sending positive status\n"); gdk_drag_status (context, suggested_action, time); } } @@ -5760,8 +5917,6 @@ gtk_tree_view_drag_drop (GtkWidget *widget, model = gtk_tree_view_get_model (tree_view); - g_print ("drop\n"); - remove_scroll_timeout (GTK_TREE_VIEW (widget)); remove_open_timeout (GTK_TREE_VIEW (widget)); @@ -5780,8 +5935,6 @@ gtk_tree_view_drag_drop (GtkWidget *widget, if (target != GDK_NONE && path != NULL) { - g_print ("have target\n"); - /* in case a motion had requested drag data, change things so we * treat drag data receives as a drop. */ @@ -5800,7 +5953,6 @@ gtk_tree_view_drag_drop (GtkWidget *widget, if (target != GDK_NONE) { - g_print ("getting data\n"); gtk_drag_get_data (widget, context, target, time); return TRUE; } @@ -5831,8 +5983,6 @@ gtk_tree_view_drag_data_received (GtkWidget *widget, if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received")) return; - - g_print ("drag data received\n"); di = get_info (tree_view); @@ -5874,8 +6024,6 @@ gtk_tree_view_drag_data_received (GtkWidget *widget, gtk_tree_path_free (src_path); } } - - g_print ("suggested action %d in drag_data_received\n", suggested_action); gdk_drag_status (context, suggested_action, time); @@ -5903,8 +6051,6 @@ gtk_tree_view_drag_data_received (GtkWidget *widget, selection_data)) accepted = TRUE; } - - g_print ("accepted: %d\n", accepted); gtk_drag_finish (context, accepted, diff --git a/gtk/gtktreeview.h b/gtk/gtktreeview.h index fd36f4d0a..cb23a4e90 100644 --- a/gtk/gtktreeview.h +++ b/gtk/gtktreeview.h @@ -155,6 +155,9 @@ void gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view, gint *wx, gint *wy); +void gtk_tree_view_set_rules_hint (GtkTreeView *tree_view, + gboolean setting); +gboolean gtk_tree_view_get_rules_hint (GtkTreeView *tree_view); /* Drag-and-Drop support */ diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 1d7dab0ee..7515327c4 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -23,6 +23,8 @@ #include "gtkbutton.h" #include "gtkalignment.h" #include "gtklabel.h" +#include "gtkhbox.h" +#include "gtkarrow.h" #include "gtkintl.h" enum @@ -38,7 +40,9 @@ enum PROP_TITLE, PROP_CLICKABLE, PROP_WIDGET, - PROP_JUSTIFICATION + PROP_ALIGNMENT, + PROP_SORT_INDICATOR, + PROP_SORT_ORDER }; enum @@ -200,13 +204,32 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, - PROP_JUSTIFICATION, - g_param_spec_enum ("justification", - _("Justification"), - _("Justification of the column"), - GTK_TYPE_JUSTIFICATION, - GTK_JUSTIFY_LEFT, + PROP_ALIGNMENT, + g_param_spec_float ("alignment", + _("Alignment"), + _("Alignment of the column header text or widget"), + 0.0, + 1.0, + 0.5, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_SORT_INDICATOR, + g_param_spec_boolean ("sort_indicator", + _("Sort indicator"), + _("Whether to show a sort indicator"), + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (object_class, + PROP_SORT_ORDER, + g_param_spec_enum ("sort_order", + _("Sort order"), + _("Sort direction the sort indicator should indicate"), + GTK_TYPE_TREE_SORT_ORDER, + GTK_TREE_SORT_ASCENDING, G_PARAM_READABLE | G_PARAM_WRITABLE)); + } static void @@ -217,7 +240,7 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) gtk_object_sink (GTK_OBJECT (tree_column)); tree_column->button = NULL; - tree_column->justification = GTK_JUSTIFY_LEFT; + tree_column->xalign = 0.0; tree_column->width = 1; tree_column->min_width = -1; tree_column->max_width = -1; @@ -227,6 +250,8 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) tree_column->visible = TRUE; tree_column->button_active = FALSE; tree_column->dirty = TRUE; + tree_column->sort_order = GTK_TREE_SORT_ASCENDING; + tree_column->show_sort_indicator = FALSE; } static void @@ -288,11 +313,21 @@ gtk_tree_view_column_set_property (GObject *object, (GtkWidget*) g_value_get_object (value)); break; - case PROP_JUSTIFICATION: - gtk_tree_view_column_set_justification (tree_column, - g_value_get_enum (value)); + case PROP_ALIGNMENT: + gtk_tree_view_column_set_alignment (tree_column, + g_value_get_float (value)); + break; + + case PROP_SORT_INDICATOR: + gtk_tree_view_column_set_sort_indicator (tree_column, + g_value_get_boolean (value)); break; + case PROP_SORT_ORDER: + gtk_tree_view_column_set_sort_order (tree_column, + g_value_get_enum (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -313,50 +348,69 @@ gtk_tree_view_column_get_property (GObject *object, switch (prop_id) { case PROP_CELL_RENDERER: - g_value_set_object (value, (GObject*) tree_column->cell); + g_value_set_object (value, + (GObject*) gtk_tree_view_column_get_cell_renderer (tree_column)); break; case PROP_VISIBLE: - g_value_set_boolean (value, tree_column->visible); + g_value_set_boolean (value, + gtk_tree_view_column_get_visible (tree_column)); break; case PROP_SIZING: - g_value_set_enum (value, tree_column->column_type); + g_value_set_enum (value, + gtk_tree_view_column_get_sizing (tree_column)); break; case PROP_WIDTH: - g_value_set_int (value, tree_column->width); + g_value_set_int (value, + gtk_tree_view_column_get_width (tree_column)); break; case PROP_MIN_WIDTH: - g_value_set_int (value, tree_column->min_width); + g_value_set_int (value, + gtk_tree_view_column_get_min_width (tree_column)); break; case PROP_MAX_WIDTH: - g_value_set_int (value, tree_column->max_width); + g_value_set_int (value, + gtk_tree_view_column_get_max_width (tree_column)); break; case PROP_TITLE: - g_value_set_string (value, tree_column->title); + g_value_set_string (value, + gtk_tree_view_column_get_title (tree_column)); break; case PROP_CLICKABLE: - g_value_set_boolean (value, tree_column->button_active); + g_value_set_boolean (value, + gtk_tree_view_column_get_clickable (tree_column)); break; case PROP_WIDGET: - g_warning ("FIXME"); + g_value_set_object (value, + (GObject*) gtk_tree_view_column_get_widget (tree_column)); break; - case PROP_JUSTIFICATION: - g_value_set_enum (value, tree_column->justification); + case PROP_ALIGNMENT: + g_value_set_float (value, + gtk_tree_view_column_get_alignment (tree_column)); break; + case PROP_SORT_INDICATOR: + g_value_set_boolean (value, + gtk_tree_view_column_get_sort_indicator (tree_column)); + break; + + case PROP_SORT_ORDER: + g_value_set_enum (value, + gtk_tree_view_column_get_sort_order (tree_column)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - } /* used to make the buttons 'unclickable' */ @@ -455,8 +509,8 @@ void gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell) { - g_return_if_fail (tree_column != NULL); g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); + if (cell) g_return_if_fail (GTK_IS_CELL_RENDERER (cell)); @@ -471,6 +525,22 @@ gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column, g_object_notify (G_OBJECT (tree_column), "cell_renderer"); } +/** + * gtk_tree_view_column_get_cell_renderer: + * @tree_column: a #GtkTreeViewColumn + * + * Gets the value set with gtk_tree_view_column_set_cell_renderer(). + * + * Return value: cell renderer for the column, or %NULL if unset + **/ +GtkCellRenderer* +gtk_tree_view_column_get_cell_renderer (GtkTreeViewColumn *tree_column) +{ + g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL); + + return tree_column->cell; +} + /** * gtk_tree_view_column_add_attribute: * @tree_column: A #GtkTreeViewColumn. @@ -787,6 +857,22 @@ gtk_tree_view_column_set_width (GtkTreeViewColumn *tree_column, g_object_notify (G_OBJECT (tree_column), "width"); } +/** + * gtk_tree_view_column_get_width: + * @tree_column: a #GtkTreeViewColumn + * + * Gets the value set by gtk_tree_view_column_set_width(). + * + * Return value: the width of the column + **/ +gint +gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column) +{ + g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0); + + return tree_column->width; +} + /** * gtk_tree_view_column_set_min_width: * @tree_column: A #GtkTreeViewColumn. @@ -923,8 +1009,13 @@ update_button_contents (GtkTreeViewColumn *tree_column) { if (tree_column->button) { - GtkWidget *alignment = GTK_BIN (tree_column->button)->child; + GtkWidget *hbox = GTK_BIN (tree_column->button)->child; + GtkWidget *alignment = tree_column->alignment; + GtkWidget *arrow = tree_column->arrow; GtkWidget *current_child = GTK_BIN (alignment)->child; + + gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign, + 0.5, 0.0, 0.0); if (tree_column->child) { @@ -958,6 +1049,50 @@ update_button_contents (GtkTreeViewColumn *tree_column) gtk_label_set_text (GTK_LABEL (current_child), ""); } + + switch (tree_column->sort_order) + { + case GTK_TREE_SORT_ASCENDING: + gtk_arrow_set (GTK_ARROW (arrow), + GTK_ARROW_DOWN, + GTK_SHADOW_IN); + break; + + case GTK_TREE_SORT_DESCENDING: + gtk_arrow_set (GTK_ARROW (arrow), + GTK_ARROW_UP, + GTK_SHADOW_IN); + break; + + default: + g_warning (G_STRLOC": bad sort order"); + break; + } + + /* Put arrow on the right if the text is left-or-center justified, + * and on the left otherwise; do this by packing boxes, so flipping + * text direction will reverse things + */ + gtk_widget_ref (arrow); + gtk_container_remove (GTK_CONTAINER (hbox), arrow); + + if (tree_column->xalign <= 0.5) + { + gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); + } + else + { + gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); + /* move it to the front */ + gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0); + } + + gtk_widget_unref (arrow); + + if (tree_column->show_sort_indicator) + gtk_widget_show (arrow); + else + gtk_widget_hide (arrow); } } @@ -995,7 +1130,7 @@ gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column, * * Return value: the title of the column. **/ -gchar * +G_CONST_RETURN gchar * gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column) { g_return_val_if_fail (tree_column != NULL, NULL); @@ -1120,54 +1255,126 @@ gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column) } /** - * gtk_tree_view_column_set_justification: + * gtk_tree_view_column_set_alignment: * @tree_column: A #GtkTreeViewColumn. - * @justification: The justification of the title. + * @xalign: alignment (0.0 for left, 0.5 for center, 1.0 for right) * - * Sets the justification of the title inside the column header. If a custom - * widget has been set, then this value is discarded. + * Sets the alignment of the title or custom widget inside the column header. **/ void -gtk_tree_view_column_set_justification (GtkTreeViewColumn *tree_column, - GtkJustification justification) +gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column, + gfloat xalign) { - GtkWidget *alignment; - g_return_if_fail (tree_column != NULL); g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); - if (tree_column->justification == justification) + if (tree_column->xalign == xalign) return; - tree_column->justification = justification; + tree_column->xalign = xalign; + + update_button_contents (tree_column); + + g_object_notify (G_OBJECT (tree_column), "alignment"); +} - alignment = GTK_BIN (tree_column->button)->child; +gfloat +gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column) +{ + g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5); - if (GTK_IS_ALIGNMENT (alignment)) + return tree_column->xalign; +} + +/** + * gtk_tree_view_column_set_sort_indicator: + * @tree_column: a #GtkTreeViewColumn + * @setting: %TRUE to display an indicator that the column is sorted + * + * Call this function with a @setting of %TRUE to display an arrow in + * the header button indicating the column is sorted. Call + * gtk_tree_view_column_set_sort_order() to change the direction of + * the arrow. + * + **/ +void +gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column, + gboolean setting) +{ + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); + + setting = setting != FALSE; + + if (setting != tree_column->show_sort_indicator) { - switch (tree_column->justification) - { - case GTK_JUSTIFY_LEFT: - gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0); - break; - - case GTK_JUSTIFY_RIGHT: - gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0); - break; - - case GTK_JUSTIFY_CENTER: - gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0); - break; - - case GTK_JUSTIFY_FILL: - gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0); - break; - - default: - break; - } + tree_column->show_sort_indicator = setting; + + update_button_contents (tree_column); + + g_object_notify (G_OBJECT (tree_column), "sort_indicator"); } +} + +/** + * gtk_tree_view_column_get_sort_indicator: + * @tree_column: a #GtkTreeViewColumn + * + * Gets the value set by gtk_tree_view_column_set_sort_indicator(). + * + * Return value: whether the sort indicator arrow is displayed + **/ +gboolean +gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column) +{ + g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE); + + return tree_column->show_sort_indicator; +} + +/** + * gtk_tree_view_column_set_sort_order: + * @tree_column: a #GtkTreeViewColumn + * @order: sort order that the sort indicator should indicate + * + * Changes the appearance of the sort indicator. (This does + * not actually sort the model - for the models shipped + * with GTK+, use at gtk_tree_sortable_set_sort_column() to do + * that. For custom models, the mechanism will vary.) The sort + * indicator changes direction to indicate normal sort or reverse + * sort. Note that you must have the sort indicator enabled to see + * anything when calling this function; see + * gtk_tree_view_column_set_sort_indicator(). + * + **/ +void +gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column, + GtkTreeSortOrder order) +{ + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); + + if (order != tree_column->sort_order) + { + tree_column->sort_order = order; + + update_button_contents (tree_column); + + g_object_notify (G_OBJECT (tree_column), "sort_order"); + } +} + +/** + * gtk_tree_view_column_get_sort_order: + * @tree_column: a #GtkTreeViewColumn + * + * Gets the value set by gtk_tree_view_column_set_sort_order(). + * + * Return value: the sort order the sort indicator is indicating + **/ +GtkTreeSortOrder +gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column) +{ + g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0); - g_object_notify (G_OBJECT (tree_column), "justification"); + return tree_column->sort_order; } diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h index ea13946c4..3dbc471af 100644 --- a/gtk/gtktreeviewcolumn.h +++ b/gtk/gtktreeviewcolumn.h @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -55,9 +56,11 @@ struct _GtkTreeViewColumn GtkWidget *tree_view; GtkWidget *button; - GtkWidget *child; + GtkWidget *child; + GtkWidget *arrow; + GtkWidget *alignment; GdkWindow *window; - GtkJustification justification; + gfloat xalign; gint id; @@ -71,9 +74,11 @@ struct _GtkTreeViewColumn GtkCellRenderer *cell; GSList *attributes; GtkTreeViewColumnSizing column_type; + GtkTreeSortOrder sort_order; guint visible : 1; guint button_active : 1; guint dirty : 1; + guint show_sort_indicator : 1; }; struct _GtkTreeViewColumnClass @@ -91,6 +96,7 @@ GtkTreeViewColumn *gtk_tree_view_column_new_with_attributes (gchar ...); void gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell); +GtkCellRenderer *gtk_tree_view_column_get_cell_renderer (GtkTreeViewColumn *tree_column); void gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column, gchar *attribute, gint column); @@ -121,18 +127,26 @@ void gtk_tree_view_column_clicked (GtkTreeViewColumn /* Options for manipulating the column headers */ -void gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column, - gchar *title); -gchar *gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column); -void gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column, - gboolean active); -gboolean gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column); -void gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column, - GtkWidget *widget); -GtkWidget *gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column); -void gtk_tree_view_column_set_justification (GtkTreeViewColumn *tree_column, - GtkJustification justification); -GtkJustification gtk_tree_view_column_get_justification (GtkTreeViewColumn *tree_column); +void gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column, + gchar *title); +G_CONST_RETURN gchar *gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column); +void gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column, + gboolean active); +gboolean gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column); +void gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column, + GtkWidget *widget); +GtkWidget * gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column); +void gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column, + gfloat xalign); +gfloat gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column); +void gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column, + gboolean setting); +gboolean gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column); +void gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column, + GtkTreeSortOrder order); +GtkTreeSortOrder gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column); + + diff --git a/tests/testtreeview.c b/tests/testtreeview.c index 5ffcecb25..226d9017a 100644 --- a/tests/testtreeview.c +++ b/tests/testtreeview.c @@ -261,12 +261,17 @@ set_columns_type (GtkTreeView *tree_view, ColumnsType type) col = gtk_tree_view_get_column (tree_view, 0); } + gtk_tree_view_set_rules_hint (tree_view, FALSE); + switch (type) { case COLUMNS_NONE: break; - case COLUMNS_LOTS: + case COLUMNS_LOTS: + /* with lots of columns we need to turn on rules */ + gtk_tree_view_set_rules_hint (tree_view, TRUE); + rend = gtk_cell_renderer_text_new (); col = gtk_tree_view_column_new_with_attributes ("Column 1", @@ -691,7 +696,7 @@ main (int argc, gtk_container_add (GTK_CONTAINER (window), table); tv = gtk_tree_view_new_with_model (models[0]); - + gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (tv), GDK_BUTTON1_MASK, row_targets, @@ -1374,6 +1379,28 @@ int_changed (GObject *object, GParamSpec *pspec, gpointer data) g_value_unset (&val); } +static void +float_modified (GtkAdjustment *adj, gpointer data) +{ + ObjectProperty *p = data; + + g_object_set (p->obj, p->prop, (float) adj->value, NULL); +} + +static void +float_changed (GObject *object, GParamSpec *pspec, gpointer data) +{ + GtkAdjustment *adj = GTK_ADJUSTMENT (data); + GValue val = { 0, }; + + g_value_init (&val, G_TYPE_FLOAT); + g_object_get_property (object, pspec->name, &val); + + if (g_value_get_float (&val) != (float) adj->value) + gtk_adjustment_set_value (adj, g_value_get_float (&val)); + + g_value_unset (&val); +} static void string_modified (GtkEntry *entry, gpointer data) @@ -1559,6 +1586,34 @@ create_prop_editor (GObject *object) object, spec->name, (GtkSignalFunc) int_modified); break; + case G_TYPE_FLOAT: + hbox = gtk_hbox_new (FALSE, 10); + label = gtk_label_new (spec->nick); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + adj = GTK_ADJUSTMENT (gtk_adjustment_new (G_PARAM_SPEC_FLOAT (spec)->default_value, + G_PARAM_SPEC_FLOAT (spec)->minimum, + G_PARAM_SPEC_FLOAT (spec)->maximum, + 0.1, + MAX ((G_PARAM_SPEC_FLOAT (spec)->maximum - + G_PARAM_SPEC_FLOAT (spec)->minimum) / 10, 0.1), + 0.0)); + + prop_edit = gtk_spin_button_new (adj, 0.1, 2); + + gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + g_object_connect_property (object, spec->name, + GTK_SIGNAL_FUNC (float_changed), + adj, G_OBJECT (adj)); + + if (can_modify) + connect_controller (G_OBJECT (adj), "value_changed", + object, spec->name, (GtkSignalFunc) float_modified); + break; + case G_TYPE_STRING: hbox = gtk_hbox_new (FALSE, 10); label = gtk_label_new (spec->nick);