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