]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormVSpace.C
Wrap most of the frontend code up inside namespace lyx::frontend.
[lyx.git] / src / frontends / xforms / FormVSpace.C
1 /**
2  * \file FormVSpace.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  * \author Jürgen Vigna
8  * \author Rob Lahaye
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "FormVSpace.h"
16 #include "ControlVSpace.h"
17 #include "forms/form_vspace.h"
18
19 #include "checkedwidgets.h"
20 #include "input_validators.h"
21 #include "Tooltips.h"
22 #include "xforms_helpers.h"
23 #include "xformsBC.h"
24
25 #include "controllers/helper_funcs.h"
26
27 #include "lyxrc.h" // to set the deafult length values
28 #include "Spacing.h"
29 #include "vspace.h"
30
31 #include "support/lstrings.h"
32 #include "support/tostr.h"
33
34 #include "lyx_forms.h"
35
36 #include <boost/bind.hpp>
37
38 using boost::bind;
39
40 using std::remove_if;
41
42 using std::vector;
43 using std::string;
44
45 namespace lyx {
46
47 using support::contains;
48 using support::getStringFromVector;
49 using support::rtrim;
50
51 namespace frontend {
52
53 namespace {
54
55 string defaultUnit("cm");
56
57 void validateVSpaceWidgets(FL_OBJECT * choice_type, FL_OBJECT * input_length)
58 {
59         // Paranoia check!
60         BOOST_ASSERT(choice_type  && choice_type->objclass  == FL_CHOICE &&
61                      input_length && input_length->objclass == FL_INPUT);
62
63         if (fl_get_choice(choice_type) != 6)
64                 return;
65
66         // If a vspace kind is "Length" but there's no text in
67         // the input field, insert nothing.
68         string const input = rtrim(getString(input_length));
69         if (input.empty())
70                 return;
71 }
72
73
74 VSpace const setVSpaceFromWidgets(FL_OBJECT * choice_type,
75                                   FL_OBJECT * input_length,
76                                   FL_OBJECT * choice_length,
77                                   bool keep)
78 {
79         // Paranoia check!
80         BOOST_ASSERT(choice_type   && choice_type->objclass   == FL_CHOICE &&
81                      input_length  && input_length->objclass  == FL_INPUT &&
82                      choice_length && choice_length->objclass == FL_CHOICE);
83
84         VSpace space;
85
86         switch (fl_get_choice(choice_type)) {
87         case 1:
88                 space = VSpace(VSpace::DEFSKIP);
89                 break;
90         case 2:
91                 space = VSpace(VSpace::SMALLSKIP);
92                 break;
93         case 3:
94                 space = VSpace(VSpace::MEDSKIP);
95                 break;
96         case 4:
97                 space = VSpace(VSpace::BIGSKIP);
98                 break;
99         case 5:
100                 space = VSpace(VSpace::VFILL);
101                 break;
102         case 6:
103                 space = VSpace(LyXGlueLength(
104                         getLengthFromWidgets(input_length, choice_length)));
105                 break;
106         }
107
108         space.setKeep(keep);
109         return space;
110 }
111
112
113 void setWidgetsFromVSpace(VSpace const & space,
114                           FL_OBJECT * choice_type,
115                           FL_OBJECT * input_length,
116                           FL_OBJECT * choice_length,
117                           FL_OBJECT * check_keep)
118 {
119         // Paranoia check!
120         BOOST_ASSERT(choice_type   && choice_type->objclass   == FL_CHOICE &&
121                      input_length  && input_length->objclass  == FL_INPUT &&
122                      choice_length && choice_length->objclass == FL_CHOICE &&
123                      check_keep    && check_keep->objclass   == FL_CHECKBUTTON);
124
125         int pos = 1;
126         switch (space.kind()) {
127         case VSpace::DEFSKIP:
128                 pos = 1;
129                 break;
130         case VSpace::SMALLSKIP:
131                 pos = 2;
132                 break;
133         case VSpace::MEDSKIP:
134                 pos = 3;
135                 break;
136         case VSpace::BIGSKIP:
137                 pos = 4;
138                 break;
139         case VSpace::VFILL:
140                 pos = 5;
141                 break;
142         case VSpace::LENGTH:
143                 pos = 6;
144                 break;
145         }
146         fl_set_choice(choice_type, pos);
147         fl_set_button(check_keep, space.keep());
148
149         bool const custom_vspace = space.kind() == VSpace::LENGTH;
150         if (custom_vspace) {
151                 string const length = space.length().asString();
152                 updateWidgetsFromLengthString(input_length, choice_length,
153                                               length, defaultUnit);
154         } else {
155                 fl_set_input(input_length, "");
156                 fl_set_choice_text(choice_length, defaultUnit.c_str());
157         }
158 }
159
160 } // namespace anon
161
162
163 typedef FormController<ControlVSpace, FormView<FD_vspace> > base_class;
164
165 FormVSpace::FormVSpace(Dialog & parent)
166         : base_class(parent, _("VSpace Settings"))
167 {}
168
169
170 void FormVSpace::build()
171 {
172         // the tabbed folder
173         dialog_.reset(build_vspace(this));
174
175         // Manage the ok, apply, restore and cancel/close buttons
176         bcview().setOK(dialog_->button_ok);
177         bcview().setApply(dialog_->button_apply);
178         bcview().setCancel(dialog_->button_close);
179         bcview().setRestore(dialog_->button_restore);
180
181         // disable for read-only documents
182         bcview().addReadOnly(dialog_->choice_space);
183         bcview().addReadOnly(dialog_->input_space);
184         bcview().addReadOnly(dialog_->choice_unit_space);
185
186         // check validity of "length + unit" input.
187         // If invalid, the label of input_space is displayed in red.
188         addCheckedGlueLength(bcview(),
189                              dialog_->input_space,
190                              dialog_->input_space);
191
192         // trigger an input event for cut&paste with middle mouse button.
193         setPrehandler(dialog_->input_space);
194
195         fl_set_input_return(dialog_->input_space, FL_RETURN_CHANGED);
196
197         string const spacing =
198                 _("DefSkip|SmallSkip|MedSkip|BigSkip|VFill|Length");
199         fl_addto_choice(dialog_->choice_space, spacing.c_str());
200
201         // Create the contents of the unit choices; don't include the "%" terms.
202         vector<string> units_vec = getLatexUnits();
203         vector<string>::iterator del =
204                 remove_if(units_vec.begin(), units_vec.end(),
205                           bind(contains<char>, _1, '%'));
206         units_vec.erase(del, units_vec.end());
207
208         string const units = getStringFromVector(units_vec, "|");
209         fl_addto_choice(dialog_->choice_unit_space, units.c_str());
210
211         // set up the tooltips
212         string str = _("Additional vertical space.");
213         tooltips().init(dialog_->choice_space, str);
214
215         // set default unit for custom length
216         switch (lyxrc.default_papersize) {
217         case PAPER_DEFAULT:
218         case PAPER_USLETTER:
219         case PAPER_LEGALPAPER:
220         case PAPER_EXECUTIVEPAPER:
221                 defaultUnit = "in";
222                 break;
223         case PAPER_A3PAPER:
224         case PAPER_A4PAPER:
225         case PAPER_A5PAPER:
226         case PAPER_B5PAPER:
227                 defaultUnit = "cm";
228                 break;
229         }
230 }
231
232
233 void FormVSpace::apply()
234 {
235         // If a vspace choice is "Length" but there's no text in
236         // the input field, insert nothing.
237         validateVSpaceWidgets(dialog_->choice_space, dialog_->input_space);
238
239         VSpace const space =
240                 setVSpaceFromWidgets(dialog_->choice_space,
241                                      dialog_->input_space,
242                                      dialog_->choice_unit_space,
243                                      fl_get_button(dialog_->check_keep));
244
245         controller().params() = space;
246 }
247
248
249 void FormVSpace::update()
250 {
251         setWidgetsFromVSpace(controller().params(),
252                              dialog_->choice_space,
253                              dialog_->input_space,
254                              dialog_->choice_unit_space,
255                              dialog_->check_keep);
256
257         bool const custom_length =
258                 fl_get_choice(dialog_->choice_space) == 6;
259         setEnabled(dialog_->input_space, custom_length);
260         setEnabled(dialog_->choice_unit_space, custom_length);
261 }
262
263
264 ButtonPolicy::SMInput FormVSpace::input(FL_OBJECT * ob, long)
265 {
266         // Enable input when custom length is chosen,
267         // disable 'keep' when no space is chosen
268         if (ob == dialog_->choice_space) {
269                 bool const custom_length =
270                         fl_get_choice(dialog_->choice_space) == 6;
271                 setEnabled(dialog_->input_space, custom_length);
272                 setEnabled(dialog_->choice_unit_space, custom_length);
273         }
274         return ButtonPolicy::SMI_VALID;
275 }
276
277 } // namespace frontend
278 } // namespace lyx