]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormParagraph.C
0fc651e5c3989e72a10729e150bb2267a84b0214
[lyx.git] / src / frontends / xforms / FormParagraph.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 2000-2001 The LyX Team.
7  *
8  *           @author Jürgen Vigna
9  *
10  *======================================================*/
11
12 #include <config.h>
13
14 #ifdef __GNUG_
15 #pragma implementation
16 #endif
17
18 #include FORMS_H_LOCATION
19
20 #include "FormParagraph.h"
21 #include "form_paragraph.h"
22 #include "Dialogs.h"
23 #include "Liason.h"
24 #include "LyXView.h"
25 #include "buffer.h"
26 #include "lyxtext.h"
27 #include "xforms_helpers.h"
28 #include "lyxrc.h" // to set the deafult length values
29 #include "BufferView.h"
30 #include "lyxtextclasslist.h"
31 #include "Spacing.h"
32 #include "ParagraphParameters.h"
33 #include "input_validators.h"
34 #include "helper_funcs.h"
35
36 #include "support/lstrings.h" 
37
38 using Liason::setMinibuffer;
39 using SigC::slot;
40
41
42 FormParagraph::FormParagraph(LyXView * lv, Dialogs * d)
43         : FormBaseBD(lv, d, _("Paragraph Layout")), par_(0)
44 {
45     // let the dialog be shown
46     // This is a permanent connection so we won't bother
47     // storing a copy because we won't be disconnecting.
48     d->showParagraph.connect(slot(this, &FormParagraph::show));
49 }
50
51
52 void FormParagraph::connect()
53 {
54         cp_ = d_->updateParagraph
55                 .connect(slot(this, &FormParagraph::changedParagraph));
56         FormBaseBD::connect();
57 }
58
59
60 void FormParagraph::disconnect()
61 {
62         cp_.disconnect();
63         FormBaseBD::disconnect();
64 }
65
66
67 Paragraph const * FormParagraph::getCurrentParagraph() const
68 {
69         return lv_->view()->getLyXText()->cursor.par();
70 }
71
72
73 void FormParagraph::changedParagraph()
74 {
75         /// Record the paragraph
76         Paragraph const * const p = getCurrentParagraph();
77         if (p == 0 || p == par_)
78                 return;
79 #ifdef WITH_WARNINGS
80 #warning Please someone of you GUII people have a look at this!
81 #endif
82         // shouldn't we chage the par_ pointer too?
83         // anyway for me the below function does just nothing!
84         // (Jug 20020108)
85
86         // For now don't bother checking if the params are different,
87         // just activate the Apply button
88         bc().valid();
89 }
90
91
92 void FormParagraph::redraw()
93 {
94         if( form() && form()->visible )
95                 fl_redraw_form( form() );
96 }
97
98
99 FL_FORM * FormParagraph::form() const
100 {
101     if (dialog_.get()) return dialog_->form;
102     return 0;
103 }
104
105
106 void FormParagraph::build()
107 {
108     // the tabbed folder
109     dialog_.reset(build_paragraph());
110
111     fl_addto_choice(dialog_->choice_space_above,
112                     _(" None | Defskip | Smallskip "
113                       "| Medskip | Bigskip | VFill | Length "));
114     fl_addto_choice(dialog_->choice_space_below,
115                     _(" None | Defskip | Smallskip "
116                       "| Medskip | Bigskip | VFill | Length ")); 
117
118     fl_addto_choice(dialog_->choice_linespacing,
119                     _(" Default | Single | OneHalf | Double | Other "));
120  
121     fl_set_input_return(dialog_->input_space_above, FL_RETURN_CHANGED);
122     fl_set_input_return(dialog_->input_space_below, FL_RETURN_CHANGED);
123     fl_set_input_return(dialog_->input_labelwidth, FL_RETURN_CHANGED);
124     fl_set_input_return(dialog_->input_linespacing, FL_RETURN_CHANGED);
125     fl_set_input_filter(dialog_->input_linespacing, fl_unsigned_float_filter);
126     fl_set_input_filter(dialog_->input_space_above, fl_float_filter);
127     fl_set_input_filter(dialog_->input_space_below, fl_float_filter);
128
129     // Create the contents of the unit choices
130     // Don't include the "%" terms...
131     std::vector<string> units_vec = getLatexUnits();
132     for (std::vector<string>::iterator it = units_vec.begin();
133        it != units_vec.end(); ++it) {
134        if (contains(*it, "%"))
135                it = units_vec.erase(it, it+1) - 1;
136     }
137     string units = getStringFromVector(units_vec, "|");
138
139     fl_addto_choice(dialog_->choice_value_space_above,  units.c_str());
140     fl_addto_choice(dialog_->choice_value_space_below, units.c_str());
141
142     // Manage the ok, apply, restore and cancel/close buttons
143     bc_.setOK(dialog_->button_ok);
144     bc_.setApply(dialog_->button_apply);
145     bc_.setCancel(dialog_->button_cancel);
146     bc_.setRestore(dialog_->button_restore);
147
148     bc_.addReadOnly (dialog_->group_radio_alignment);
149     // bc_.addReadOnly (dialog_->radio_align_right);
150     // bc_.addReadOnly (dialog_->radio_align_left);
151     // bc_.addReadOnly (dialog_->radio_align_block);
152     // bc_.addReadOnly (dialog_->radio_align_center);
153     bc_.addReadOnly (dialog_->check_lines_top);
154     bc_.addReadOnly (dialog_->check_lines_bottom);
155     bc_.addReadOnly (dialog_->check_pagebreaks_top);
156     bc_.addReadOnly (dialog_->check_pagebreaks_bottom);
157     bc_.addReadOnly (dialog_->choice_space_above);
158     bc_.addReadOnly (dialog_->input_space_above);
159     bc_.addReadOnly (dialog_->check_space_above);
160     bc_.addReadOnly (dialog_->choice_space_below);
161     bc_.addReadOnly (dialog_->input_space_below);
162     bc_.addReadOnly (dialog_->check_space_below);
163     bc_.addReadOnly (dialog_->choice_linespacing);
164     bc_.addReadOnly (dialog_->input_linespacing); 
165     bc_.addReadOnly (dialog_->check_noindent);
166     bc_.addReadOnly (dialog_->input_labelwidth);
167 }
168
169
170 void FormParagraph::apply()
171 {
172     if (!lv_->view()->available() || !dialog_.get())
173         return;
174
175     VSpace space_top, space_bottom;
176     LyXAlignment align;
177     string labelwidthstring;
178     bool noindent;
179
180     // If a vspace kind is "Length" but there's no text in
181     // the input field, reset the kind to "None". 
182     if ((fl_get_choice (dialog_->choice_space_above) == 7) &&
183         !*(fl_get_input (dialog_->input_space_above)))
184     {
185         fl_set_choice (dialog_->choice_space_above, 1);
186     }
187     if ((fl_get_choice (dialog_->choice_space_below) == 7) &&
188         !*(fl_get_input (dialog_->input_space_below)))
189     {
190         fl_set_choice (dialog_->choice_space_below, 1);
191     }
192    
193     bool line_top = fl_get_button(dialog_->check_lines_top);
194     bool line_bottom = fl_get_button(dialog_->check_lines_bottom);
195     bool pagebreak_top = fl_get_button(dialog_->check_pagebreaks_top);
196     bool pagebreak_bottom = fl_get_button(dialog_->check_pagebreaks_bottom);
197     
198     switch (fl_get_choice (dialog_->choice_space_above)) {
199     case 1:
200         space_top = VSpace(VSpace::NONE);
201         break;
202     case 2:
203         space_top = VSpace(VSpace::DEFSKIP);
204         break;
205     case 3:
206         space_top = VSpace(VSpace::SMALLSKIP);
207         break;
208     case 4:
209         space_top = VSpace(VSpace::MEDSKIP);
210         break;
211     case 5:
212         space_top = VSpace(VSpace::BIGSKIP);
213         break;
214     case 6:
215         space_top = VSpace(VSpace::VFILL);
216         break;
217     case 7:
218     {
219             string const length =
220                     getLengthFromWidgets(dialog_->input_space_above,
221                                          dialog_->choice_value_space_above);
222         space_top =
223                 VSpace(LyXGlueLength(length));
224         break;
225     }
226     }
227
228     if (fl_get_button (dialog_->check_space_above))
229         space_top.setKeep (true);
230     switch (fl_get_choice (dialog_->choice_space_below)) {
231     case 1:
232         space_bottom = VSpace(VSpace::NONE);
233         break;
234     case 2:
235         space_bottom = VSpace(VSpace::DEFSKIP);
236         break;
237     case 3:
238         space_bottom = VSpace(VSpace::SMALLSKIP);
239         break;
240     case 4:
241         space_bottom = VSpace(VSpace::MEDSKIP);
242         break;
243     case 5:
244         space_bottom = VSpace(VSpace::BIGSKIP);
245         break;
246     case 6:
247         space_bottom = VSpace(VSpace::VFILL);
248         break;
249     case 7:
250         string const length =
251                 getLengthFromWidgets(dialog_->input_space_below,
252                 dialog_->choice_value_space_below);
253         space_bottom = VSpace(LyXGlueLength(length));
254         break;
255     }
256     if (fl_get_button (dialog_->check_space_below))
257         space_bottom.setKeep (true);
258
259     if (fl_get_button(dialog_->radio_align_left))
260         align = LYX_ALIGN_LEFT;
261     else if (fl_get_button(dialog_->radio_align_right))
262         align = LYX_ALIGN_RIGHT;
263     else if (fl_get_button(dialog_->radio_align_center))
264         align = LYX_ALIGN_CENTER;
265     else 
266         align = LYX_ALIGN_BLOCK;
267    
268     labelwidthstring = fl_get_input(dialog_->input_labelwidth);
269     noindent = fl_get_button(dialog_->check_noindent);
270     Spacing::Space linespacing = Spacing::Default;
271     string other_linespacing;
272     switch (fl_get_choice(dialog_->choice_linespacing)) {
273         case 1: linespacing = Spacing::Default; break;
274         case 2: linespacing = Spacing::Single; break;
275         case 3: linespacing = Spacing::Onehalf; break;
276         case 4: linespacing = Spacing::Double; break;
277         case 5:
278             linespacing = Spacing::Other;
279             other_linespacing = fl_get_input(dialog_->input_linespacing);
280             break;
281     }
282
283     Spacing const spacing(linespacing, other_linespacing);
284     LyXText * text(lv_->view()->getLyXText());
285     text->setParagraph(lv_->view(), line_top, line_bottom, pagebreak_top,
286                        pagebreak_bottom, space_top, space_bottom, spacing,
287                        align, labelwidthstring, noindent);
288
289
290     // Actually apply these settings
291     lv_->view()->update(text, 
292                         BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
293     lv_->buffer()->markDirty();
294     setMinibuffer(lv_, _("Paragraph layout set"));
295 }
296
297
298 void FormParagraph::update()
299 {
300     if (!dialog_.get())
301         return;
302
303     // Do this first; some objects may be de/activated subsequently.
304     bc_.readOnly(lv_->buffer()->isReadonly());
305
306     Buffer * buf = lv_->view()->buffer();
307
308     /// Record the paragraph
309     par_ = getCurrentParagraph();
310
311     fl_set_input(dialog_->input_labelwidth,
312                  par_->getLabelWidthString().c_str());
313     setEnabled(dialog_->input_labelwidth,
314                (par_->getLabelWidthString() != _("Senseless with this layout!")));
315
316     fl_set_button(dialog_->radio_align_right, 0);
317     fl_set_button(dialog_->radio_align_left, 0);
318     fl_set_button(dialog_->radio_align_center, 0);
319     fl_set_button(dialog_->radio_align_block, 0);
320
321     int align = par_->getAlign();
322     if (align == LYX_ALIGN_LAYOUT)
323         align = textclasslist.Style(buf->params.textclass,
324                                     par_->getLayout()).align;
325
326     switch (align) {
327     case LYX_ALIGN_RIGHT:
328         fl_set_button(dialog_->radio_align_right, 1);
329         break;
330     case LYX_ALIGN_LEFT:
331         fl_set_button(dialog_->radio_align_left, 1);
332         break;
333     case LYX_ALIGN_CENTER:
334         fl_set_button(dialog_->radio_align_center, 1);
335         break;
336     default:
337         fl_set_button(dialog_->radio_align_block, 1);
338         break;
339     }
340
341     LyXAlignment alignpos =
342             textclasslist.Style(buf->params.textclass,
343                                 par_->getLayout()).alignpossible;
344
345     setEnabled(dialog_->radio_align_block,  bool(alignpos & LYX_ALIGN_BLOCK));
346     setEnabled(dialog_->radio_align_center, bool(alignpos & LYX_ALIGN_CENTER));
347     setEnabled(dialog_->radio_align_left,   bool(alignpos & LYX_ALIGN_LEFT));
348     setEnabled(dialog_->radio_align_right,  bool(alignpos & LYX_ALIGN_RIGHT));
349     
350     // no inset-text-owned paragraph may have pagebreaks
351     setEnabled(dialog_->check_pagebreaks_top, !par_->inInset());
352     setEnabled(dialog_->check_pagebreaks_bottom, !par_->inInset());
353
354     fl_set_button(dialog_->check_lines_top,
355                   par_->params().lineTop());
356     fl_set_button(dialog_->check_lines_bottom,
357                   par_->params().lineBottom());
358     fl_set_button(dialog_->check_pagebreaks_top,
359                   par_->params().pagebreakTop());
360     fl_set_button(dialog_->check_pagebreaks_bottom,
361                   par_->params().pagebreakBottom());
362     fl_set_button(dialog_->check_noindent,
363                   par_->params().noindent());
364
365     int linespacing;
366     Spacing const space = par_->params().spacing();
367
368     switch (space.getSpace()) {
369         default: linespacing = 1; break;
370         case Spacing::Single: linespacing = 2; break;
371         case Spacing::Onehalf: linespacing = 3; break;
372         case Spacing::Double: linespacing = 4; break;
373         case Spacing::Other: linespacing = 5; break;
374     }
375  
376     fl_set_choice(dialog_->choice_linespacing, linespacing);
377     if (space.getSpace() == Spacing::Other) {
378         string const sp = tostr(space.getValue());
379         fl_set_input(dialog_->input_linespacing, sp.c_str());
380         setEnabled(dialog_->input_linespacing, true);
381     } else {
382         fl_set_input(dialog_->input_linespacing, "");
383         setEnabled(dialog_->input_linespacing, false);
384     }
385
386     fl_set_input (dialog_->input_space_above, "");
387
388     setEnabled(dialog_->input_space_above, false);
389     setEnabled(dialog_->choice_value_space_above, false);
390     switch (par_->params().spaceTop().kind()) {
391     case VSpace::NONE:
392         fl_set_choice (dialog_->choice_space_above, 1);
393         break;
394     case VSpace::DEFSKIP:
395         fl_set_choice (dialog_->choice_space_above, 2);
396         break;
397     case VSpace::SMALLSKIP:
398         fl_set_choice (dialog_->choice_space_above, 3);
399         break;
400     case VSpace::MEDSKIP:
401         fl_set_choice (dialog_->choice_space_above, 4);
402         break;
403     case VSpace::BIGSKIP:
404         fl_set_choice (dialog_->choice_space_above, 5);
405         break;
406     case VSpace::VFILL:
407         fl_set_choice (dialog_->choice_space_above, 6);
408         break;
409     case VSpace::LENGTH:
410     {
411         fl_set_choice (dialog_->choice_space_above, 7);
412         setEnabled(dialog_->input_space_above, true);
413         setEnabled(dialog_->choice_value_space_above, true);
414         bool const metric = lyxrc.default_papersize > 3;
415         string const default_unit = metric ? "cm" : "in";
416         string const length = par_->params().spaceTop().length().asString();
417         updateWidgetsFromLengthString(dialog_->input_space_above,
418                           dialog_->choice_value_space_above,
419                           length, default_unit);
420             break;
421     }
422     }
423     
424     fl_set_button (dialog_->check_space_above,
425            par_->params().spaceTop().keep());
426     fl_set_input (dialog_->input_space_below, "");
427
428     setEnabled(dialog_->input_space_below, false);
429     setEnabled(dialog_->choice_value_space_below, false);
430     switch (par_->params().spaceBottom().kind()) {
431     case VSpace::NONE:
432         fl_set_choice (dialog_->choice_space_below, 1);
433         break;
434     case VSpace::DEFSKIP:
435         fl_set_choice (dialog_->choice_space_below, 2);
436         break;
437     case VSpace::SMALLSKIP:
438         fl_set_choice (dialog_->choice_space_below, 3);
439         break;
440     case VSpace::MEDSKIP:
441         fl_set_choice (dialog_->choice_space_below, 4);
442         break;
443     case VSpace::BIGSKIP:
444         fl_set_choice (dialog_->choice_space_below, 5);
445         break;
446     case VSpace::VFILL:
447         fl_set_choice (dialog_->choice_space_below, 6);
448         break;
449     case VSpace::LENGTH:
450     {
451         fl_set_choice (dialog_->choice_space_below, 7);
452         setEnabled(dialog_->input_space_below, true);
453         setEnabled(dialog_->choice_value_space_below, true);
454         bool const metric = lyxrc.default_papersize > 3;
455         string const default_unit = metric ? "cm" : "in";
456         string const length =
457                 par_->params().spaceBottom().length().asString();
458         updateWidgetsFromLengthString(dialog_->input_space_below,
459                           dialog_->choice_value_space_below,
460                           length, default_unit);
461             break;
462     }
463     }
464
465     fl_set_button(dialog_->check_space_below,
466                   par_->params().spaceBottom().keep());
467     fl_set_button(dialog_->check_noindent,
468                   par_->params().noindent());
469 }
470
471
472 bool FormParagraph::input(FL_OBJECT * ob, long)
473 {
474     bool valid = true; 
475
476     fl_hide_object(dialog_->text_warning);
477
478     // First check the buttons which are exclusive and you have to
479     // check only the actuall de/activated button.
480     //
481     // "Synchronize" the choices and input fields, making it
482     // impossible to commit senseless data.
483
484     if (ob == dialog_->choice_space_above) {
485         if (fl_get_choice (dialog_->choice_space_above) != 7) {
486             fl_set_input (dialog_->input_space_above, "");
487             setEnabled (dialog_->input_space_above, false);
488             setEnabled (dialog_->choice_value_space_above, false);
489         } else {
490             setEnabled (dialog_->input_space_above, !lv_->buffer()->isReadonly());
491             setEnabled (dialog_->choice_value_space_above, !lv_->buffer()->isReadonly());
492             bool const metric = lyxrc.default_papersize > 3;
493             int const default_unit = metric ? 8 : 9;
494             if (strip(fl_get_input(dialog_->input_space_above)).empty())
495                 fl_set_choice(dialog_->choice_value_space_above,
496                               default_unit);
497         }
498     }
499     if (ob == dialog_->choice_space_below) {
500         if (fl_get_choice (dialog_->choice_space_below) != 7) {
501             fl_set_input (dialog_->input_space_below, "");
502             setEnabled (dialog_->input_space_below, false);
503             setEnabled (dialog_->choice_value_space_below, false);
504         } else {
505             setEnabled (dialog_->input_space_below, !lv_->buffer()->isReadonly());
506             setEnabled (dialog_->choice_value_space_below, !lv_->buffer()->isReadonly());
507             bool const metric = lyxrc.default_papersize > 3;
508             int const default_unit = metric ? 8 : 9;
509             if (strip(fl_get_input(dialog_->input_space_below)).empty())
510                     fl_set_choice(dialog_->choice_value_space_below,
511                                   default_unit);
512         }
513     }
514  
515     if (fl_get_choice (dialog_->choice_linespacing) == 5)
516         setEnabled (dialog_->input_linespacing, true);
517     else {
518         setEnabled (dialog_->input_linespacing, false);
519         fl_set_input (dialog_->input_linespacing, "");
520     }
521
522     double spacing(strToDbl(fl_get_input(dialog_->input_linespacing)));
523
524     if (fl_get_choice (dialog_->choice_linespacing) == 5
525         && int(spacing) == 0)
526         valid = false;
527
528     return valid;
529 }