Re: RFC: Tooltips redesign (needed e.g. for row dependent tips in treeview)



On Fri, 2004-10-22 at 18:47 +0200, Christof Petig wrote:
> Hi,
> 
> After having commented on bug #80980 and #50619 without an answer in a 
> week I'm asking here for further comments.
> 
> Up to now the tooltip design is based on a static tip per widget. To 
> support per row (or column or cell) tooltips in treeview the tooltip API 
> has to get redesigned.
> 
> Two possible implementations come to my mind:
> 
> 1) Adding the option of using a function pointer as an argument to 
> gtk_tooltips_set_tip. Storing that in GtkTooltipsData and using it (if 
> !=NULL) to query the tip according to the relative mouse position. 
> [perhaps using a boolean argument to distinguish between normal and 
> private tip].
> 
> E.g. void gtk_tooltips_set_tip_function(GtkTooltips   *tooltips, 
> GtkWidget *widget, const gchar *(fun)(GtkWidget*,gint x,gint y,gboolean 
> private_tip));
> 
> This option keeps the current logic of an (widget-)external tip object.
> 
> 2) Adding a signal to each widget to query for the matching tip. (three 
> arguments: x,y,private) call this signal if there is no tip registered 
> for this widget. This could gradually eliminate the need to store the 
> tips outside of the widget structure.
> 
> This option delegates figuring out the tip text back to the widget.
> 
> Which way to go? (I'd prefer 2 since I do not know the reason for 
> starting with 1 in the past).

I'm not really enthused about a callback-based approach here. It 
seems simple at first glance, but I think it would get pretty complex
for the case where tooltip texts or tooltip areas change dynamically.
(For tooltip areas, think scrolling in a GtkTreeView.)

It also doesn't handle the case of "keyboard_mode" for tooltips - 
try Control-F1 in a dialog with tooltips - the tooltip for the
currently selected widget is displayed and you can browse
tooltips by tabbing between widgets.

And it isn't very extensible - think about setting markup for a
tooltip, or as suggested recently putting a widget in a tooltip
(not sure that is a good idea, but it's at least a conceivable
approach)

Are these problems addressable within the callback model? Yes,
I think so. But I think you'd lose the essential simplicity of it. 
You'd have to introduce some objects and/or interfaces that 
are passed around, multiple callbacks, etc. (Feel free to prove
me wrong and come up with a detailed proposal.)

Here's an alternate approach I came up with talking to Jonathan (he's
promised a more detailed writeup of GtkTreeView requirements) is a
little more of a radical change.

 * We ditch (deprecate) GtkTooltips; GtkTooltips objects are 90% just
   annoying to create and memory manage.

 * The one case where the tooltips object isn't just annoying is
   the sticky delay behavior where mousing between tooltips in 
   a single group doesn't involve a full delay for it to pop up.
   For this functionality, we add GtkTooltipsGroup, along the
   lines of GtkSizeGroup.

 * For simple cases, we add "tooltip" and "tooltip-uses-markup" 
   properties to GtkWidget.

 * We can reimplement GtkTooltips using GtkTooltipsGroup and
   gtk_widget_set_tooltip().

 * For custom tooltips, we introduce the GtkTooltipsWindow widget,
   There is a singleton GtkTooltipsWindow object per toplevel,
   which can be retrieved with:

    gtk_widget_get_tooltips_window()

   This both handles the display of the yellow rectangle, and the 
   logic for showing/hiding the tooltip based on keyboard and 
   mouse actions.

    typedef enum { GTK_TOOLTIPS_MOUSE, GTK_TOOLTIPS_KEYBOARD } GtkTooltipsContext;

    void gtk_tooltips_window_begin (GtkTooltipsWindow *window,
                                    GtkTooltipsContext context,
                                    GObject           *owner);
    void gtk_tooltips_window_end   (GtkTooltipsWindow *window,
                                    GtkTooltipsContext context,
                                    GObject           *owner);
    void gtk_tooltips_window_set_text (GtkTooltipsWindow  *window,
                                       GtkTooltipsContext  context,
                                       GObject            *owner,
                                       const char         *text);
    void gtk_tooltips_window_set_markup (GtkTooltipsWindow  *window,
                                         GtkTooltipsContext  context,
                                         GObject            *owner,
                                         const char         *markup);
    void gtk_tooltips_window_set_area   (GtkTooltipsWindow  *window,
                                         GtkTooltipsContext  context,
                                         GdkWindow          *relative_to,
                                         int x, int y, int width, int height);
    void gtk_tooltips_window_set_group  (GtkTooltipsWindow  *window,
                                         GtkTooltipsContext  context,
                                         GObject            *owner,
                                         GtkTooltipsGroup    group);

The concepts of the above are:

 - The GtkTooltipsWindow keeps two stacks of "active objects" for
   keyboard and mouse focus. With each object in the stack, we
   store text/markup rectangle, and possible GtkTooltipsGroup.

 - You call  tw.begin (MOUSE) on when the mouse enters a tooltips
   area, tw.begin (KEYBOARD) on a tooltips object getting 
   keyboard focus and tw.end (MOUSE/KEYBOARD) on 
   mouse leave / focus out.

 - The 'GObject *owner*' arguments allow proper handling of nested
   tooltips areas. (think a treeview with tooltips with tooltips
   on individual rows.) It can be any GObject - the widget itself,
   a GdkWindow, whatever.

A lot of the details of the above maybe should be a little different
than I've sketched out, but I think it is a whole lot simpler than
any callback-based mechanism with the same set of functionality.

Regards,
						Owen

Attachment: signature.asc
Description: This is a digitally signed message part



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]