diff options
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | gtk/gtk.symbols | 3 | ||||
-rw-r--r-- | gtk/gtktooltip.c | 188 | ||||
-rw-r--r-- | gtk/gtktooltip.h | 3 | ||||
-rw-r--r-- | gtk/gtktreeview.c | 108 | ||||
-rw-r--r-- | gtk/gtktreeview.h | 10 | ||||
-rw-r--r-- | tests/testtooltips.c | 2 |
7 files changed, 275 insertions, 59 deletions
@@ -1,3 +1,23 @@ +2007-07-13 Kristian Rietveld <kris@imendio.com> + + #408327, improve tooltip positioning. + + * gtk/gtk.symbols: updated. + + * gtk/gtktooltip.[ch] (gtk_tooltip_position): factor out + positioning code in here, + (gtk_tooltip_set_tip_area): new function to set the tooltip + area, + (gtk_tooltip_reset), (_gtk_tooltip_handle_event): hide tooltip + once the pointer leaves the tip area. + + * gtk/gtktreeview.[ch] (gtk_tree_view_set_tooltip_row), + (gtk_tree_view_set_tooltip_cell): convenience functions to set + tip area for row/column/cell. + + * tests/testtooltips.c (query_tooltip_tree_view_cb): use + gtk_tree_view_set_tooltip_row. + 2007-07-12 Cody Russell <bratsche@gnome.org> * gdk/win32/gdkevents-win32.c diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index b99de6773f..0d305ee691 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -4079,6 +4079,7 @@ gtk_tooltip_set_icon gtk_tooltip_set_icon_from_stock gtk_tooltip_set_markup gtk_tooltip_set_text +gtk_tooltip_set_tip_area gtk_tooltip_trigger_tooltip_query #endif #endif @@ -4466,6 +4467,8 @@ gtk_tree_view_set_search_entry gtk_tree_view_set_search_equal_func gtk_tree_view_set_search_position_func gtk_tree_view_set_show_expanders +gtk_tree_view_set_tooltip_row +gtk_tree_view_set_tooltip_cell gtk_tree_view_set_vadjustment #ifndef GTK_DISABLE_DEPRECATED gtk_tree_view_tree_to_widget_coords diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c index 5b137de794..f7fe733bf3 100644 --- a/gtk/gtktooltip.c +++ b/gtk/gtktooltip.c @@ -64,8 +64,11 @@ struct _GtkTooltip guint timeout_id; guint browse_mode_timeout_id; + GdkRectangle tip_area; + guint browse_mode_enabled : 1; guint keyboard_mode_enabled : 1; + guint tip_area_set : 1; }; struct _GtkTooltipClass @@ -328,6 +331,37 @@ gtk_tooltip_set_custom (GtkTooltip *tooltip, } /** + * gtk_tooltip_set_tip_area: + * @tooltip: a #GtkTooltip + * @rect: a #GdkRectangle + * + * Sets the area of the widget, where the contents of this tooltip apply, + * to be @rect (in widget coordinates). This is especially useful for + * properly setting tooltips on #GtkTreeView rows and cells, #GtkIconViews, + * etc. + * + * For setting tooltips on #GtkTreeView, please refer to the convenience + * functions for this: gtk_tree_view_set_tooltip_row() and + * gtk_tree_view_set_tooltip_cell(). + * + * Since: 2.12 + */ +void +gtk_tooltip_set_tip_area (GtkTooltip *tooltip, + GdkRectangle *rect) +{ + g_return_if_fail (GTK_IS_TOOLTIP (tooltip)); + + if (!rect) + tooltip->tip_area_set = FALSE; + else + { + tooltip->tip_area_set = TRUE; + tooltip->tip_area = *rect; + } +} + +/** * gtk_tooltip_trigger_tooltip_query: * @display: a #GdkDisplay * @@ -367,6 +401,7 @@ gtk_tooltip_reset (GtkTooltip *tooltip) gtk_tooltip_set_markup (tooltip, NULL); gtk_tooltip_set_icon (tooltip, NULL); gtk_tooltip_set_custom (tooltip, NULL); + gtk_tooltip_set_tip_area (tooltip, NULL); } static gboolean @@ -634,6 +669,76 @@ gtk_tooltip_run_requery (GtkWidget **widget, } static void +gtk_tooltip_position (GtkTooltip *tooltip, + GdkDisplay *display, + GtkWidget *new_tooltip_widget) +{ + gint x, y; + GdkScreen *screen; + + tooltip->tooltip_widget = new_tooltip_widget; + + /* Position the tooltip */ + /* FIXME: should we swap this when RTL is enabled? */ + if (tooltip->keyboard_mode_enabled) + { + gdk_window_get_origin (new_tooltip_widget->window, &x, &y); + if (GTK_WIDGET_NO_WINDOW (new_tooltip_widget)) + { + x += new_tooltip_widget->allocation.x; + y += new_tooltip_widget->allocation.y; + } + + /* For keyboard mode we position the tooltip below the widget, + * right of the center of the widget. + */ + x += new_tooltip_widget->allocation.width / 2; + y += new_tooltip_widget->allocation.height + 4; + } + else + { + guint cursor_size; + + x = tooltip->last_x; + y = tooltip->last_y; + + /* For mouse mode, we position the tooltip right of the cursor, + * a little below the cursor's center. + */ + cursor_size = gdk_display_get_default_cursor_size (display); + x += cursor_size / 2; + y += cursor_size / 2; + } + + screen = gtk_widget_get_screen (new_tooltip_widget); + + /* Show it */ + if (tooltip->current_window) + { + gint monitor_num; + GdkRectangle monitor; + GtkRequisition requisition; + + gtk_widget_size_request (GTK_WIDGET (tooltip->current_window), + &requisition); + + monitor_num = gdk_screen_get_monitor_at_point (screen, x, y); + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + + if (x + requisition.width > monitor.x + monitor.width) + x -= x - (monitor.x + monitor.width) + requisition.width; + else if (x < monitor.x) + x = monitor.x; + + if (y + requisition.height > monitor.y + monitor.height) + y -= y - (monitor.y + monitor.height) + requisition.height; + + gtk_window_move (GTK_WINDOW (tooltip->current_window), x, y); + gtk_widget_show (GTK_WIDGET (tooltip->current_window)); + } +} + +static void gtk_tooltip_show_tooltip (GdkDisplay *display) { gint x, y; @@ -687,40 +792,9 @@ gtk_tooltip_show_tooltip (GdkDisplay *display) tooltip->current_window = GTK_WINDOW (GTK_TOOLTIP (tooltip)->window); } - /* Position the tooltip */ - /* FIXME: should we swap this when RTL is enabled? */ - if (tooltip->keyboard_mode_enabled) - { - gdk_window_get_origin (tooltip_widget->window, &x, &y); - if (GTK_WIDGET_NO_WINDOW (tooltip_widget)) - { - x += tooltip_widget->allocation.x; - y += tooltip_widget->allocation.y; - } - - /* For keyboard mode we position the tooltip below the widget, - * right of the center of the widget. - */ - x += tooltip_widget->allocation.width / 2; - y += tooltip_widget->allocation.height + 4; - } - else - { - guint cursor_size; - - x = tooltip->last_x; - y = tooltip->last_y; - - /* For mouse mode, we position the tooltip right of the cursor, - * a little below the cursor's center. - */ - cursor_size = gdk_display_get_default_cursor_size (display); - x += cursor_size / 2; - y += cursor_size / 2; - } - screen = gtk_widget_get_screen (tooltip_widget); + /* FIXME: should use tooltip->current_window iso tooltip->window */ if (screen != gtk_widget_get_screen (tooltip->window)) { g_signal_handlers_disconnect_by_func (display, @@ -733,32 +807,7 @@ gtk_tooltip_show_tooltip (GdkDisplay *display) G_CALLBACK (gtk_tooltip_display_closed), tooltip); } - tooltip->tooltip_widget = tooltip_widget; - - /* Show it */ - if (tooltip->current_window) - { - gint monitor_num; - GdkRectangle monitor; - GtkRequisition requisition; - - gtk_widget_size_request (GTK_WIDGET (tooltip->current_window), - &requisition); - - monitor_num = gdk_screen_get_monitor_at_point (screen, x, y); - gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); - - if (x + requisition.width > monitor.x + monitor.width) - x -= x - (monitor.x + monitor.width) + requisition.width; - else if (x < monitor.x) - x = monitor.x; - - if (y + requisition.height > monitor.y + monitor.height) - y -= y - (monitor.y + monitor.height) + requisition.height; - - gtk_window_move (GTK_WINDOW (tooltip->current_window), x, y); - gtk_widget_show (GTK_WIDGET (tooltip->current_window)); - } + gtk_tooltip_position (tooltip, display, tooltip_widget); /* Now a tooltip is visible again on the display, make sure browse * mode is enabled. @@ -1063,11 +1112,32 @@ _gtk_tooltip_handle_event (GdkEvent *event) case GDK_SCROLL: if (current_tooltip) { + gboolean tip_area_set; + GdkRectangle tip_area; + gboolean hide_tooltip; + + tip_area_set = current_tooltip->tip_area_set; + tip_area = current_tooltip->tip_area; + return_value = gtk_tooltip_run_requery (&has_tooltip_widget, current_tooltip, &x, &y); - if (!return_value) + /* Requested to be hidden? */ + hide_tooltip = !return_value; + + /* Is the pointer above another widget now? */ + if (GTK_TOOLTIP_VISIBLE (current_tooltip)) + hide_tooltip |= has_tooltip_widget != current_tooltip->tooltip_widget; + + /* Did the pointer move out of the previous "context area"? */ + if (tip_area_set) + hide_tooltip |= (x <= tip_area.x + || x >= tip_area.x + tip_area.width + || y <= tip_area.y + || y >= tip_area.y + tip_area.height); + + if (hide_tooltip) gtk_tooltip_hide_tooltip (current_tooltip); else gtk_tooltip_start_delay (display); diff --git a/gtk/gtktooltip.h b/gtk/gtktooltip.h index eb9ff41f56..bc498af478 100644 --- a/gtk/gtktooltip.h +++ b/gtk/gtktooltip.h @@ -45,6 +45,9 @@ void gtk_tooltip_set_icon_from_stock (GtkTooltip *tooltip, void gtk_tooltip_set_custom (GtkTooltip *tooltip, GtkWidget *custom_widget); +void gtk_tooltip_set_tip_area (GtkTooltip *tooltip, + GdkRectangle *rect); + void gtk_tooltip_trigger_tooltip_query (GdkDisplay *display); diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 74f4b02757..b351e4a220 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -42,6 +42,7 @@ #include "gtkentry.h" #include "gtkframe.h" #include "gtktreemodelsort.h" +#include "gtktooltip.h" #include "gtkprivate.h" #include "gtkalias.h" @@ -15171,5 +15172,112 @@ gtk_tree_view_get_level_indentation (GtkTreeView *tree_view) return tree_view->priv->level_indentation; } +/** + * gtk_tree_view_set_tooltip_row: + * @tree_view: a #GtkTreeView + * @tooltip: a #GtkTooltip + * @path: a #GtkTreePath + * + * Sets the tip area of @tooltip to be the area covered by the row at @path. + * See also gtk_tooltip_set_tip_area(). + * + * Since: 2.12 + */ +void +gtk_tree_view_set_tooltip_row (GtkTreeView *tree_view, + GtkTooltip *tooltip, + GtkTreePath *path) +{ + g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + g_return_if_fail (GTK_IS_TOOLTIP (tooltip)); + + gtk_tree_view_set_tooltip_cell (tree_view, tooltip, path, NULL, NULL); +} + +/** + * gtk_tree_view_set_tooltip_cell: + * @tree_view: a #GtkTreeView + * @tooltip: a #GtkTooltip + * @path: a #GtkTreePath or %NULL + * @column: a #GtkTreeViewColumn or %NULL + * @cell: a #GtkCellRendererText or %NULL + * + * Sets the tip area of @tooltip to the area @path, @column and @cell have + * in common. For example if @path is %NULL and @column is set, the tip + * area will be set to the full area covered by @column. See also + * gtk_tooltip_set_tip_area(). + * + * Since: 2.12 + */ +void +gtk_tree_view_set_tooltip_cell (GtkTreeView *tree_view, + GtkTooltip *tooltip, + GtkTreePath *path, + GtkTreeViewColumn *column, + GtkCellRenderer *cell) +{ + GdkRectangle rect; + + g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + g_return_if_fail (GTK_IS_TOOLTIP (tooltip)); + + if (column) + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column)); + + if (cell) + g_return_if_fail (GTK_IS_CELL_RENDERER (cell)); + + /* Determine x values. */ + if (column && cell) + { + GdkRectangle tmp; + gint start, width; + + gtk_tree_view_get_cell_area (tree_view, NULL, column, &tmp); + gtk_tree_view_column_cell_get_position (column, cell, &start, &width); + + /* FIXME: a need a path here to correctly correct for indent */ + + gtk_tree_view_convert_bin_window_to_widget_coords (tree_view, + tmp.x + start, 0, + &rect.x, NULL); + rect.width = width; + } + else if (column) + { + GdkRectangle tmp; + + gtk_tree_view_get_background_area (tree_view, NULL, column, &tmp); + gtk_tree_view_convert_bin_window_to_widget_coords (tree_view, + tmp.x, 0, + &rect.x, NULL); + rect.width = tmp.width; + } + else + { + rect.x = GTK_WIDGET (tree_view)->allocation.x; + rect.width = GTK_WIDGET (tree_view)->allocation.width; + } + + /* Determine y values. */ + if (path) + { + GdkRectangle tmp; + + gtk_tree_view_get_background_area (tree_view, path, NULL, &tmp); + gtk_tree_view_convert_bin_window_to_widget_coords (tree_view, + 0, tmp.y, + NULL, &rect.y); + rect.height = tmp.height; + } + else + { + rect.y = 0; + rect.height = tree_view->priv->vadjustment->page_size; + } + + gtk_tooltip_set_tip_area (tooltip, &rect); +} + #define __GTK_TREE_VIEW_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtktreeview.h b/gtk/gtktreeview.h index cd5fc487a4..0818081367 100644 --- a/gtk/gtktreeview.h +++ b/gtk/gtktreeview.h @@ -402,6 +402,16 @@ void gtk_tree_view_set_level_indentation (GtkTreeView gint indentation); gint gtk_tree_view_get_level_indentation (GtkTreeView *tree_view); +/* Convenience functions for setting tooltips */ +void gtk_tree_view_set_tooltip_row (GtkTreeView *tree_view, + GtkTooltip *tooltip, + GtkTreePath *path); +void gtk_tree_view_set_tooltip_cell (GtkTreeView *tree_view, + GtkTooltip *tooltip, + GtkTreePath *path, + GtkTreeViewColumn *column, + GtkCellRenderer *cell); + G_END_DECLS diff --git a/tests/testtooltips.c b/tests/testtooltips.c index 358cb90654..22f54da6c9 100644 --- a/tests/testtooltips.c +++ b/tests/testtooltips.c @@ -135,6 +135,8 @@ query_tooltip_tree_view_cb (GtkWidget *widget, g_snprintf (buffer, 511, "<b>Path %s:</b> %s", pathstring, tmp); gtk_tooltip_set_markup (tooltip, buffer); + gtk_tree_view_set_tooltip_row (tree_view, tooltip, path); + gtk_tree_path_free (path); g_free (pathstring); g_free (tmp); |