1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 2000 The LyX Team.
10 *======================================================*/
15 #pragma implementation
18 #include FORMS_H_LOCATION
20 #include "FormParagraph.h"
21 #include "form_paragraph.h"
27 #include "xforms_helpers.h"
29 #include "lyxparagraph.h"
32 using Liason::setMinibuffer;
34 FormParagraph::FormParagraph(LyXView * lv, Dialogs * d)
35 : FormBaseBD(lv, d, _("Paragraph Layout"))
37 // let the popup be shown
38 // This is a permanent connection so we won't bother
39 // storing a copy because we won't be disconnecting.
40 d->showLayoutParagraph.connect(slot(this, &FormParagraph::show));
44 void FormParagraph::redraw()
46 if( form() && form()->visible )
47 fl_redraw_form( form() );
51 FL_FORM * outer_form = fl_get_active_folder(dialog_->tabbed_folder);
52 if (outer_form && outer_form->visible)
53 fl_redraw_form( outer_form );
57 FL_FORM * FormParagraph::form() const
59 if (dialog_.get()) return dialog_->form;
64 void FormParagraph::build()
67 dialog_.reset(build_tabbed_paragraph());
69 // Workaround dumb xforms sizing bug
73 // Manage the ok, apply, restore and cancel/close buttons
74 bc_.setOK(dialog_->button_ok);
75 bc_.setApply(dialog_->button_apply);
76 bc_.setCancel(dialog_->button_cancel);
77 bc_.setUndoAll(dialog_->button_restore);
80 // the general paragraph data form
81 general_.reset(build_paragraph_general());
83 fl_addto_choice(general_->choice_space_above,
84 _(" None | Defskip | Smallskip "
85 "| Medskip | Bigskip | VFill | Length "));
86 fl_addto_choice(general_->choice_space_below,
87 _(" None | Defskip | Smallskip "
88 "| Medskip | Bigskip | VFill | Length "));
90 fl_set_input_return(general_->input_space_above, FL_RETURN_CHANGED);
91 fl_set_input_return(general_->input_space_below, FL_RETURN_CHANGED);
92 fl_set_input_return(general_->input_labelwidth, FL_RETURN_CHANGED);
94 bc_.addReadOnly (general_->radio_align_right);
95 bc_.addReadOnly (general_->radio_align_left);
96 bc_.addReadOnly (general_->radio_align_block);
97 bc_.addReadOnly (general_->radio_align_center);
98 bc_.addReadOnly (general_->check_lines_top);
99 bc_.addReadOnly (general_->check_lines_bottom);
100 bc_.addReadOnly (general_->check_pagebreaks_top);
101 bc_.addReadOnly (general_->check_pagebreaks_bottom);
102 bc_.addReadOnly (general_->choice_space_above);
103 bc_.addReadOnly (general_->input_space_above);
104 bc_.addReadOnly (general_->check_space_above);
105 bc_.addReadOnly (general_->choice_space_below);
106 bc_.addReadOnly (general_->input_space_below);
107 bc_.addReadOnly (general_->check_space_below);
108 bc_.addReadOnly (general_->check_noindent);
109 bc_.addReadOnly (general_->input_labelwidth);
112 // the document class form
113 extra_.reset(build_paragraph_extra());
115 fl_set_input_return(extra_->input_pextra_width, FL_RETURN_CHANGED);
116 fl_set_input_return(extra_->input_pextra_widthp, FL_RETURN_CHANGED);
118 bc_.addReadOnly (extra_->radio_pextra_indent);
119 bc_.addReadOnly (extra_->radio_pextra_minipage);
120 bc_.addReadOnly (extra_->radio_pextra_floatflt);
121 bc_.addReadOnly (extra_->radio_pextra_hfill);
122 bc_.addReadOnly (extra_->radio_pextra_startmp);
125 // now make them fit together
126 fl_addto_tabfolder(dialog_->tabbed_folder,_("General"), general_->form);
128 fl_addto_tabfolder(dialog_->tabbed_folder,_("Extra"), extra_->form);
133 void FormParagraph::apply()
135 if (!lv_->view()->available() || !dialog_.get())
143 lv_->view()->update(lv_->view()->text,
144 BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
145 lv_->buffer()->markDirty();
146 setMinibuffer(lv_, _("Paragraph layout set"));
150 void FormParagraph::update()
159 bc_.readOnly(lv_->buffer()->isReadonly());
163 void FormParagraph::general_apply()
165 VSpace space_top, space_bottom;
167 string labelwidthstring;
170 // If a vspace kind is "Length" but there's no text in
171 // the input field, reset the kind to "None".
172 if ((fl_get_choice (general_->choice_space_above) == 7) &&
173 !*(fl_get_input (general_->input_space_above)))
175 fl_set_choice (general_->choice_space_above, 1);
177 if ((fl_get_choice (general_->choice_space_below) == 7) &&
178 !*(fl_get_input (general_->input_space_below)))
180 fl_set_choice (general_->choice_space_below, 1);
183 bool line_top = fl_get_button(general_->check_lines_top);
184 bool line_bottom = fl_get_button(general_->check_lines_bottom);
185 bool pagebreak_top = fl_get_button(general_->check_pagebreaks_top);
186 bool pagebreak_bottom = fl_get_button(general_->check_pagebreaks_bottom);
188 switch (fl_get_choice (general_->choice_space_above)) {
190 space_top = VSpace(VSpace::NONE);
193 space_top = VSpace(VSpace::DEFSKIP);
196 space_top = VSpace(VSpace::SMALLSKIP);
199 space_top = VSpace(VSpace::MEDSKIP);
202 space_top = VSpace(VSpace::BIGSKIP);
205 space_top = VSpace(VSpace::VFILL);
209 VSpace(LyXGlueLength(fl_get_input(general_->input_space_above)));
212 if (fl_get_button (general_->check_space_above))
213 space_top.setKeep (true);
214 switch (fl_get_choice (general_->choice_space_below)) {
216 space_bottom = VSpace(VSpace::NONE);
219 space_bottom = VSpace(VSpace::DEFSKIP);
222 space_bottom = VSpace(VSpace::SMALLSKIP);
225 space_bottom = VSpace(VSpace::MEDSKIP);
228 space_bottom = VSpace(VSpace::BIGSKIP);
231 space_bottom = VSpace(VSpace::VFILL);
235 VSpace(LyXGlueLength(fl_get_input(general_->input_space_below)));
238 if (fl_get_button (general_->check_space_below))
239 space_bottom.setKeep (true);
241 if (fl_get_button(general_->radio_align_left))
242 align = LYX_ALIGN_LEFT;
243 else if (fl_get_button(general_->radio_align_right))
244 align = LYX_ALIGN_RIGHT;
245 else if (fl_get_button(general_->radio_align_center))
246 align = LYX_ALIGN_CENTER;
248 align = LYX_ALIGN_BLOCK;
250 labelwidthstring = fl_get_input(general_->input_labelwidth);
251 noindent = fl_get_button(general_->check_noindent);
254 if (lv_->view()->theLockingInset())
255 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
257 text = lv_->view()->text;
258 text->SetParagraph(lv_->view(), line_top, line_bottom, pagebreak_top,
259 pagebreak_bottom, space_top, space_bottom, align,
260 labelwidthstring, noindent);
265 void FormParagraph::extra_apply()
267 char const * width = fl_get_input(extra_->input_pextra_width);
268 char const * widthp = fl_get_input(extra_->input_pextra_widthp);
269 LyXText * text = lv_->view()->text;
270 int type = LyXParagraph::PEXTRA_NONE;
271 LyXParagraph::MINIPAGE_ALIGNMENT
272 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
275 start_minipage = false;
277 if (fl_get_button(extra_->radio_pextra_indent)) {
278 type = LyXParagraph::PEXTRA_INDENT;
279 } else if (fl_get_button(extra_->radio_pextra_minipage)) {
280 type = LyXParagraph::PEXTRA_MINIPAGE;
281 hfill = fl_get_button(extra_->radio_pextra_hfill);
282 start_minipage = fl_get_button(extra_->radio_pextra_startmp);
283 if (fl_get_button(extra_->radio_pextra_top))
284 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
285 else if (fl_get_button(extra_->radio_pextra_middle))
286 alignment = LyXParagraph::MINIPAGE_ALIGN_MIDDLE;
287 else if (fl_get_button(extra_->radio_pextra_bottom))
288 alignment = LyXParagraph::MINIPAGE_ALIGN_BOTTOM;
289 } else if (fl_get_button(extra_->radio_pextra_floatflt)) {
290 type = LyXParagraph::PEXTRA_FLOATFLT;
292 text->SetParagraphExtraOpt(lv_->view(), type, width, widthp, alignment,
293 hfill, start_minipage);
298 void FormParagraph::general_update()
303 Buffer * buf = lv_->view()->buffer();
306 if (lv_->view()->theLockingInset())
307 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
309 text = lv_->view()->text;
311 fl_set_input(general_->input_labelwidth,
312 text->cursor.par()->GetLabelWidthString().c_str());
313 fl_set_button(general_->radio_align_right, 0);
314 fl_set_button(general_->radio_align_left, 0);
315 fl_set_button(general_->radio_align_center, 0);
316 fl_set_button(general_->radio_align_block, 0);
318 int align = text->cursor.par()->GetAlign();
319 if (align == LYX_ALIGN_LAYOUT)
320 align = textclasslist.Style(buf->params.textclass,
321 text->cursor.par()->GetLayout()).align;
324 case LYX_ALIGN_RIGHT:
325 fl_set_button(general_->radio_align_right, 1);
328 fl_set_button(general_->radio_align_left, 1);
330 case LYX_ALIGN_CENTER:
331 fl_set_button(general_->radio_align_center, 1);
334 fl_set_button(general_->radio_align_block, 1);
339 fl_set_button(general_->check_lines_top,
340 text->cursor.par()->FirstPhysicalPar()->params.lineTop());
342 fl_set_button(general_->check_lines_bottom,
343 text->cursor.par()->FirstPhysicalPar()->params.lineBottom());
345 fl_set_button(general_->check_pagebreaks_top,
346 text->cursor.par()->FirstPhysicalPar()->params.pagebreakTop());
348 fl_set_button(general_->check_pagebreaks_bottom,
349 text->cursor.par()->FirstPhysicalPar()->params.pagebreakBottom());
350 fl_set_button(general_->check_noindent,
351 text->cursor.par()->FirstPhysicalPar()->params.noindent());
353 fl_set_button(general_->check_lines_top,
354 text->cursor.par()->params.lineTop());
355 fl_set_button(general_->check_lines_bottom,
356 text->cursor.par()->params.lineBottom());
357 fl_set_button(general_->check_pagebreaks_top,
358 text->cursor.par()->params.pagebreakTop());
359 fl_set_button(general_->check_pagebreaks_bottom,
360 text->cursor.par()->params.pagebreakBottom());
361 fl_set_button(general_->check_noindent,
362 text->cursor.par()->params.noindent());
364 fl_set_input (general_->input_space_above, "");
367 switch (text->cursor.par()->FirstPhysicalPar()->params.spaceTop().kind()) {
369 switch (text->cursor.par()->params.spaceTop().kind()) {
373 fl_set_choice (general_->choice_space_above, 1);
375 case VSpace::DEFSKIP:
376 fl_set_choice (general_->choice_space_above, 2);
378 case VSpace::SMALLSKIP:
379 fl_set_choice (general_->choice_space_above, 3);
381 case VSpace::MEDSKIP:
382 fl_set_choice (general_->choice_space_above, 4);
384 case VSpace::BIGSKIP:
385 fl_set_choice (general_->choice_space_above, 5);
388 fl_set_choice (general_->choice_space_above, 6);
391 fl_set_choice (general_->choice_space_above, 7);
393 fl_set_input(general_->input_space_above,
394 text->cursor.par()->FirstPhysicalPar()->
395 params.spaceTop().length().asString().c_str());
397 fl_set_input(general_->input_space_above, text->cursor.par()->
398 params.spaceTop().length().asString().c_str());
403 fl_set_button(general_->check_space_above,
404 text->cursor.par()->FirstPhysicalPar()->
405 params.spaceTop().keep());
406 fl_set_input(general_->input_space_below, "");
407 switch (text->cursor.par()->FirstPhysicalPar()->
408 params.spaceBottom().kind()) {
410 fl_set_button (general_->check_space_above,
411 text->cursor.par()->params.spaceTop().keep());
412 fl_set_input (general_->input_space_below, "");
413 switch (text->cursor.par()->params.spaceBottom().kind()) {
416 fl_set_choice (general_->choice_space_below, 1);
418 case VSpace::DEFSKIP:
419 fl_set_choice (general_->choice_space_below, 2);
421 case VSpace::SMALLSKIP:
422 fl_set_choice (general_->choice_space_below, 3);
424 case VSpace::MEDSKIP:
425 fl_set_choice (general_->choice_space_below, 4);
427 case VSpace::BIGSKIP:
428 fl_set_choice (general_->choice_space_below, 5);
431 fl_set_choice (general_->choice_space_below, 6);
434 fl_set_choice (general_->choice_space_below, 7);
436 fl_set_input(general_->input_space_below,
437 text->cursor.par()->FirstPhysicalPar()->
438 params.spaceBottom().length().asString().c_str());
441 fl_set_button(general_->check_space_below,
442 text->cursor.par()->FirstPhysicalPar()->
443 params.spaceBottom().keep());
444 fl_set_button(general_->check_noindent,
445 text->cursor.par()->FirstPhysicalPar()->params.noindent());
447 bool const enable = (!text->cursor.par()->FirstPhysicalPar()->InInset());
449 setEnabled(general_->check_pagebreaks_top, enable);
450 setEnabled(general_->check_pagebreaks_bottom, enable);
453 fl_set_button(general_->check_pagebreaks_top, 0);
454 fl_set_button(general_->check_pagebreaks_bottom, 0);
458 fl_set_input(general_->input_space_below, text->cursor.par()->
459 params.spaceBottom().length().asString().c_str());
462 fl_set_button(general_->check_space_below,
463 text->cursor.par()->params.spaceBottom().keep());
464 fl_set_button(general_->check_noindent,
465 text->cursor.par()->params.noindent());
471 void FormParagraph::extra_update()
473 if (!lv_->view()->available() || !extra_.get())
476 LyXParagraph * par = lv_->view()->text->cursor.par();
478 setEnabled(extra_->input_pextra_width, true);
479 setEnabled(extra_->input_pextra_widthp, true);
481 fl_set_input(extra_->input_pextra_width,
482 par->params.pextraWidth().c_str());
483 fl_set_input(extra_->input_pextra_widthp,
484 par->params.pextraWidthp().c_str());
485 switch (par->params.pextraAlignment()) {
486 case LyXParagraph::MINIPAGE_ALIGN_TOP:
487 fl_set_button(extra_->radio_pextra_top, 1);
489 case LyXParagraph::MINIPAGE_ALIGN_MIDDLE:
490 fl_set_button(extra_->radio_pextra_middle, 1);
492 case LyXParagraph::MINIPAGE_ALIGN_BOTTOM:
493 fl_set_button(extra_->radio_pextra_bottom, 1);
496 fl_set_button(extra_->radio_pextra_hfill,
497 par->params.pextraHfill());
498 fl_set_button(extra_->radio_pextra_startmp,
499 par->params.pextraStartMinipage());
500 if (par->params.pextraType() == LyXParagraph::PEXTRA_INDENT) {
501 fl_set_button(extra_->radio_pextra_indent, 1);
502 fl_set_button(extra_->radio_pextra_minipage, 0);
503 fl_set_button(extra_->radio_pextra_floatflt, 0);
504 setEnabled(extra_->radio_pextra_top, false);
505 setEnabled(extra_->radio_pextra_middle, false);
506 setEnabled(extra_->radio_pextra_bottom, false);
507 input(extra_->radio_pextra_indent, 0);
508 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE) {
509 fl_set_button(extra_->radio_pextra_indent, 0);
510 fl_set_button(extra_->radio_pextra_minipage, 1);
511 fl_set_button(extra_->radio_pextra_floatflt, 0);
512 setEnabled(extra_->radio_pextra_top, true);
513 setEnabled(extra_->radio_pextra_middle, true);
514 setEnabled(extra_->radio_pextra_bottom, true);
515 input(extra_->radio_pextra_minipage, 0);
516 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_FLOATFLT) {
517 fl_set_button(extra_->radio_pextra_indent, 0);
518 fl_set_button(extra_->radio_pextra_minipage, 0);
519 fl_set_button(extra_->radio_pextra_floatflt, 1);
520 setEnabled(extra_->radio_pextra_top, false);
521 setEnabled(extra_->radio_pextra_middle, false);
522 setEnabled(extra_->radio_pextra_bottom, false);
523 input(extra_->radio_pextra_floatflt, 0);
525 fl_set_button(extra_->radio_pextra_indent, 0);
526 fl_set_button(extra_->radio_pextra_minipage, 0);
527 fl_set_button(extra_->radio_pextra_floatflt, 0);
528 setEnabled(extra_->input_pextra_width, false);
529 setEnabled(extra_->input_pextra_widthp, false);
530 setEnabled(extra_->radio_pextra_top, false);
531 setEnabled(extra_->radio_pextra_middle, false);
532 setEnabled(extra_->radio_pextra_bottom, false);
535 fl_hide_object(dialog_->text_warning);
540 bool FormParagraph::input(FL_OBJECT * ob, long)
544 fl_hide_object(dialog_->text_warning);
546 // First check the buttons which are exclusive and you have to
547 // check only the actuall de/activated button.
549 // general form first
551 // "Synchronize" the choices and input fields, making it
552 // impossible to commit senseless data.
554 if (fl_get_choice (general_->choice_space_above) != 7)
555 fl_set_input (general_->input_space_above, "");
557 if (fl_get_choice (general_->choice_space_below) != 7)
558 fl_set_input (general_->input_space_below, "");
562 // then the extra form
564 if (ob == extra_->radio_pextra_indent) {
565 bool const enable = (fl_get_button(extra_->radio_pextra_indent) != 0);
568 fl_set_button(extra_->radio_pextra_minipage, 0);
569 fl_set_button(extra_->radio_pextra_floatflt, 0);
572 setEnabled(extra_->input_pextra_width, enable);
573 setEnabled(extra_->input_pextra_widthp, enable);
575 setEnabled(extra_->radio_pextra_top, false);
576 setEnabled(extra_->radio_pextra_middle, false);
577 setEnabled(extra_->radio_pextra_bottom, false);
578 setEnabled(extra_->radio_pextra_hfill, false);
579 setEnabled(extra_->radio_pextra_startmp, false);
581 } else if (ob == extra_->radio_pextra_minipage) {
582 bool const enable = (fl_get_button(extra_->radio_pextra_minipage) != 0);
585 fl_set_button(extra_->radio_pextra_indent, 0);
586 fl_set_button(extra_->radio_pextra_floatflt, 0);
589 setEnabled(extra_->input_pextra_width, enable);
590 setEnabled(extra_->input_pextra_widthp, enable);
591 setEnabled(extra_->radio_pextra_top, enable);
592 setEnabled(extra_->radio_pextra_middle, enable);
593 setEnabled(extra_->radio_pextra_bottom, enable);
594 setEnabled(extra_->radio_pextra_hfill, enable);
595 setEnabled(extra_->radio_pextra_startmp, enable);
596 } else if (ob == extra_->radio_pextra_floatflt) {
597 bool const enable = (fl_get_button(extra_->radio_pextra_floatflt) != 0);
600 fl_set_button(extra_->radio_pextra_indent, 0);
601 fl_set_button(extra_->radio_pextra_minipage, 0);
604 setEnabled(extra_->input_pextra_width, enable);
605 setEnabled(extra_->input_pextra_widthp, enable);
607 setEnabled(extra_->radio_pextra_top, false);
608 setEnabled(extra_->radio_pextra_middle, false);
609 setEnabled(extra_->radio_pextra_bottom, false);
610 setEnabled(extra_->radio_pextra_hfill, false);
611 setEnabled(extra_->radio_pextra_startmp, false);
616 // first the general form
618 string input = fl_get_input (general_->input_space_above);
619 bool invalid = false;
621 if (fl_get_choice(general_->choice_space_above)==7)
622 invalid = !input.empty() && !isValidGlueLength(input);
624 input = fl_get_input (general_->input_space_below);
626 if (fl_get_choice(general_->choice_space_below)==7)
627 invalid = invalid || (!input.empty() && !isValidGlueLength(input));
629 if (ob == general_->input_space_above || ob == general_->input_space_below) {
631 fl_set_object_label(dialog_->text_warning,
632 _("Warning: Invalid Length (valid example: 10mm)"));
633 fl_show_object(dialog_->text_warning);
636 fl_hide_object(dialog_->text_warning);
643 // then the extra form
645 int n = fl_get_button(extra_->radio_pextra_indent) +
646 fl_get_button(extra_->radio_pextra_minipage) +
647 fl_get_button(extra_->radio_pextra_floatflt);
648 string s1 = fl_get_input(extra_->input_pextra_width);
649 string s2 = fl_get_input(extra_->input_pextra_widthp);
650 if (!n) { // no button pressed both should be deactivated now
651 setEnabled(extra_->input_pextra_width, false);
652 setEnabled(extra_->input_pextra_widthp, false);
653 fl_hide_object(dialog_->text_warning);
654 } else if (s1.empty() && s2.empty()) {
655 setEnabled(extra_->input_pextra_width, true);
656 setEnabled(extra_->input_pextra_widthp, true);
657 fl_hide_object(dialog_->text_warning);
659 } else if (!s1.empty()) { // LyXLength parameter
660 setEnabled(extra_->input_pextra_width, true);
661 setEnabled(extra_->input_pextra_widthp, false);
662 if (!isValidLength(s1)) {
663 fl_set_object_label(dialog_->text_warning,
664 _("Warning: Invalid Length (valid example: 10mm)"));
665 fl_show_object(dialog_->text_warning);
668 } else { // !s2.empty() % parameter
669 setEnabled(extra_->input_pextra_width, false);
670 setEnabled(extra_->input_pextra_widthp, true);
671 if ((lyx::atoi(s2) < 0 ) || (lyx::atoi(s2) > 100)) {
673 fl_set_object_label(dialog_->text_warning,
674 _("Warning: Invalid percent value (0-100)"));
675 fl_show_object(dialog_->text_warning);