]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBase.C
Stabilise the tooltips interface and use it successfully in the Bibtex,
[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 "Tooltips.h"
24 #include "xforms_helpers.h" // formatted
25
26 extern "C" {
27
28 // Callback function invoked by xforms when the dialog is closed by the
29 // window manager
30 static int C_FormBaseWMHideCB(FL_FORM * form, void *);
31
32 // Use this to diaplay feedback messages or to trigger an input event on paste
33 // with the middle mouse button
34 static int C_FormBasePrehandler(FL_OBJECT * ob, int event,
35                                 FL_Coord, FL_Coord, int key, void *);
36
37 } // extern "C"
38
39
40 FormBase::FormBase(ControlButtons & c, string const & t, bool allowResize)
41         : ViewBC<xformsBC>(c), minw_(0), minh_(0), allow_resize_(allowResize),
42           title_(t), warning_posted_(false), tooltip_level_(NO_TOOLTIP)
43
44 {
45         tooltip_ = new Tooltips;
46         tooltip_->getTooltip.connect(SigC::slot(this, &FormBase::getTooltip));
47 }
48
49
50 FormBase::~FormBase()
51 {
52         delete tooltip_;
53 }
54
55 void FormBase::redraw()
56 {
57         if (form() && form()->visible)
58                 fl_redraw_form(form());
59 }
60
61
62 void FormBase::show()
63 {
64         if (!form()) {
65                 build();
66         }
67
68         // use minw_ to flag whether the dialog has ever been shown
69         // (Needed now that build() is/should be called from the controller)
70         if (minw_ == 0) {
71                 bc().refresh();
72
73                 // work around dumb xforms sizing bug
74                 minw_ = form()->w;
75                 minh_ = form()->h;
76
77                 fl_set_form_atclose(form(), C_FormBaseWMHideCB, 0);
78         }
79
80         fl_freeze_form(form());
81         update();  // make sure its up-to-date
82         fl_unfreeze_form(form());
83
84         if (form()->visible) {
85                 fl_raise_form(form());
86                 /* This XMapWindow() will hopefully ensure that
87                  * iconified dialogs are de-iconified. Mad props
88                  * out to those crazy Xlib guys for forgetting a
89                  * XDeiconifyWindow(). At least WindowMaker, when
90                  * being notified of the redirected MapRequest will
91                  * specifically de-iconify. From source, fvwm2 seems
92                  * to do the same.
93                  */
94                 XMapWindow(fl_get_display(), form()->window);
95         } else {
96                 // calls to fl_set_form_minsize/maxsize apply only to the next
97                 // fl_show_form(), so this comes first.
98                 fl_set_form_minsize(form(), minw_, minh_);
99                 if (!allow_resize_)
100                         fl_set_form_maxsize(form(), minw_, minh_);
101
102                 fl_show_form(form(),
103                         FL_PLACE_MOUSE | FL_FREE_SIZE,
104                         (controller_.IconifyWithMain() ? FL_TRANSIENT : 0),
105                         title_.c_str());
106         }
107 }
108
109
110 void FormBase::hide()
111 {
112         if (form() && form()->visible)
113                 fl_hide_form(form());
114 }
115
116
117 void FormBase::InputCB(FL_OBJECT * ob, long data)
118 {
119         // It is possible to set the choice to 0 when using the
120         // keyboard shortcuts. This work-around deals with the problem.
121         if (ob && ob->objclass == FL_CHOICE && fl_get_choice(ob) < 1) {
122                 fl_set_choice(ob, 1);
123         }
124
125         bc().input(input(ob, data));
126 }
127
128
129 ButtonPolicy::SMInput FormBase::input(FL_OBJECT *, long)
130 {
131         return ButtonPolicy::SMI_VALID;
132 }
133
134
135 // preemptive handler for feedback messages
136 void FormBase::FeedbackCB(FL_OBJECT * ob, int event)
137 {
138         lyx::Assert(ob);
139
140         switch (event) {
141         case FL_ENTER:
142                 warning_posted_ = false;
143                 feedback(ob);
144                 break;
145
146         case FL_LEAVE:
147                 if (!warning_posted_)
148                         clear_feedback();
149                 break;
150
151         default:
152                 break;
153         }
154 }
155
156
157 void FormBase::setTooltipHandler(FL_OBJECT * ob)
158 {
159         tooltip_->activateTooltip(ob);
160 }
161
162
163 string FormBase::getTooltip(FL_OBJECT const * ob)
164 {
165         lyx::Assert(ob);
166
167         switch (tooltip_level_) {
168         case VERBOSE_TOOLTIP: 
169         {
170                 string str = getVerboseTooltip(ob);
171                 if (!str.empty())
172                         return formatted(_(str), 400);
173                 // else, fall through
174         }
175         
176         case MINIMAL_TOOLTIP:
177                 return getMinimalTooltip(ob);
178                 
179         case NO_TOOLTIP:
180         default:
181                 return string();
182         }
183         
184 }
185                 
186
187 /// Fill the tooltips chooser with the standard descriptions
188 void FormBase::fillTooltipChoice(FL_OBJECT * ob)
189 {
190         lyx::Assert(ob && ob->objclass == FL_CHOICE);
191
192         fl_clear_choice(ob);
193         fl_addto_choice(ob, _(" None | Normal | Verbose "));
194
195         switch(tooltip_level_){
196         case NO_TOOLTIP:
197                 fl_set_choice(ob, 1);
198                 break;
199         case MINIMAL_TOOLTIP:
200                 fl_set_choice(ob, 2);
201                 break;
202         case VERBOSE_TOOLTIP:
203                 fl_set_choice(ob, 3);
204                 break;
205         }
206 }
207
208
209 void FormBase::setTooltipLevel(FL_OBJECT * ob)
210 {
211         lyx::Assert(ob && ob->objclass == FL_CHOICE &&
212                     fl_get_choice_maxitems(ob) == 3);
213
214         switch(fl_get_choice(ob)){
215         case 1:
216                 tooltip_level_ = NO_TOOLTIP;
217                 break;
218         case 2:
219                 tooltip_level_ = MINIMAL_TOOLTIP;
220                 break;
221         case 3:
222                 tooltip_level_ = VERBOSE_TOOLTIP;
223                 break;
224         }
225 }
226
227
228 void FormBase::setPrehandler(FL_OBJECT * ob)
229 {
230         lyx::Assert(ob);
231         fl_set_object_prehandler(ob, C_FormBasePrehandler);
232 }
233
234
235 void FormBase::setWarningPosted(bool warning)
236 {
237         warning_posted_ = warning;
238 }
239
240
241 namespace {
242
243 FormBase * GetForm(FL_OBJECT * ob)
244 {
245         lyx::Assert(ob && ob->form && ob->form->u_vdata);
246         FormBase * pre = static_cast<FormBase *>(ob->form->u_vdata);
247         return pre;
248 }
249
250 } // namespace anon
251
252
253 extern "C" {
254
255 void C_FormBaseApplyCB(FL_OBJECT * ob, long)
256 {
257         GetForm(ob)->ApplyButton();
258 }
259
260
261 void C_FormBaseOKCB(FL_OBJECT * ob, long)
262 {
263         GetForm(ob)->OKButton();
264 }
265
266
267 void C_FormBaseCancelCB(FL_OBJECT * ob, long)
268 {
269         FormBase * form = GetForm(ob);
270         form->CancelButton();
271 }
272
273
274 void C_FormBaseRestoreCB(FL_OBJECT * ob, long)
275 {
276         GetForm(ob)->RestoreButton();
277 }
278
279
280 void C_FormBaseInputCB(FL_OBJECT * ob, long d)
281 {
282         GetForm(ob)->InputCB(ob, d);
283 }
284
285
286 static int C_FormBaseWMHideCB(FL_FORM * form, void *)
287 {
288         // Close the dialog cleanly, even if the WM is used to do so.
289         lyx::Assert(form && form->u_vdata);
290         FormBase * pre = static_cast<FormBase *>(form->u_vdata);
291         pre->CancelButton();
292         return FL_CANCEL;
293 }
294
295
296 static int C_FormBasePrehandler(FL_OBJECT * ob, int event,
297                                 FL_Coord, FL_Coord, int key, void *)
298 {
299         // Note that the return value is important in the pre-emptive handler.
300         // Don't return anything other than 0.
301         lyx::Assert(ob);
302
303         // Don't Assert this one, as it can happen quite naturally when things
304         // are being deleted in the d-tor.
305         //Assert(ob->form);
306         if (!ob->form) return 0;
307
308         FormBase * pre = static_cast<FormBase *>(ob->form->u_vdata);
309         if (!pre) return 0;
310
311         if (event == FL_PUSH && key == 2 && ob->objclass == FL_INPUT) {
312                 // Trigger an input event when pasting in an xforms input object
313                 // using the middle mouse button.
314                 pre->InputCB(ob, 0);
315
316         } else if (event == FL_ENTER || event == FL_LEAVE){
317                 // Post feedback as the mouse enters the object,
318                 // remove it as the mouse leaves.
319                 pre->FeedbackCB(ob, event);
320         }
321
322         return 0;
323 }
324  
325 } // extern "C"