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