diff options
37 files changed, 2781 insertions, 431 deletions
@@ -1,3 +1,79 @@ +2001-01-26 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor + + * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to + not offset by TREE_VIEW_HEADER_HEIGHT + (gtk_tree_view_tree_to_widget_coords): fix to not offset by + TREE_VIEW_HEADER_HEIGHT + + * configure.in (included_loaders): for me, --with-included-loaders + generates the error "the specified loader yes does not exist", + i.e. the arg defaults to "yes", so change test for value "" + to test for value "yes", and include all loaders in that case. + + * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function + + * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly + handle TREE_VIEW_VERTICAL_SEPARATOR + (gtk_tree_view_bin_expose): fix to consider the row offset as + pointing halfway into vertical separator. + (gtk_tree_view_draw_node_focus_rect): ditto + + * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add + --gtk-debug=updates, which causes gdk_window_set_debug_updates + (TRUE) to be called. + + * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a + debug mode where the invalid region is colored in on invalidate, + so you can see the flicker and know whether your redraw code is + doing a good job. + + * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in + tree window coordinates (clip rect is in tree window coords) + + * gtk/Makefile.am: add gtktreednd.[hc] + + * gtk/gtkliststore.c: implement gtktreednd interfaces. + + * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support + drag-and-drop data operations on a model (so we can set up tree + drag-and-drop automatically) + + * gtk/testgtk.c: Add a window to change sensitivity in the + GtkLabel test; add a way to change the entry frame in GtkEntry + test + + * gtk/gtkentry.c (gtk_entry_set_has_frame): + (gtk_entry_get_has_frame): new functions to remove the frame + around an entry + (gtk_entry_size_request): shrink requisition if no frame + (gtk_entry_draw_focus): don't draw frame if no frame + + * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for + checks inside a cell renderer + (gtk_default_draw_option): ditto for options + + * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove + children from the alignment, not the button + (gtk_tree_view_column_init): ref/sink the column, to emulate + GObject refcounting. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): + Use theme functions to draw the toggles + + * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors + + * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and + GdkPangoAttrEmbossed to use in rendering insensitive text + + * gdk/gdkpango.c (gdk_draw_layout_line): render new properties + + * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity + using new GDK features + 2001-01-24 <alexl@redhat.com> * gtk/gtkimage.c: diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 79db30750d..d0e5037365 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,79 @@ +2001-01-26 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor + + * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to + not offset by TREE_VIEW_HEADER_HEIGHT + (gtk_tree_view_tree_to_widget_coords): fix to not offset by + TREE_VIEW_HEADER_HEIGHT + + * configure.in (included_loaders): for me, --with-included-loaders + generates the error "the specified loader yes does not exist", + i.e. the arg defaults to "yes", so change test for value "" + to test for value "yes", and include all loaders in that case. + + * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function + + * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly + handle TREE_VIEW_VERTICAL_SEPARATOR + (gtk_tree_view_bin_expose): fix to consider the row offset as + pointing halfway into vertical separator. + (gtk_tree_view_draw_node_focus_rect): ditto + + * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add + --gtk-debug=updates, which causes gdk_window_set_debug_updates + (TRUE) to be called. + + * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a + debug mode where the invalid region is colored in on invalidate, + so you can see the flicker and know whether your redraw code is + doing a good job. + + * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in + tree window coordinates (clip rect is in tree window coords) + + * gtk/Makefile.am: add gtktreednd.[hc] + + * gtk/gtkliststore.c: implement gtktreednd interfaces. + + * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support + drag-and-drop data operations on a model (so we can set up tree + drag-and-drop automatically) + + * gtk/testgtk.c: Add a window to change sensitivity in the + GtkLabel test; add a way to change the entry frame in GtkEntry + test + + * gtk/gtkentry.c (gtk_entry_set_has_frame): + (gtk_entry_get_has_frame): new functions to remove the frame + around an entry + (gtk_entry_size_request): shrink requisition if no frame + (gtk_entry_draw_focus): don't draw frame if no frame + + * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for + checks inside a cell renderer + (gtk_default_draw_option): ditto for options + + * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove + children from the alignment, not the button + (gtk_tree_view_column_init): ref/sink the column, to emulate + GObject refcounting. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): + Use theme functions to draw the toggles + + * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors + + * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and + GdkPangoAttrEmbossed to use in rendering insensitive text + + * gdk/gdkpango.c (gdk_draw_layout_line): render new properties + + * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity + using new GDK features + 2001-01-24 <alexl@redhat.com> * gtk/gtkimage.c: diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 79db30750d..d0e5037365 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,79 @@ +2001-01-26 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor + + * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to + not offset by TREE_VIEW_HEADER_HEIGHT + (gtk_tree_view_tree_to_widget_coords): fix to not offset by + TREE_VIEW_HEADER_HEIGHT + + * configure.in (included_loaders): for me, --with-included-loaders + generates the error "the specified loader yes does not exist", + i.e. the arg defaults to "yes", so change test for value "" + to test for value "yes", and include all loaders in that case. + + * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function + + * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly + handle TREE_VIEW_VERTICAL_SEPARATOR + (gtk_tree_view_bin_expose): fix to consider the row offset as + pointing halfway into vertical separator. + (gtk_tree_view_draw_node_focus_rect): ditto + + * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add + --gtk-debug=updates, which causes gdk_window_set_debug_updates + (TRUE) to be called. + + * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a + debug mode where the invalid region is colored in on invalidate, + so you can see the flicker and know whether your redraw code is + doing a good job. + + * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in + tree window coordinates (clip rect is in tree window coords) + + * gtk/Makefile.am: add gtktreednd.[hc] + + * gtk/gtkliststore.c: implement gtktreednd interfaces. + + * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support + drag-and-drop data operations on a model (so we can set up tree + drag-and-drop automatically) + + * gtk/testgtk.c: Add a window to change sensitivity in the + GtkLabel test; add a way to change the entry frame in GtkEntry + test + + * gtk/gtkentry.c (gtk_entry_set_has_frame): + (gtk_entry_get_has_frame): new functions to remove the frame + around an entry + (gtk_entry_size_request): shrink requisition if no frame + (gtk_entry_draw_focus): don't draw frame if no frame + + * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for + checks inside a cell renderer + (gtk_default_draw_option): ditto for options + + * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove + children from the alignment, not the button + (gtk_tree_view_column_init): ref/sink the column, to emulate + GObject refcounting. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): + Use theme functions to draw the toggles + + * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors + + * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and + GdkPangoAttrEmbossed to use in rendering insensitive text + + * gdk/gdkpango.c (gdk_draw_layout_line): render new properties + + * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity + using new GDK features + 2001-01-24 <alexl@redhat.com> * gtk/gtkimage.c: diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 79db30750d..d0e5037365 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,79 @@ +2001-01-26 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor + + * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to + not offset by TREE_VIEW_HEADER_HEIGHT + (gtk_tree_view_tree_to_widget_coords): fix to not offset by + TREE_VIEW_HEADER_HEIGHT + + * configure.in (included_loaders): for me, --with-included-loaders + generates the error "the specified loader yes does not exist", + i.e. the arg defaults to "yes", so change test for value "" + to test for value "yes", and include all loaders in that case. + + * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function + + * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly + handle TREE_VIEW_VERTICAL_SEPARATOR + (gtk_tree_view_bin_expose): fix to consider the row offset as + pointing halfway into vertical separator. + (gtk_tree_view_draw_node_focus_rect): ditto + + * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add + --gtk-debug=updates, which causes gdk_window_set_debug_updates + (TRUE) to be called. + + * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a + debug mode where the invalid region is colored in on invalidate, + so you can see the flicker and know whether your redraw code is + doing a good job. + + * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in + tree window coordinates (clip rect is in tree window coords) + + * gtk/Makefile.am: add gtktreednd.[hc] + + * gtk/gtkliststore.c: implement gtktreednd interfaces. + + * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support + drag-and-drop data operations on a model (so we can set up tree + drag-and-drop automatically) + + * gtk/testgtk.c: Add a window to change sensitivity in the + GtkLabel test; add a way to change the entry frame in GtkEntry + test + + * gtk/gtkentry.c (gtk_entry_set_has_frame): + (gtk_entry_get_has_frame): new functions to remove the frame + around an entry + (gtk_entry_size_request): shrink requisition if no frame + (gtk_entry_draw_focus): don't draw frame if no frame + + * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for + checks inside a cell renderer + (gtk_default_draw_option): ditto for options + + * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove + children from the alignment, not the button + (gtk_tree_view_column_init): ref/sink the column, to emulate + GObject refcounting. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): + Use theme functions to draw the toggles + + * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors + + * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and + GdkPangoAttrEmbossed to use in rendering insensitive text + + * gdk/gdkpango.c (gdk_draw_layout_line): render new properties + + * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity + using new GDK features + 2001-01-24 <alexl@redhat.com> * gtk/gtkimage.c: diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 79db30750d..d0e5037365 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,79 @@ +2001-01-26 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor + + * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to + not offset by TREE_VIEW_HEADER_HEIGHT + (gtk_tree_view_tree_to_widget_coords): fix to not offset by + TREE_VIEW_HEADER_HEIGHT + + * configure.in (included_loaders): for me, --with-included-loaders + generates the error "the specified loader yes does not exist", + i.e. the arg defaults to "yes", so change test for value "" + to test for value "yes", and include all loaders in that case. + + * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function + + * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly + handle TREE_VIEW_VERTICAL_SEPARATOR + (gtk_tree_view_bin_expose): fix to consider the row offset as + pointing halfway into vertical separator. + (gtk_tree_view_draw_node_focus_rect): ditto + + * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add + --gtk-debug=updates, which causes gdk_window_set_debug_updates + (TRUE) to be called. + + * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a + debug mode where the invalid region is colored in on invalidate, + so you can see the flicker and know whether your redraw code is + doing a good job. + + * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in + tree window coordinates (clip rect is in tree window coords) + + * gtk/Makefile.am: add gtktreednd.[hc] + + * gtk/gtkliststore.c: implement gtktreednd interfaces. + + * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support + drag-and-drop data operations on a model (so we can set up tree + drag-and-drop automatically) + + * gtk/testgtk.c: Add a window to change sensitivity in the + GtkLabel test; add a way to change the entry frame in GtkEntry + test + + * gtk/gtkentry.c (gtk_entry_set_has_frame): + (gtk_entry_get_has_frame): new functions to remove the frame + around an entry + (gtk_entry_size_request): shrink requisition if no frame + (gtk_entry_draw_focus): don't draw frame if no frame + + * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for + checks inside a cell renderer + (gtk_default_draw_option): ditto for options + + * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove + children from the alignment, not the button + (gtk_tree_view_column_init): ref/sink the column, to emulate + GObject refcounting. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): + Use theme functions to draw the toggles + + * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors + + * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and + GdkPangoAttrEmbossed to use in rendering insensitive text + + * gdk/gdkpango.c (gdk_draw_layout_line): render new properties + + * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity + using new GDK features + 2001-01-24 <alexl@redhat.com> * gtk/gtkimage.c: diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 79db30750d..d0e5037365 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,79 @@ +2001-01-26 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor + + * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to + not offset by TREE_VIEW_HEADER_HEIGHT + (gtk_tree_view_tree_to_widget_coords): fix to not offset by + TREE_VIEW_HEADER_HEIGHT + + * configure.in (included_loaders): for me, --with-included-loaders + generates the error "the specified loader yes does not exist", + i.e. the arg defaults to "yes", so change test for value "" + to test for value "yes", and include all loaders in that case. + + * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function + + * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly + handle TREE_VIEW_VERTICAL_SEPARATOR + (gtk_tree_view_bin_expose): fix to consider the row offset as + pointing halfway into vertical separator. + (gtk_tree_view_draw_node_focus_rect): ditto + + * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add + --gtk-debug=updates, which causes gdk_window_set_debug_updates + (TRUE) to be called. + + * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a + debug mode where the invalid region is colored in on invalidate, + so you can see the flicker and know whether your redraw code is + doing a good job. + + * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in + tree window coordinates (clip rect is in tree window coords) + + * gtk/Makefile.am: add gtktreednd.[hc] + + * gtk/gtkliststore.c: implement gtktreednd interfaces. + + * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support + drag-and-drop data operations on a model (so we can set up tree + drag-and-drop automatically) + + * gtk/testgtk.c: Add a window to change sensitivity in the + GtkLabel test; add a way to change the entry frame in GtkEntry + test + + * gtk/gtkentry.c (gtk_entry_set_has_frame): + (gtk_entry_get_has_frame): new functions to remove the frame + around an entry + (gtk_entry_size_request): shrink requisition if no frame + (gtk_entry_draw_focus): don't draw frame if no frame + + * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for + checks inside a cell renderer + (gtk_default_draw_option): ditto for options + + * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove + children from the alignment, not the button + (gtk_tree_view_column_init): ref/sink the column, to emulate + GObject refcounting. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): + Use theme functions to draw the toggles + + * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors + + * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and + GdkPangoAttrEmbossed to use in rendering insensitive text + + * gdk/gdkpango.c (gdk_draw_layout_line): render new properties + + * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity + using new GDK features + 2001-01-24 <alexl@redhat.com> * gtk/gtkimage.c: diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 79db30750d..d0e5037365 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,79 @@ +2001-01-26 Havoc Pennington <hp@redhat.com> + + * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor + + * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to + not offset by TREE_VIEW_HEADER_HEIGHT + (gtk_tree_view_tree_to_widget_coords): fix to not offset by + TREE_VIEW_HEADER_HEIGHT + + * configure.in (included_loaders): for me, --with-included-loaders + generates the error "the specified loader yes does not exist", + i.e. the arg defaults to "yes", so change test for value "" + to test for value "yes", and include all loaders in that case. + + * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function + + * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly + handle TREE_VIEW_VERTICAL_SEPARATOR + (gtk_tree_view_bin_expose): fix to consider the row offset as + pointing halfway into vertical separator. + (gtk_tree_view_draw_node_focus_rect): ditto + + * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add + --gtk-debug=updates, which causes gdk_window_set_debug_updates + (TRUE) to be called. + + * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a + debug mode where the invalid region is colored in on invalidate, + so you can see the flicker and know whether your redraw code is + doing a good job. + + * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in + tree window coordinates (clip rect is in tree window coords) + + * gtk/Makefile.am: add gtktreednd.[hc] + + * gtk/gtkliststore.c: implement gtktreednd interfaces. + + * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support + drag-and-drop data operations on a model (so we can set up tree + drag-and-drop automatically) + + * gtk/testgtk.c: Add a window to change sensitivity in the + GtkLabel test; add a way to change the entry frame in GtkEntry + test + + * gtk/gtkentry.c (gtk_entry_set_has_frame): + (gtk_entry_get_has_frame): new functions to remove the frame + around an entry + (gtk_entry_size_request): shrink requisition if no frame + (gtk_entry_draw_focus): don't draw frame if no frame + + * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for + checks inside a cell renderer + (gtk_default_draw_option): ditto for options + + * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove + children from the alignment, not the button + (gtk_tree_view_column_init): ref/sink the column, to emulate + GObject refcounting. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink + + * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): + Use theme functions to draw the toggles + + * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors + + * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and + GdkPangoAttrEmbossed to use in rendering insensitive text + + * gdk/gdkpango.c (gdk_draw_layout_line): render new properties + + * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity + using new GDK features + 2001-01-24 <alexl@redhat.com> * gtk/gtkimage.c: diff --git a/configure.in b/configure.in index 8448e73f7d..19652b4c25 100644 --- a/configure.in +++ b/configure.in @@ -914,7 +914,7 @@ AC_ARG_WITH(included_loaders, [ --with-included-loaders=LOADER1,LOADER2,... Bui all_loaders="png,bmp,wbmp,gif,ico,jpeg,pnm,ras,tiff,xpm" included_loaders="" # If no loaders specified, include all -if test "x$with_included_loaders" = x ; then +if test "x$with_included_loaders" = xyes ; then included_loaders="$all_loaders" else included_loaders="$with_included_loaders" diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c index 7f4d2e6423..53dc4f514a 100644 --- a/gdk/gdkpango.c +++ b/gdk/gdkpango.c @@ -31,13 +31,18 @@ struct _GdkPangoContextInfo GdkColormap *colormap; }; +static PangoAttrType gdk_pango_attr_stipple_type; +static PangoAttrType gdk_pango_attr_embossed_type; + static void gdk_pango_get_item_properties (PangoItem *item, PangoUnderline *uline, gint *rise, - PangoAttrColor *fg_color, + PangoColor *fg_color, gboolean *fg_set, - PangoAttrColor *bg_color, + PangoColor *bg_color, gboolean *bg_set, + gboolean *embossed, + GdkBitmap **stipple, gboolean *shape_set, PangoRectangle *ink_rect, PangoRectangle *logical_rect); @@ -70,38 +75,40 @@ gdk_pango_context_get_info (PangoContext *context, gboolean create) static GdkGC * gdk_pango_get_gc (PangoContext *context, - PangoAttrColor *fg_color, + PangoColor *fg_color, + GdkBitmap *stipple, GdkGC *base_gc) { - GdkPangoContextInfo *info; - GdkColormap *colormap; GdkColor color; + GdkGC *result; + GdkPangoContextInfo *info; g_return_val_if_fail (context != NULL, NULL); info = gdk_pango_context_get_info (context, FALSE); - if (info && info->colormap) - colormap = info->colormap; - else - colormap = gdk_colormap_get_system(); - - /* FIXME. FIXME. FIXME. Only works for true color */ - + if (info == NULL || info->colormap == NULL) + { + g_warning ("you must set the colormap on a PangoContext before using it to draw a layout"); + return NULL; + } + color.red = fg_color->red; color.green = fg_color->green; color.blue = fg_color->blue; - if (gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE)) - { - GdkGC *result = gdk_gc_new (gdk_parent_root); - gdk_gc_copy (result, base_gc); - gdk_gc_set_foreground (result, &color); + result = gdk_gc_new (gdk_parent_root); + gdk_gc_copy (result, base_gc); + gdk_rgb_find_color (info->colormap, &color); + gdk_gc_set_foreground (result, &color); - return result; + if (stipple) + { + gdk_gc_set_fill (result, GDK_STIPPLED); + gdk_gc_set_stipple (result, stipple); } - else - return gdk_gc_ref (base_gc); + + return result; } static void @@ -158,6 +165,8 @@ gdk_draw_layout_line (GdkDrawable *drawable, PangoContext *context; gint x_off = 0; gint rise = 0; + gboolean embossed; + GdkBitmap *stipple; g_return_if_fail (drawable != NULL); g_return_if_fail (gc != NULL); @@ -171,7 +180,7 @@ gdk_draw_layout_line (GdkDrawable *drawable, { PangoUnderline uline = PANGO_UNDERLINE_NONE; PangoLayoutRun *run = tmp_list->data; - PangoAttrColor fg_color, bg_color; + PangoColor fg_color, bg_color; gboolean fg_set, bg_set, shape_set; GdkGC *fg_gc; gint risen_y; @@ -182,6 +191,8 @@ gdk_draw_layout_line (GdkDrawable *drawable, &rise, &fg_color, &fg_set, &bg_color, &bg_set, + &embossed, + &stipple, &shape_set, &ink_rect, &logical_rect); @@ -201,28 +212,48 @@ gdk_draw_layout_line (GdkDrawable *drawable, if (bg_set) { - GdkGC *bg_gc = gdk_pango_get_gc (context, &bg_color, gc); - + GdkGC *bg_gc = gdk_pango_get_gc (context, &bg_color, stipple, gc); + gdk_draw_rectangle (drawable, bg_gc, TRUE, x + (x_off + logical_rect.x) / PANGO_SCALE, risen_y + overall_rect.y / PANGO_SCALE, logical_rect.width / PANGO_SCALE, overall_rect.height / PANGO_SCALE); + if (stipple) + gdk_gc_set_fill (bg_gc, GDK_SOLID); + gdk_pango_free_gc (context, bg_gc); } - if (fg_set) - fg_gc = gdk_pango_get_gc (context, &fg_color, gc); + if (fg_set || stipple) + fg_gc = gdk_pango_get_gc (context, &fg_color, stipple, gc); else fg_gc = gc; - + if (!shape_set) - gdk_draw_glyphs (drawable, fg_gc, run->item->analysis.font, - x + x_off / PANGO_SCALE, - risen_y, - run->glyphs); + { + gint gx, gy; + gx = x + x_off / PANGO_SCALE; + gy = risen_y; + + if (embossed) + { + PangoColor color = { 65535, 65535, 65535 }; + GdkGC *white_gc = gdk_pango_get_gc (context, &color, stipple, fg_gc); + gdk_draw_glyphs (drawable, white_gc, run->item->analysis.font, + gx + 1, + gy + 1, + run->glyphs); + gdk_pango_free_gc (context, white_gc); + } + + gdk_draw_glyphs (drawable, fg_gc, run->item->analysis.font, + gx, gy, + run->glyphs); + } + switch (uline) { case PANGO_UNDERLINE_NONE: @@ -249,8 +280,8 @@ gdk_draw_layout_line (GdkDrawable *drawable, risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1); break; } - - if (fg_set) + + if (fg_gc != gc) gdk_pango_free_gc (context, fg_gc); x_off += logical_rect.width; @@ -307,10 +338,12 @@ static void gdk_pango_get_item_properties (PangoItem *item, PangoUnderline *uline, gint *rise, - PangoAttrColor *fg_color, + PangoColor *fg_color, gboolean *fg_set, - PangoAttrColor *bg_color, + PangoColor *bg_color, gboolean *bg_set, + gboolean *embossed, + GdkBitmap **stipple, gboolean *shape_set, PangoRectangle *ink_rect, PangoRectangle *logical_rect) @@ -328,6 +361,12 @@ gdk_pango_get_item_properties (PangoItem *item, if (rise) *rise = 0; + + if (embossed) + *embossed = FALSE; + + if (stipple) + *stipple = NULL; while (tmp_list) { @@ -342,7 +381,7 @@ gdk_pango_get_item_properties (PangoItem *item, case PANGO_ATTR_FOREGROUND: if (fg_color) - *fg_color = *((PangoAttrColor *)attr); + *fg_color = ((PangoAttrColor *)attr)->color; if (fg_set) *fg_set = TRUE; @@ -350,7 +389,7 @@ gdk_pango_get_item_properties (PangoItem *item, case PANGO_ATTR_BACKGROUND: if (bg_color) - *bg_color = *((PangoAttrColor *)attr); + *bg_color = ((PangoAttrColor *)attr)->color; if (bg_set) *bg_set = TRUE; @@ -371,9 +410,144 @@ gdk_pango_get_item_properties (PangoItem *item, break; default: + /* stipple_type and embossed_type aren't necessarily + * initialized, but they are 0, which is an + * invalid type so won't occur. + */ + if (stipple && attr->klass->type == gdk_pango_attr_stipple_type) + { + *stipple = ((GdkPangoAttrStipple*)attr)->stipple; + } + else if (embossed && attr->klass->type == gdk_pango_attr_embossed_type) + { + *embossed = ((GdkPangoAttrEmbossed*)attr); + } break; } tmp_list = tmp_list->next; } } + +static PangoAttribute * +gdk_pango_attr_stipple_copy (const PangoAttribute *attr) +{ + const GdkPangoAttrStipple *src = (const GdkPangoAttrStipple*) attr; + + return gdk_pango_attr_stipple_new (src->stipple); +} + +static void +gdk_pango_attr_stipple_destroy (PangoAttribute *attr) +{ + GdkPangoAttrStipple *st = (GdkPangoAttrStipple*) attr; + + if (st->stipple) + g_object_unref (G_OBJECT (st->stipple)); + + g_free (attr); +} + +static gboolean +gdk_pango_attr_stipple_compare (const PangoAttribute *attr1, + const PangoAttribute *attr2) +{ + const GdkPangoAttrStipple *a = (const GdkPangoAttrStipple*) attr1; + const GdkPangoAttrStipple *b = (const GdkPangoAttrStipple*) attr2; + + return a->stipple == b->stipple; +} + +/** + * gdk_pango_attr_stipple_new: + * @stipple: a bitmap to be set as stipple + * + * Creates a new attribute containing a stipple bitmap to be used when + * rendering the text. + * + * Return value: new #PangoAttribute + **/ + +PangoAttribute * +gdk_pango_attr_stipple_new (GdkBitmap *stipple) +{ + GdkPangoAttrStipple *result; + + static PangoAttrClass klass = { + 0, + gdk_pango_attr_stipple_copy, + gdk_pango_attr_stipple_destroy, + gdk_pango_attr_stipple_compare + }; + + if (!klass.type) + klass.type = gdk_pango_attr_stipple_type = + pango_attr_type_register ("GdkPangoAttrStipple"); + + result = g_new (GdkPangoAttrStipple, 1); + result->attr.klass = &klass; + + if (stipple) + g_object_ref (stipple); + + result->stipple = stipple; + + return (PangoAttribute *)result; +} + +static PangoAttribute * +gdk_pango_attr_embossed_copy (const PangoAttribute *attr) +{ + const GdkPangoAttrEmbossed *e = (const GdkPangoAttrEmbossed*) attr; + + return gdk_pango_attr_embossed_new (e->embossed); +} + +static void +gdk_pango_attr_embossed_destroy (PangoAttribute *attr) +{ + g_free (attr); +} + +static gboolean +gdk_pango_attr_embossed_compare (const PangoAttribute *attr1, + const PangoAttribute *attr2) +{ + const GdkPangoAttrEmbossed *e1 = (const GdkPangoAttrEmbossed*) attr1; + const GdkPangoAttrEmbossed *e2 = (const GdkPangoAttrEmbossed*) attr2; + + return e1->embossed == e2->embossed; +} + +/** + * gdk_pango_attr_embossed_new: + * @embossed: a bitmap to be set as embossed + * + * Creates a new attribute containing a embossed bitmap to be used when + * rendering the text. + * + * Return value: new #PangoAttribute + **/ + +PangoAttribute * +gdk_pango_attr_embossed_new (gboolean embossed) +{ + GdkPangoAttrEmbossed *result; + + static PangoAttrClass klass = { + 0, + gdk_pango_attr_embossed_copy, + gdk_pango_attr_embossed_destroy, + gdk_pango_attr_embossed_compare + }; + + if (!klass.type) + klass.type = gdk_pango_attr_embossed_type = + pango_attr_type_register ("GdkPangoAttrEmbossed"); + + result = g_new (GdkPangoAttrEmbossed, 1); + result->attr.klass = &klass; + result->embossed = embossed; + + return (PangoAttribute *)result; +} diff --git a/gdk/gdkpango.h b/gdk/gdkpango.h index 8fc91a71f5..f553fa01dc 100644 --- a/gdk/gdkpango.h +++ b/gdk/gdkpango.h @@ -38,6 +38,26 @@ PangoContext *gdk_pango_context_get (void); void gdk_pango_context_set_colormap (PangoContext *context, GdkColormap *colormap); +/* Attributes use to render insensitive text in GTK+. */ + +typedef struct _GdkPangoAttrStipple GdkPangoAttrStipple; +typedef struct _GdkPangoAttrEmbossed GdkPangoAttrEmbossed; + +struct _GdkPangoAttrStipple +{ + PangoAttribute attr; + GdkBitmap *stipple; +}; + +struct _GdkPangoAttrEmbossed +{ + PangoAttribute attr; + gboolean embossed; +}; + +PangoAttribute *gdk_pango_attr_stipple_new (GdkBitmap *bitmap); +PangoAttribute *gdk_pango_attr_embossed_new (gboolean embossed); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 0a703045fd..55d5e9d590 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -1637,6 +1637,7 @@ gdk_window_get_image (GdkDrawable *drawable, static GSList *update_windows = NULL; static guint update_idle = 0; +static gboolean debug_updates = FALSE; static void gdk_window_process_updates_internal (GdkWindow *window) @@ -1659,6 +1660,13 @@ gdk_window_process_updates_internal (GdkWindow *window) GdkRectangle window_rect; gint width, height; + if (debug_updates) + { + /* Make sure we see the red invalid area before redrawing. */ + gdk_flush (); + g_usleep (70000); + } + gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height); window_rect.x = 0; @@ -1725,9 +1733,9 @@ gdk_window_process_updates (GdkWindow *window, g_return_if_fail (window != NULL); g_return_if_fail (GDK_IS_WINDOW (window)); - + if (private->update_area) - { + { gdk_window_process_updates_internal (window); update_windows = g_slist_remove (update_windows, window); } @@ -1798,6 +1806,28 @@ gdk_window_invalidate_region (GdkWindow *window, if (!gdk_region_empty (visible_region)) { + if (debug_updates) + { + /* Draw ugly color all over the newly-invalid region */ + GdkRectangle ugly_rect; + GdkGC *ugly_gc; + GdkColor ugly_color = { 0, 60000, 10000, 10000 }; + + ugly_gc = gdk_gc_new (window); + + gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color); + + gdk_region_get_clipbox (visible_region, &ugly_rect); + + gdk_draw_rectangle (window, + ugly_gc, + TRUE, + ugly_rect.x, ugly_rect.y, + ugly_rect.width, ugly_rect.height); + + g_object_unref (G_OBJECT (ugly_gc)); + } + if (private->update_area) { gdk_region_union (private->update_area, visible_region); @@ -1916,3 +1946,8 @@ gdk_window_thaw_updates (GdkWindow *window) gdk_window_update_idle, NULL, NULL); } +void +gdk_window_set_debug_updates (gboolean setting) +{ + debug_updates = setting; +} diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index 12ab145ed9..435e5868dc 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -413,7 +413,8 @@ void gdk_window_process_all_updates (void); void gdk_window_process_updates (GdkWindow *window, gboolean update_children); - +/* Enable/disable flicker, so you can tell if your code is inefficient. */ +void gdk_window_set_debug_updates (gboolean setting); #ifdef __cplusplus } diff --git a/gtk/Makefile.am b/gtk/Makefile.am index bdd2659b57..0869168b66 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -170,6 +170,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \ gtktoolbar.h \ gtktooltips.h \ gtktree.h \ + gtktreednd.h \ gtktreeitem.h \ gtktreemodel.h \ gtktreemodelsimple.h \ @@ -335,6 +336,7 @@ gtk_c_sources = @STRIP_BEGIN@ \ gtktree.c \ gtktreeitem.c \ gtktreedatalist.c \ + gtktreednd.c \ gtktreemodel.c \ gtktreemodelsimple.c \ gtktreemodelsort.c \ @@ -138,6 +138,7 @@ #include <gtk/gtktoolbar.h> #include <gtk/gtktooltips.h> #include <gtk/gtktree.h> +#include <gtk/gtktreednd.h> #include <gtk/gtktreeitem.h> #include <gtk/gtktreemodel.h> #include <gtk/gtktreemodelsimple.h> diff --git a/gtk/gtkcellrenderer.c b/gtk/gtkcellrenderer.c index 5324cbe92c..d7724f49ab 100644 --- a/gtk/gtkcellrenderer.c +++ b/gtk/gtkcellrenderer.c @@ -72,6 +72,10 @@ gtk_cell_renderer_get_type (void) static void gtk_cell_renderer_init (GtkCellRenderer *cell) { + /* FIXME remove on port to GtkObject */ + gtk_object_ref (GTK_OBJECT (cell)); + gtk_object_sink (GTK_OBJECT (cell)); + cell->xpad = 0; cell->ypad = 0; cell->xalign = 0.5; @@ -211,6 +215,27 @@ gtk_cell_renderer_get_size (GtkCellRenderer *cell, GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (cell, widget, width, height); } +/** + * gtk_cell_renderer_render: + * @cell: a #GtkCellRenderer + * @window: a #GdkDrawable to draw to + * @widget: the widget owning @window + * @background_area: entire cell area (including tree expanders and maybe padding on the sides) + * @cell_area: area normally rendered by a cell renderer + * @expose_area: area that actually needs updating + * @flags: flags that affect rendering + * + * Invokes the virtual render function of the #GtkCellRenderer. The + * three passed-in rectangles are areas of @window. Most renderers + * will draw to @cell_area; the xalign, yalign, xpad, and ypad fields + * of the #GtkCellRenderer should be honored with respect to + * @cell_area. @background_area includes the blank space around the + * cell, and also the area containing the tree expander; so the + * @background_area rectangles for all cells tile to cover the entire + * @window. Cell renderers can use the @background_area to draw custom expanders, for + * example. @expose_area is a clip rectangle. + * + **/ void gtk_cell_renderer_render (GtkCellRenderer *cell, GdkWindow *window, diff --git a/gtk/gtkcellrenderertoggle.c b/gtk/gtkcellrenderertoggle.c index d6dfa75471..4ff6c7e520 100644 --- a/gtk/gtkcellrenderertoggle.c +++ b/gtk/gtkcellrenderertoggle.c @@ -226,7 +226,9 @@ gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, GtkCellRendererToggle *celltoggle = (GtkCellRendererToggle *) cell; gint width, height; gint real_xoffset, real_yoffset; - + GtkShadowType shadow; + GtkStateType state; + width = MIN (TOGGLE_WIDTH, cell_area->width - cell->xpad * 2); height = MIN (TOGGLE_WIDTH, cell_area->height - cell->ypad * 2); @@ -238,57 +240,33 @@ gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, real_yoffset = cell->yalign * (cell_area->height - height - (2 * cell->ypad)); real_yoffset = MAX (real_yoffset, 0) + cell->ypad; - gdk_gc_set_clip_rectangle (widget->style->black_gc, cell_area); + shadow = celltoggle->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT; - if (!celltoggle->radio) + if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) + state = GTK_STATE_SELECTED; + else + state = GTK_STATE_NORMAL; + + if (celltoggle->radio) { - gdk_draw_rectangle (window, - widget->style->black_gc, - FALSE, - cell_area->x + real_xoffset, - cell_area->y + real_yoffset, - width, height); - if (celltoggle->active) - { - gdk_draw_line (window, - widget->style->black_gc, - cell_area->x + real_xoffset, - cell_area->y + real_yoffset, - cell_area->x + real_xoffset + width, - cell_area->y + real_yoffset + height); - gdk_draw_line (window, - widget->style->black_gc, - cell_area->x + real_xoffset + width, - cell_area->y + real_yoffset, - cell_area->x + real_xoffset, - cell_area->y + real_yoffset + height); - } + gtk_paint_option (widget->style, + window, + state, shadow, + cell_area, widget, "cellradio", + cell_area->x + real_xoffset, + cell_area->y + real_yoffset, + width, height); } else { - gdk_draw_arc (window, - widget->style->black_gc, - FALSE, - cell_area->x + real_xoffset, - cell_area->y + real_yoffset, - width, - height, - 0, 360*64); - if (celltoggle->active) - { - gdk_draw_arc (window, - widget->style->black_gc, - TRUE, - cell_area->x + real_xoffset + 2, - cell_area->y + real_yoffset + 2, - width - 4, - height - 4, - 0, 360*64); - } + gtk_paint_check (widget->style, + window, + state, shadow, + cell_area, widget, "cellcheck", + cell_area->x + real_xoffset, + cell_area->y + real_yoffset, + width, height); } - - - gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL); } static gint diff --git a/gtk/gtkdebug.h b/gtk/gtkdebug.h index 78e74d16b5..1a03e8af52 100644 --- a/gtk/gtkdebug.h +++ b/gtk/gtkdebug.h @@ -38,7 +38,8 @@ typedef enum { GTK_DEBUG_DND = 1 << 3, GTK_DEBUG_PLUGSOCKET = 1 << 4, GTK_DEBUG_TEXT = 1 << 5, - GTK_DEBUG_TREE = 1 << 6 + GTK_DEBUG_TREE = 1 << 6, + GTK_DEBUG_UPDATES = 1 << 7 } GtkDebugFlag; #ifdef G_ENABLE_DEBUG diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index ecfcb86a83..7f471229ed 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -675,6 +675,8 @@ gtk_entry_init (GtkEntry *entry) entry->visible = TRUE; entry->invisible_char = '*'; entry->dnd_position = -1; + + entry->has_frame = TRUE; gtk_drag_dest_set (GTK_WIDGET (entry), GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_HIGHLIGHT, @@ -760,8 +762,17 @@ gtk_entry_realize (GtkWidget *widget) widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (widget->window, entry); - attributes.x = widget->style->xthickness; - attributes.y = widget->style->ythickness; + if (entry->has_frame) + { + attributes.x = widget->style->xthickness; + attributes.y = widget->style->ythickness; + } + else + { + attributes.x = 0; + attributes.y = 0; + } + attributes.width = widget->allocation.width - attributes.x * 2; attributes.height = requisition.height - attributes.y * 2; attributes.cursor = gdk_cursor_new (GDK_XTERM); @@ -816,6 +827,7 @@ gtk_entry_size_request (GtkWidget *widget, PangoFontMetrics metrics; PangoFont *font; gchar *lang; + gint xborder, yborder; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_ENTRY (widget)); @@ -835,10 +847,25 @@ gtk_entry_size_request (GtkWidget *widget, entry->ascent = metrics.ascent; entry->descent = metrics.descent; + + xborder = INNER_BORDER; + yborder = INNER_BORDER; - requisition->width = MIN_ENTRY_WIDTH + (widget->style->xthickness + INNER_BORDER) * 2; + if (entry->has_frame) + { + xborder += widget->style->xthickness; + yborder += widget->style->ythickness; + } + else + { + /* add 1 pixel to draw focus rect in widget->window */ + xborder += 1; + yborder += 1; + } + + requisition->width = MIN_ENTRY_WIDTH + xborder * 2; requisition->height = ((metrics.ascent + metrics.descent) / PANGO_SCALE + - (widget->style->ythickness + INNER_BORDER) * 2); + yborder * 2); } static void @@ -847,7 +874,8 @@ gtk_entry_size_allocate (GtkWidget *widget, { GtkEntry *entry; GtkEditable *editable; - + gint xborder, yborder; + g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_ENTRY (widget)); g_return_if_fail (allocation != NULL); @@ -856,6 +884,18 @@ gtk_entry_size_allocate (GtkWidget *widget, entry = GTK_ENTRY (widget); editable = GTK_EDITABLE (widget); + if (entry->has_frame) + { + xborder = widget->style->xthickness; + yborder = widget->style->ythickness; + } + else + { + /* 1 pixel for focus rect */ + xborder = 1; + yborder = 1; + } + if (GTK_WIDGET_REALIZED (widget)) { /* We call gtk_widget_get_child_requisition, since we want (for @@ -870,10 +910,10 @@ gtk_entry_size_allocate (GtkWidget *widget, allocation->y + (allocation->height - requisition.height) / 2, allocation->width, requisition.height); gdk_window_move_resize (entry->text_area, - widget->style->xthickness, - widget->style->ythickness, - allocation->width - widget->style->xthickness * 2, - requisition.height - widget->style->ythickness * 2); + xborder, + yborder, + allocation->width - xborder * 2, + requisition.height - yborder * 2); gtk_entry_recompute (entry); } @@ -883,37 +923,45 @@ static void gtk_entry_draw_focus (GtkWidget *widget) { gint width, height; - gint x, y; - + GtkEntry *entry; + g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_ENTRY (widget)); + entry = GTK_ENTRY (widget); + if (GTK_WIDGET_DRAWABLE (widget)) - { - x = 0; - y = 0; - gdk_window_get_size (widget->window, &width, &height); + { + if (entry->has_frame) + { + gint x = 0, y = 0; - if (GTK_WIDGET_HAS_FOCUS (widget)) - { - x += 1; - y += 1; - width -= 2; - height -= 2; - } + gdk_window_get_size (widget->window, &width, &height); + + if (GTK_WIDGET_HAS_FOCUS (widget)) + { + x += 1; + y += 1; + width -= 2; + height -= 2; + } - gtk_paint_shadow (widget->style, widget->window, - GTK_STATE_NORMAL, GTK_SHADOW_IN, - NULL, widget, "entry", - x, y, width, height); + gtk_paint_shadow (widget->style, widget->window, + GTK_STATE_NORMAL, GTK_SHADOW_IN, + NULL, widget, "entry", + x, y, width, height); + } + else + gdk_window_clear (widget->window); + if (GTK_WIDGET_HAS_FOCUS (widget)) - { - gdk_window_get_size (widget->window, &width, &height); - gtk_paint_focus (widget->style, widget->window, - NULL, widget, "entry", - 0, 0, width - 1, height - 1); - } + { + gdk_window_get_size (widget->window, &width, &height); + gtk_paint_focus (widget->style, widget->window, + NULL, widget, "entry", + 0, 0, width - 1, height - 1); + } } } @@ -2582,6 +2630,43 @@ gtk_entry_set_max_length (GtkEntry *entry, entry->text_max_length = max; } +/** + * gtk_entry_set_has_frame: + * @entry: a #GtkEntry + * @setting: new value + * + * Sets whether the entry has a beveled frame around it. + **/ +void +gtk_entry_set_has_frame (GtkEntry *entry, + gboolean setting) +{ + g_return_if_fail (GTK_IS_ENTRY (entry)); + + setting = (setting != FALSE); + + if (entry->has_frame != setting) + gtk_widget_queue_resize (GTK_WIDGET (entry)); + + entry->has_frame = setting; +} + +/** + * gtk_entry_get_has_frame: + * @entry: a #GtkEntry + * + * + * + * Return value: whether the entry has a beveled frame + **/ +gboolean +gtk_entry_get_has_frame (GtkEntry *entry) +{ + g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE); + + return entry->has_frame; +} + /* Quick hack of a popup menu */ static void diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h index 553837603d..c8dbcdd835 100644 --- a/gtk/gtkentry.h +++ b/gtk/gtkentry.h @@ -76,6 +76,8 @@ struct _GtkEntry guint need_im_reset : 1; + guint has_frame : 1; + guint button; guint timer; guint recompute_idle; @@ -138,6 +140,9 @@ void gtk_entry_set_invisible_char (GtkEntry *entry, gunichar ch); void gtk_entry_set_editable (GtkEntry *entry, gboolean editable); +void gtk_entry_set_has_frame (GtkEntry *entry, + gboolean setting); +gboolean gtk_entry_get_has_frame (GtkEntry *entry); /* text is truncated if needed */ void gtk_entry_set_max_length (GtkEntry *entry, guint16 max); diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index b045f2e60d..ef3300430f 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -22,6 +22,7 @@ #include "gtkliststore.h" #include "gtktreedatalist.h" #include "gtksignal.h" +#include "gtktreednd.h" #include <gobject/gvaluecollector.h> #define G_SLIST(x) ((GSList *) x) @@ -39,6 +40,8 @@ static guint list_store_signals[LAST_SIGNAL] = { 0 }; static void gtk_list_store_init (GtkListStore *list_store); static void gtk_list_store_class_init (GtkListStoreClass *class); static void gtk_list_store_tree_model_init (GtkTreeModelIface *iface); +static void gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface); +static void gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface); static guint gtk_list_store_get_flags (GtkTreeModel *tree_model); static gint gtk_list_store_get_n_columns (GtkTreeModel *tree_model); static GType gtk_list_store_get_column_type (GtkTreeModel *tree_model, @@ -69,6 +72,15 @@ static gboolean gtk_list_store_iter_parent (GtkTreeModel *tree_mode GtkTreeIter *iter, GtkTreeIter *child); +static gboolean gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source, + GtkTreePath *path); +static gboolean gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data); +static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, + GtkTreePath *dest, + GtkSelectionData *selection_data); + GtkType gtk_list_store_get_type (void) @@ -97,10 +109,30 @@ gtk_list_store_get_type (void) NULL }; + static const GInterfaceInfo drag_source_info = + { + (GInterfaceInitFunc) gtk_list_store_drag_source_init, + NULL, + NULL + }; + + static const GInterfaceInfo drag_dest_info = + { + (GInterfaceInitFunc) gtk_list_store_drag_dest_init, + NULL, + NULL + }; + list_store_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkListStore", &list_store_info, 0); g_type_add_interface_static (list_store_type, GTK_TYPE_TREE_MODEL, &tree_model_info); + g_type_add_interface_static (list_store_type, + GTK_TYPE_TREE_DRAG_SOURCE, + &drag_source_info); + g_type_add_interface_static (list_store_type, + GTK_TYPE_TREE_DRAG_DEST, + &drag_dest_info); } return list_store_type; @@ -168,6 +200,19 @@ gtk_list_store_tree_model_init (GtkTreeModelIface *iface) } static void +gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface) +{ + iface->drag_data_delete = gtk_list_store_drag_data_delete; + iface->drag_data_get = gtk_list_store_drag_data_get; +} + +static void +gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface) +{ + iface->drag_data_received = gtk_list_store_drag_data_received; +} + +static void gtk_list_store_init (GtkListStore *list_store) { list_store->root = NULL; @@ -646,21 +691,17 @@ remove_link_saving_prev (GSList *list, return list; } -void -gtk_list_store_remove (GtkListStore *list_store, - GtkTreeIter *iter) +static void +gtk_list_store_remove_silently (GtkListStore *list_store, + GtkTreeIter *iter, + GtkTreePath *path) { - GtkTreePath *path; - - g_return_if_fail (list_store != NULL); - g_return_if_fail (GTK_IS_LIST_STORE (list_store)); - g_return_if_fail (iter->user_data != NULL); - if (G_SLIST (iter->user_data)->data) - _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data, - list_store->column_headers); - - path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter); + { + _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data, + list_store->column_headers); + G_SLIST (iter->user_data)->data = NULL; + } { GSList *prev = NULL; @@ -674,6 +715,23 @@ gtk_list_store_remove (GtkListStore *list_store, } list_store->stamp ++; +} + +void +gtk_list_store_remove (GtkListStore *list_store, + GtkTreeIter *iter) +{ + GtkTreePath *path; + + g_return_if_fail (list_store != NULL); + g_return_if_fail (GTK_IS_LIST_STORE (list_store)); + g_return_if_fail (iter->user_data != NULL); + + + path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter); + + gtk_list_store_remove_silently (list_store, iter, path); + gtk_signal_emit_by_name (GTK_OBJECT (list_store), "deleted", path); @@ -901,3 +959,164 @@ gtk_list_store_append (GtkListStore *list_store, path, iter); gtk_tree_path_free (path); } + +static gboolean +gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + GtkTreeIter iter; + g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE); + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), + &iter, + path)) + { + gtk_list_store_remove (GTK_LIST_STORE (drag_source), + &iter); + return TRUE; + } + else + { + return FALSE; + } +} + +static gboolean +gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data) +{ + g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE); + + /* Note that we don't need to handle the GTK_TREE_MODEL_ROW + * target, because the default handler does it for us, but + * we do anyway for the convenience of someone maybe overriding the + * default handler. + */ + + if (gtk_selection_data_set_tree_row (selection_data, + GTK_TREE_MODEL (drag_source), + path)) + { + return TRUE; + } + else + { + /* FIXME handle text targets at least. */ + } + + return FALSE; +} + +static gboolean +gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, + GtkTreePath *dest, + GtkSelectionData *selection_data) +{ + GtkTreeModel *tree_model; + GtkListStore *list_store; + GtkTreeModel *src_model = NULL; + GtkTreePath *src_path = NULL; + gboolean retval = FALSE; + + g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE); + + tree_model = GTK_TREE_MODEL (drag_dest); + list_store = GTK_LIST_STORE (drag_dest); + + if (gtk_selection_data_get_tree_row (selection_data, + &src_model, + &src_path) && + src_model == tree_model) + { + /* Copy the given row to a new position */ + GtkTreeIter src_iter; + GtkTreeIter dest_iter; + GtkTreePath *prev; + + if (!gtk_tree_model_get_iter (src_model, + &src_iter, + src_path)) + goto out; + + /* Get the path to insert _after_ (dest is the path to insert _before_) */ + prev = gtk_tree_path_copy (dest); + + if (!gtk_tree_path_prev (prev)) + { + /* dest was the first spot in the list; which means we are supposed + * to prepend. + */ + gtk_list_store_prepend (GTK_LIST_STORE (tree_model), + &dest_iter); + + retval = TRUE; + } + else + { + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model), + &dest_iter, + prev)) + { + GtkTreeIter tmp_iter = dest_iter; + gtk_list_store_insert_after (GTK_LIST_STORE (tree_model), + &dest_iter, + &tmp_iter); + retval = TRUE; + } + } + + gtk_tree_path_free (prev); + + /* If we succeeded in creating dest_iter, copy data from src + */ + if (retval) + { + GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data; + GtkTreeDataList *copy_head = NULL; + GtkTreeDataList *copy_prev = NULL; + GtkTreeDataList *copy_iter = NULL; + gint col; + + col = 0; + while (dl) + { + 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; + + if (copy_prev) + copy_prev->next = copy_iter; + + copy_prev = copy_iter; + + dl = dl->next; + ++col; + } + + G_SLIST (dest_iter.user_data)->data = copy_head; + + gtk_signal_emit_by_name (GTK_OBJECT (tree_model), + "changed", + NULL, &dest_iter); + } + } + else + { + /* FIXME maybe add some data targets eventually, or handle text + * targets in the simple case. + */ + } + + out: + + if (src_path) + gtk_tree_path_free (src_path); + + return retval; +} diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index d3ba241d4c..ebb324efb0 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -148,7 +148,8 @@ static const GDebugKey gtk_debug_keys[] = { {"dnd", GTK_DEBUG_DND}, {"plugsocket", GTK_DEBUG_PLUGSOCKET}, {"text", GTK_DEBUG_TEXT}, - {"tree", GTK_DEBUG_TREE} + {"tree", GTK_DEBUG_TREE}, + {"updates", GTK_DEBUG_UPDATES} }; static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey); @@ -346,6 +347,9 @@ gtk_init_check (int *argc, } } } + + if (gtk_debug_flags & GTK_DEBUG_UPDATES) + gdk_window_set_debug_updates (TRUE); /* load gtk modules */ gtk_modules = g_slist_reverse (gtk_modules); diff --git a/gtk/gtkrbtree.c b/gtk/gtkrbtree.c index 8259b91fde..e8bbf2d9d0 100644 --- a/gtk/gtkrbtree.c +++ b/gtk/gtkrbtree.c @@ -641,7 +641,12 @@ _gtk_rbtree_node_find_offset (GtkRBTree *tree, GtkRBNode *node) { GtkRBNode *last; - gint retval = node->left->offset; + gint retval; + + g_assert (node); + g_assert (node->left); + + retval = node->left->offset; while (tree && node && node != tree->nil) { @@ -904,6 +909,22 @@ _gtk_rbtree_prev_full (GtkRBTree *tree, } } +gint +_gtk_rbtree_get_depth (GtkRBTree *tree) +{ + GtkRBTree *tmp_tree; + gint depth = 0; + + tmp_tree = tree->parent_tree; + while (tmp_tree) + { + ++depth; + tmp_tree = tmp_tree->parent_tree; + } + + return depth; +} + static void _gtk_rbtree_traverse_pre_order (GtkRBTree *tree, GtkRBNode *node, diff --git a/gtk/gtkrbtree.h b/gtk/gtkrbtree.h index 32aed44178..40c779320c 100644 --- a/gtk/gtkrbtree.h +++ b/gtk/gtkrbtree.h @@ -123,6 +123,7 @@ void _gtk_rbtree_prev_full (GtkRBTree *tree, GtkRBTree **new_tree, GtkRBNode **new_node); +gint _gtk_rbtree_get_depth (GtkRBTree *tree); /* This func just checks the integrity of the tree */ /* It will go away later. */ diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index d86986e525..054bf21dfc 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -2476,8 +2476,34 @@ gtk_default_draw_check (GtkStyle *style, gint width, gint height) { - gtk_paint_box (style, window, state_type, shadow_type, area, widget, detail, - x, y, width, height); + if (detail && strcmp (detail, "cellcheck") == 0) + { + gdk_draw_rectangle (window, + widget->style->fg_gc[state_type], + FALSE, + x, y, + width, height); + + if (shadow_type == GTK_SHADOW_IN) + { + gdk_draw_line (window, + widget->style->fg_gc[state_type], + x, y, + x + width, + y + height); + gdk_draw_line (window, + widget->style->fg_gc[state_type], + x + width, + y, + x, + y + height); + } + } + else + { + gtk_paint_box (style, window, state_type, shadow_type, area, widget, detail, + x, y, width, height); + } } static void @@ -2493,8 +2519,33 @@ gtk_default_draw_option (GtkStyle *style, gint width, gint height) { - gtk_paint_diamond (style, window, state_type, shadow_type, area, widget, - detail, x, y, width, height); + if (detail && strcmp (detail, "cellradio") == 0) + { + gdk_draw_arc (window, + widget->style->fg_gc[state_type], + FALSE, + x, y, + width, + height, + 0, 360*64); + + if (shadow_type == GTK_SHADOW_IN) + { + gdk_draw_arc (window, + widget->style->fg_gc[state_type], + TRUE, + x + 2, + y + 2, + width - 4, + height - 4, + 0, 360*64); + } + } + else + { + gtk_paint_diamond (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + } } static void @@ -3420,6 +3471,155 @@ gtk_default_draw_expander (GtkStyle *style, #undef PM_SIZE } +typedef struct _ByteRange ByteRange; + +struct _ByteRange +{ + guint start; + guint end; +}; + +static ByteRange* +range_new (guint start, + guint end) +{ + ByteRange *br = g_new (ByteRange, 1); + + br->start = start; + br->end = end; + + return br; +} + +static PangoLayout* +get_insensitive_layout (PangoLayout *layout) +{ + GSList *embossed_ranges = NULL; + GSList *stippled_ranges = NULL; + PangoLayoutIter *iter; + GSList *tmp_list = NULL; + PangoLayout *new_layout; + PangoAttrList *attrs; + GdkBitmap *stipple = NULL; + + iter = pango_layout_get_iter (layout); + + do + { + PangoLayoutRun *run; + PangoAttribute *attr; + gboolean need_stipple = FALSE; + ByteRange *br; + + run = pango_layout_iter_get_run (iter); + + if (run) + { + tmp_list = run->item->extra_attrs; + + while (tmp_list != NULL) + { + attr = tmp_list->data; + switch (attr->klass->type) + { + case PANGO_ATTR_FOREGROUND: + case PANGO_ATTR_BACKGROUND: + need_stipple = TRUE; + break; + + default: + break; + } + + if (need_stipple) + break; + + tmp_list = g_slist_next (tmp_list); + } + + br = range_new (run->item->offset, run->item->offset + run->item->length); + + if (need_stipple) + stippled_ranges = g_slist_prepend (stippled_ranges, br); + else + embossed_ranges = g_slist_prepend (embossed_ranges, br); + } + } + while (pango_layout_iter_next_run (iter)); + + pango_layout_iter_free (iter); + + new_layout = pango_layout_copy (layout); + + attrs = pango_layout_get_attributes (new_layout); + + if (attrs == NULL) + { + /* Create attr list if there wasn't one */ + attrs = pango_attr_list_new (); + pango_layout_set_attributes (new_layout, attrs); + pango_attr_list_unref (attrs); + } + + tmp_list = embossed_ranges; + while (tmp_list != NULL) + { + PangoAttribute *attr; + ByteRange *br = tmp_list->data; + + attr = gdk_pango_attr_embossed_new (TRUE); + + attr->start_index = br->start; + attr->end_index = br->end; + + pango_attr_list_change (attrs, attr); + + g_free (br); + + tmp_list = g_slist_next (tmp_list); + } + + g_slist_free (embossed_ranges); + + tmp_list = stippled_ranges; + while (tmp_list != NULL) + { + PangoAttribute *attr; + ByteRange *br = tmp_list->data; + + if (stipple == NULL) + { +#define gray50_width 2 +#define gray50_height 2 + static char gray50_bits[] = { + 0x02, 0x01 + }; + + stipple = gdk_bitmap_create_from_data (NULL, + gray50_bits, gray50_width, + gray50_height); + } + + attr = gdk_pango_attr_stipple_new (stipple); + + attr->start_index = br->start; + attr->end_index = br->end; + + pango_attr_list_change (attrs, attr); + + g_free (br); + + tmp_list = g_slist_next (tmp_list); + } + + g_slist_free (stippled_ranges); + + if (stipple) + g_object_unref (G_OBJECT (stipple)); + + return new_layout; +} + static void gtk_default_draw_layout (GtkStyle *style, GdkWindow *window, @@ -3435,24 +3635,25 @@ gtk_default_draw_layout (GtkStyle *style, g_return_if_fail (window != NULL); if (area) - { - gdk_gc_set_clip_rectangle (style->white_gc, area); - gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area); - } + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area); - /* FIXME this is frickin' ugly with any kind of attributes set on the - * text being rendered - */ if (state_type == GTK_STATE_INSENSITIVE) - gdk_draw_layout (window, style->white_gc, x + 1, y + 1, layout); + { + PangoLayout *ins; - gdk_draw_layout (window, style->fg_gc[state_type], x, y, layout); + ins = get_insensitive_layout (layout); + + gdk_draw_layout (window, style->fg_gc[state_type], x, y, ins); - if (area) + g_object_unref (G_OBJECT (ins)); + } + else { - gdk_gc_set_clip_rectangle (style->white_gc, NULL); - gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL); + gdk_draw_layout (window, style->fg_gc[state_type], x, y, layout); } + + if (area) + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL); } static void diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index ff9bdca23d..f220646b66 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -1499,9 +1499,9 @@ static void convert_color (GdkColor *result, PangoAttrColor *attr) { - result->red = attr->red; - result->blue = attr->blue; - result->green = attr->green; + result->red = attr->color.red; + result->blue = attr->color.blue; + result->green = attr->color.green; } /* This function is used to convert the preedit string attributes, which are diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index e18340d65f..cc20068967 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -4373,7 +4373,7 @@ gtk_text_view_drag_motion (GtkWidget *widget, } else if (gtk_text_buffer_get_selection_bounds (get_buffer (text_view), &start, &end) && - gtk_text_iter_in_range (&newplace, &start, &end)) + gtk_text_iter_in_range (&newplace, &start, &end)) { /* We're inside the selection. */ } diff --git a/gtk/gtktreedatalist.c b/gtk/gtktreedatalist.c index 6fdf9d2e9e..b55b730af5 100644 --- a/gtk/gtktreedatalist.c +++ b/gtk/gtktreedatalist.c @@ -234,4 +234,48 @@ _gtk_tree_data_list_value_to_node (GtkTreeDataList *list, } } +GtkTreeDataList* +_gtk_tree_data_list_node_copy (GtkTreeDataList *list, + GType type) +{ + GtkTreeDataList *new_list; + + new_list = _gtk_tree_data_list_alloc (); + + switch (type) + { + case G_TYPE_UINT: + case G_TYPE_INT: + case G_TYPE_UCHAR: + case G_TYPE_CHAR: + case G_TYPE_BOOLEAN: + case G_TYPE_POINTER: + case G_TYPE_FLOAT: + new_list->data = list->data; + break; + case G_TYPE_STRING: + new_list->data.v_pointer = g_strdup (list->data.v_pointer); + break; + + default: + if (g_type_is_a (type, G_TYPE_OBJECT)) + { + new_list->data.v_pointer = list->data.v_pointer; + if (new_list->data.v_pointer) + g_object_ref (G_OBJECT (new_list->data.v_pointer)); + } + else if (g_type_is_a (type, G_TYPE_BOXED)) + { + if (list->data.v_pointer) + new_list->data.v_pointer = g_boxed_copy (type, list->data.v_pointer); + else + new_list->data.v_pointer = NULL; + } + else + g_warning ("Unsupported node type (%s) copied.", g_type_name (type)); + break; + } + + return new_list; +} diff --git a/gtk/gtktreedatalist.h b/gtk/gtktreedatalist.h index 1149fdad01..66fe375920 100644 --- a/gtk/gtktreedatalist.h +++ b/gtk/gtktreedatalist.h @@ -50,6 +50,8 @@ void _gtk_tree_data_list_node_to_value (GtkTreeDataList *list, void _gtk_tree_data_list_value_to_node (GtkTreeDataList *list, GValue *value); +GtkTreeDataList *_gtk_tree_data_list_node_copy (GtkTreeDataList *list, + GType type); #endif /* __GTK_TREE_DATA_LIST_H__ */ diff --git a/gtk/gtktreednd.c b/gtk/gtktreednd.c new file mode 100644 index 0000000000..f798022c25 --- /dev/null +++ b/gtk/gtktreednd.c @@ -0,0 +1,265 @@ +/* gtktreednd.c + * Copyright (C) 2001 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <string.h> +#include "gtktreednd.h" + +GType +gtk_tree_drag_source_get_type (void) +{ + static GType our_type = 0; + + if (!our_type) + { + static const GTypeInfo our_info = + { + sizeof (GtkTreeDragSourceIface), /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + our_type = g_type_register_static (G_TYPE_INTERFACE, "GtkTreeDragSource", &our_info, 0); + } + + return our_type; +} + + +GType +gtk_tree_drag_dest_get_type (void) +{ + static GType our_type = 0; + + if (!our_type) + { + static const GTypeInfo our_info = + { + sizeof (GtkTreeDragDestIface), /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + our_type = g_type_register_static (G_TYPE_INTERFACE, "GtkTreeDragDest", &our_info, 0); + } + + return our_type; +} + + +/** + * gtk_tree_drag_source_drag_data_delete: + * @drag_source: a #GtkTreeDragSource + * @path: row that was being dragged + * + * Asks the #GtkTreeDragSource to delete the row at @path, because + * it was moved somewhere else via drag-and-drop. Returns %FALSE + * if the deletion fails because @path no longer exists, or for + * some model-specific reason. Should robustly handle a @path no + * longer found in the model! + * + * Return value: %TRUE if the row was successfully deleted + **/ +gboolean +gtk_tree_drag_source_drag_data_delete (GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + GtkTreeDragSourceIface *iface = GTK_TREE_DRAG_SOURCE_GET_IFACE (drag_source); + + g_return_val_if_fail (iface->drag_data_delete != NULL, FALSE); + g_return_val_if_fail (path != NULL, FALSE); + + return (* iface->drag_data_delete) (drag_source, path); +} + +/** + * gtk_tree_drag_source_drag_data_get: + * @drag_source: a #GtkTreeDragSource + * @path: row that was dragged + * @selection_data: a #GtkSelectionData to fill with data from the dragged row + * + * Asks the #GtkTreeDragSource to fill in @selection_data with a + * representation of the row at @path. @selection_data->target gives + * the required type of the data. Should robustly handle a @path no + * longer found in the model! + * + * Return value: %TRUE if data of the required type was provided + **/ +gboolean +gtk_tree_drag_source_drag_data_get (GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data) +{ + GtkTreeDragSourceIface *iface = GTK_TREE_DRAG_SOURCE_GET_IFACE (drag_source); + + g_return_val_if_fail (iface->drag_data_get != NULL, FALSE); + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (selection_data != NULL, FALSE); + + return (* iface->drag_data_get) (drag_source, path, selection_data); +} + +/** + * gtk_tree_drag_dest_drag_data_received: + * @drag_dest: a #GtkTreeDragDest + * @dest: row to drop in front of + * @selection_data: data to drop + * + * Asks the #GtkTreeDragDest to insert a row before the path @dest, + * deriving the contents of the row from @selection_data. If @dest is + * outside the tree so that inserting before it is impossible, %FALSE + * will be returned. Also, %FALSE may be returned if the new row is + * not created for some model-specific reason. Should robustly handle + * a @dest no longer found in the model! + * + * Return value: whether a new row was created before position @dest + **/ +gboolean +gtk_tree_drag_dest_drag_data_received (GtkTreeDragDest *drag_dest, + GtkTreePath *dest, + GtkSelectionData *selection_data) +{ + GtkTreeDragDestIface *iface = GTK_TREE_DRAG_DEST_GET_IFACE (drag_dest); + + g_return_val_if_fail (iface->drag_data_received != NULL, FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + g_return_val_if_fail (selection_data != NULL, FALSE); + + return (* iface->drag_data_received) (drag_dest, dest, selection_data); +} + +typedef struct _TreeRowData TreeRowData; + +struct _TreeRowData +{ + GtkTreeModel *model; + gchar path[4]; +}; + +/** + * gtk_selection_data_set_tree_row: + * @selection_data: some #GtkSelectionData + * @tree_model: a #GtkTreeModel + * @path: a row in @tree_model + * + * Sets selection data of target type %GTK_TREE_MODEL_ROW. Normally used + * in a drag_data_get handler. + * + * Return value: %TRUE if the #GtkSelectionData had the proper target type to allow us to set a tree row + **/ +gboolean +gtk_selection_data_set_tree_row (GtkSelectionData *selection_data, + GtkTreeModel *tree_model, + GtkTreePath *path) +{ + TreeRowData *trd; + gchar *path_str; + gint len; + gint struct_size; + + g_return_val_if_fail (selection_data != NULL, FALSE); + g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + + if (selection_data->target != gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) + return FALSE; + + path_str = gtk_tree_path_to_string (path); + + len = strlen (path_str); + + /* the old allocate-end-of-struct-to-hold-string trick */ + struct_size = sizeof (TreeRowData) + len + 1 - + (sizeof (TreeRowData) - G_STRUCT_OFFSET (TreeRowData, path)); + + trd = g_malloc (struct_size); + + strcpy (trd->path, path_str); + + trd->model = tree_model; + + gtk_selection_data_set (selection_data, + gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE), + 8, /* bytes */ + (void*)trd, + struct_size); + + g_free (trd); + + return TRUE; +} + +/** + * gtk_selection_data_get_tree_row: + * @selection_data: a #GtkSelectionData + * @tree_model: a #GtkTreeModel + * @path: row in @tree_model + * + * Obtains a @tree_model and @path from selection data of target type + * %GTK_TREE_MODEL_ROW. Normally called from a drag_data_received handler. + * This function can only be used if @selection_data originates from the same + * process that's calling this function, because a pointer to the tree model + * is being passed around. If you aren't in the same process, then you'll + * get memory corruption. In the #GtkTreeDragDest drag_data_received handler, + * you can assume that selection data of type %GTK_TREE_MODEL_ROW is + * in from the current process. The returned path must be freed with + * gtk_tree_path_free(). + * + * Return value: %TRUE if @selection_data had target type %GTK_TREE_MODEL_ROW and + * is otherwise valid + **/ +gboolean +gtk_selection_data_get_tree_row (GtkSelectionData *selection_data, + GtkTreeModel **tree_model, + GtkTreePath **path) +{ + TreeRowData *trd; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (tree_model) + *tree_model = NULL; + + if (path) + *path = NULL; + + if (selection_data->target != gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) + return FALSE; + + trd = (void*) selection_data->data; + + if (tree_model) + *tree_model = trd->model; + + if (path) + *path = gtk_tree_path_new_from_string (trd->path); + + return TRUE; +} diff --git a/gtk/gtktreednd.h b/gtk/gtktreednd.h new file mode 100644 index 0000000000..1257ed25f6 --- /dev/null +++ b/gtk/gtktreednd.h @@ -0,0 +1,109 @@ +/* gtktreednd.h + * Copyright (C) 2001 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GTK_TREE_DND_H__ +#define __GTK_TREE_DND_H__ + +#include <gtk/gtktreemodel.h> +#include <gtk/gtkdnd.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GTK_TYPE_TREE_DRAG_SOURCE (gtk_tree_drag_source_get_type ()) +#define GTK_TREE_DRAG_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TREE_DRAG_SOURCE, GtkTreeDragSource)) +#define GTK_IS_TREE_DRAG_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TREE_DRAG_SOURCE)) +#define GTK_TREE_DRAG_SOURCE_GET_IFACE(obj) ((GtkTreeDragSourceIface *)g_type_interface_peek (((GTypeInstance *)GTK_TREE_DRAG_SOURCE (obj))->g_class, GTK_TYPE_TREE_DRAG_SOURCE)) + +typedef struct _GtkTreeDragSource GtkTreeDragSource; /* Dummy typedef */ +typedef struct _GtkTreeDragSourceIface GtkTreeDragSourceIface; + +struct _GtkTreeDragSourceIface +{ + GTypeInterface g_iface; + + /* VTable - not signals */ + + gboolean (* drag_data_get) (GtkTreeDragSource *dragsource, + GtkTreePath *path, + GtkSelectionData *selection_data); + + gboolean (* drag_data_delete) (GtkTreeDragSource *dragsource, + GtkTreePath *path); +}; + +GType gtk_tree_drag_source_get_type (void) G_GNUC_CONST; + +/* Deletes the given row, or returns FALSE if it can't */ +gboolean gtk_tree_drag_source_drag_data_delete (GtkTreeDragSource *drag_source, + GtkTreePath *path); + +/* Fills in selection_data with type selection_data->target based on + * the row denoted by path, returns TRUE if it does anything + */ +gboolean gtk_tree_drag_source_drag_data_get (GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data); + +#define GTK_TYPE_TREE_DRAG_DEST (gtk_tree_drag_dest_get_type ()) +#define GTK_TREE_DRAG_DEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TREE_DRAG_DEST, GtkTreeDragDest)) +#define GTK_IS_TREE_DRAG_DEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TREE_DRAG_DEST)) +#define GTK_TREE_DRAG_DEST_GET_IFACE(obj) ((GtkTreeDragDestIface *)g_type_interface_peek (((GTypeInstance *)GTK_TREE_DRAG_DEST (obj))->g_class, GTK_TYPE_TREE_DRAG_DEST)) + +typedef struct _GtkTreeDragDest GtkTreeDragDest; /* Dummy typedef */ +typedef struct _GtkTreeDragDestIface GtkTreeDragDestIface; + +struct _GtkTreeDragDestIface +{ + GTypeInterface g_iface; + + /* VTable - not signals */ + + gboolean (* drag_data_received) (GtkTreeDragDest *dragdest, + GtkTreePath *dest, + GtkSelectionData *selection_data); + +}; + +GType gtk_tree_drag_dest_get_type (void) G_GNUC_CONST; + +/* Inserts a row before dest which contains data in selection_data, + * or returns FALSE if it can't + */ +gboolean gtk_tree_drag_dest_drag_data_received (GtkTreeDragDest *drag_dest, + GtkTreePath *dest, + GtkSelectionData *selection_data); + +/* The selection data would normally have target type GTK_TREE_MODEL_ROW in this + * case. If the target is wrong these functions return FALSE. + */ +gboolean gtk_selection_data_set_tree_row (GtkSelectionData *selection_data, + GtkTreeModel *tree_model, + GtkTreePath *path); +gboolean gtk_selection_data_get_tree_row (GtkSelectionData *selection_data, + GtkTreeModel **tree_model, + GtkTreePath **path); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_TREE_DND_H__ */ diff --git a/gtk/gtktreemodel.h b/gtk/gtktreemodel.h index 74fd34da7e..b15b92b673 100644 --- a/gtk/gtktreemodel.h +++ b/gtk/gtktreemodel.h @@ -179,7 +179,7 @@ gboolean gtk_tree_model_iter_parent (GtkTreeModel *tree_model, void gtk_tree_model_ref_iter (GtkTreeModel *tree_model, GtkTreeIter *iter); void gtk_tree_model_unref_iter (GtkTreeModel *tree_model, - GtkTreeIter *iter); + GtkTreeIter *iter); #ifdef __cplusplus } diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 78d093c56c..73d5a9fd37 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -20,6 +20,7 @@ #include "gtktreeview.h" #include "gtkrbtree.h" +#include "gtktreednd.h" #include "gtktreeprivate.h" #include "gtkcellrenderer.h" #include "gtksignal.h" @@ -35,9 +36,35 @@ #define TREE_VIEW_DRAG_WIDTH 6 #define TREE_VIEW_EXPANDER_WIDTH 14 #define TREE_VIEW_EXPANDER_HEIGHT 14 -#define TREE_VIEW_VERTICAL_SEPARATOR 2 + +/* The TREE_VIEW_VERTICAL_SEPARATOR is the space between rows. The + * GTK_RBNODE_GET_HEIGHT() value includes the separators; the offset + * of each row points to the center of the inter-row space. For an odd + * separator, the extra pixel by convention goes _below_ the row. So + * a node in the rbtree owns TREE_VIEW_VERTICAL_SEPARATOR/2 pixels + * above the row, and TREE_VIEW_VERTICAL_SEPARATOR/2 + + * TREE_VIEW_VERTICAL_SEPARATOR%2 pixels below the row. + */ + +/* Set to large number for debugging. Should normally be 2. */ +#define TREE_VIEW_VERTICAL_SEPARATOR 11 + #define TREE_VIEW_HORIZONTAL_SEPARATOR 0 +/* The "background" areas of all rows/cells add up to cover the entire tree. + * The background includes all inter-row and inter-cell spacing. + * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(), + * i.e. just the cells, no spacing. + */ + +#define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (_gtk_rbtree_node_find_offset ((tree), (node)) + TREE_VIEW_HEADER_HEIGHT ((tree_view))) +#define CELL_FIRST_PIXEL(tree_view,tree,node) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + TREE_VIEW_VERTICAL_SEPARATOR/2) + +#define BACKGROUND_HEIGHT(node) (GTK_RBNODE_GET_HEIGHT (node)) +#define CELL_HEIGHT(node) (BACKGROUND_HEIGHT (node) - TREE_VIEW_VERTICAL_SEPARATOR); + +#define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) - TREE_VIEW_HEADER_HEIGHT (tree_view)) +#define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) + TREE_VIEW_HEADER_HEIGHT (tree_view)) typedef struct _GtkTreeViewChild GtkTreeViewChild; @@ -152,13 +179,16 @@ static void gtk_tree_view_queue_draw_node (GtkTreeView *tree_view, GtkRBTree *tree, GtkRBNode *node, GdkRectangle *clip_rect); +static void gtk_tree_view_queue_draw_path (GtkTreeView *tree_view, + GtkTreePath *path, + GdkRectangle *clip_rect); static void gtk_tree_view_draw_arrow (GtkTreeView *tree_view, GtkRBTree *tree, GtkRBNode *node, gint x, gint y); -static void gtk_tree_view_get_arrow_range (GtkTreeView *tree_view, - gint *x1, +static void gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view, + gint *x1, gint *x2); static gint gtk_tree_view_new_column_width (GtkTreeView *tree_view, gint i, @@ -821,9 +851,9 @@ gtk_tree_view_draw_node_focus_rect (GtkWidget *widget, widget->style->fg_gc[GTK_STATE_NORMAL], FALSE, 0, - _gtk_rbtree_node_find_offset (tree, node) + TREE_VIEW_HEADER_HEIGHT (tree_view), + BACKGROUND_FIRST_PIXEL (tree_view, tree, node), bin_window_width - 2, - GTK_RBNODE_GET_HEIGHT (node)); + BACKGROUND_HEIGHT (node) - 1); } GdkPixmap* @@ -836,7 +866,6 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, GtkCellRenderer *cell; gint i; gint cell_offset; - gint max_height; GList *list; GdkRectangle background_area; GtkWidget *widget; @@ -860,20 +889,18 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, &iter, path)) return NULL; - - max_height = GTK_RBNODE_GET_HEIGHT (node); cell_offset = x; - background_area.y = y + TREE_VIEW_VERTICAL_SEPARATOR; - background_area.height = max_height - TREE_VIEW_VERTICAL_SEPARATOR; + background_area.y = y; + background_area.height = BACKGROUND_HEIGHT (node); gdk_drawable_get_size (tree_view->priv->bin_window, &bin_window_width, NULL); drawable = gdk_pixmap_new (tree_view->priv->bin_window, bin_window_width + 2, - max_height + 2, + background_area.height + 2, -1); gdk_draw_rectangle (drawable, @@ -881,14 +908,14 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, TRUE, 0, 0, bin_window_width + 2, - max_height + 2); + background_area.height + 2); gdk_draw_rectangle (drawable, widget->style->black_gc, FALSE, 0, 0, bin_window_width + 1, - max_height + 1); + background_area.height + 1); for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next) { @@ -907,6 +934,9 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, 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; if (i == tree_view->priv->expander_column && TREE_VIEW_DRAW_EXPANDERS(tree_view)) @@ -972,8 +1002,11 @@ gtk_tree_view_bin_expose (GtkWidget *widget, * height to find the right node. */ new_y = (event->area.y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):event->area.y; + + /* y_offset is the */ + y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, - new_y - TREE_VIEW_HEADER_HEIGHT (tree_view), + TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y), &tree, &node) + new_y - event->area.y; if (node == NULL) @@ -1015,13 +1048,13 @@ gtk_tree_view_bin_expose (GtkWidget *widget, max_height = MAX (TREE_VIEW_EXPANDER_MIN_HEIGHT, GTK_RBNODE_GET_HEIGHT (node)); else */ - max_height = GTK_RBNODE_GET_HEIGHT (node); + 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; + background_area.y = y_offset + event->area.y + TREE_VIEW_VERTICAL_SEPARATOR / 2; background_area.height = max_height - TREE_VIEW_VERTICAL_SEPARATOR; flags = 0; @@ -1236,11 +1269,11 @@ coords_are_over_arrow (GtkTreeView *tree_view, if ((node->flags & GTK_RBNODE_IS_PARENT) == 0) return FALSE; - arrow.y = _gtk_rbtree_node_find_offset (tree, node) + TREE_VIEW_HEADER_HEIGHT (tree_view); + arrow.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node); - arrow.height = GTK_RBNODE_GET_HEIGHT (node); + arrow.height = BACKGROUND_HEIGHT (node); - gtk_tree_view_get_arrow_range (tree_view, &arrow.x, &x2); + gtk_tree_view_get_arrow_xrange (tree_view, &arrow.x, &x2); arrow.width = x2 - arrow.x; @@ -1256,21 +1289,10 @@ do_unprelight (GtkTreeView *tree_view, gint x, gint y) { - gint y1, y2; - if (tree_view->priv->prelight_node == NULL) return; - y1 = _gtk_rbtree_node_find_offset (tree_view->priv->prelight_tree, - tree_view->priv->prelight_node) + - TREE_VIEW_HEADER_HEIGHT (tree_view); - - y2 = y1 + GTK_RBNODE_GET_HEIGHT (tree_view->priv->prelight_node); - - if (tree_view->priv->prelight_node) - GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT); - - /* FIXME queue draw on y1-y2 range */ + GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT); if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT) && !coords_are_over_arrow (tree_view, @@ -1286,15 +1308,12 @@ do_unprelight (GtkTreeView *tree_view, tree_view->priv->prelight_tree, tree_view->priv->prelight_node, x, - y); + y); } tree_view->priv->prelight_node = NULL; tree_view->priv->prelight_tree = NULL; - - /* FIXME */ - gtk_widget_queue_draw (GTK_WIDGET (tree_view)); } static void @@ -1312,8 +1331,6 @@ do_prelight (GtkTreeView *tree_view, tree_view->priv->prelight_tree = tree; GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT); - - gtk_widget_queue_draw (GTK_WIDGET (tree_view)); } static gboolean @@ -1324,6 +1341,8 @@ gtk_tree_view_motion (GtkWidget *widget, GtkRBTree *tree; GtkRBNode *node; gint new_y; + GtkRBTree *old_prelight_tree; + GtkRBNode *old_prelight_node; tree_view = (GtkTreeView *) widget; @@ -1357,11 +1376,15 @@ gtk_tree_view_motion (GtkWidget *widget, gtk_tree_view_maybe_begin_dragging_row (tree_view, event); + old_prelight_tree = tree_view->priv->prelight_tree; + old_prelight_node = tree_view->priv->prelight_node; + do_unprelight (tree_view, event->x, event->y); new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y; - _gtk_rbtree_find_offset (tree_view->priv->tree, new_y - TREE_VIEW_HEADER_HEIGHT (tree_view), + _gtk_rbtree_find_offset (tree_view->priv->tree, + TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y), &tree, &node); @@ -1376,6 +1399,21 @@ gtk_tree_view_motion (GtkWidget *widget, do_prelight (tree_view, tree, node, event->x, new_y); + if (old_prelight_node != tree_view->priv->prelight_node) + { + if (old_prelight_node) + gtk_tree_view_queue_draw_node (tree_view, + old_prelight_tree, + old_prelight_node, + NULL); + + if (tree_view->priv->prelight_node) + gtk_tree_view_queue_draw_node (tree_view, + tree_view->priv->prelight_tree, + tree_view->priv->prelight_node, + NULL); + } + return TRUE; } @@ -1411,7 +1449,7 @@ gtk_tree_view_enter_notify (GtkWidget *widget, new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y; _gtk_rbtree_find_offset (tree_view->priv->tree, - new_y - TREE_VIEW_HEADER_HEIGHT (tree_view), + TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y), &tree, &node); @@ -1420,6 +1458,12 @@ gtk_tree_view_enter_notify (GtkWidget *widget, do_prelight (tree_view, tree, node, event->x, new_y); + if (tree_view->priv->prelight_node) + gtk_tree_view_queue_draw_node (tree_view, + tree_view->priv->prelight_tree, + tree_view->priv->prelight_node, + NULL); + return TRUE; } @@ -1434,6 +1478,12 @@ gtk_tree_view_leave_notify (GtkWidget *widget, tree_view = GTK_TREE_VIEW (widget); + if (tree_view->priv->prelight_node) + gtk_tree_view_queue_draw_node (tree_view, + tree_view->priv->prelight_tree, + tree_view->priv->prelight_node, + NULL); + do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */ return TRUE; @@ -1491,7 +1541,7 @@ gtk_tree_view_button_press (GtkWidget *widget, /* find the node that was clicked */ new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y; y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, - new_y - TREE_VIEW_HEADER_HEIGHT (tree_view), + TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y), &tree, &node) + new_y - (gint)event->y; @@ -2233,7 +2283,8 @@ gtk_tree_view_forall (GtkContainer *container, for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next) { - column = tmp_list->data; + column = tmp_list->data; + if (column->button) (* callback) (column->button, callback_data); } @@ -2283,8 +2334,7 @@ gtk_tree_view_changed (GtkTreeModel *model, gtk_widget_queue_resize (GTK_WIDGET (data)); else { - /* FIXME: just redraw the node */ - gtk_widget_queue_draw (GTK_WIDGET (data)); + gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL); } } @@ -2849,7 +2899,7 @@ gtk_tree_view_create_buttons (GtkTreeView *tree_view) for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++) { column = list->data; - + if (column->button != NULL) continue; @@ -3021,52 +3071,6 @@ _gtk_tree_view_find_node (GtkTreeView *tree_view, } static void -gtk_tree_view_get_arrow_range (GtkTreeView *tree_view, - gint *x1, - gint *x2) -{ - gint x_offset = 0; - GList *list; - GtkTreeViewColumn *tmp_column = NULL; - gint total_width; - gint i; - - i = 0; - total_width = 0; - for (list = tree_view->priv->columns; list; list = list->next) - { - tmp_column = list->data; - - if (i == tree_view->priv->expander_column) - { - x_offset = total_width; - break; - } - - if (tmp_column->visible) - total_width += tmp_column->width; - - ++i; - } - - if (x1) - *x1 = x_offset; - - if (tmp_column && tmp_column->visible) - { - /* +1 because x2 isn't included in the range. */ - if (x2) - *x2 = x_offset + tree_view->priv->tab_offset + 1; - } - else - { - /* return an empty range, the expander column is hidden */ - if (x2) - *x2 = x_offset; - } -} - -static void gtk_tree_view_queue_draw_node (GtkTreeView *tree_view, GtkRBTree *tree, GtkRBNode *node, @@ -3074,28 +3078,43 @@ gtk_tree_view_queue_draw_node (GtkTreeView *tree_view, { GdkRectangle rect; + if (!GTK_WIDGET_REALIZED (tree_view)) + return; + rect.x = 0; rect.width = tree_view->priv->width; - rect.y = _gtk_rbtree_node_find_offset (tree, node) + - TREE_VIEW_VERTICAL_SEPARATOR/2 + - TREE_VIEW_HEADER_HEIGHT (tree_view); - rect.height = GTK_RBNODE_GET_HEIGHT (node) + TREE_VIEW_VERTICAL_SEPARATOR; + + rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node); + rect.height = BACKGROUND_HEIGHT (node); + if (clip_rect) { GdkRectangle new_rect; - gdk_rectangle_intersect (clip_rect, &rect, &new_rect); - gtk_widget_queue_draw_area (GTK_WIDGET (tree_view), - new_rect.x, new_rect.y, - new_rect.width, new_rect.height); + + gdk_rectangle_intersect (clip_rect, &rect, &new_rect); + + gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE); } else { - gtk_widget_queue_draw_area (GTK_WIDGET (tree_view), - rect.x, rect.y, - rect.width, rect.height); + gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE); } } +static void +gtk_tree_view_queue_draw_path (GtkTreeView *tree_view, + GtkTreePath *path, + GdkRectangle *clip_rect) +{ + GtkRBTree *tree = NULL; + GtkRBNode *node = NULL; + + _gtk_tree_view_find_node (tree_view, path, &tree, &node); + + if (tree) + gtk_tree_view_queue_draw_node (tree_view, tree, node, clip_rect); +} + /* x and y are the mouse position */ static void @@ -3109,21 +3128,18 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view, GtkStateType state; GtkWidget *widget; gint x_offset = 0; - gint y_offset = 0; if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT)) return; widget = GTK_WIDGET (tree_view); - y_offset = _gtk_rbtree_node_find_offset (tree, node) + TREE_VIEW_HEADER_HEIGHT (tree_view); - - gtk_tree_view_get_arrow_range (tree_view, &x_offset, NULL); + gtk_tree_view_get_arrow_xrange (tree_view, &x_offset, NULL); area.x = x_offset; - area.y = y_offset + TREE_VIEW_VERTICAL_SEPARATOR; + area.y = CELL_FIRST_PIXEL (tree_view, tree, node); area.width = tree_view->priv->tab_offset - 2; - area.height = GTK_RBNODE_GET_HEIGHT (node) - TREE_VIEW_VERTICAL_SEPARATOR; + area.height = CELL_HEIGHT (node); if (node == tree_view->priv->button_pressed_node) { @@ -3755,7 +3771,6 @@ gtk_tree_view_append_column (GtkTreeView *tree_view, g_return_val_if_fail (column->tree_view == NULL, -1); g_object_ref (G_OBJECT (column)); - gtk_object_sink (GTK_OBJECT (column)); tree_view->priv->columns = g_list_append (tree_view->priv->columns, column); column->tree_view = GTK_WIDGET (tree_view); @@ -3820,7 +3835,7 @@ gtk_tree_view_insert_column (GtkTreeView *tree_view, g_return_val_if_fail (column->tree_view == NULL, -1); g_object_ref (G_OBJECT (column)); - gtk_object_sink (GTK_OBJECT (column)); + tree_view->priv->columns = g_list_insert (tree_view->priv->columns, column, position); column->tree_view = GTK_WIDGET (tree_view); @@ -3965,7 +3980,7 @@ gtk_tree_view_scroll_to_cell (GtkTreeView *tree_view, return; } - gtk_tree_view_get_cell_rect (tree_view, path, column, &cell_rect); + gtk_tree_view_get_cell_area (tree_view, path, column, &cell_rect); gtk_tree_view_get_visible_rect (tree_view, &vis_rect); dest_x = vis_rect.x; @@ -3999,14 +4014,16 @@ gtk_tree_view_scroll_to_cell (GtkTreeView *tree_view, * @cell_x: A pointer where the X coordinate relative to the cell can be placed, or %NULL * @cell_y: A pointer where the Y coordinate relative to the cell can be placed, or %NULL * - * Finds the path at the point (@x, @y) relative to @window. If @window is - * NULL, then the point is found relative to the widget coordinates. This - * function is expected to be called after an event, with event->window being - * passed in as @window. It is primarily for things like popup menus. If @path - * is non-NULL, then it will be filled with the #GtkTreePath at that point. - * This path should be freed with #gtk_tree_path_free. If @column is non-NULL, - * then it will be filled with the column at that point. @cell_x and @cell_y return - * the coordinates relative to the cell. + * Finds the path at the point (@x, @y) relative to @window. If + * @window is NULL, then the point is found relative to the widget + * coordinates. This function is expected to be called after an + * event, with event->window being passed in as @window. It is + * primarily for things like popup menus. If @path is non-NULL, then + * it will be filled with the #GtkTreePath at that point. This path + * should be freed with #gtk_tree_path_free. If @column is non-NULL, + * then it will be filled with the column at that point. @cell_x and + * @cell_y return the coordinates relative to the cell background + * (i.e. the background_area passed to gtk_cell_renderer_render()). * * Return value: TRUE if a row exists at that coordinate. **/ @@ -4086,7 +4103,7 @@ gtk_tree_view_get_path_at_pos (GtkTreeView *tree_view, if (window) { y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree, - y - TREE_VIEW_HEADER_HEIGHT (tree_view), + TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y), &tree, &node); } else @@ -4094,8 +4111,8 @@ gtk_tree_view_get_path_at_pos (GtkTreeView *tree_view, if (y < TREE_VIEW_HEADER_HEIGHT (tree_view)) return FALSE; - y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree, y - TREE_VIEW_HEADER_HEIGHT (tree_view) + - tree_view->priv->vadjustment->value, + y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree, + TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y + tree_view->priv->vadjustment->value), &tree, &node); } @@ -4111,28 +4128,182 @@ gtk_tree_view_get_path_at_pos (GtkTreeView *tree_view, return TRUE; } + +static void +gtk_tree_view_get_background_xrange (GtkTreeView *tree_view, + GtkRBTree *tree, + GtkTreeViewColumn *column, + gint *x1, + gint *x2) +{ + GtkTreeViewColumn *tmp_column = NULL; + gint total_width; + GList *list; + + if (x1) + *x1 = 0; + + if (x2) + *x2 = 0; + + total_width = 0; + for (list = tree_view->priv->columns; list; list = list->next) + { + tmp_column = list->data; + + if (tmp_column == column) + break; + + if (tmp_column->visible) + total_width += tmp_column->width; + } + + if (tmp_column != column) + { + g_warning (G_STRLOC": passed-in column isn't in the tree"); + return; + } + + if (x1) + *x1 = total_width; + + if (x2) + { + if (column->visible) + *x2 = total_width + column->width; + else + *x2 = total_width; /* width of 0 */ + } +} + +static void +gtk_tree_view_get_cell_xrange (GtkTreeView *tree_view, + GtkRBTree *tree, + GtkTreeViewColumn *column, + gint *x1, + gint *x2) +{ + GtkTreeViewColumn *tmp_column = NULL; + gint total_width; + GList *list; + gint i; + + if (x1) + *x1 = 0; + + if (x2) + *x2 = 0; + + i = 0; + total_width = 0; + for (list = tree_view->priv->columns; list; list = list->next) + { + tmp_column = list->data; + + if (tmp_column == column) + break; + + if (tmp_column->visible) + total_width += tmp_column->width; + + ++i; + } + + if (tmp_column != column) + { + g_warning (G_STRLOC": passed-in column isn't in the tree"); + return; + } + + /* Remember we're getting the cell range, i.e. the cell_area passed + * to the cell renderer. + */ + + if (i == tree_view->priv->expander_column) + total_width += tree_view->priv->tab_offset * _gtk_rbtree_get_depth (tree); + + if (x1) + *x1 = total_width; + + if (x2) + { + if (column->visible) + *x2 = total_width + column->width; + else + *x2 = total_width; /* width of 0 */ + } +} + +static void +gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view, + gint *x1, + gint *x2) +{ + gint x_offset = 0; + GList *list; + GtkTreeViewColumn *tmp_column = NULL; + gint total_width; + gint i; + + i = 0; + total_width = 0; + for (list = tree_view->priv->columns; list; list = list->next) + { + tmp_column = list->data; + + if (i == tree_view->priv->expander_column) + { + x_offset = total_width; + break; + } + + if (tmp_column->visible) + total_width += tmp_column->width; + + ++i; + } + + if (x1) + *x1 = x_offset; + + if (tmp_column && tmp_column->visible) + { + /* +1 because x2 isn't included in the range. */ + if (x2) + *x2 = x_offset + tree_view->priv->tab_offset + 1; + } + else + { + /* return an empty range, the expander column is hidden */ + if (x2) + *x2 = x_offset; + } +} + + /** - * gtk_tree_view_get_cell_rect: + * gtk_tree_view_get_cell_area: * @tree_view: a #GtkTreeView * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes * @rect: rectangle to fill with cell rect * - * Fills the bounding rectangle in tree window coordinates for the cell - * at the row specified by @path and the column specified by @column. - * If @path is %NULL, the y and height fields of the rectangle will be filled - * with 0. If @column is %NULL, the x and width fields will be filled with 0. + * Fills the bounding rectangle in tree window coordinates for the + * cell at the row specified by @path and the column specified by + * @column. If @path is %NULL, the y and height fields of the + * rectangle will be filled with 0. If @column is %NULL, the x and + * width fields will be filled with 0. The sum of all cell rects does + * not cover the entire tree; there are extra pixels in between rows, + * for example. The returned rectangle is equivalent to the @cell_area + * passed to gtk_cell_renderer_render(). * **/ void -gtk_tree_view_get_cell_rect (GtkTreeView *tree_view, +gtk_tree_view_get_cell_area (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, GdkRectangle *rect) { - GtkTreeViewColumn *tmp_column = NULL; - gint total_width; - GList *list; GtkRBTree *tree = NULL; GtkRBNode *node = NULL; @@ -4157,35 +4328,85 @@ gtk_tree_view_get_cell_rect (GtkTreeView *tree_view, return; } - rect->y = _gtk_rbtree_node_find_offset (tree, node) + TREE_VIEW_HEADER_HEIGHT (tree_view); + /* Remember that the rbtree stores node height including the vertical + * separator, see comment at top of file. + */ + rect->y = CELL_FIRST_PIXEL (tree_view, tree, node); + + rect->height = CELL_HEIGHT (node); + } + + if (column) + { + gint x2 = 0; - rect->height = GTK_RBNODE_GET_HEIGHT (node); + gtk_tree_view_get_cell_xrange (tree_view, tree, column, &rect->x, &x2); + rect->width = x2 - rect->x; } +} + + +/** + * gtk_tree_view_get_background_area: + * @tree_view: a #GtkTreeView + * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates + * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes + * @rect: rectangle to fill with cell background rect + * + * Fills the bounding rectangle in tree window coordinates for the + * cell at the row specified by @path and the column specified by + * @column. If @path is %NULL, the y and height fields of the + * rectangle will be filled with 0. If @column is %NULL, the x and + * width fields will be filled with 0. The returned rectangle is + * equivalent to the @background_area passed to + * gtk_cell_renderer_render(). These background areas tile to cover + * the entire tree window (except for the area used for header + * buttons). Contrast with the cell_area, returned by + * gtk_tree_view_get_cell_area(), which returns only the cell itself, + * excluding surrounding borders and the tree expander area. + * + **/ +void +gtk_tree_view_get_background_area (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + GdkRectangle *rect) +{ + GtkRBTree *tree = NULL; + GtkRBNode *node = NULL; + + g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column)); + g_return_if_fail (rect != NULL); - if (column && column->visible) + rect->x = 0; + rect->y = 0; + rect->width = 0; + rect->height = 0; + + if (path) { - total_width = 0; - for (list = tree_view->priv->columns; list; list = list->next) - { - tmp_column = list->data; - - if (tmp_column == column) - { - rect->x = total_width; - break; - } - - if (tmp_column->visible) - total_width += tmp_column->width; - } + /* Get vertical coords */ - if (tmp_column != column) + _gtk_tree_view_find_node (tree_view, path, &tree, &node); + + if (tree == NULL) { - g_warning (G_STRLOC": passed-in column isn't in the tree"); + g_warning (G_STRLOC": no row corresponding to path"); return; } - - rect->width = column->width; + + rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node); + + rect->height = BACKGROUND_HEIGHT (node); + } + + if (column) + { + gint x2 = 0; + + gtk_tree_view_get_background_xrange (tree_view, tree, column, &rect->x, &x2); + rect->width = x2 - rect->x; } } @@ -4458,8 +4679,7 @@ gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view, if (ty) { - *ty = wy - TREE_VIEW_HEADER_HEIGHT (tree_view) + - tree_view->priv->vadjustment->value; + *ty = wy + tree_view->priv->vadjustment->value; } } @@ -4491,13 +4711,45 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view, if (wy) { - *wy = ty + TREE_VIEW_HEADER_HEIGHT (tree_view) - - tree_view->priv->vadjustment->value; + *wy = ty - tree_view->priv->vadjustment->value; } } /* Drag-and-drop */ +void +set_source_row (GdkDragContext *context, + GtkTreePath *source_row) +{ + g_object_set_data_full (G_OBJECT (context), + "gtk-tree-view-source-row", + source_row ? gtk_tree_path_copy (source_row) : NULL, + (GDestroyNotify) (source_row ? gtk_tree_path_free : NULL)); +} + +GtkTreePath* +get_source_row (GdkDragContext *context) +{ + return g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row"); +} + + +void +set_dest_row (GdkDragContext *context, + GtkTreePath *dest_row) +{ + g_object_set_data_full (G_OBJECT (context), + "gtk-tree-view-dest-row", + dest_row ? gtk_tree_path_copy (dest_row) : NULL, + (GDestroyNotify) (dest_row ? gtk_tree_path_free : NULL)); +} + +GtkTreePath* +get_dest_row (GdkDragContext *context) +{ + return g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row"); +} + typedef struct _TreeViewDragInfo TreeViewDragInfo; struct _TreeViewDragInfo @@ -4506,7 +4758,6 @@ struct _TreeViewDragInfo GtkTargetList *source_target_list; GdkDragAction source_actions; GClosure *row_draggable_closure; - GtkTreePath *source_row; GtkTargetList *dest_target_list; GClosure *location_droppable_closure; @@ -4529,13 +4780,9 @@ clear_source_info (TreeViewDragInfo *di) if (di->row_draggable_closure) g_closure_unref (di->row_draggable_closure); - - if (di->source_row) - gtk_tree_path_free (di->source_row); di->source_target_list = NULL; di->row_draggable_closure = NULL; - di->source_row = NULL; } static void @@ -4766,7 +5013,6 @@ gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view) } } - void gtk_tree_view_set_drag_dest_row (GtkTreeView *tree_view, GtkTreePath *path, @@ -4778,21 +5024,42 @@ gtk_tree_view_set_drag_dest_row (GtkTreeView *tree_view, g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + g_print ("drag dest row %p -> %p\n", tree_view->priv->drag_dest_row, path); + if (tree_view->priv->drag_dest_row) { - /* FIXME queue undraw on previous location */ + gtk_tree_view_queue_draw_path (tree_view, tree_view->priv->drag_dest_row, NULL); gtk_tree_path_free (tree_view->priv->drag_dest_row); } tree_view->priv->drag_dest_pos = pos; if (path) - tree_view->priv->drag_dest_row = gtk_tree_path_copy (path); + { + tree_view->priv->drag_dest_row = gtk_tree_path_copy (path); + gtk_tree_view_queue_draw_path (tree_view, tree_view->priv->drag_dest_row, NULL); + } else tree_view->priv->drag_dest_row = NULL; +} + +void +gtk_tree_view_get_drag_dest_row (GtkTreeView *tree_view, + GtkTreePath **path, + GtkTreeViewDropPosition *pos) +{ + g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + + if (path) + { + if (tree_view->priv->drag_dest_row) + *path = gtk_tree_path_copy (tree_view->priv->drag_dest_row); + else + *path = NULL; + } - /* FIXME this is crap, queue draw only on the newly-highlighted row */ - gtk_widget_queue_draw (GTK_WIDGET (tree_view)); + if (pos) + *pos = tree_view->priv->drag_dest_pos; } gboolean @@ -4823,7 +5090,7 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView *tree_view, if (path) *path = NULL; - /* remember that drag_x and drag_y are in widget coords, convert to rbtree */ + /* remember that drag_x and drag_y are in widget coords, convert to tree window */ gtk_tree_view_widget_to_tree_coords (tree_view, drag_x, drag_y, &x, &y); @@ -4842,8 +5109,8 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView *tree_view, &cell_y)) return FALSE; - gtk_tree_view_get_cell_rect (tree_view, tmp_path, column, - &cell); + gtk_tree_view_get_background_area (tree_view, tmp_path, column, + &cell); offset_into_row = cell_y; @@ -4879,24 +5146,6 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView *tree_view, return TRUE; } -gboolean -gtk_selection_data_set_tree_row (GtkSelectionData *selection_data, - GtkTreeView *tree_view, - GtkTreePath *path) -{ - - return FALSE; -} - -gboolean -gtk_selection_data_get_tree_row (GtkSelectionData *selection_data, - GtkTreeView **tree_view, - GtkTreePath **path) -{ - return FALSE; -} - - static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, GdkEventMotion *event) @@ -4969,7 +5218,8 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, gdk_pixmap_unref (row_pix); } - di->source_row = path; + set_source_row (context, path); + gtk_tree_path_free (path); return TRUE; } @@ -4998,38 +5248,99 @@ gtk_tree_view_drag_data_get (GtkWidget *widget, guint time) { GtkTreeView *tree_view; - + GtkTreeModel *model; + TreeViewDragInfo *di; + GtkTreePath *source_row; + tree_view = GTK_TREE_VIEW (widget); - if (selection_data->target == gdk_atom_intern ("GTK_TREE_VIEW_ROW", FALSE)) - { - TreeViewDragInfo *di; + model = gtk_tree_view_get_model (tree_view); - di = get_info (GTK_TREE_VIEW (widget)); + if (model == NULL) + return; - if (di == NULL) - { - /* There's a race where someone could have unset - * drag source before the data is requested - */ - return; - } - + di = get_info (GTK_TREE_VIEW (widget)); + + if (di == NULL) + return; + + source_row = get_source_row (context); + + if (source_row == NULL) + return; + + /* We can implement the GTK_TREE_MODEL_ROW target generically for + * any model; for DragSource models there are some other targets + * we also support. + */ + + if (GTK_IS_TREE_DRAG_SOURCE (model) && + gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model), + source_row, + selection_data)) + return; + + /* If drag_data_get does nothing, try providing row data. */ + if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) + { gtk_selection_data_set_tree_row (selection_data, - GTK_TREE_VIEW (widget), - di->source_row); + model, + source_row); + } +} + + +static gboolean +check_model_dnd (GtkTreeModel *model, + GType required_iface, + const gchar *signal) +{ + if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface)) + { + g_warning ("You must override the default '%s' handler " + "on GtkTreeView when using models that don't support " + "the %s interface. The simplest way to do this " + "is to connect to '%s' and call " + "gtk_signal_emit_stop_by_name() in your signal handler to prevent " + "the default handler from running. Look at the source code " + "for the default handler in gtktreeview.c to get an idea what " + "your handler should do. (gtktreeview.c is in the GTK source " + "code.)", + signal, g_type_name (required_iface), signal); + return FALSE; } + else + return TRUE; } static void gtk_tree_view_drag_data_delete (GtkWidget *widget, GdkDragContext *context) { - /* FIXME we need to delete the source_row if we're doing automagical - * reordering stuff. - */ -} + TreeViewDragInfo *di; + GtkTreeModel *model; + GtkTreeView *tree_view; + GtkTreePath *source_row; + + tree_view = GTK_TREE_VIEW (widget); + model = gtk_tree_view_get_model (tree_view); + + if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete")) + return; + + di = get_info (tree_view); + if (di == NULL) + return; + + source_row = get_source_row (context); + + + gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model), + source_row); + + set_source_row (context, NULL); +} static void remove_open_timeout (GtkTreeView *tree_view) @@ -5051,6 +5362,7 @@ 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); @@ -5078,21 +5390,24 @@ open_row_timeout (gpointer data) return TRUE; } +/* Returns TRUE if event should not be propagated to parent widgets */ static gboolean -gtk_tree_view_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) +set_destination_row (GtkTreeView *tree_view, + GdkDragContext *context, + gint x, + gint y, + GdkDragAction *suggested_action) { GtkTreePath *path = NULL; - TreeViewDragInfo *di; GtkTreeViewDropPosition pos; - GtkTreeView *tree_view; + TreeViewDragInfo *di; + GtkWidget *widget; - tree_view = GTK_TREE_VIEW (widget); + *suggested_action = 0; - di = get_info (GTK_TREE_VIEW (widget)); + widget = GTK_WIDGET (tree_view); + + di = get_info (tree_view); if (di == NULL) { @@ -5100,6 +5415,7 @@ gtk_tree_view_drag_motion (GtkWidget *widget, * 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); @@ -5110,7 +5426,12 @@ gtk_tree_view_drag_motion (GtkWidget *widget, return FALSE; /* no longer a drop site */ } - ensure_scroll_timeout (tree_view); + /* We don't take this target */ + if (gtk_drag_dest_find_target (widget, context, di->dest_target_list) == GDK_NONE) + { + g_print ("bad target, not accepting\n"); + return FALSE; + } if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, @@ -5119,9 +5440,8 @@ gtk_tree_view_drag_motion (GtkWidget *widget, { /* can't drop here */ remove_open_timeout (tree_view); - - gdk_drag_status (context, 0, time); + g_print ("no drag row here\n"); gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, GTK_TREE_VIEW_DROP_BEFORE); @@ -5141,13 +5461,11 @@ gtk_tree_view_drag_motion (GtkWidget *widget, pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))) remove_open_timeout (tree_view); - if (TRUE /* FIXME if the location droppable predicate */ && - gtk_drag_dest_find_target (widget, context, di->dest_target_list) != GDK_NONE) + if (TRUE /* FIXME if the location droppable predicate */) { GtkWidget *source_widget; - GdkDragAction suggested_action; - suggested_action = context->suggested_action; + *suggested_action = context->suggested_action; source_widget = gtk_drag_get_source_widget (context); @@ -5157,34 +5475,73 @@ gtk_tree_view_drag_motion (GtkWidget *widget, * pressed ctrl or alt to affect available actions */ if ((context->actions & GDK_ACTION_MOVE) != 0) - suggested_action = GDK_ACTION_MOVE; + *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); - - if (tree_view->priv->open_dest_timeout == 0) - { - tree_view->priv->open_dest_timeout = - gtk_timeout_add (250, open_row_timeout, tree_view); - } - - gdk_drag_status (context, suggested_action, time); } else { /* can't drop here */ remove_open_timeout (tree_view); - gdk_drag_status (context, 0, time); - + g_print ("droppable predicate false\n"); gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, GTK_TREE_VIEW_DROP_BEFORE); } - gtk_tree_path_free (path); + return TRUE; +} + +static gboolean +gtk_tree_view_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GtkTreePath *path = NULL; + GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; + GdkDragAction suggested_action = 0; + + tree_view = GTK_TREE_VIEW (widget); + + g_print ("motion\n"); + + if (!set_destination_row (tree_view, context, x, y, &suggested_action)) + return FALSE; + + ensure_scroll_timeout (tree_view); + gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos); + + if (path == NULL) + { + /* Can't drop here. */ + g_print ("not over a dest row\n"); + gdk_drag_status (context, 0, time); + } + else + { + if (tree_view->priv->open_dest_timeout == 0 && + (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER || + pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)) + { + tree_view->priv->open_dest_timeout = + gtk_timeout_add (250, open_row_timeout, tree_view); + } + + g_print ("status\n"); + gdk_drag_status (context, suggested_action, time); + } + + if (path) + gtk_tree_path_free (path); + return TRUE; } @@ -5195,22 +5552,59 @@ gtk_tree_view_drag_drop (GtkWidget *widget, gint y, guint time) { + GtkTreePath *path = NULL; + GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; + GdkDragAction suggested_action = 0; GdkAtom target = GDK_NONE; TreeViewDragInfo *di; - GtkTreeView *tree_view; - + GtkTreeModel *model; + tree_view = GTK_TREE_VIEW (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)); - + di = get_info (tree_view); - if (di && tree_view->priv->drag_dest_row && di->dest_target_list) - target = gtk_drag_dest_find_target (widget, context, di->dest_target_list); + if (di == NULL) + return FALSE; + + if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop")) + return FALSE; + + if (!set_destination_row (tree_view, context, x, y, &suggested_action)) + return FALSE; + gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos); + + if (path != NULL && di->dest_target_list) + { + target = gtk_drag_dest_find_target (widget, context, di->dest_target_list); + + if (target != GDK_NONE) + { + g_print ("have target\n"); + + set_dest_row (context, path); + } + } + + if (path) + gtk_tree_path_free (path); + + /* Unset this thing */ + gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), + NULL, + GTK_TREE_VIEW_DROP_BEFORE); + if (target != GDK_NONE) { + g_print ("getting data\n"); gtk_drag_get_data (widget, context, target, time); return TRUE; } @@ -5226,21 +5620,48 @@ gtk_tree_view_drag_data_received (GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time) -{ +{ + TreeViewDragInfo *di; + gboolean accepted = FALSE; + GtkTreeModel *model; + GtkTreeView *tree_view; + GtkTreePath *dest_row; + + tree_view = GTK_TREE_VIEW (widget); + + model = gtk_tree_view_get_model (tree_view); + + 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); + + if (di == NULL) + return; + + dest_row = get_dest_row (context); + + if (dest_row == NULL) + return; + if (selection_data->length >= 0) { - /* FIXME respond to contents of selection_data */ - + if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model), + dest_row, + selection_data)) + accepted = TRUE; + + + /* Don't clear drop_row, we may need it in drag_data_delete */ } - - gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), - NULL, - GTK_TREE_VIEW_DROP_BEFORE); gtk_drag_finish (context, - (selection_data->length >= 0), + accepted, (context->action == GDK_ACTION_MOVE), - time); + time); + g_print ("accepted: %d\n", accepted); } diff --git a/gtk/gtktreeview.h b/gtk/gtktreeview.h index d15109eff2..22890ae66a 100644 --- a/gtk/gtktreeview.h +++ b/gtk/gtktreeview.h @@ -125,7 +125,11 @@ gboolean gtk_tree_view_get_path_at_pos (GtkTreeView *tr GtkTreeViewColumn **column, gint *cell_x, gint *cell_y); -void gtk_tree_view_get_cell_rect (GtkTreeView *tree_view, +void gtk_tree_view_get_cell_area (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + GdkRectangle *rect); +void gtk_tree_view_get_background_area (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, GdkRectangle *rect); @@ -190,6 +194,9 @@ void gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view); void gtk_tree_view_set_drag_dest_row (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewDropPosition pos); +void gtk_tree_view_get_drag_dest_row (GtkTreeView *tree_view, + GtkTreePath **path, + GtkTreeViewDropPosition *pos); gboolean gtk_tree_view_get_dest_row_at_pos (GtkTreeView *tree_view, gint drag_x, gint drag_y, @@ -198,16 +205,6 @@ gboolean gtk_tree_view_get_dest_row_at_pos (GtkTreeView *tree_vi GdkPixmap* gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, GtkTreePath *path); -/* The selection data would normally have target type GTK_TREE_VIEW_ROW in this - * case. If the target is wrong these functions return FALSE. - */ -gboolean gtk_selection_data_set_tree_row (GtkSelectionData *selection_data, - GtkTreeView *tree_view, - GtkTreePath *path); -gboolean gtk_selection_data_get_tree_row (GtkSelectionData *selection_data, - GtkTreeView **tree_view, - GtkTreePath **path); - #ifdef __cplusplus diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 140bbb6a7e..1d7dab0eee 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -212,6 +212,10 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) static void gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) { + /* FIXME remove on port to GtkObject */ + gtk_object_ref (GTK_OBJECT (tree_column)); + gtk_object_sink (GTK_OBJECT (tree_column)); + tree_column->button = NULL; tree_column->justification = GTK_JUSTIFY_LEFT; tree_column->width = 1; @@ -919,17 +923,18 @@ update_button_contents (GtkTreeViewColumn *tree_column) { if (tree_column->button) { - GtkWidget *current_child = GTK_BIN (GTK_BIN (tree_column->button)->child)->child; + GtkWidget *alignment = GTK_BIN (tree_column->button)->child; + GtkWidget *current_child = GTK_BIN (alignment)->child; if (tree_column->child) { if (current_child != tree_column->child) { - gtk_container_remove (GTK_CONTAINER (tree_column->button), + gtk_container_remove (GTK_CONTAINER (alignment), current_child); - gtk_container_add (GTK_CONTAINER (tree_column->button), - tree_column->child); + gtk_container_add (GTK_CONTAINER (alignment), + tree_column->child); } } else @@ -940,7 +945,7 @@ update_button_contents (GtkTreeViewColumn *tree_column) gtk_widget_show (current_child); - gtk_container_add (GTK_CONTAINER (tree_column->button), + gtk_container_add (GTK_CONTAINER (alignment), current_child); } diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 534c93736f..acdaa65ed9 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -2002,6 +2002,34 @@ create_get_image (void) /* * Label Demo */ +static void +sensitivity_toggled (GtkWidget *toggle, + GtkWidget *widget) +{ + gtk_widget_set_sensitive (widget, GTK_TOGGLE_BUTTON (toggle)->active); +} + +static GtkWidget* +create_sensitivity_control (GtkWidget *widget) +{ + GtkWidget *button; + GtkWidget *toplevel; + + button = gtk_toggle_button_new_with_label ("Sensitive"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), + GTK_WIDGET_IS_SENSITIVE (widget)); + + gtk_signal_connect (GTK_OBJECT (button), + "toggled", + GTK_SIGNAL_FUNC (sensitivity_toggled), + widget); + + gtk_widget_show_all (button); + + return button; +} + void create_labels (void) { static GtkWidget *window = NULL; @@ -2009,7 +2037,8 @@ void create_labels (void) GtkWidget *vbox; GtkWidget *frame; GtkWidget *label; - + GtkWidget *button; + if (!window) { guint keyval; @@ -2020,9 +2049,20 @@ void create_labels (void) &window); gtk_window_set_title (GTK_WINDOW (window), "Label"); + vbox = gtk_vbox_new (FALSE, 5); + hbox = gtk_hbox_new (FALSE, 5); - gtk_container_add (GTK_CONTAINER (window), hbox); + gtk_container_add (GTK_CONTAINER (window), vbox); + + gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + button = create_sensitivity_control (hbox); + + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (window), 5); @@ -2127,8 +2167,8 @@ void create_labels (void) gtk_container_add (GTK_CONTAINER (frame), label); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - } + if (!GTK_WIDGET_VISIBLE (window)) gtk_widget_show_all (window); else @@ -3275,6 +3315,14 @@ create_scrolled_windows (void) */ static void +entry_toggle_frame (GtkWidget *checkbutton, + GtkWidget *entry) +{ + gtk_entry_set_has_frame (GTK_ENTRY(entry), + GTK_TOGGLE_BUTTON(checkbutton)->active); +} + +static void entry_toggle_editable (GtkWidget *checkbutton, GtkWidget *entry) { @@ -3394,6 +3442,13 @@ create_entry (void) gtk_signal_connect (GTK_OBJECT(invisible_char_check), "toggled", GTK_SIGNAL_FUNC(entry_toggle_invisible_char), entry); gtk_widget_show (invisible_char_check); + + editable_check = gtk_check_button_new_with_label("Has Frame"); + gtk_box_pack_start (GTK_BOX (box2), editable_check, FALSE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT(editable_check), "toggled", + GTK_SIGNAL_FUNC(entry_toggle_frame), entry); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(editable_check), TRUE); + gtk_widget_show (editable_check); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); diff --git a/tests/testgtk.c b/tests/testgtk.c index 534c93736f..acdaa65ed9 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -2002,6 +2002,34 @@ create_get_image (void) /* * Label Demo */ +static void +sensitivity_toggled (GtkWidget *toggle, + GtkWidget *widget) +{ + gtk_widget_set_sensitive (widget, GTK_TOGGLE_BUTTON (toggle)->active); +} + +static GtkWidget* +create_sensitivity_control (GtkWidget *widget) +{ + GtkWidget *button; + GtkWidget *toplevel; + + button = gtk_toggle_button_new_with_label ("Sensitive"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), + GTK_WIDGET_IS_SENSITIVE (widget)); + + gtk_signal_connect (GTK_OBJECT (button), + "toggled", + GTK_SIGNAL_FUNC (sensitivity_toggled), + widget); + + gtk_widget_show_all (button); + + return button; +} + void create_labels (void) { static GtkWidget *window = NULL; @@ -2009,7 +2037,8 @@ void create_labels (void) GtkWidget *vbox; GtkWidget *frame; GtkWidget *label; - + GtkWidget *button; + if (!window) { guint keyval; @@ -2020,9 +2049,20 @@ void create_labels (void) &window); gtk_window_set_title (GTK_WINDOW (window), "Label"); + vbox = gtk_vbox_new (FALSE, 5); + hbox = gtk_hbox_new (FALSE, 5); - gtk_container_add (GTK_CONTAINER (window), hbox); + gtk_container_add (GTK_CONTAINER (window), vbox); + + gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + button = create_sensitivity_control (hbox); + + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (window), 5); @@ -2127,8 +2167,8 @@ void create_labels (void) gtk_container_add (GTK_CONTAINER (frame), label); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - } + if (!GTK_WIDGET_VISIBLE (window)) gtk_widget_show_all (window); else @@ -3275,6 +3315,14 @@ create_scrolled_windows (void) */ static void +entry_toggle_frame (GtkWidget *checkbutton, + GtkWidget *entry) +{ + gtk_entry_set_has_frame (GTK_ENTRY(entry), + GTK_TOGGLE_BUTTON(checkbutton)->active); +} + +static void entry_toggle_editable (GtkWidget *checkbutton, GtkWidget *entry) { @@ -3394,6 +3442,13 @@ create_entry (void) gtk_signal_connect (GTK_OBJECT(invisible_char_check), "toggled", GTK_SIGNAL_FUNC(entry_toggle_invisible_char), entry); gtk_widget_show (invisible_char_check); + + editable_check = gtk_check_button_new_with_label("Has Frame"); + gtk_box_pack_start (GTK_BOX (box2), editable_check, FALSE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT(editable_check), "toggled", + GTK_SIGNAL_FUNC(entry_toggle_frame), entry); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(editable_check), TRUE); + gtk_widget_show (editable_check); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); diff --git a/tests/testtreeview.c b/tests/testtreeview.c index 6181114d04..5ffcecb255 100644 --- a/tests/testtreeview.c +++ b/tests/testtreeview.c @@ -314,11 +314,11 @@ set_columns_type (GtkTreeView *tree_view, ColumnsType type) image = gtk_image_new_from_pixbuf (pixbuf); + g_object_unref (G_OBJECT (pixbuf)); + gtk_widget_show (image); gtk_tree_view_column_set_widget (col, image); - - g_object_unref (G_OBJECT (pixbuf)); g_object_unref (G_OBJECT (rend)); g_object_unref (G_OBJECT (col)); @@ -346,6 +346,98 @@ set_columns_type (GtkTreeView *tree_view, ColumnsType type) g_object_unref (G_OBJECT (rend)); g_object_unref (G_OBJECT (col)); +#if 0 + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Column 5", + rend, + "text", 3, + NULL); + + setup_column (col); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Column 6", + rend, + "text", 4, + NULL); + + setup_column (col); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Column 7", + rend, + "text", 5, + NULL); + + setup_column (col); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Column 8", + rend, + "text", 6, + NULL); + + setup_column (col); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Column 9", + rend, + "text", 7, + NULL); + + setup_column (col); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + + + rend = gtk_cell_renderer_text_new (); + + col = gtk_tree_view_column_new_with_attributes ("Column 10", + rend, + "text", 8, + NULL); + + setup_column (col); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); + + g_object_unref (G_OBJECT (rend)); + g_object_unref (G_OBJECT (col)); + +#endif + gtk_tree_view_set_expander_column (tree_view, 1); /* FALL THRU */ @@ -544,12 +636,12 @@ columns_selected (GtkOptionMenu *om, gpointer data) enum { - TARGET_GTK_TREE_VIEW_ROW + TARGET_GTK_TREE_MODEL_ROW }; static GtkTargetEntry row_targets[] = { - { "GTK_TREE_VIEW_ROW", GTK_TARGET_SAME_APP, - TARGET_GTK_TREE_VIEW_ROW } + { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_APP, + TARGET_GTK_TREE_MODEL_ROW } }; int |