]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBase.C
Provide the framework for really easy feedback messages.
[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
24 extern "C" {
25
26 // Callback function invoked by xforms when the dialog is closed by the
27 // window manager
28 static int C_FormBaseWMHideCB(FL_FORM * form, void *);
29
30 // Use this to diaplay feedback messages or to trigger an input event on paste
31 // with the middle mouse button
32 static int C_FormBasePrehandler(FL_OBJECT * ob, int event,
33                                 FL_Coord, FL_Coord, int key, void *);
34
35 } // extern "C"
36
37
38 FormBase::FormBase(ControlButtons & c, string const & t, bool allowResize)
39         : ViewBC<xformsBC>(c), minw_(0), minh_(0), allow_resize_(allowResize),
40           title_(t), warning_posted_(false)
41
42 {}
43
44
45 void FormBase::redraw()
46 {
47         if (form() && form()->visible)
48                 fl_redraw_form(form());
49 }
50
51
52 void FormBase::show()
53 {
54         if (!form()) {
55                 build();
56         }
57
58         // use minw_ to flag whether the dialog has ever been shown
59         // (Needed now that build() is/should be called from the controller)
60         if (minw_ == 0) {
61                 bc().refresh();
62
63                 // work around dumb xforms sizing bug
64                 minw_ = form()->w;
65                 minh_ = form()->h;
66
67                 fl_set_form_atclose(form(), C_FormBaseWMHideCB, 0);
68         }
69
70         fl_freeze_form(form());
71         update();  // make sure its up-to-date
72         fl_unfreeze_form(form());
73
74         if (form()->visible) {
75                 fl_raise_form(form());
76                 /* This XMapWindow() will hopefully ensure that
77                  * iconified dialogs are de-iconified. Mad props
78                  * out to those crazy Xlib guys for forgetting a
79                  * XDeiconifyWindow(). At least WindowMaker, when
80                  * being notified of the redirected MapRequest will
81                  * specifically de-iconify. From source, fvwm2 seems
82                  * to do the same.
83                  */
84                 XMapWindow(fl_get_display(), form()->window);
85         } else {
86                 // calls to fl_set_form_minsize/maxsize apply only to the next
87                 // fl_show_form(), so this comes first.
88                 fl_set_form_minsize(form(), minw_, minh_);
89                 if (!allow_resize_)
90                         fl_set_form_maxsize(form(), minw_, minh_);
91
92                 fl_show_form(form(),
93                         FL_PLACE_MOUSE | FL_FREE_SIZE,
94                         (controller_.IconifyWithMain() ? FL_TRANSIENT : 0),
95                         title_.c_str());
96         }
97 }
98
99
100 void FormBase::hide()
101 {
102         if (form() && form()->visible)
103                 fl_hide_form(form());
104 }
105
106
107 void FormBase::InputCB(FL_OBJECT * ob, long data)
108 {
109         // It is possible to set the choice to 0 when using the
110         // keyboard shortcuts. This work-around deals with the problem.
111         if (ob && ob->objclass == FL_CHOICE && fl_get_choice(ob) < 1) {
112                 fl_set_choice(ob, 1);
113         }
114
115         bc().input(input(ob, data));
116 }
117
118
119 ButtonPolicy::SMInput FormBase::input(FL_OBJECT *, long)
120 {
121         return ButtonPolicy::SMI_VALID;
122 }
123
124
125 // preemptive handler for feedback messages
126 void FormBase::FeedbackCB(FL_OBJECT * ob, int event)
127 {
128         lyx::Assert(ob);
129
130         switch (event) {
131         case FL_ENTER:
132                 warning_posted_ = false;
133                 feedback(ob);
134                 break;
135
136         case FL_LEAVE:
137                 if (!warning_posted_)
138                         clear_feedback();
139                 break;
140
141         default:
142                 break;
143         }
144 }
145
146
147 void FormBase::setPrehandler(FL_OBJECT * ob)
148 {
149         lyx::Assert(ob);
150         fl_set_object_prehandler(ob, C_FormBasePrehandler);
151 }
152
153
154 void FormBase::setWarningPosted(bool warning)
155 {
156         warning_posted_ = warning;
157 }
158
159
160 namespace {
161
162 FormBase * GetForm(FL_OBJECT * ob)
163 {
164         lyx::Assert(ob && ob->form && ob->form->u_vdata);
165         FormBase * pre = static_cast<FormBase *>(ob->form->u_vdata);
166         return pre;
167 }
168
169 } // namespace anon
170
171
172 extern "C" {
173
174 static int C_FormBaseWMHideCB(FL_FORM * form, void *)
175 {
176         // Close the dialog cleanly, even if the WM is used to do so.
177         lyx::Assert(form && form->u_vdata);
178         FormBase * pre = static_cast<FormBase *>(form->u_vdata);
179         pre->CancelButton();
180         return FL_CANCEL;
181 }
182
183
184 void C_FormBaseApplyCB(FL_OBJECT * ob, long)
185 {
186         GetForm(ob)->ApplyButton();
187 }
188
189
190 void C_FormBaseOKCB(FL_OBJECT * ob, long)
191 {
192         GetForm(ob)->OKButton();
193 }
194
195
196 void C_FormBaseCancelCB(FL_OBJECT * ob, long)
197 {
198         FormBase * form = GetForm(ob);
199         form->CancelButton();
200 }
201
202
203 void C_FormBaseRestoreCB(FL_OBJECT * ob, long)
204 {
205         GetForm(ob)->RestoreButton();
206 }
207
208
209 void C_FormBaseInputCB(FL_OBJECT * ob, long d)
210 {
211         GetForm(ob)->InputCB(ob, d);
212 }
213
214
215 static int C_FormBasePrehandler(FL_OBJECT * ob, int event,
216                                 FL_Coord, FL_Coord, int key, void *)
217 {
218         // Note that the return value is important in the pre-emptive handler.
219         // Don't return anything other than 0.
220         lyx::Assert(ob);
221
222         // Don't Assert this one, as it can happen quite naturally when things
223         // are being deleted in the d-tor.
224         //Assert(ob->form);
225         if (!ob->form) return 0;
226
227         FormBase * pre = static_cast<FormBase *>(ob->form->u_vdata);
228         if (!pre) return 0;
229
230         if (event == FL_PUSH && key == 2 && ob->objclass == FL_INPUT) {
231                 // Trigger an input event when pasting in an xforms input object
232                 // using the middle mouse button.
233                 pre->InputCB(ob, 0);
234
235         } else if (event == FL_ENTER || event == FL_LEAVE){
236                 // Post feedback as the mouse enters the object,
237                 // remove it as the mouse leaves.
238                 pre->FeedbackCB(ob, event);
239         }
240
241         return 0;
242 }
243         
244 } // extern "C"