|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_Tooltip.cxx 8018 2010-12-12 19:52:26Z matt $" 00003 // 00004 // Tooltip source file for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 #include <FL/Fl_Tooltip.H> 00029 #include <FL/fl_draw.H> 00030 #include <FL/Fl_Menu_Window.H> 00031 00032 #include <stdio.h> 00033 #include <string.h> // strdup() 00034 00035 float Fl_Tooltip::delay_ = 1.0f; 00036 float Fl_Tooltip::hoverdelay_ = 0.2f; 00037 Fl_Color Fl_Tooltip::color_ = fl_color_cube(FL_NUM_RED - 1, 00038 FL_NUM_GREEN - 1, 00039 FL_NUM_BLUE - 2); 00040 Fl_Color Fl_Tooltip::textcolor_ = FL_BLACK; 00041 Fl_Font Fl_Tooltip::font_ = FL_HELVETICA; 00042 Fl_Fontsize Fl_Tooltip::size_ = FL_NORMAL_SIZE; 00043 00044 #define MAX_WIDTH 400 00045 00046 static const char* tip; 00050 class Fl_TooltipBox : public Fl_Menu_Window { 00051 public: 00053 Fl_TooltipBox() : Fl_Menu_Window(0, 0) { 00054 set_override(); 00055 set_tooltip_window(); 00056 end(); 00057 } 00058 void draw(); 00059 void layout(); 00061 void show() { 00062 if (tip) Fl_Menu_Window::show(); 00063 } 00064 }; 00065 00066 Fl_Widget* Fl_Tooltip::widget_ = 0; 00067 static Fl_TooltipBox *window = 0; 00068 static int Y,H; 00069 00070 #ifdef __APPLE__ 00071 // returns the unique tooltip window 00072 Fl_Window *Fl_Tooltip::current_window(void) 00073 { 00074 return (Fl_Window*)window; 00075 } 00076 #endif 00077 00078 void Fl_TooltipBox::layout() { 00079 fl_font(Fl_Tooltip::font(), Fl_Tooltip::size()); 00080 int ww, hh; 00081 ww = MAX_WIDTH; 00082 fl_measure(tip, ww, hh, FL_ALIGN_LEFT|FL_ALIGN_WRAP|FL_ALIGN_INSIDE); 00083 ww += 6; hh += 6; 00084 00085 // find position on the screen of the widget: 00086 int ox = Fl::event_x_root(); 00087 int oy = Y + H+2; 00088 for (Fl_Widget* p = Fl_Tooltip::current(); p; p = p->window()) { 00089 oy += p->y(); 00090 } 00091 int scr_x, scr_y, scr_w, scr_h; 00092 Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); 00093 if (ox+ww > scr_x+scr_w) ox = scr_x+scr_w - ww; 00094 if (ox < scr_x) ox = scr_x; 00095 if (H > 30) { 00096 oy = Fl::event_y_root()+13; 00097 if (oy+hh > scr_y+scr_h) oy -= 23+hh; 00098 } else { 00099 if (oy+hh > scr_y+scr_h) oy -= (4+hh+H); 00100 } 00101 if (oy < scr_y) oy = scr_y; 00102 00103 resize(ox, oy, ww, hh); 00104 } 00105 00106 void Fl_TooltipBox::draw() { 00107 draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Tooltip::color()); 00108 fl_color(Fl_Tooltip::textcolor()); 00109 fl_font(Fl_Tooltip::font(), Fl_Tooltip::size()); 00110 fl_draw(tip, 3, 3, w()-6, h()-6, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP)); 00111 } 00112 00113 static char recent_tooltip; 00114 00115 static void recent_timeout(void*) { 00116 #ifdef DEBUG 00117 puts("recent_timeout();"); 00118 #endif // DEBUG 00119 00120 recent_tooltip = 0; 00121 } 00122 00123 static char recursion; 00124 00125 static void tooltip_timeout(void*) { 00126 #ifdef DEBUG 00127 puts("tooltip_timeout();"); 00128 #endif // DEBUG 00129 00130 if (recursion) return; 00131 recursion = 1; 00132 if (!tip || !*tip) { 00133 if (window) window->hide(); 00134 } else { 00135 //if (Fl::grab()) return; 00136 if (!window) window = new Fl_TooltipBox; 00137 // this cast bypasses the normal Fl_Window label() code: 00138 ((Fl_Widget*)window)->label(tip); 00139 window->layout(); 00140 window->redraw(); 00141 // printf("tooltip_timeout: Showing window %p with tooltip \"%s\"...\n", 00142 // window, tip ? tip : "(null)"); 00143 window->show(); 00144 } 00145 00146 Fl::remove_timeout(recent_timeout); 00147 recent_tooltip = 1; 00148 recursion = 0; 00149 } 00150 00160 void Fl_Tooltip::enter_(Fl_Widget* w) { 00161 #ifdef DEBUG 00162 printf("Fl_Tooltip::enter_(w=%p)\n", w); 00163 printf(" window=%p\n", window); 00164 #endif // DEBUG 00165 00166 // find the enclosing group with a tooltip: 00167 Fl_Widget* tw = w; 00168 for (;;) { 00169 if (!tw) {exit_(0); return;} 00170 if (tw == widget_) return; 00171 if (tw->tooltip()) break; 00172 tw = tw->parent(); 00173 } 00174 enter_area(w, 0, 0, w->w(), w->h(), tw->tooltip()); 00175 } 00183 void Fl_Tooltip::current(Fl_Widget* w) { 00184 #ifdef DEBUG 00185 printf("Fl_Tooltip::current(w=%p)\n", w); 00186 #endif // DEBUG 00187 00188 exit_(0); 00189 // find the enclosing group with a tooltip: 00190 Fl_Widget* tw = w; 00191 for (;;) { 00192 if (!tw) return; 00193 if (tw->tooltip()) break; 00194 tw = tw->parent(); 00195 } 00196 // act just like Fl_Tooltip::enter_() except we can remember a zero: 00197 widget_ = w; 00198 } 00199 00200 // Hide any visible tooltip. 00202 void Fl_Tooltip::exit_(Fl_Widget *w) { 00203 #ifdef DEBUG 00204 printf("Fl_Tooltip::exit_(w=%p)\n", w); 00205 printf(" widget=%p, window=%p\n", widget_, window); 00206 #endif // DEBUG 00207 00208 if (!widget_ || (w && w == window)) return; 00209 widget_ = 0; 00210 Fl::remove_timeout(tooltip_timeout); 00211 Fl::remove_timeout(recent_timeout); 00212 if (window && window->visible()) window->hide(); 00213 if (recent_tooltip) { 00214 if (Fl::event_state() & FL_BUTTONS) recent_tooltip = 0; 00215 else Fl::add_timeout(Fl_Tooltip::hoverdelay(), recent_timeout); 00216 } 00217 } 00218 00219 // Get ready to display a tooltip. The widget and the xywh box inside 00220 // it define an area the tooltip is for, this along with the current 00221 // mouse position places the tooltip (the mouse is assumed to point 00222 // inside or near the box). 00234 void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char* t) 00235 { 00236 (void)x; 00237 (void)w; 00238 00239 #ifdef DEBUG 00240 printf("Fl_Tooltip::enter_area(wid=%p, x=%d, y=%d, w=%d, h=%d, t=\"%s\")\n", 00241 wid, x, y, w, h, t ? t : "(null)"); 00242 printf(" recursion=%d, window=%p\n", recursion, window); 00243 #endif // DEBUG 00244 00245 if (recursion) return; 00246 if (!t || !*t || !enabled()) { 00247 exit_(0); 00248 return; 00249 } 00250 // do nothing if it is the same: 00251 if (wid==widget_ /*&& x==X && y==Y && w==W && h==H*/ && t==tip) return; 00252 Fl::remove_timeout(tooltip_timeout); 00253 Fl::remove_timeout(recent_timeout); 00254 // remember it: 00255 widget_ = wid; Y = y; H = h; tip = t; 00256 // popup the tooltip immediately if it was recently up: 00257 if (recent_tooltip) { 00258 if (window) window->hide(); 00259 Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout); 00260 } else if (Fl_Tooltip::delay() < .1) { 00261 #ifdef WIN32 00262 // possible fix for the Windows titlebar, it seems to want the 00263 // window to be destroyed, moving it messes up the parenting: 00264 if (window && window->visible()) window->hide(); 00265 #endif // WIN32 00266 tooltip_timeout(0); 00267 } else { 00268 if (window && window->visible()) window->hide(); 00269 Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout); 00270 } 00271 00272 #ifdef DEBUG 00273 printf(" tip=\"%s\", window->shown()=%d\n", tip ? tip : "(null)", 00274 window ? window->shown() : 0); 00275 #endif // DEBUG 00276 } 00277 00278 void Fl_Tooltip::set_enter_exit_once_() { 00279 static char beenhere = 0; 00280 if (!beenhere) { 00281 beenhere = 1; 00282 Fl_Tooltip::enter = Fl_Tooltip::enter_; 00283 Fl_Tooltip::exit = Fl_Tooltip::exit_; 00284 } 00285 } 00286 00304 void Fl_Widget::tooltip(const char *text) { 00305 Fl_Tooltip::set_enter_exit_once_(); 00306 if (flags() & COPIED_TOOLTIP) { 00307 // reassigning a copied tooltip remains the same copied tooltip 00308 if (tooltip_ == text) return; 00309 free((void*)(tooltip_)); // free maintained copy 00310 clear_flag(COPIED_TOOLTIP); // disable copy flag (WE don't make copies) 00311 } 00312 tooltip_ = text; 00313 } 00314 00330 void Fl_Widget::copy_tooltip(const char *text) { 00331 Fl_Tooltip::set_enter_exit_once_(); 00332 if (flags() & COPIED_TOOLTIP) free((void *)(tooltip_)); 00333 if (text) { 00334 set_flag(COPIED_TOOLTIP); 00335 tooltip_ = strdup(text); 00336 } else { 00337 clear_flag(COPIED_TOOLTIP); 00338 tooltip_ = (char *)0; 00339 } 00340 } 00341 00342 // 00343 // End of "$Id: Fl_Tooltip.cxx 8018 2010-12-12 19:52:26Z matt $". 00344 //