]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBase.C
Framework to select the verbosity of the tooltip.
[lyx.git] / src / frontends / xforms / FormBase.C
1 /* This file is part of
2  * ====================================================== 
3  *
4  *           LyX, The Document Processor
5  *
6  *           Copyright 2000-2001 The LyX Team.
7  *
8  * ======================================================
9  *
10  * \author Angus Leeming <a.leeming@ic.ac.uk>
11  */
12
13 #include <config.h>
14
15 #ifdef __GNUG__
16 #pragma implementation
17 #endif
18
19 #include "Dialogs.h"
20 #include "FormBase.h"
21 #include "xformsBC.h"
22 #include "support/LAssert.h"
23 #include "xforms_helpers.h" // formatted
24
25 #if FL_REVISION < 89
26
27 namespace {
28
29 int TooltipHandler(FL_OBJECT *ob, int event);
30
31 void TooltipTimerCB(FL_OBJECT * timer, long data);
32  
33 }
34
35 extern "C" {
36
37 static int C_FormBaseTooltipHandler(FL_OBJECT * ob, int event,
38                                     FL_Coord, FL_Coord, int, void *)
39 {
40         return TooltipHandler(ob, event);
41 }
42
43 static void C_FormBaseTooltipTimerCB(FL_OBJECT * ob, long data)
44 {
45         TooltipTimerCB(ob, data);
46 }
47
48 }
49  
50 #endif // FL_REVISION < 89
51
52
53 extern "C" {
54
55 // Callback function invoked by xforms when the dialog is closed by the
56 // window manager
57 static int C_FormBaseWMHideCB(FL_FORM * form, void *);
58
59 // Use this to diaplay feedback messages or to trigger an input event on paste
60 // with the middle mouse button
61 static int C_FormBasePrehandler(FL_OBJECT * ob, int event,
62                                 FL_Coord, FL_Coord, int key, void *);
63
64 } // extern "C"
65
66
67 FormBase::FormBase(ControlButtons & c, string const & t, bool allowResize)
68         : ViewBC<xformsBC>(c), minw_(0), minh_(0), allow_resize_(allowResize),
69           title_(t), warning_posted_(false), tooltip_level_(VERBOSE_TOOLTIP)
70
71 {
72 #if FL_REVISION < 89
73         tooltip_timer_ = 0;
74 #endif
75 }
76
77
78 void FormBase::redraw()
79 {
80         if (form() && form()->visible)
81                 fl_redraw_form(form());
82 }
83
84
85 void FormBase::show()
86 {
87         if (!form()) {
88                 build();
89         }
90
91         // use minw_ to flag whether the dialog has ever been shown
92         // (Needed now that build() is/should be called from the controller)
93         if (minw_ == 0) {
94                 bc().refresh();
95
96                 // work around dumb xforms sizing bug
97                 minw_ = form()->w;
98                 minh_ = form()->h;
99
100                 fl_set_form_atclose(form(), C_FormBaseWMHideCB, 0);
101         }
102
103         fl_freeze_form(form());
104         update();  // make sure its up-to-date
105         fl_unfreeze_form(form());
106
107         if (form()->visible) {
108                 fl_raise_form(form());
109                 /* This XMapWindow() will hopefully ensure that
110                  * iconified dialogs are de-iconified. Mad props
111                  * out to those crazy Xlib guys for forgetting a
112                  * XDeiconifyWindow(). At least WindowMaker, when
113                  * being notified of the redirected MapRequest will
114                  * specifically de-iconify. From source, fvwm2 seems
115                  * to do the same.
116                  */
117                 XMapWindow(fl_get_display(), form()->window);
118         } else {
119                 // calls to fl_set_form_minsize/maxsize apply only to the next
120                 // fl_show_form(), so this comes first.
121                 fl_set_form_minsize(form(), minw_, minh_);
122                 if (!allow_resize_)
123                         fl_set_form_maxsize(form(), minw_, minh_);
124
125                 fl_show_form(form(),
126                         FL_PLACE_MOUSE | FL_FREE_SIZE,
127                         (controller_.IconifyWithMain() ? FL_TRANSIENT : 0),
128                         title_.c_str());
129         }
130 }
131
132
133 void FormBase::hide()
134 {
135         if (form() && form()->visible)
136                 fl_hide_form(form());
137 }
138
139
140 void FormBase::InputCB(FL_OBJECT * ob, long data)
141 {
142         // It is possible to set the choice to 0 when using the
143         // keyboard shortcuts. This work-around deals with the problem.
144         if (ob && ob->objclass == FL_CHOICE && fl_get_choice(ob) < 1) {
145                 fl_set_choice(ob, 1);
146         }
147
148         bc().input(input(ob, data));
149 }
150
151
152 ButtonPolicy::SMInput FormBase::input(FL_OBJECT *, long)
153 {
154         return ButtonPolicy::SMI_VALID;
155 }
156
157
158 // preemptive handler for feedback messages
159 void FormBase::FeedbackCB(FL_OBJECT * ob, int event)
160 {
161         lyx::Assert(ob);
162
163         switch (event) {
164         case FL_ENTER:
165                 warning_posted_ = false;
166                 feedback(ob);
167                 break;
168
169         case FL_LEAVE:
170                 if (!warning_posted_)
171                         clear_feedback();
172                 break;
173
174         default:
175                 break;
176         }
177 }
178
179
180 void FormBase::setTooltipHandler(FL_OBJECT * ob)
181 {
182         lyx::Assert(ob);
183
184 #if FL_REVISION < 89
185         if (!tooltip_timer_) {
186                 fl_addto_form(form());
187                 tooltip_timer_ = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 0, 0, "");
188                 fl_end_form();
189         }
190
191         fl_set_object_posthandler(ob, C_FormBaseTooltipHandler);
192         ob->u_cdata = reinterpret_cast<char *>(tooltip_timer_);
193
194 #else
195         string const help(getTooltip(ob));
196         if (!help.empty())
197                 fl_set_object_helper(ob, help.c_str()); 
198 #endif // FL_REVISION < 89
199 }
200
201
202 string const FormBase::getTooltip(FL_OBJECT * ob) const
203 {
204         lyx::Assert(ob);
205
206         switch (tooltip_level_) {
207         case VERBOSE_TOOLTIP: 
208         {
209                 string str = getVerboseTooltip(ob);
210                 if (!str.empty())
211                         return formatted(_(str), 400);
212                 // else, fall through
213         }
214         
215         case MINIMAL_TOOLTIP:
216                 return getMinimalTooltip(ob);
217                 
218         case NO_TOOLTIP:
219         default:
220                 return string();
221         }
222         
223 }
224                 
225
226 void FormBase::setTooltipLevel(TooltipLevel level)
227 {
228         tooltip_level_ = level;
229 }
230
231
232 void FormBase::setPrehandler(FL_OBJECT * ob)
233 {
234         lyx::Assert(ob);
235         fl_set_object_prehandler(ob, C_FormBasePrehandler);
236 }
237
238
239 void FormBase::setWarningPosted(bool warning)
240 {
241         warning_posted_ = warning;
242 }
243
244
245 namespace {
246
247 FormBase * GetForm(FL_OBJECT * ob)
248 {
249         lyx::Assert(ob && ob->form && ob->form->u_vdata);
250         FormBase * pre = static_cast<FormBase *>(ob->form->u_vdata);
251         return pre;
252 }
253
254 } // namespace anon
255
256
257 extern "C" {
258
259 void C_FormBaseApplyCB(FL_OBJECT * ob, long)
260 {
261         GetForm(ob)->ApplyButton();
262 }
263
264
265 void C_FormBaseOKCB(FL_OBJECT * ob, long)
266 {
267         GetForm(ob)->OKButton();
268 }
269
270
271 void C_FormBaseCancelCB(FL_OBJECT * ob, long)
272 {
273         FormBase * form = GetForm(ob);
274         form->CancelButton();
275 }
276
277
278 void C_FormBaseRestoreCB(FL_OBJECT * ob, long)
279 {
280         GetForm(ob)->RestoreButton();
281 }
282
283
284 void C_FormBaseInputCB(FL_OBJECT * ob, long d)
285 {
286         GetForm(ob)->InputCB(ob, d);
287 }
288
289
290 static int C_FormBaseWMHideCB(FL_FORM * form, void *)
291 {
292         // Close the dialog cleanly, even if the WM is used to do so.
293         lyx::Assert(form && form->u_vdata);
294         FormBase * pre = static_cast<FormBase *>(form->u_vdata);
295         pre->CancelButton();
296         return FL_CANCEL;
297 }
298
299
300 static int C_FormBasePrehandler(FL_OBJECT * ob, int event,
301                                 FL_Coord, FL_Coord, int key, void *)
302 {
303         // Note that the return value is important in the pre-emptive handler.
304         // Don't return anything other than 0.
305         lyx::Assert(ob);
306
307         // Don't Assert this one, as it can happen quite naturally when things
308         // are being deleted in the d-tor.
309         //Assert(ob->form);
310         if (!ob->form) return 0;
311
312         FormBase * pre = static_cast<FormBase *>(ob->form->u_vdata);
313         if (!pre) return 0;
314
315         if (event == FL_PUSH && key == 2 && ob->objclass == FL_INPUT) {
316                 // Trigger an input event when pasting in an xforms input object
317                 // using the middle mouse button.
318                 pre->InputCB(ob, 0);
319
320         } else if (event == FL_ENTER || event == FL_LEAVE){
321                 // Post feedback as the mouse enters the object,
322                 // remove it as the mouse leaves.
323                 pre->FeedbackCB(ob, event);
324         }
325
326         return 0;
327 }
328  
329 } // extern "C"
330
331
332 #if FL_REVISION < 89
333
334 namespace {
335
336 void TooltipTimerCB(FL_OBJECT * timer, long data)
337 {
338         FL_OBJECT * ob = reinterpret_cast<FL_OBJECT*>(data);
339         lyx::Assert(ob && ob->form);
340
341         string const help = GetForm(timer)->getTooltip(ob);
342         if (help.empty())
343                 return;
344
345         fl_show_oneliner(help.c_str(),
346                          ob->form->x + ob->x,
347                          ob->form->y + ob->y + ob->h);
348 }
349
350
351 // post_handler for bubble-help (Matthias)
352 int TooltipHandler(FL_OBJECT *ob, int event)
353 {
354         lyx::Assert(ob);
355         FL_OBJECT * timer = reinterpret_cast<FL_OBJECT *>(ob->u_cdata);
356         lyx::Assert(timer);
357
358         // We do not test for empty help here, since this can never happen
359         if (event == FL_ENTER){
360                 fl_set_object_callback(timer,
361                                        C_FormBaseTooltipTimerCB,
362                                        reinterpret_cast<long>(ob));
363                 fl_set_timer(timer, 1);
364         }
365         else if (event != FL_MOTION){
366                 fl_set_timer(timer, 0);
367                 fl_hide_oneliner();
368         }
369         return 0;
370 }
371
372 } // namespace anon
373
374 #endif // FL_REVISION < 89