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