]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/Tooltips.C
iThe cursor now behaves properly in the dialogs...
[lyx.git] / src / frontends / xforms / Tooltips.C
1 /*
2  * \file Tooltips.C
3  * Copyright 2002 the LyX Team
4  * Read the file COPYING
5  *
6  * \author Angus Leeming, a.leeming@ic.ac.uk
7  */
8
9 /*
10  *
11  * Tooltips for xforms. xforms 0.89 supports them directly, but 0.88 needs
12  * a bit of jiggery pokery. This class wraps it all up in a neat interface.
13  * Based on code originally in Toolbar_pimpl.C that appears to have been
14  * written by Matthias Ettrich and Jean-Marc Lasgouttes.
15  */
16
17 #include <config.h>
18
19 #ifdef __GNUG__
20 #pragma implementation
21 #endif
22
23 #include "Tooltips.h"
24 #include "Dialogs.h"
25 #include "xforms_helpers.h" // formatted
26 #include "gettext.h"
27 #include "support/lstrings.h"
28 #include "support/LAssert.h"
29
30 using SigC::slot;
31
32
33 bool Tooltips::enabled_ = false;
34
35 SigC::Signal0<void> Tooltips::tooltipsToggled;
36
37
38 #if FL_REVISION >= 89
39
40 Tooltips::Tooltips()
41 {
42         static bool first = true;
43         if (first) {
44                 first = false;
45                 Dialogs::toggleTooltips.connect(slot(&Tooltips::toggleEnabled));
46         }
47         tooltipsToggled.connect(slot(this, &Tooltips::toggleTooltips));
48 }
49
50
51 void Tooltips::toggleEnabled()
52 {
53         enabled_ = !enabled_;
54         tooltipsToggled();
55 }
56
57
58 void Tooltips::toggleTooltips()
59 {
60         if (tooltipsMap.empty())
61                 // There are no objects with tooltips in this dialog, so
62                 // just go away. Don't change the cursor to a question mark.
63                 return;
64
65         TooltipsMap::iterator it  = tooltipsMap.begin();
66         TooltipsMap::iterator end = tooltipsMap.end();
67         for (; it != end; ++it) {
68                 FL_OBJECT * const ob = it->first;
69                 char const * const c_str = enabled_ ? it->second.c_str() : 0;
70                 fl_set_object_helper(ob, c_str);
71         }
72
73         FL_OBJECT * const ob = tooltipsMap.begin()->first;
74
75         // The dialog is not visible
76         if (!ob->form->window)
77                 return;
78
79         // Set the cursor to a question mark or back to the default.
80         int const cursor = enabled_ ? XC_question_arrow : FL_DEFAULT_CURSOR;
81         fl_set_cursor(ob->form->window, cursor);
82 }
83
84
85 void Tooltips::initTooltip(FL_OBJECT * ob, string const & tip)
86 {
87         lyx::Assert(ob && ob->form);
88
89         // Paranoia check!
90         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
91         if (it != tooltipsMap.end())
92                 return;
93
94         string const str = strip(frontStrip(tip));
95         if (str.empty())
96                 return;
97
98         // Store the tooltip string
99         tooltipsMap[ob] = formatted(_(str), 400);
100
101         // Set the initial state of the tooltips
102         char const * const c_str = enabled_ ? str.c_str() : 0;
103         fl_set_object_helper(ob, c_str);
104 }
105
106
107 #else // if FL_REVISION < 89
108
109 namespace {
110
111 int TooltipHandler(FL_OBJECT *ob, int event);
112
113 void TooltipTimerCB(FL_OBJECT * timer, long data);
114  
115 }
116
117 extern "C" {
118
119 static int C_TooltipHandler(FL_OBJECT * ob, int event,
120                                     FL_Coord, FL_Coord, int, void *)
121 {
122         return TooltipHandler(ob, event);
123 }
124
125
126 static void C_TooltipTimerCB(FL_OBJECT * ob, long data)
127 {
128         TooltipTimerCB(ob, data);
129 }
130
131 }
132  
133
134 Tooltips::Tooltips()
135         : tooltip_timer_(0)
136 {
137         static bool first = true;
138         if (first) {
139                 first = false;
140                 Dialogs::toggleTooltips.connect(slot(&Tooltips::toggleEnabled));
141         }
142         tooltipsToggled.connect(slot(this, &Tooltips::toggleTooltips));
143 }
144
145
146 void Tooltips::toggleEnabled()
147 {
148         enabled_ = !enabled_;
149         tooltipsToggled();
150 }
151
152
153 void Tooltips::toggleTooltips()
154 {
155         if (tooltipsMap.empty())
156                 // There are no objects with tooltips in this dialog, so
157                 // just go away. Don't change the cursor to a question mark.
158                 return;
159
160         FL_OBJECT * const ob = tooltipsMap.begin()->first;
161
162         // The dialog is not visible
163         if (!ob->form->window)
164                 return;
165
166         // Set the cursor to a question mark or back to the default.
167         int const cursor = enabled_ ? XC_question_arrow : FL_DEFAULT_CURSOR;
168         fl_set_cursor(ob->form->window, cursor);
169 }
170
171
172 void Tooltips::initTooltip(FL_OBJECT * ob, string const & tip)
173 {
174         lyx::Assert(ob && ob->form);
175
176         // Paranoia check!
177         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
178         if (it != tooltipsMap.end())
179                 return;
180
181         string const str = strip(frontStrip(tip));
182         if (str.empty())
183                 return;
184
185         // Store the tooltip string
186         tooltipsMap[ob] = formatted(_(str), 400);
187
188         if (!tooltip_timer_) {
189                 if (fl_current_form && ob->form != fl_current_form)
190                         fl_end_form();
191
192                 bool const open_form = !fl_current_form;
193                 if (open_form)
194                         fl_addto_form(ob->form);
195
196                 tooltip_timer_ = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 0, 0, "");
197
198                 if (open_form)
199                         fl_end_form();
200         }
201
202         fl_set_object_posthandler(ob, C_TooltipHandler);
203         ob->u_cdata = reinterpret_cast<char *>(tooltip_timer_);
204         tooltip_timer_->u_vdata = this;
205 }
206
207
208 string const Tooltips::getTooltip(FL_OBJECT * ob) const 
209 {
210         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
211         if (it == tooltipsMap.end())
212                 return string();
213         return it->second;
214 }
215
216
217 namespace {
218
219 void TooltipTimerCB(FL_OBJECT * timer, long data)
220 {
221         FL_OBJECT * ob = reinterpret_cast<FL_OBJECT*>(data);
222         lyx::Assert(ob && ob->form && timer && timer->u_vdata);
223         FL_FORM * form = ob->form;
224         Tooltips * tooltip = static_cast<Tooltips *>(timer->u_vdata);
225
226         string const help = tooltip->getTooltip(ob);
227         if (help.empty())
228                 return;
229
230         fl_show_oneliner(help.c_str(),
231                          form->x + ob->x, form->y + ob->y + ob->h);
232 }
233
234
235 // post_handler for tooltip help
236 int TooltipHandler(FL_OBJECT * ob, int event)
237 {
238         if (!Tooltips::enabled())
239                 return 0;
240
241         lyx::Assert(ob);
242         FL_OBJECT * timer = reinterpret_cast<FL_OBJECT *>(ob->u_cdata);
243         lyx::Assert(timer);
244
245         // We do not test for empty help here, since this can never happen
246         if (event == FL_ENTER) {
247                 fl_set_object_callback(timer,
248                                        C_TooltipTimerCB,
249                                        reinterpret_cast<long>(ob));
250                 fl_set_timer(timer, 1);
251         }
252         else if (event != FL_MOTION) {
253                 fl_set_timer(timer, 0);
254                 fl_hide_oneliner();
255         }
256         return 0;
257 }
258
259 } // namespace anon
260
261 #endif // FL_REVISION >= 89