]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBaseDeprecated.C
Fix broken tooltips.
[lyx.git] / src / frontends / xforms / FormBaseDeprecated.C
1 /**
2  * \file FormBaseDeprecated.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 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include "Dialogs.h"
18 #include "FormBaseDeprecated.h"
19 #include "xformsBC.h"
20 #include "xforms_resize.h"
21 #include "Tooltips.h"
22 #include FORMS_H_LOCATION
23
24 #include "lyxrc.h"
25
26 #include "frontends/LyXView.h"
27
28 #include "support/LAssert.h"
29 #include "support/filetools.h" //  LibFileSearch
30
31 #include <boost/bind.hpp>
32
33 extern "C" {
34
35 #if FL_VERSION > 0 || FL_REVISION >= 89
36 // This should be in forms.h but isn't
37 void fl_hide_tooltip();
38 #endif
39
40 // Callback function invoked by xforms when the dialog is closed by the
41 // window manager
42 static int C_WMHideCB(FL_FORM *, void *);
43
44 // Callback function invoked by the xforms pre- and post-handler routines
45 static int C_PrehandlerCB(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *);
46
47 } // extern "C"
48
49
50 FormBaseDeprecated::FormBaseDeprecated(LyXView & lv, Dialogs & d,
51                                        string const & t, bool allowResize)
52         : lv_(lv), d_(d), title_(t), icon_pixmap_(0), icon_mask_(0),
53           minw_(0), minh_(0), allow_resize_(allowResize),
54           tooltips_(new Tooltips())
55 {}
56
57
58 FormBaseDeprecated::~FormBaseDeprecated()
59 {
60         if (icon_pixmap_)
61                 XFreePixmap(fl_get_display(), icon_pixmap_);
62
63         delete tooltips_;
64 }
65
66
67 Tooltips & FormBaseDeprecated::tooltips()
68 {
69         return *tooltips_;
70 }
71
72
73 void FormBaseDeprecated::redraw()
74 {
75         if (form() && form()->visible)
76                 fl_redraw_form(form());
77 }
78
79
80 void FormBaseDeprecated::connect()
81 {
82         fl_set_form_minsize(form(), minw_, minh_);
83         r_ = d_.redrawGUI().connect(boost::bind(&FormBaseDeprecated::redraw, this));
84 }
85
86
87 void FormBaseDeprecated::disconnect()
88 {
89         h_.disconnect();
90         r_.disconnect();
91 }
92
93
94 void FormBaseDeprecated::prepare_to_show()
95 {
96         build();
97
98         double const scale = scale_to_fit_tabs(form());
99         if (scale > 1.001)
100                 scale_form(form(), scale);
101
102         bc().refresh();
103
104         // work around dumb xforms sizing bug
105         minw_ = form()->w;
106         minh_ = form()->h;
107
108         fl_set_form_atclose(form(), C_WMHideCB, 0);
109
110         // set the title for the minimized form
111         if (!lyxrc.dialogs_iconify_with_main)
112                 fl_winicontitle(form()->window, title_.c_str());
113
114         //  assign an icon to the form
115         string const iconname = LibFileSearch("images", "lyx", "xpm");
116         if (!iconname.empty()) {
117                 unsigned int w, h;
118                 icon_pixmap_ = fl_read_pixmapfile(fl_root,
119                                                   iconname.c_str(),
120                                                   &w,
121                                                   &h,
122                                                   &icon_mask_,
123                                                   0, 0, 0);
124                 fl_set_form_icon(form(), icon_pixmap_, icon_mask_);
125         }
126 }
127
128
129 void FormBaseDeprecated::show()
130 {
131         if (!form()) {
132                 prepare_to_show();
133         }
134
135         // make sure the form is up to date.
136         fl_freeze_form(form());
137         update();
138         fl_unfreeze_form(form());
139
140         if (form()->visible) {
141                 fl_raise_form(form());
142                 /* This XMapWindow() will hopefully ensure that
143                  * iconified dialogs are de-iconified. Mad props
144                  * out to those crazy Xlib guys for forgetting a
145                  * XDeiconifyWindow(). At least WindowMaker, when
146                  * being notified of the redirected MapRequest will
147                  * specifically de-iconify. From source, fvwm2 seems
148                  * to do the same.
149                  */
150                 XMapWindow(fl_get_display(), form()->window);
151         } else {
152                 connect();
153
154                 // calls to fl_set_form_minsize/maxsize apply only to the next
155                 // fl_show_form(), so this comes first.
156                 fl_set_form_minsize(form(), minw_, minh_);
157                 if (!allow_resize_)
158                         fl_set_form_maxsize(form(), minw_, minh_);
159
160                 string const maximize_title = "LyX: " + title_;
161                 int const iconify_policy =
162                         lyxrc.dialogs_iconify_with_main ? FL_TRANSIENT : 0;
163
164                 fl_show_form(form(),
165                              FL_PLACE_MOUSE | FL_FREE_SIZE,
166                              iconify_policy,
167                              maximize_title.c_str());
168         }
169 }
170
171
172 void FormBaseDeprecated::hide()
173 {
174 #if FL_VERSION > 0 || FL_REVISION >= 89
175         // Does no harm if none is visible and ensures that the tooltip form
176         // is hidden should the dialog be closed from the keyboard.
177         fl_hide_tooltip();
178 #endif
179
180         // xforms sometimes tries to process a hint-type MotionNotify, and
181         // use XQueryPointer, without verifying if the window still exists.
182         // So we try to clear out motion events in the queue before the
183         // DestroyNotify
184         XSync(fl_get_display(), false);
185
186         if (form() && form()->visible) {
187                 // some dialogs might do things to the form first
188                 // such as the nested tabfolder problem in Preferences
189                 disconnect();
190                 fl_hide_form(form());
191         }
192 }
193
194
195 void FormBaseDeprecated::setPrehandler(FL_OBJECT * ob)
196 {
197         lyx::Assert(ob);
198         fl_set_object_prehandler(ob, C_PrehandlerCB);
199 }
200
201
202 void FormBaseDeprecated::WMHideCB()
203 {
204         hide();
205         bc().hide();
206 }
207
208
209 void FormBaseDeprecated::ApplyCB()
210 {
211         apply();
212         bc().apply();
213 }
214
215
216 void FormBaseDeprecated::OKCB()
217 {
218         ok();
219         bc().ok();
220 }
221
222
223 void FormBaseDeprecated::CancelCB()
224 {
225         cancel();
226         bc().cancel();
227 }
228
229
230 void FormBaseDeprecated::InputCB(FL_OBJECT * ob, long data)
231 {
232         // It is possible to set the choice to 0 when using the
233         // keyboard shortcuts. This work-around deals with the problem.
234         if (ob && ob->objclass == FL_CHOICE && fl_get_choice(ob) < 1) {
235                 fl_set_choice(ob, 1);
236         }
237
238         bc().valid(input(ob, data));
239 }
240
241
242 void FormBaseDeprecated::RestoreCB()
243 {
244         bc().restore();
245         restore();
246 }
247
248
249 FormBaseBI::FormBaseBI(LyXView & lv, Dialogs & d, string const & t,
250                        bool allowResize)
251         : FormBaseDeprecated(lv, d, t, allowResize)
252 {}
253
254
255 void FormBaseBI::connect()
256 {
257         h_ = d_.hideAll.connect(boost::bind(&FormBaseBI::hide, this));
258         FormBaseDeprecated::connect();
259 }
260
261
262 FormBaseBD::FormBaseBD(LyXView & lv, Dialogs & d, string const & t,
263                        bool allowResize)
264         : FormBaseDeprecated(lv, d, t, allowResize)
265 {}
266
267
268 void FormBaseBD::connect()
269 {
270         u_ = d_.updateBufferDependent.
271                 connect(boost::bind(&FormBaseBD::updateSlot, this, _1));
272         h_ = d_.hideBufferDependent.
273                 connect(boost::bind(&FormBaseBD::hide, this));
274         FormBaseDeprecated::connect();
275 }
276
277
278 void FormBaseBD::disconnect()
279 {
280         u_.disconnect();
281         FormBaseDeprecated::disconnect();
282 }
283
284
285 namespace {
286
287 FormBaseDeprecated * GetForm(FL_OBJECT * ob)
288 {
289         lyx::Assert(ob && ob->form && ob->form->u_vdata);
290         FormBaseDeprecated * ptr =
291                 static_cast<FormBaseDeprecated *>(ob->form->u_vdata);
292         return ptr;
293 }
294
295 } // namespace anon
296
297
298 extern "C" {
299
300 void C_FormBaseDeprecatedApplyCB(FL_OBJECT * ob, long)
301 {
302         GetForm(ob)->ApplyCB();
303 }
304
305
306 void C_FormBaseDeprecatedOKCB(FL_OBJECT * ob, long)
307 {
308         GetForm(ob)->OKCB();
309 }
310
311
312 void C_FormBaseDeprecatedCancelCB(FL_OBJECT * ob, long)
313 {
314         GetForm(ob)->CancelCB();
315 }
316
317
318 void C_FormBaseDeprecatedInputCB(FL_OBJECT * ob, long d)
319 {
320         GetForm(ob)->InputCB(ob, d);
321 }
322
323
324 void C_FormBaseDeprecatedRestoreCB(FL_OBJECT * ob, long)
325 {
326         GetForm(ob)->RestoreCB();
327 }
328
329 static int C_WMHideCB(FL_FORM * form, void *)
330 {
331         // Close the dialog cleanly, even if the WM is used to do so.
332         lyx::Assert(form && form->u_vdata);
333         FormBaseDeprecated * ptr =
334                 static_cast<FormBaseDeprecated *>(form->u_vdata);
335         ptr->WMHideCB();
336         return FL_CANCEL;
337 }
338
339 static int C_PrehandlerCB(FL_OBJECT * ob, int event,
340                           FL_Coord, FL_Coord, int key, void *)
341 {
342         // Note that the return value is important in the pre-emptive handler.
343         // Don't return anything other than 0.
344         lyx::Assert(ob);
345
346         // Don't Assert this one, as it can happen quite naturally when things
347         // are being deleted in the d-tor.
348         //Assert(ob->form);
349         if (!ob->form) return 0;
350
351         FormBaseDeprecated * ptr =
352                 static_cast<FormBaseDeprecated *>(ob->form->u_vdata);
353
354         if (ptr)
355                 ptr->PrehandlerCB(ob, event, key);
356
357         return 0;
358 }
359
360 } // extern "C"