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