]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/Tooltips.C
3bcc3e6fee5d160ca3fedf9bb0d81b3f34ec2efe
[lyx.git] / src / frontends / xforms / Tooltips.C
1 /**
2  * \file Tooltips.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming 
7  *
8  * Full author contact details are available in file CREDITS
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 "xforms_helpers.h" // formatted
25 #include "gettext.h"
26 #include "support/lstrings.h"
27 #include "support/LAssert.h"
28 #include FORMS_H_LOCATION
29
30 #include <boost/bind.hpp>
31
32 bool Tooltips::enabled_ = true;
33
34 boost::signal0<void> Tooltips::toggled;
35
36
37 #if FL_VERSION > 0 || FL_REVISION >= 89
38
39 Tooltips::Tooltips()
40 {
41         toggled.connect(boost::bind(&Tooltips::set, this));
42 }
43
44
45 void Tooltips::toggleEnabled()
46 {
47         enabled_ = !enabled_;
48         toggled();
49 }
50
51
52 void Tooltips::set()
53 {
54         if (tooltipsMap.empty())
55                 // There are no objects with tooltips in this dialog, so
56                 // just go away. Don't change the cursor to a question mark.
57                 return;
58
59         TooltipsMap::iterator it  = tooltipsMap.begin();
60         TooltipsMap::iterator end = tooltipsMap.end();
61         for (; it != end; ++it) {
62                 FL_OBJECT * const ob = it->first;
63                 char const * const c_str = enabled_ ? it->second.c_str() : 0;
64                 fl_set_object_helper(ob, c_str);
65         }
66 }
67
68
69 void Tooltips::init(FL_OBJECT * ob, string const & tip)
70 {
71         lyx::Assert(ob && ob->form);
72
73         // Paranoia check!
74         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
75         if (it != tooltipsMap.end())
76                 return;
77
78         string str = trim(tip);
79         if (str.empty())
80                 return;
81
82         // Store the tooltip string
83         str = formatted(str, 400);
84         tooltipsMap[ob] = str;
85
86         // Set the tooltip
87         char const * const c_str = enabled_ ? str.c_str() : 0;
88         fl_set_object_helper(ob, c_str);
89 }
90
91
92 #else // if FL_REVISION < 89
93
94 namespace {
95
96 int TooltipHandler(FL_OBJECT *ob, int event);
97
98 void TooltipTimerCB(FL_OBJECT * timer, long data);
99
100 }
101
102 extern "C" {
103
104 static int C_TooltipHandler(FL_OBJECT * ob, int event,
105                                     FL_Coord, FL_Coord, int, void *)
106 {
107         return TooltipHandler(ob, event);
108 }
109
110
111 static void C_TooltipTimerCB(FL_OBJECT * ob, long data)
112 {
113         TooltipTimerCB(ob, data);
114 }
115
116 }
117
118
119 Tooltips::Tooltips()
120         : tooltip_timer_(0)
121 {
122         toggled.connect(boost::bind(&Tooltips::set, this));
123 }
124
125
126 void Tooltips::toggleEnabled()
127 {
128         enabled_ = !enabled_;
129         toggled();
130 }
131
132
133 void Tooltips::set()
134 {}
135
136
137 void Tooltips::init(FL_OBJECT * ob, string const & tip)
138 {
139         lyx::Assert(ob && ob->form);
140
141         // Paranoia check!
142         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
143         if (it != tooltipsMap.end())
144                 return;
145
146         string const str = trim(tip);
147         if (str.empty())
148                 return;
149
150         // Store the tooltip string
151         tooltipsMap[ob] = formatted(str, 400);
152
153         if (!tooltip_timer_) {
154                 if (fl_current_form && ob->form != fl_current_form)
155                         fl_end_form();
156
157                 bool const open_form = !fl_current_form;
158                 if (open_form)
159                         fl_addto_form(ob->form);
160
161                 tooltip_timer_ = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 0, 0, "");
162
163                 if (open_form)
164                         fl_end_form();
165         }
166
167         fl_set_object_posthandler(ob, C_TooltipHandler);
168         ob->u_cdata = reinterpret_cast<char *>(tooltip_timer_);
169         tooltip_timer_->u_vdata = this;
170 }
171
172
173 string const Tooltips::get(FL_OBJECT * ob) const
174 {
175         TooltipsMap::const_iterator it = tooltipsMap.find(ob);
176         if (it == tooltipsMap.end())
177                 return string();
178         return it->second;
179 }
180
181
182 namespace {
183
184 void TooltipTimerCB(FL_OBJECT * timer, long data)
185 {
186         FL_OBJECT * ob = reinterpret_cast<FL_OBJECT*>(data);
187         lyx::Assert(ob && ob->form && timer && timer->u_vdata);
188         FL_FORM * form = ob->form;
189         Tooltips * tooltip = static_cast<Tooltips *>(timer->u_vdata);
190
191         string const help = tooltip->get(ob);
192         if (help.empty())
193                 return;
194
195         fl_show_oneliner(help.c_str(),
196                          form->x + ob->x, form->y + ob->y + ob->h);
197 }
198
199
200 // post_handler for tooltip help
201 int TooltipHandler(FL_OBJECT * ob, int event)
202 {
203         if (!Tooltips::enabled())
204                 return 0;
205
206         lyx::Assert(ob);
207         FL_OBJECT * timer = reinterpret_cast<FL_OBJECT *>(ob->u_cdata);
208         lyx::Assert(timer);
209
210         // We do not test for empty help here, since this can never happen
211         if (event == FL_ENTER) {
212                 fl_set_object_callback(timer,
213                                        C_TooltipTimerCB,
214                                        reinterpret_cast<long>(ob));
215                 fl_set_timer(timer, 1);
216         }
217         else if (event != FL_MOTION) {
218                 fl_set_timer(timer, 0);
219                 fl_hide_oneliner();
220         }
221         return 0;
222 }
223
224 } // namespace anon
225
226 #endif // FL_REVISION >= 89