Adds a new event FL_TOOLTIP_EVENT...
... and Fl_Tootip::override_text() to allow users to dynamically generate tooltips.
This commit is contained in:
parent
cb86a37676
commit
b7189192e2
@ -414,7 +414,11 @@ enum Fl_Event { // events
|
|||||||
/** A zoom event (ctrl/+/-/0/ or cmd/+/-/0/) was processed.
|
/** A zoom event (ctrl/+/-/0/ or cmd/+/-/0/) was processed.
|
||||||
Use Fl::add_handler() to be notified of this event.
|
Use Fl::add_handler() to be notified of this event.
|
||||||
*/
|
*/
|
||||||
FL_ZOOM_EVENT = 27
|
FL_ZOOM_EVENT = 27,
|
||||||
|
/** A tooltip is about to pop up for this widget. The mouse coordinates are
|
||||||
|
available in Fl::event_x() and Fl::event_y(). Change the widget tooltip
|
||||||
|
as needed. */
|
||||||
|
FL_TOOLTIP_EVENT = 28
|
||||||
// DEV NOTE: Keep this list in sync with FL/names.h
|
// DEV NOTE: Keep this list in sync with FL/names.h
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -95,6 +95,8 @@ public:
|
|||||||
static void wrap_width(int v) { wrap_width_ = v; }
|
static void wrap_width(int v) { wrap_width_ = v; }
|
||||||
/** Returns the window that is used for tooltips */
|
/** Returns the window that is used for tooltips */
|
||||||
static Fl_Window* current_window(void);
|
static Fl_Window* current_window(void);
|
||||||
|
/** \brief Temporarily Override Tooltip Text during an FL_TOOLTIP_EVENT. */
|
||||||
|
static int override_text(const char *new_text);
|
||||||
|
|
||||||
// These should not be public, but Fl_Widget::tooltip() needs them...
|
// These should not be public, but Fl_Widget::tooltip() needs them...
|
||||||
// fabien: made it private with only a friend function access
|
// fabien: made it private with only a friend function access
|
||||||
@ -104,20 +106,22 @@ private:
|
|||||||
static void enter_(Fl_Widget* w);
|
static void enter_(Fl_Widget* w);
|
||||||
static void exit_(Fl_Widget *w);
|
static void exit_(Fl_Widget *w);
|
||||||
static void set_enter_exit_once_();
|
static void set_enter_exit_once_();
|
||||||
|
static void tooltip_timeout_(void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static float delay_; //!< delay before a tooltip is shown
|
static float delay_; //!< delay before a tooltip is shown
|
||||||
static float hidedelay_; //!< delay until tooltip is closed again
|
static float hidedelay_; //!< delay until tooltip is closed again
|
||||||
static float hoverdelay_; //!< delay between tooltips
|
static float hoverdelay_; //!< delay between tooltips
|
||||||
static Fl_Color color_;
|
static Fl_Color color_;
|
||||||
static Fl_Color textcolor_;
|
static Fl_Color textcolor_;
|
||||||
static Fl_Font font_;
|
static Fl_Font font_;
|
||||||
static Fl_Fontsize size_;
|
static Fl_Fontsize size_;
|
||||||
static Fl_Widget* widget_; //!< Keeps track of the current target widget
|
static Fl_Widget* widget_; //!< Keeps track of the current target widget
|
||||||
static int margin_width_; //!< distance around tooltip text left+right
|
static int margin_width_; //!< distance around tooltip text left+right
|
||||||
static int margin_height_; //!< distance around tooltip text top+bottom
|
static int margin_height_; //!< distance around tooltip text top+bottom
|
||||||
static int wrap_width_; //!< maximum width of tooltip text before it word wraps
|
static int wrap_width_; //!< maximum width of tooltip text before it word wraps
|
||||||
static const int draw_symbols_; // 1 = draw @-symbols in tooltips, 0 = no
|
static const int draw_symbols_; // 1 = draw @-symbols in tooltips, 0 = no
|
||||||
|
static char *override_text_; //!< a copy of the last text for an overridden tooltip
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -73,9 +73,10 @@ const char * const fl_eventnames[] =
|
|||||||
"FL_FULLSCREEN",
|
"FL_FULLSCREEN",
|
||||||
"FL_ZOOM_GESTURE",
|
"FL_ZOOM_GESTURE",
|
||||||
"FL_ZOOM_EVENT",
|
"FL_ZOOM_EVENT",
|
||||||
"FL_EVENT_28", // not yet defined, just in case it /will/ be defined ...
|
"FL_TOOLTIP_EVENT",
|
||||||
"FL_EVENT_29", // not yet defined, just in case it /will/ be defined ...
|
"FL_EVENT_29", // not yet defined, just in case it /will/ be defined ...
|
||||||
"FL_EVENT_30" // not yet defined, just in case it /will/ be defined ...
|
"FL_EVENT_30", // not yet defined, just in case it /will/ be defined ...
|
||||||
|
"FL_EVENT_31" // not yet defined, just in case it /will/ be defined ...
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -25,6 +25,9 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
float Fl_Tooltip::delay_ = 1.0f;
|
float Fl_Tooltip::delay_ = 1.0f;
|
||||||
float Fl_Tooltip::hidedelay_ = 12.0f;
|
float Fl_Tooltip::hidedelay_ = 12.0f;
|
||||||
float Fl_Tooltip::hoverdelay_ = 0.2f;
|
float Fl_Tooltip::hoverdelay_ = 0.2f;
|
||||||
@ -38,6 +41,7 @@ int Fl_Tooltip::margin_width_ = 3;
|
|||||||
int Fl_Tooltip::margin_height_ = 3;
|
int Fl_Tooltip::margin_height_ = 3;
|
||||||
int Fl_Tooltip::wrap_width_ = 400;
|
int Fl_Tooltip::wrap_width_ = 400;
|
||||||
const int Fl_Tooltip::draw_symbols_ = 1;
|
const int Fl_Tooltip::draw_symbols_ = 1;
|
||||||
|
char *Fl_Tooltip::override_text_ = nullptr;
|
||||||
|
|
||||||
static const char* tip;
|
static const char* tip;
|
||||||
|
|
||||||
@ -154,14 +158,49 @@ static void tooltip_hide_timeout(void*) {
|
|||||||
recent_tooltip = 0;
|
recent_tooltip = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tooltip_timeout(void*) {
|
/**
|
||||||
|
Use this method to temporarily change the tooltip text before it is displayed.
|
||||||
|
|
||||||
|
When FLTK sends an FL_TOOLTIP_EVENT to the widget under the mouse pointer,
|
||||||
|
you can handle this event to modify the tooltip text dynamically. The
|
||||||
|
provided text will be copied into a local buffer. To apply the override,
|
||||||
|
the event handler must return 1.
|
||||||
|
|
||||||
|
To disable the tooltip for the current event, set the override text to nullptr
|
||||||
|
or an empty string ("") and return 1.
|
||||||
|
|
||||||
|
\param[in] new_text a C string that will be copied into a buffer
|
||||||
|
\return always 1, so this call can finish the FL_TOOLTIP_EVENT handling.
|
||||||
|
|
||||||
|
\see void Fl_Widget::tooltip(const char *text).
|
||||||
|
|
||||||
|
\see `test/color_chooser.cxx` for a usage example.
|
||||||
|
*/
|
||||||
|
int Fl_Tooltip::override_text(const char *new_text) {
|
||||||
|
if (new_text != override_text_) {
|
||||||
|
if (window && window->label()==override_text_)
|
||||||
|
((Fl_Widget *) window)->label(nullptr);
|
||||||
|
if (override_text_)
|
||||||
|
::free(override_text_);
|
||||||
|
override_text_ = nullptr;
|
||||||
|
if (new_text)
|
||||||
|
override_text_ = ::strdup(new_text);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl_Tooltip::tooltip_timeout_(void*) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
puts("tooltip_timeout();");
|
puts("tooltip_timeout_();");
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
if (recursion) return;
|
if (recursion) return;
|
||||||
recursion = 1;
|
recursion = 1;
|
||||||
if (!top_win_iconified_()) { // no tooltip if top win iconified (STR #3157)
|
if (!top_win_iconified_()) { // no tooltip if top win iconified (STR #3157)
|
||||||
|
if (Fl_Tooltip::current()) {
|
||||||
|
if (Fl_Tooltip::current()->handle(FL_TOOLTIP_EVENT))
|
||||||
|
tip = Fl_Tooltip::override_text_;
|
||||||
|
}
|
||||||
if (!tip || !*tip) {
|
if (!tip || !*tip) {
|
||||||
if (window) window->hide();
|
if (window) window->hide();
|
||||||
Fl::remove_timeout(tooltip_hide_timeout);
|
Fl::remove_timeout(tooltip_hide_timeout);
|
||||||
@ -253,7 +292,7 @@ void Fl_Tooltip::exit_(Fl_Widget *w) {
|
|||||||
|
|
||||||
if (!widget_ || (w && w == window)) return;
|
if (!widget_ || (w && w == window)) return;
|
||||||
widget_ = 0;
|
widget_ = 0;
|
||||||
Fl::remove_timeout(tooltip_timeout);
|
Fl::remove_timeout(tooltip_timeout_);
|
||||||
Fl::remove_timeout(recent_timeout);
|
Fl::remove_timeout(recent_timeout);
|
||||||
if (window && window->visible()) {
|
if (window && window->visible()) {
|
||||||
window->hide();
|
window->hide();
|
||||||
@ -298,7 +337,7 @@ void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char*
|
|||||||
}
|
}
|
||||||
// do nothing if it is the same:
|
// do nothing if it is the same:
|
||||||
if (wid==widget_ /*&& x==X && y==currentTooltipY && w==W && h==currentTooltipH*/ && t==tip) return;
|
if (wid==widget_ /*&& x==X && y==currentTooltipY && w==W && h==currentTooltipH*/ && t==tip) return;
|
||||||
Fl::remove_timeout(tooltip_timeout);
|
Fl::remove_timeout(tooltip_timeout_);
|
||||||
Fl::remove_timeout(recent_timeout);
|
Fl::remove_timeout(recent_timeout);
|
||||||
// remember it:
|
// remember it:
|
||||||
widget_ = wid; currentTooltipY = y; currentTooltipH = h; tip = t;
|
widget_ = wid; currentTooltipY = y; currentTooltipH = h; tip = t;
|
||||||
@ -308,7 +347,7 @@ void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char*
|
|||||||
window->hide();
|
window->hide();
|
||||||
Fl::remove_timeout(tooltip_hide_timeout);
|
Fl::remove_timeout(tooltip_hide_timeout);
|
||||||
}
|
}
|
||||||
Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout);
|
Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout_);
|
||||||
} else if (Fl_Tooltip::delay() < .1) {
|
} else if (Fl_Tooltip::delay() < .1) {
|
||||||
// possible fix for the Windows titlebar, it seems to want the
|
// possible fix for the Windows titlebar, it seems to want the
|
||||||
// window to be destroyed, moving it messes up the parenting:
|
// window to be destroyed, moving it messes up the parenting:
|
||||||
@ -316,13 +355,13 @@ void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char*
|
|||||||
window->hide();
|
window->hide();
|
||||||
Fl::remove_timeout(tooltip_hide_timeout);
|
Fl::remove_timeout(tooltip_hide_timeout);
|
||||||
}
|
}
|
||||||
tooltip_timeout(0);
|
tooltip_timeout_(nullptr);
|
||||||
} else {
|
} else {
|
||||||
if (window && window->visible()) {
|
if (window && window->visible()) {
|
||||||
window->hide();
|
window->hide();
|
||||||
Fl::remove_timeout(tooltip_hide_timeout);
|
Fl::remove_timeout(tooltip_hide_timeout);
|
||||||
}
|
}
|
||||||
Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout);
|
Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout_);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -341,19 +380,25 @@ void Fl_Tooltip::set_enter_exit_once_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the current tooltip text.
|
Sets the Tooltip Text for a Widget.
|
||||||
|
|
||||||
Sets a string of text to display in a popup tooltip window when the user
|
Assigns a tooltip string that appears in a popup when the user hovers over
|
||||||
hovers the mouse over the widget. The string is <I>not</I> copied, so
|
the widget. The provided string is not copied. The caller must eensure it
|
||||||
make sure any formatted string is stored in a static, global,
|
remains valid by storing it in a static, global, or dynamically allocated
|
||||||
or allocated buffer. If you want a copy made and managed for you,
|
buffer. If you need the tooltip string to be copied and managed automatically,
|
||||||
use the copy_tooltip() method, which will manage the tooltip string
|
use copy_tooltip().
|
||||||
automatically.
|
|
||||||
|
By default, a widget inherits the tooltip of its parent if none is explicitly
|
||||||
|
set. If you assign a tooltip to a group but not to its child widgets, the
|
||||||
|
child widgets will display the group’s tooltip. To prevent inheritance, set
|
||||||
|
the child’s tooltip to an empty string ("").
|
||||||
|
|
||||||
|
Tooltips can be updated dynamically before they are displayed. When a tooltip
|
||||||
|
is about to be shown, FLTK sends an `FL_TOOLTIP_EVENT` to the widget’s
|
||||||
|
`handle()` method. Developers can override the tooltip text temporarily
|
||||||
|
using `Fl_Tooltip::override_text(const char* new_text)` and returning 1 from
|
||||||
|
`handle()` to apply the change.
|
||||||
|
|
||||||
If no tooltip is set, the tooltip of the parent is inherited. Setting a
|
|
||||||
tooltip for a group and setting no tooltip for a child will show the
|
|
||||||
group's tooltip instead. To avoid this behavior, you can set the child's
|
|
||||||
tooltip to an empty string ("").
|
|
||||||
\param[in] text New tooltip text (no copy is made)
|
\param[in] text New tooltip text (no copy is made)
|
||||||
\see copy_tooltip(const char*), tooltip()
|
\see copy_tooltip(const char*), tooltip()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include <FL/fl_show_colormap.H>
|
#include <FL/fl_show_colormap.H>
|
||||||
#include <FL/Fl_Color_Chooser.H>
|
#include <FL/Fl_Color_Chooser.H>
|
||||||
#include <FL/Fl_Image.H>
|
#include <FL/Fl_Image.H>
|
||||||
|
#include <FL/Fl_Tooltip.H>
|
||||||
#include <FL/platform.H>
|
#include <FL/platform.H>
|
||||||
#include <FL/fl_draw.H>
|
#include <FL/fl_draw.H>
|
||||||
|
|
||||||
@ -84,6 +85,22 @@ void cb2(Fl_Widget *, void *v) {
|
|||||||
bx->parent()->redraw();
|
bx->parent()->redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Image_Box: public Fl_Box {
|
||||||
|
public:
|
||||||
|
Image_Box(int x, int y, int w, int h, const char *label = nullptr)
|
||||||
|
: Fl_Box(x, y, w, h, label) { }
|
||||||
|
int handle(int event) {
|
||||||
|
if (event == FL_TOOLTIP_EVENT) {
|
||||||
|
const char *color_name_lut[] = { "blue", "green", "black", "red" };
|
||||||
|
int quadrant = (Fl::event_x() < x()+w()/2) + 2*(Fl::event_y() < y()+h()/2);
|
||||||
|
char buf[80];
|
||||||
|
::snprintf(buf, 79, "Color %s at x=%d, y=%d", color_name_lut[quadrant], Fl::event_x(), Fl::event_y());
|
||||||
|
return Fl_Tooltip::override_text(buf);
|
||||||
|
}
|
||||||
|
return Fl_Box::handle(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
Fl::set_color(fullcolor_cell,145,159,170);
|
Fl::set_color(fullcolor_cell,145,159,170);
|
||||||
Fl_Window window(400,400);
|
Fl_Window window(400,400);
|
||||||
@ -98,7 +115,8 @@ int main(int argc, char ** argv) {
|
|||||||
b1.callback(cb1,&box);
|
b1.callback(cb1,&box);
|
||||||
Fl_Button b2(120,120,180,30,"fl_color_chooser()");
|
Fl_Button b2(120,120,180,30,"fl_color_chooser()");
|
||||||
b2.callback(cb2,&box);
|
b2.callback(cb2,&box);
|
||||||
Fl_Box image_box(160,190,width,height,0);
|
Image_Box image_box(160,190,width,height,0);
|
||||||
|
image_box.tooltip("Image Box");
|
||||||
make_image();
|
make_image();
|
||||||
(new Fl_RGB_Image(image, width, height))->label(&image_box);
|
(new Fl_RGB_Image(image, width, height))->label(&image_box);
|
||||||
Fl_Box b(160,310,120,30,"Example of fl_draw_image()");
|
Fl_Box b(160,310,120,30,"Example of fl_draw_image()");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user