summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Enumerations.H6
-rw-r--r--FL/Fl_Tooltip.H12
-rw-r--r--FL/names.h5
-rw-r--r--src/Fl_Tooltip.cxx81
-rw-r--r--test/color_chooser.cxx20
5 files changed, 98 insertions, 26 deletions
diff --git a/FL/Enumerations.H b/FL/Enumerations.H
index 2478a8c58..db6465096 100644
--- a/FL/Enumerations.H
+++ b/FL/Enumerations.H
@@ -414,7 +414,11 @@ enum Fl_Event { // events
/** A zoom event (ctrl/+/-/0/ or cmd/+/-/0/) was processed.
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
};
diff --git a/FL/Fl_Tooltip.H b/FL/Fl_Tooltip.H
index b79d93149..d417ba189 100644
--- a/FL/Fl_Tooltip.H
+++ b/FL/Fl_Tooltip.H
@@ -95,6 +95,8 @@ public:
static void wrap_width(int v) { wrap_width_ = v; }
/** Returns the window that is used for tooltips */
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...
// fabien: made it private with only a friend function access
@@ -104,20 +106,22 @@ private:
static void enter_(Fl_Widget* w);
static void exit_(Fl_Widget *w);
static void set_enter_exit_once_();
+ static void tooltip_timeout_(void*);
private:
- static float delay_; //!< delay before a tooltip is shown
- static float hidedelay_; //!< delay until tooltip is closed again
- static float hoverdelay_; //!< delay between tooltips
+ static float delay_; //!< delay before a tooltip is shown
+ static float hidedelay_; //!< delay until tooltip is closed again
+ static float hoverdelay_; //!< delay between tooltips
static Fl_Color color_;
static Fl_Color textcolor_;
static Fl_Font font_;
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_height_; //!< distance around tooltip text top+bottom
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 char *override_text_; //!< a copy of the last text for an overridden tooltip
};
#endif
diff --git a/FL/names.h b/FL/names.h
index 984afbfe0..e47d005ec 100644
--- a/FL/names.h
+++ b/FL/names.h
@@ -73,9 +73,10 @@ const char * const fl_eventnames[] =
"FL_FULLSCREEN",
"FL_ZOOM_GESTURE",
"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_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 ...
};
/**
diff --git a/src/Fl_Tooltip.cxx b/src/Fl_Tooltip.cxx
index 674c57a49..f80956039 100644
--- a/src/Fl_Tooltip.cxx
+++ b/src/Fl_Tooltip.cxx
@@ -25,6 +25,9 @@
#include <stdio.h>
+
+#define DEBUG
+
float Fl_Tooltip::delay_ = 1.0f;
float Fl_Tooltip::hidedelay_ = 12.0f;
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::wrap_width_ = 400;
const int Fl_Tooltip::draw_symbols_ = 1;
+char *Fl_Tooltip::override_text_ = nullptr;
static const char* tip;
@@ -154,14 +158,49 @@ static void tooltip_hide_timeout(void*) {
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
- puts("tooltip_timeout();");
+ puts("tooltip_timeout_();");
#endif // DEBUG
if (recursion) return;
recursion = 1;
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 (window) window->hide();
Fl::remove_timeout(tooltip_hide_timeout);
@@ -253,7 +292,7 @@ void Fl_Tooltip::exit_(Fl_Widget *w) {
if (!widget_ || (w && w == window)) return;
widget_ = 0;
- Fl::remove_timeout(tooltip_timeout);
+ Fl::remove_timeout(tooltip_timeout_);
Fl::remove_timeout(recent_timeout);
if (window && window->visible()) {
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:
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);
// remember it:
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();
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) {
// possible fix for the Windows titlebar, it seems to want the
// 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();
Fl::remove_timeout(tooltip_hide_timeout);
}
- tooltip_timeout(0);
+ tooltip_timeout_(nullptr);
} else {
if (window && window->visible()) {
window->hide();
Fl::remove_timeout(tooltip_hide_timeout);
}
- Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout);
+ Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout_);
}
#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
- hovers the mouse over the widget. The string is <I>not</I> copied, so
- make sure any formatted string is stored in a static, global,
- or allocated buffer. If you want a copy made and managed for you,
- use the copy_tooltip() method, which will manage the tooltip string
- automatically.
+ Assigns a tooltip string that appears in a popup when the user hovers over
+ the widget. The provided string is not copied. The caller must eensure it
+ remains valid by storing it in a static, global, or dynamically allocated
+ buffer. If you need the tooltip string to be copied and managed automatically,
+ use copy_tooltip().
+
+ 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)
\see copy_tooltip(const char*), tooltip()
*/
diff --git a/test/color_chooser.cxx b/test/color_chooser.cxx
index 61fbc4caf..a9a7a5ca1 100644
--- a/test/color_chooser.cxx
+++ b/test/color_chooser.cxx
@@ -21,6 +21,7 @@
#include <FL/fl_show_colormap.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_Image.H>
+#include <FL/Fl_Tooltip.H>
#include <FL/platform.H>
#include <FL/fl_draw.H>
@@ -84,6 +85,22 @@ void cb2(Fl_Widget *, void *v) {
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) {
Fl::set_color(fullcolor_cell,145,159,170);
Fl_Window window(400,400);
@@ -98,7 +115,8 @@ int main(int argc, char ** argv) {
b1.callback(cb1,&box);
Fl_Button b2(120,120,180,30,"fl_color_chooser()");
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();
(new Fl_RGB_Image(image, width, height))->label(&image_box);
Fl_Box b(160,310,120,30,"Example of fl_draw_image()");