]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/Tooltips.C
sourcedoc-friendly files.
[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         // Set the cursor to a question mark or back to the default.
74         FL_OBJECT * const ob = tooltipsMap.begin()->first;
75         int const cursor = enabled_ ? XC_question_arrow : FL_DEFAULT_CURSOR;
76         fl_set_cursor(FL_ObjWin(ob), cursor);
77 }
78
79
80 void Tooltips::initTooltip(FL_OBJECT * ob, string const & tip)
81 {
82         lyx::Assert(ob);
83
84         // Paranoia check!
85         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
86         if (it != tooltipsMap.end())
87                 return;
88
89         string const str = strip(frontStrip(tip));
90         if (str.empty())
91                 return;
92
93         // Store the tooltip string
94         tooltipsMap[ob] = formatted(_(str), 400);
95
96         // Set the initial state of the tooltips
97         char const * const c_str = enabled_ ? str.c_str() : 0;
98         fl_set_object_helper(ob, c_str);
99 }
100
101
102 #else // if FL_REVISION < 89
103
104 namespace {
105
106 int TooltipHandler(FL_OBJECT *ob, int event);
107
108 void TooltipTimerCB(FL_OBJECT * timer, long data);
109  
110 }
111
112 extern "C" {
113
114 static int C_TooltipHandler(FL_OBJECT * ob, int event,
115                                     FL_Coord, FL_Coord, int, void *)
116 {
117         return TooltipHandler(ob, event);
118 }
119
120
121 static void C_TooltipTimerCB(FL_OBJECT * ob, long data)
122 {
123         TooltipTimerCB(ob, data);
124 }
125
126 }
127  
128
129 Tooltips::Tooltips()
130         : tooltip_timer_(0)
131 {
132         static bool first = true;
133         if (first) {
134                 first = false;
135                 Dialogs::toggleTooltips.connect(slot(&Tooltips::toggleEnabled));
136         }
137         tooltipsToggled.connect(slot(this, &Tooltips::toggleTooltips));
138 }
139
140
141 void Tooltips::toggleEnabled()
142 {
143         enabled_ = !enabled_;
144         tooltipsToggled();
145 }
146
147
148 void Tooltips::toggleTooltips()
149 {
150         if (tooltipsMap.empty())
151                 // There are no objects with tooltips in this dialog, so
152                 // just go away. Don't change the cursor to a question mark.
153                 return;
154
155         // Set the cursor to a question mark or back to the default.
156         FL_OBJECT * const ob = tooltipsMap.begin()->first;
157         int const cursor = enabled_ ? XC_question_arrow : FL_DEFAULT_CURSOR;
158         fl_set_cursor(FL_ObjWin(ob), cursor);
159 }
160
161
162 void Tooltips::initTooltip(FL_OBJECT * ob, string const & tip)
163 {
164         lyx::Assert(ob);
165
166         // Paranoia check!
167         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
168         if (it != tooltipsMap.end())
169                 return;
170
171         string const str = strip(frontStrip(tip));
172         if (str.empty())
173                 return;
174
175         // Store the tooltip string
176         tooltipsMap[ob] = formatted(_(str), 400);
177
178         if (!tooltip_timer_) {
179                 lyx::Assert(ob->form);
180                 if (fl_current_form && ob->form != fl_current_form)
181                         fl_end_form();
182
183                 bool const open_form = !fl_current_form;
184                 if (open_form)
185                         fl_addto_form(ob->form);
186
187                 tooltip_timer_ = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 0, 0, "");
188
189                 if (open_form)
190                         fl_end_form();
191         }
192
193         fl_set_object_posthandler(ob, C_TooltipHandler);
194         ob->u_cdata = reinterpret_cast<char *>(tooltip_timer_);
195         tooltip_timer_->u_vdata = this;
196 }
197
198
199 string const Tooltips::getTooltip(FL_OBJECT * ob) const 
200 {
201         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
202         if (it == tooltipsMap.end())
203                 return string();
204         return it->second;
205 }
206
207
208 namespace {
209
210 void TooltipTimerCB(FL_OBJECT * timer, long data)
211 {
212         FL_OBJECT * ob = reinterpret_cast<FL_OBJECT*>(data);
213         lyx::Assert(ob && ob->form && timer && timer->u_vdata);
214         FL_FORM * form = ob->form;
215         Tooltips * tooltip = static_cast<Tooltips *>(timer->u_vdata);
216
217         string const help = tooltip->getTooltip(ob);
218         if (help.empty())
219                 return;
220
221         fl_show_oneliner(help.c_str(),
222                          form->x + ob->x, form->y + ob->y + ob->h);
223 }
224
225
226 // post_handler for tooltip help
227 int TooltipHandler(FL_OBJECT * ob, int event)
228 {
229         if (!Tooltips::enabled())
230                 return 0;
231
232         lyx::Assert(ob);
233         FL_OBJECT * timer = reinterpret_cast<FL_OBJECT *>(ob->u_cdata);
234         lyx::Assert(timer);
235
236         // We do not test for empty help here, since this can never happen
237         if (event == FL_ENTER) {
238                 fl_set_object_callback(timer,
239                                        C_TooltipTimerCB,
240                                        reinterpret_cast<long>(ob));
241                 fl_set_timer(timer, 1);
242         }
243         else if (event != FL_MOTION) {
244                 fl_set_timer(timer, 0);
245                 fl_hide_oneliner();
246         }
247         return 0;
248 }
249
250 } // namespace anon
251
252 #endif // FL_REVISION >= 89