summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog76
-rw-r--r--ChangeLog.pre-2-076
-rw-r--r--ChangeLog.pre-2-1076
-rw-r--r--ChangeLog.pre-2-276
-rw-r--r--ChangeLog.pre-2-476
-rw-r--r--ChangeLog.pre-2-676
-rw-r--r--ChangeLog.pre-2-876
-rw-r--r--configure.in2
-rw-r--r--gdk/gdkpango.c246
-rw-r--r--gdk/gdkpango.h20
-rw-r--r--gdk/gdkwindow.c39
-rw-r--r--gdk/gdkwindow.h3
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkcellrenderer.c25
-rw-r--r--gtk/gtkcellrenderertoggle.c70
-rw-r--r--gtk/gtkdebug.h3
-rw-r--r--gtk/gtkentry.c149
-rw-r--r--gtk/gtkentry.h5
-rw-r--r--gtk/gtkliststore.c245
-rw-r--r--gtk/gtkmain.c6
-rw-r--r--gtk/gtkrbtree.c23
-rw-r--r--gtk/gtkrbtree.h1
-rw-r--r--gtk/gtkstyle.c233
-rw-r--r--gtk/gtktextlayout.c6
-rw-r--r--gtk/gtktextview.c2
-rw-r--r--gtk/gtktreedatalist.c44
-rw-r--r--gtk/gtktreedatalist.h2
-rw-r--r--gtk/gtktreednd.c265
-rw-r--r--gtk/gtktreednd.h109
-rw-r--r--gtk/gtktreemodel.h2
-rw-r--r--gtk/gtktreeview.c919
-rw-r--r--gtk/gtktreeview.h19
-rw-r--r--gtk/gtktreeviewcolumn.c15
-rw-r--r--gtk/testgtk.c61
-rw-r--r--tests/testgtk.c61
-rw-r--r--tests/testtreeview.c102
37 files changed, 2781 insertions, 431 deletions
diff --git a/ChangeLog b/ChangeLog
index 79db30750d..d0e5037365 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index f07d5ab9bf..a84b83e2db 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -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