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;
35 FormParagraph::FormParagraph(LyXView * lv, Dialogs * d)
36 : FormBaseBD(lv, d, _("Paragraph Layout"))
38 // let the popup be shown
39 // This is a permanent connection so we won't bother
40 // storing a copy because we won't be disconnecting.
41 d->showLayoutParagraph.connect(slot(this, &FormParagraph::show));
45 void FormParagraph::redraw()
47 if( form() && form()->visible )
48 fl_redraw_form( form() );
52 FL_FORM * outer_form = fl_get_active_folder(dialog_->tabbed_folder);
53 if (outer_form && outer_form->visible)
54 fl_redraw_form( outer_form );
58 FL_FORM * FormParagraph::form() const
60 if (dialog_.get()) return dialog_->form;
65 void FormParagraph::build()
68 dialog_.reset(build_tabbed_paragraph());
70 // Manage the ok, apply, restore and cancel/close buttons
71 bc_.setOK(dialog_->button_ok);
72 bc_.setApply(dialog_->button_apply);
73 bc_.setCancel(dialog_->button_cancel);
74 bc_.setUndoAll(dialog_->button_restore);
77 // the general paragraph data form
78 general_.reset(build_paragraph_general());
80 fl_addto_choice(general_->choice_space_above,
81 _(" None | Defskip | Smallskip "
82 "| Medskip | Bigskip | VFill | Length "));
83 fl_addto_choice(general_->choice_space_below,
84 _(" None | Defskip | Smallskip "
85 "| Medskip | Bigskip | VFill | Length "));
87 fl_set_input_return(general_->input_space_above, FL_RETURN_CHANGED);
88 fl_set_input_return(general_->input_space_below, FL_RETURN_CHANGED);
89 fl_set_input_return(general_->input_labelwidth, FL_RETURN_CHANGED);
91 bc_.addReadOnly (general_->radio_align_right);
92 bc_.addReadOnly (general_->radio_align_left);
93 bc_.addReadOnly (general_->radio_align_block);
94 bc_.addReadOnly (general_->radio_align_center);
95 bc_.addReadOnly (general_->check_lines_top);
96 bc_.addReadOnly (general_->check_lines_bottom);
97 bc_.addReadOnly (general_->check_pagebreaks_top);
98 bc_.addReadOnly (general_->check_pagebreaks_bottom);
99 bc_.addReadOnly (general_->choice_space_above);
100 bc_.addReadOnly (general_->input_space_above);
101 bc_.addReadOnly (general_->check_space_above);
102 bc_.addReadOnly (general_->choice_space_below);
103 bc_.addReadOnly (general_->input_space_below);
104 bc_.addReadOnly (general_->check_space_below);
105 bc_.addReadOnly (general_->check_noindent);
106 bc_.addReadOnly (general_->input_labelwidth);
109 // the document class form
110 extra_.reset(build_paragraph_extra());
112 fl_set_input_return(extra_->input_pextra_width, FL_RETURN_CHANGED);
113 fl_set_input_return(extra_->input_pextra_widthp, FL_RETURN_CHANGED);
115 bc_.addReadOnly (extra_->radio_pextra_indent);
116 bc_.addReadOnly (extra_->radio_pextra_minipage);
117 bc_.addReadOnly (extra_->radio_pextra_floatflt);
118 bc_.addReadOnly (extra_->radio_pextra_hfill);
119 bc_.addReadOnly (extra_->radio_pextra_startmp);
122 // now make them fit together
123 fl_addto_tabfolder(dialog_->tabbed_folder,_("General"), general_->form);
125 fl_addto_tabfolder(dialog_->tabbed_folder,_("Extra"), extra_->form);
130 void FormParagraph::apply()
132 if (!lv_->view()->available() || !dialog_.get())
140 lv_->view()->update(lv_->view()->text,
141 BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
142 lv_->buffer()->markDirty();
143 setMinibuffer(lv_, _("Paragraph layout set"));
147 void FormParagraph::update()
156 bc_.readOnly(lv_->buffer()->isReadonly());
160 void FormParagraph::general_apply()
162 VSpace space_top, space_bottom;
164 string labelwidthstring;
167 // If a vspace kind is "Length" but there's no text in
168 // the input field, reset the kind to "None".
169 if ((fl_get_choice (general_->choice_space_above) == 7) &&
170 !*(fl_get_input (general_->input_space_above)))
172 fl_set_choice (general_->choice_space_above, 1);
174 if ((fl_get_choice (general_->choice_space_below) == 7) &&
175 !*(fl_get_input (general_->input_space_below)))
177 fl_set_choice (general_->choice_space_below, 1);
180 bool line_top = fl_get_button(general_->check_lines_top);
181 bool line_bottom = fl_get_button(general_->check_lines_bottom);
182 bool pagebreak_top = fl_get_button(general_->check_pagebreaks_top);
183 bool pagebreak_bottom = fl_get_button(general_->check_pagebreaks_bottom);
185 switch (fl_get_choice (general_->choice_space_above)) {
187 space_top = VSpace(VSpace::NONE);
190 space_top = VSpace(VSpace::DEFSKIP);
193 space_top = VSpace(VSpace::SMALLSKIP);
196 space_top = VSpace(VSpace::MEDSKIP);
199 space_top = VSpace(VSpace::BIGSKIP);
202 space_top = VSpace(VSpace::VFILL);
206 VSpace(LyXGlueLength(fl_get_input(general_->input_space_above)));
209 if (fl_get_button (general_->check_space_above))
210 space_top.setKeep (true);
211 switch (fl_get_choice (general_->choice_space_below)) {
213 space_bottom = VSpace(VSpace::NONE);
216 space_bottom = VSpace(VSpace::DEFSKIP);
219 space_bottom = VSpace(VSpace::SMALLSKIP);
222 space_bottom = VSpace(VSpace::MEDSKIP);
225 space_bottom = VSpace(VSpace::BIGSKIP);
228 space_bottom = VSpace(VSpace::VFILL);
232 VSpace(LyXGlueLength(fl_get_input(general_->input_space_below)));
235 if (fl_get_button (general_->check_space_below))
236 space_bottom.setKeep (true);
238 if (fl_get_button(general_->radio_align_left))
239 align = LYX_ALIGN_LEFT;
240 else if (fl_get_button(general_->radio_align_right))
241 align = LYX_ALIGN_RIGHT;
242 else if (fl_get_button(general_->radio_align_center))
243 align = LYX_ALIGN_CENTER;
245 align = LYX_ALIGN_BLOCK;
247 labelwidthstring = fl_get_input(general_->input_labelwidth);
248 noindent = fl_get_button(general_->check_noindent);
251 if (lv_->view()->theLockingInset())
252 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
254 text = lv_->view()->text;
255 text->SetParagraph(lv_->view(), line_top, line_bottom, pagebreak_top,
256 pagebreak_bottom, space_top, space_bottom, align,
257 labelwidthstring, noindent);
262 void FormParagraph::extra_apply()
264 char const * width = fl_get_input(extra_->input_pextra_width);
265 char const * widthp = fl_get_input(extra_->input_pextra_widthp);
266 LyXText * text = lv_->view()->text;
267 int type = LyXParagraph::PEXTRA_NONE;
268 LyXParagraph::MINIPAGE_ALIGNMENT
269 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
272 start_minipage = false;
274 if (fl_get_button(extra_->radio_pextra_indent)) {
275 type = LyXParagraph::PEXTRA_INDENT;
276 } else if (fl_get_button(extra_->radio_pextra_minipage)) {
277 type = LyXParagraph::PEXTRA_MINIPAGE;
278 hfill = fl_get_button(extra_->radio_pextra_hfill);
279 start_minipage = fl_get_button(extra_->radio_pextra_startmp);
280 if (fl_get_button(extra_->radio_pextra_top))
281 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
282 else if (fl_get_button(extra_->radio_pextra_middle))
283 alignment = LyXParagraph::MINIPAGE_ALIGN_MIDDLE;
284 else if (fl_get_button(extra_->radio_pextra_bottom))
285 alignment = LyXParagraph::MINIPAGE_ALIGN_BOTTOM;
286 } else if (fl_get_button(extra_->radio_pextra_floatflt)) {
287 type = LyXParagraph::PEXTRA_FLOATFLT;
289 text->SetParagraphExtraOpt(lv_->view(), type, width, widthp, alignment,
290 hfill, start_minipage);
295 void FormParagraph::general_update()
300 Buffer * buf = lv_->view()->buffer();
303 if (lv_->view()->theLockingInset())
304 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
306 text = lv_->view()->text;
308 fl_set_input(general_->input_labelwidth,
309 text->cursor.par()->GetLabelWidthString().c_str());
310 fl_set_button(general_->radio_align_right, 0);
311 fl_set_button(general_->radio_align_left, 0);
312 fl_set_button(general_->radio_align_center, 0);
313 fl_set_button(general_->radio_align_block, 0);
315 int align = text->cursor.par()->GetAlign();
316 if (align == LYX_ALIGN_LAYOUT)
317 align = textclasslist.Style(buf->params.textclass,
318 text->cursor.par()->GetLayout()).align;
321 case LYX_ALIGN_RIGHT:
322 fl_set_button(general_->radio_align_right, 1);
325 fl_set_button(general_->radio_align_left, 1);
327 case LYX_ALIGN_CENTER:
328 fl_set_button(general_->radio_align_center, 1);
331 fl_set_button(general_->radio_align_block, 1);
336 fl_set_button(general_->check_lines_top,
337 text->cursor.par()->FirstPhysicalPar()->params.lineTop());
339 fl_set_button(general_->check_lines_bottom,
340 text->cursor.par()->FirstPhysicalPar()->params.lineBottom());
342 fl_set_button(general_->check_pagebreaks_top,
343 text->cursor.par()->FirstPhysicalPar()->params.pagebreakTop());
345 fl_set_button(general_->check_pagebreaks_bottom,
346 text->cursor.par()->FirstPhysicalPar()->params.pagebreakBottom());
347 fl_set_button(general_->check_noindent,
348 text->cursor.par()->FirstPhysicalPar()->params.noindent());
350 fl_set_button(general_->check_lines_top,
351 text->cursor.par()->params.lineTop());
352 fl_set_button(general_->check_lines_bottom,
353 text->cursor.par()->params.lineBottom());
354 fl_set_button(general_->check_pagebreaks_top,
355 text->cursor.par()->params.pagebreakTop());
356 fl_set_button(general_->check_pagebreaks_bottom,
357 text->cursor.par()->params.pagebreakBottom());
358 fl_set_button(general_->check_noindent,
359 text->cursor.par()->params.noindent());
361 fl_set_input (general_->input_space_above, "");
364 switch (text->cursor.par()->FirstPhysicalPar()->params.spaceTop().kind()) {
366 switch (text->cursor.par()->params.spaceTop().kind()) {
370 fl_set_choice (general_->choice_space_above, 1);
372 case VSpace::DEFSKIP:
373 fl_set_choice (general_->choice_space_above, 2);
375 case VSpace::SMALLSKIP:
376 fl_set_choice (general_->choice_space_above, 3);
378 case VSpace::MEDSKIP:
379 fl_set_choice (general_->choice_space_above, 4);
381 case VSpace::BIGSKIP:
382 fl_set_choice (general_->choice_space_above, 5);
385 fl_set_choice (general_->choice_space_above, 6);
388 fl_set_choice (general_->choice_space_above, 7);
390 fl_set_input(general_->input_space_above,
391 text->cursor.par()->FirstPhysicalPar()->
392 params.spaceTop().length().asString().c_str());
394 fl_set_input(general_->input_space_above, text->cursor.par()->
395 params.spaceTop().length().asString().c_str());
400 fl_set_button(general_->check_space_above,
401 text->cursor.par()->FirstPhysicalPar()->
402 params.spaceTop().keep());
403 fl_set_input(general_->input_space_below, "");
404 switch (text->cursor.par()->FirstPhysicalPar()->
405 params.spaceBottom().kind()) {
407 fl_set_button (general_->check_space_above,
408 text->cursor.par()->params.spaceTop().keep());
409 fl_set_input (general_->input_space_below, "");
410 switch (text->cursor.par()->params.spaceBottom().kind()) {
413 fl_set_choice (general_->choice_space_below, 1);
415 case VSpace::DEFSKIP:
416 fl_set_choice (general_->choice_space_below, 2);
418 case VSpace::SMALLSKIP:
419 fl_set_choice (general_->choice_space_below, 3);
421 case VSpace::MEDSKIP:
422 fl_set_choice (general_->choice_space_below, 4);
424 case VSpace::BIGSKIP:
425 fl_set_choice (general_->choice_space_below, 5);
428 fl_set_choice (general_->choice_space_below, 6);
431 fl_set_choice (general_->choice_space_below, 7);
433 fl_set_input(general_->input_space_below,
434 text->cursor.par()->FirstPhysicalPar()->
435 params.spaceBottom().length().asString().c_str());
438 fl_set_button(general_->check_space_below,
439 text->cursor.par()->FirstPhysicalPar()->
440 params.spaceBottom().keep());
441 fl_set_button(general_->check_noindent,
442 text->cursor.par()->FirstPhysicalPar()->params.noindent());
444 bool const enable = (!text->cursor.par()->FirstPhysicalPar()->InInset());
446 setEnabled(general_->check_pagebreaks_top, enable);
447 setEnabled(general_->check_pagebreaks_bottom, enable);
450 fl_set_button(general_->check_pagebreaks_top, 0);
451 fl_set_button(general_->check_pagebreaks_bottom, 0);
455 fl_set_input(general_->input_space_below, text->cursor.par()->
456 params.spaceBottom().length().asString().c_str());
459 fl_set_button(general_->check_space_below,
460 text->cursor.par()->params.spaceBottom().keep());
461 fl_set_button(general_->check_noindent,
462 text->cursor.par()->params.noindent());
468 void FormParagraph::extra_update()
470 if (!lv_->view()->available() || !extra_.get())
473 LyXParagraph * par = lv_->view()->text->cursor.par();
475 setEnabled(extra_->input_pextra_width, true);
476 setEnabled(extra_->input_pextra_widthp, true);
478 fl_set_input(extra_->input_pextra_width,
479 par->params.pextraWidth().c_str());
480 fl_set_input(extra_->input_pextra_widthp,
481 par->params.pextraWidthp().c_str());
482 switch (par->params.pextraAlignment()) {
483 case LyXParagraph::MINIPAGE_ALIGN_TOP:
484 fl_set_button(extra_->radio_pextra_top, 1);
486 case LyXParagraph::MINIPAGE_ALIGN_MIDDLE:
487 fl_set_button(extra_->radio_pextra_middle, 1);
489 case LyXParagraph::MINIPAGE_ALIGN_BOTTOM:
490 fl_set_button(extra_->radio_pextra_bottom, 1);
493 fl_set_button(extra_->radio_pextra_hfill,
494 par->params.pextraHfill());
495 fl_set_button(extra_->radio_pextra_startmp,
496 par->params.pextraStartMinipage());
497 if (par->params.pextraType() == LyXParagraph::PEXTRA_INDENT) {
498 fl_set_button(extra_->radio_pextra_indent, 1);
499 fl_set_button(extra_->radio_pextra_minipage, 0);
500 fl_set_button(extra_->radio_pextra_floatflt, 0);
501 setEnabled(extra_->radio_pextra_top, false);
502 setEnabled(extra_->radio_pextra_middle, false);
503 setEnabled(extra_->radio_pextra_bottom, false);
504 input(extra_->radio_pextra_indent, 0);
505 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE) {
506 fl_set_button(extra_->radio_pextra_indent, 0);
507 fl_set_button(extra_->radio_pextra_minipage, 1);
508 fl_set_button(extra_->radio_pextra_floatflt, 0);
509 setEnabled(extra_->radio_pextra_top, true);
510 setEnabled(extra_->radio_pextra_middle, true);
511 setEnabled(extra_->radio_pextra_bottom, true);
512 input(extra_->radio_pextra_minipage, 0);
513 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_FLOATFLT) {
514 fl_set_button(extra_->radio_pextra_indent, 0);
515 fl_set_button(extra_->radio_pextra_minipage, 0);
516 fl_set_button(extra_->radio_pextra_floatflt, 1);
517 setEnabled(extra_->radio_pextra_top, false);
518 setEnabled(extra_->radio_pextra_middle, false);
519 setEnabled(extra_->radio_pextra_bottom, false);
520 input(extra_->radio_pextra_floatflt, 0);
522 fl_set_button(extra_->radio_pextra_indent, 0);
523 fl_set_button(extra_->radio_pextra_minipage, 0);
524 fl_set_button(extra_->radio_pextra_floatflt, 0);
525 setEnabled(extra_->input_pextra_width, false);
526 setEnabled(extra_->input_pextra_widthp, false);
527 setEnabled(extra_->radio_pextra_top, false);
528 setEnabled(extra_->radio_pextra_middle, false);
529 setEnabled(extra_->radio_pextra_bottom, false);
532 fl_hide_object(dialog_->text_warning);
537 bool FormParagraph::input(FL_OBJECT * ob, long)
541 fl_hide_object(dialog_->text_warning);
543 // First check the buttons which are exclusive and you have to
544 // check only the actuall de/activated button.
546 // general form first
548 // "Synchronize" the choices and input fields, making it
549 // impossible to commit senseless data.
551 if (fl_get_choice (general_->choice_space_above) != 7)
552 fl_set_input (general_->input_space_above, "");
554 if (fl_get_choice (general_->choice_space_below) != 7)
555 fl_set_input (general_->input_space_below, "");
559 // then the extra form
561 if (ob == extra_->radio_pextra_indent) {
562 bool const enable = (fl_get_button(extra_->radio_pextra_indent) != 0);
565 fl_set_button(extra_->radio_pextra_minipage, 0);
566 fl_set_button(extra_->radio_pextra_floatflt, 0);
569 setEnabled(extra_->input_pextra_width, enable);
570 setEnabled(extra_->input_pextra_widthp, enable);
572 setEnabled(extra_->radio_pextra_top, false);
573 setEnabled(extra_->radio_pextra_middle, false);
574 setEnabled(extra_->radio_pextra_bottom, false);
575 setEnabled(extra_->radio_pextra_hfill, false);
576 setEnabled(extra_->radio_pextra_startmp, false);
578 } else if (ob == extra_->radio_pextra_minipage) {
579 bool const enable = (fl_get_button(extra_->radio_pextra_minipage) != 0);
582 fl_set_button(extra_->radio_pextra_indent, 0);
583 fl_set_button(extra_->radio_pextra_floatflt, 0);
586 setEnabled(extra_->input_pextra_width, enable);
587 setEnabled(extra_->input_pextra_widthp, enable);
588 setEnabled(extra_->radio_pextra_top, enable);
589 setEnabled(extra_->radio_pextra_middle, enable);
590 setEnabled(extra_->radio_pextra_bottom, enable);
591 setEnabled(extra_->radio_pextra_hfill, enable);
592 setEnabled(extra_->radio_pextra_startmp, enable);
593 } else if (ob == extra_->radio_pextra_floatflt) {
594 bool const enable = (fl_get_button(extra_->radio_pextra_floatflt) != 0);
597 fl_set_button(extra_->radio_pextra_indent, 0);
598 fl_set_button(extra_->radio_pextra_minipage, 0);
601 setEnabled(extra_->input_pextra_width, enable);
602 setEnabled(extra_->input_pextra_widthp, enable);
604 setEnabled(extra_->radio_pextra_top, false);
605 setEnabled(extra_->radio_pextra_middle, false);
606 setEnabled(extra_->radio_pextra_bottom, false);
607 setEnabled(extra_->radio_pextra_hfill, false);
608 setEnabled(extra_->radio_pextra_startmp, false);
613 // first the general form
615 string input = fl_get_input (general_->input_space_above);
616 bool invalid = false;
618 if (fl_get_choice(general_->choice_space_above)==7)
619 invalid = !input.empty() && !isValidGlueLength(input);
621 input = fl_get_input (general_->input_space_below);
623 if (fl_get_choice(general_->choice_space_below)==7)
624 invalid = invalid || (!input.empty() && !isValidGlueLength(input));
626 if (ob == general_->input_space_above || ob == general_->input_space_below) {
628 fl_set_object_label(dialog_->text_warning,
629 _("Warning: Invalid Length (valid example: 10mm)"));
630 fl_show_object(dialog_->text_warning);
633 fl_hide_object(dialog_->text_warning);
640 // then the extra form
642 int n = fl_get_button(extra_->radio_pextra_indent) +
643 fl_get_button(extra_->radio_pextra_minipage) +
644 fl_get_button(extra_->radio_pextra_floatflt);
645 string s1 = fl_get_input(extra_->input_pextra_width);
646 string s2 = fl_get_input(extra_->input_pextra_widthp);
647 if (!n) { // no button pressed both should be deactivated now
648 setEnabled(extra_->input_pextra_width, false);
649 setEnabled(extra_->input_pextra_widthp, false);
650 fl_hide_object(dialog_->text_warning);
651 } else if (s1.empty() && s2.empty()) {
652 setEnabled(extra_->input_pextra_width, true);
653 setEnabled(extra_->input_pextra_widthp, true);
654 fl_hide_object(dialog_->text_warning);
656 } else if (!s1.empty()) { // LyXLength parameter
657 setEnabled(extra_->input_pextra_width, true);
658 setEnabled(extra_->input_pextra_widthp, false);
659 if (!isValidLength(s1)) {
660 fl_set_object_label(dialog_->text_warning,
661 _("Warning: Invalid Length (valid example: 10mm)"));
662 fl_show_object(dialog_->text_warning);
665 } else { // !s2.empty() % parameter
666 setEnabled(extra_->input_pextra_width, false);
667 setEnabled(extra_->input_pextra_widthp, true);
668 if ((lyx::atoi(s2) < 0 ) || (lyx::atoi(s2) > 100)) {
670 fl_set_object_label(dialog_->text_warning,
671 _("Warning: Invalid percent value (0-100)"));
672 fl_show_object(dialog_->text_warning);