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 dialog 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_.setRestore(dialog_->button_restore);
76 // the general paragraph data form
77 general_.reset(build_paragraph_general());
79 fl_addto_choice(general_->choice_space_above,
80 _(" None | Defskip | Smallskip "
81 "| Medskip | Bigskip | VFill | Length "));
82 fl_addto_choice(general_->choice_space_below,
83 _(" None | Defskip | Smallskip "
84 "| Medskip | Bigskip | VFill | Length "));
86 fl_set_input_return(general_->input_space_above, FL_RETURN_CHANGED);
87 fl_set_input_return(general_->input_space_below, FL_RETURN_CHANGED);
88 fl_set_input_return(general_->input_labelwidth, FL_RETURN_CHANGED);
90 bc_.addReadOnly (general_->radio_align_right);
91 bc_.addReadOnly (general_->radio_align_left);
92 bc_.addReadOnly (general_->radio_align_block);
93 bc_.addReadOnly (general_->radio_align_center);
94 bc_.addReadOnly (general_->check_lines_top);
95 bc_.addReadOnly (general_->check_lines_bottom);
96 bc_.addReadOnly (general_->check_pagebreaks_top);
97 bc_.addReadOnly (general_->check_pagebreaks_bottom);
98 bc_.addReadOnly (general_->choice_space_above);
99 bc_.addReadOnly (general_->input_space_above);
100 bc_.addReadOnly (general_->check_space_above);
101 bc_.addReadOnly (general_->choice_space_below);
102 bc_.addReadOnly (general_->input_space_below);
103 bc_.addReadOnly (general_->check_space_below);
104 bc_.addReadOnly (general_->check_noindent);
105 bc_.addReadOnly (general_->input_labelwidth);
108 // the document class form
109 extra_.reset(build_paragraph_extra());
111 fl_set_input_return(extra_->input_pextra_width, FL_RETURN_CHANGED);
112 fl_set_input_return(extra_->input_pextra_widthp, FL_RETURN_CHANGED);
114 bc_.addReadOnly (extra_->radio_pextra_indent);
115 bc_.addReadOnly (extra_->radio_pextra_minipage);
116 bc_.addReadOnly (extra_->radio_pextra_floatflt);
117 bc_.addReadOnly (extra_->radio_pextra_hfill);
118 bc_.addReadOnly (extra_->radio_pextra_startmp);
121 // now make them fit together
122 fl_addto_tabfolder(dialog_->tabbed_folder,_("General"), general_->form);
124 fl_addto_tabfolder(dialog_->tabbed_folder,_("Extra"), extra_->form);
129 void FormParagraph::apply()
131 if (!lv_->view()->available() || !dialog_.get())
139 lv_->view()->update(lv_->view()->text,
140 BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
141 lv_->buffer()->markDirty();
142 setMinibuffer(lv_, _("Paragraph layout set"));
146 void FormParagraph::update()
155 bc_.readOnly(lv_->buffer()->isReadonly());
159 void FormParagraph::general_apply()
161 VSpace space_top, space_bottom;
163 string labelwidthstring;
166 // If a vspace kind is "Length" but there's no text in
167 // the input field, reset the kind to "None".
168 if ((fl_get_choice (general_->choice_space_above) == 7) &&
169 !*(fl_get_input (general_->input_space_above)))
171 fl_set_choice (general_->choice_space_above, 1);
173 if ((fl_get_choice (general_->choice_space_below) == 7) &&
174 !*(fl_get_input (general_->input_space_below)))
176 fl_set_choice (general_->choice_space_below, 1);
179 bool line_top = fl_get_button(general_->check_lines_top);
180 bool line_bottom = fl_get_button(general_->check_lines_bottom);
181 bool pagebreak_top = fl_get_button(general_->check_pagebreaks_top);
182 bool pagebreak_bottom = fl_get_button(general_->check_pagebreaks_bottom);
184 switch (fl_get_choice (general_->choice_space_above)) {
186 space_top = VSpace(VSpace::NONE);
189 space_top = VSpace(VSpace::DEFSKIP);
192 space_top = VSpace(VSpace::SMALLSKIP);
195 space_top = VSpace(VSpace::MEDSKIP);
198 space_top = VSpace(VSpace::BIGSKIP);
201 space_top = VSpace(VSpace::VFILL);
205 VSpace(LyXGlueLength(fl_get_input(general_->input_space_above)));
208 if (fl_get_button (general_->check_space_above))
209 space_top.setKeep (true);
210 switch (fl_get_choice (general_->choice_space_below)) {
212 space_bottom = VSpace(VSpace::NONE);
215 space_bottom = VSpace(VSpace::DEFSKIP);
218 space_bottom = VSpace(VSpace::SMALLSKIP);
221 space_bottom = VSpace(VSpace::MEDSKIP);
224 space_bottom = VSpace(VSpace::BIGSKIP);
227 space_bottom = VSpace(VSpace::VFILL);
231 VSpace(LyXGlueLength(fl_get_input(general_->input_space_below)));
234 if (fl_get_button (general_->check_space_below))
235 space_bottom.setKeep (true);
237 if (fl_get_button(general_->radio_align_left))
238 align = LYX_ALIGN_LEFT;
239 else if (fl_get_button(general_->radio_align_right))
240 align = LYX_ALIGN_RIGHT;
241 else if (fl_get_button(general_->radio_align_center))
242 align = LYX_ALIGN_CENTER;
244 align = LYX_ALIGN_BLOCK;
246 labelwidthstring = fl_get_input(general_->input_labelwidth);
247 noindent = fl_get_button(general_->check_noindent);
250 if (lv_->view()->theLockingInset())
251 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
253 text = lv_->view()->text;
254 text->SetParagraph(lv_->view(), line_top, line_bottom, pagebreak_top,
255 pagebreak_bottom, space_top, space_bottom, align,
256 labelwidthstring, noindent);
261 void FormParagraph::extra_apply()
263 char const * width = fl_get_input(extra_->input_pextra_width);
264 char const * widthp = fl_get_input(extra_->input_pextra_widthp);
265 LyXText * text = lv_->view()->text;
266 int type = LyXParagraph::PEXTRA_NONE;
267 LyXParagraph::MINIPAGE_ALIGNMENT
268 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
271 start_minipage = false;
273 if (fl_get_button(extra_->radio_pextra_indent)) {
274 type = LyXParagraph::PEXTRA_INDENT;
275 } else if (fl_get_button(extra_->radio_pextra_minipage)) {
276 type = LyXParagraph::PEXTRA_MINIPAGE;
277 hfill = fl_get_button(extra_->radio_pextra_hfill);
278 start_minipage = fl_get_button(extra_->radio_pextra_startmp);
279 if (fl_get_button(extra_->radio_pextra_top))
280 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
281 else if (fl_get_button(extra_->radio_pextra_middle))
282 alignment = LyXParagraph::MINIPAGE_ALIGN_MIDDLE;
283 else if (fl_get_button(extra_->radio_pextra_bottom))
284 alignment = LyXParagraph::MINIPAGE_ALIGN_BOTTOM;
285 } else if (fl_get_button(extra_->radio_pextra_floatflt)) {
286 type = LyXParagraph::PEXTRA_FLOATFLT;
288 text->SetParagraphExtraOpt(lv_->view(), type, width, widthp, alignment,
289 hfill, start_minipage);
294 void FormParagraph::general_update()
299 Buffer * buf = lv_->view()->buffer();
302 if (lv_->view()->theLockingInset())
303 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
305 text = lv_->view()->text;
307 fl_set_input(general_->input_labelwidth,
308 text->cursor.par()->GetLabelWidthString().c_str());
309 fl_set_button(general_->radio_align_right, 0);
310 fl_set_button(general_->radio_align_left, 0);
311 fl_set_button(general_->radio_align_center, 0);
312 fl_set_button(general_->radio_align_block, 0);
314 int align = text->cursor.par()->GetAlign();
315 if (align == LYX_ALIGN_LAYOUT)
316 align = textclasslist.Style(buf->params.textclass,
317 text->cursor.par()->GetLayout()).align;
320 case LYX_ALIGN_RIGHT:
321 fl_set_button(general_->radio_align_right, 1);
324 fl_set_button(general_->radio_align_left, 1);
326 case LYX_ALIGN_CENTER:
327 fl_set_button(general_->radio_align_center, 1);
330 fl_set_button(general_->radio_align_block, 1);
335 fl_set_button(general_->check_lines_top,
336 text->cursor.par()->FirstPhysicalPar()->params.lineTop());
338 fl_set_button(general_->check_lines_bottom,
339 text->cursor.par()->FirstPhysicalPar()->params.lineBottom());
341 fl_set_button(general_->check_pagebreaks_top,
342 text->cursor.par()->FirstPhysicalPar()->params.pagebreakTop());
344 fl_set_button(general_->check_pagebreaks_bottom,
345 text->cursor.par()->FirstPhysicalPar()->params.pagebreakBottom());
346 fl_set_button(general_->check_noindent,
347 text->cursor.par()->FirstPhysicalPar()->params.noindent());
349 fl_set_button(general_->check_lines_top,
350 text->cursor.par()->params.lineTop());
351 fl_set_button(general_->check_lines_bottom,
352 text->cursor.par()->params.lineBottom());
353 fl_set_button(general_->check_pagebreaks_top,
354 text->cursor.par()->params.pagebreakTop());
355 fl_set_button(general_->check_pagebreaks_bottom,
356 text->cursor.par()->params.pagebreakBottom());
357 fl_set_button(general_->check_noindent,
358 text->cursor.par()->params.noindent());
360 fl_set_input (general_->input_space_above, "");
363 switch (text->cursor.par()->FirstPhysicalPar()->params.spaceTop().kind()) {
365 switch (text->cursor.par()->params.spaceTop().kind()) {
369 fl_set_choice (general_->choice_space_above, 1);
371 case VSpace::DEFSKIP:
372 fl_set_choice (general_->choice_space_above, 2);
374 case VSpace::SMALLSKIP:
375 fl_set_choice (general_->choice_space_above, 3);
377 case VSpace::MEDSKIP:
378 fl_set_choice (general_->choice_space_above, 4);
380 case VSpace::BIGSKIP:
381 fl_set_choice (general_->choice_space_above, 5);
384 fl_set_choice (general_->choice_space_above, 6);
387 fl_set_choice (general_->choice_space_above, 7);
389 fl_set_input(general_->input_space_above,
390 text->cursor.par()->FirstPhysicalPar()->
391 params.spaceTop().length().asString().c_str());
393 fl_set_input(general_->input_space_above, text->cursor.par()->
394 params.spaceTop().length().asString().c_str());
399 fl_set_button(general_->check_space_above,
400 text->cursor.par()->FirstPhysicalPar()->
401 params.spaceTop().keep());
402 fl_set_input(general_->input_space_below, "");
403 switch (text->cursor.par()->FirstPhysicalPar()->
404 params.spaceBottom().kind()) {
406 fl_set_button (general_->check_space_above,
407 text->cursor.par()->params.spaceTop().keep());
408 fl_set_input (general_->input_space_below, "");
409 switch (text->cursor.par()->params.spaceBottom().kind()) {
412 fl_set_choice (general_->choice_space_below, 1);
414 case VSpace::DEFSKIP:
415 fl_set_choice (general_->choice_space_below, 2);
417 case VSpace::SMALLSKIP:
418 fl_set_choice (general_->choice_space_below, 3);
420 case VSpace::MEDSKIP:
421 fl_set_choice (general_->choice_space_below, 4);
423 case VSpace::BIGSKIP:
424 fl_set_choice (general_->choice_space_below, 5);
427 fl_set_choice (general_->choice_space_below, 6);
430 fl_set_choice (general_->choice_space_below, 7);
432 fl_set_input(general_->input_space_below,
433 text->cursor.par()->FirstPhysicalPar()->
434 params.spaceBottom().length().asString().c_str());
437 fl_set_button(general_->check_space_below,
438 text->cursor.par()->FirstPhysicalPar()->
439 params.spaceBottom().keep());
440 fl_set_button(general_->check_noindent,
441 text->cursor.par()->FirstPhysicalPar()->params.noindent());
443 bool const enable = (!text->cursor.par()->FirstPhysicalPar()->InInset());
445 setEnabled(general_->check_pagebreaks_top, enable);
446 setEnabled(general_->check_pagebreaks_bottom, enable);
449 fl_set_button(general_->check_pagebreaks_top, 0);
450 fl_set_button(general_->check_pagebreaks_bottom, 0);
454 fl_set_input(general_->input_space_below, text->cursor.par()->
455 params.spaceBottom().length().asString().c_str());
458 fl_set_button(general_->check_space_below,
459 text->cursor.par()->params.spaceBottom().keep());
460 fl_set_button(general_->check_noindent,
461 text->cursor.par()->params.noindent());
467 void FormParagraph::extra_update()
469 if (!lv_->view()->available() || !extra_.get())
472 LyXParagraph * par = lv_->view()->text->cursor.par();
474 setEnabled(extra_->input_pextra_width, true);
475 setEnabled(extra_->input_pextra_widthp, true);
477 fl_set_input(extra_->input_pextra_width,
478 par->params.pextraWidth().c_str());
479 fl_set_input(extra_->input_pextra_widthp,
480 par->params.pextraWidthp().c_str());
481 switch (par->params.pextraAlignment()) {
482 case LyXParagraph::MINIPAGE_ALIGN_TOP:
483 fl_set_button(extra_->radio_pextra_top, 1);
485 case LyXParagraph::MINIPAGE_ALIGN_MIDDLE:
486 fl_set_button(extra_->radio_pextra_middle, 1);
488 case LyXParagraph::MINIPAGE_ALIGN_BOTTOM:
489 fl_set_button(extra_->radio_pextra_bottom, 1);
492 fl_set_button(extra_->radio_pextra_hfill,
493 par->params.pextraHfill());
494 fl_set_button(extra_->radio_pextra_startmp,
495 par->params.pextraStartMinipage());
496 if (par->params.pextraType() == LyXParagraph::PEXTRA_INDENT) {
497 fl_set_button(extra_->radio_pextra_indent, 1);
498 fl_set_button(extra_->radio_pextra_minipage, 0);
499 fl_set_button(extra_->radio_pextra_floatflt, 0);
500 setEnabled(extra_->radio_pextra_top, false);
501 setEnabled(extra_->radio_pextra_middle, false);
502 setEnabled(extra_->radio_pextra_bottom, false);
503 input(extra_->radio_pextra_indent, 0);
504 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE) {
505 fl_set_button(extra_->radio_pextra_indent, 0);
506 fl_set_button(extra_->radio_pextra_minipage, 1);
507 fl_set_button(extra_->radio_pextra_floatflt, 0);
508 setEnabled(extra_->radio_pextra_top, true);
509 setEnabled(extra_->radio_pextra_middle, true);
510 setEnabled(extra_->radio_pextra_bottom, true);
511 input(extra_->radio_pextra_minipage, 0);
512 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_FLOATFLT) {
513 fl_set_button(extra_->radio_pextra_indent, 0);
514 fl_set_button(extra_->radio_pextra_minipage, 0);
515 fl_set_button(extra_->radio_pextra_floatflt, 1);
516 setEnabled(extra_->radio_pextra_top, false);
517 setEnabled(extra_->radio_pextra_middle, false);
518 setEnabled(extra_->radio_pextra_bottom, false);
519 input(extra_->radio_pextra_floatflt, 0);
521 fl_set_button(extra_->radio_pextra_indent, 0);
522 fl_set_button(extra_->radio_pextra_minipage, 0);
523 fl_set_button(extra_->radio_pextra_floatflt, 0);
524 setEnabled(extra_->input_pextra_width, false);
525 setEnabled(extra_->input_pextra_widthp, false);
526 setEnabled(extra_->radio_pextra_top, false);
527 setEnabled(extra_->radio_pextra_middle, false);
528 setEnabled(extra_->radio_pextra_bottom, false);
531 fl_hide_object(dialog_->text_warning);
536 bool FormParagraph::input(FL_OBJECT * ob, long)
540 fl_hide_object(dialog_->text_warning);
542 // First check the buttons which are exclusive and you have to
543 // check only the actuall de/activated button.
545 // general form first
547 // "Synchronize" the choices and input fields, making it
548 // impossible to commit senseless data.
550 if (fl_get_choice (general_->choice_space_above) != 7)
551 fl_set_input (general_->input_space_above, "");
553 if (fl_get_choice (general_->choice_space_below) != 7)
554 fl_set_input (general_->input_space_below, "");
558 // then the extra form
560 if (ob == extra_->radio_pextra_indent) {
561 bool const enable = (fl_get_button(extra_->radio_pextra_indent) != 0);
564 fl_set_button(extra_->radio_pextra_minipage, 0);
565 fl_set_button(extra_->radio_pextra_floatflt, 0);
568 setEnabled(extra_->input_pextra_width, enable);
569 setEnabled(extra_->input_pextra_widthp, enable);
571 setEnabled(extra_->radio_pextra_top, false);
572 setEnabled(extra_->radio_pextra_middle, false);
573 setEnabled(extra_->radio_pextra_bottom, false);
574 setEnabled(extra_->radio_pextra_hfill, false);
575 setEnabled(extra_->radio_pextra_startmp, false);
577 } else if (ob == extra_->radio_pextra_minipage) {
578 bool const enable = (fl_get_button(extra_->radio_pextra_minipage) != 0);
581 fl_set_button(extra_->radio_pextra_indent, 0);
582 fl_set_button(extra_->radio_pextra_floatflt, 0);
585 setEnabled(extra_->input_pextra_width, enable);
586 setEnabled(extra_->input_pextra_widthp, enable);
587 setEnabled(extra_->radio_pextra_top, enable);
588 setEnabled(extra_->radio_pextra_middle, enable);
589 setEnabled(extra_->radio_pextra_bottom, enable);
590 setEnabled(extra_->radio_pextra_hfill, enable);
591 setEnabled(extra_->radio_pextra_startmp, enable);
592 } else if (ob == extra_->radio_pextra_floatflt) {
593 bool const enable = (fl_get_button(extra_->radio_pextra_floatflt) != 0);
596 fl_set_button(extra_->radio_pextra_indent, 0);
597 fl_set_button(extra_->radio_pextra_minipage, 0);
600 setEnabled(extra_->input_pextra_width, enable);
601 setEnabled(extra_->input_pextra_widthp, enable);
603 setEnabled(extra_->radio_pextra_top, false);
604 setEnabled(extra_->radio_pextra_middle, false);
605 setEnabled(extra_->radio_pextra_bottom, false);
606 setEnabled(extra_->radio_pextra_hfill, false);
607 setEnabled(extra_->radio_pextra_startmp, false);
612 // first the general form
614 string input = fl_get_input (general_->input_space_above);
615 bool invalid = false;
617 if (fl_get_choice(general_->choice_space_above)==7)
618 invalid = !input.empty() && !isValidGlueLength(input);
620 input = fl_get_input (general_->input_space_below);
622 if (fl_get_choice(general_->choice_space_below)==7)
623 invalid = invalid || (!input.empty() && !isValidGlueLength(input));
625 if (ob == general_->input_space_above || ob == general_->input_space_below) {
627 fl_set_object_label(dialog_->text_warning,
628 _("Warning: Invalid Length (valid example: 10mm)"));
629 fl_show_object(dialog_->text_warning);
632 fl_hide_object(dialog_->text_warning);
639 // then the extra form
641 int n = fl_get_button(extra_->radio_pextra_indent) +
642 fl_get_button(extra_->radio_pextra_minipage) +
643 fl_get_button(extra_->radio_pextra_floatflt);
644 string s1 = fl_get_input(extra_->input_pextra_width);
645 string s2 = fl_get_input(extra_->input_pextra_widthp);
646 if (!n) { // no button pressed both should be deactivated now
647 setEnabled(extra_->input_pextra_width, false);
648 setEnabled(extra_->input_pextra_widthp, false);
649 fl_hide_object(dialog_->text_warning);
650 } else if (s1.empty() && s2.empty()) {
651 setEnabled(extra_->input_pextra_width, true);
652 setEnabled(extra_->input_pextra_widthp, true);
653 fl_hide_object(dialog_->text_warning);
655 } else if (!s1.empty()) { // LyXLength parameter
656 setEnabled(extra_->input_pextra_width, true);
657 setEnabled(extra_->input_pextra_widthp, false);
658 if (!isValidLength(s1)) {
659 fl_set_object_label(dialog_->text_warning,
660 _("Warning: Invalid Length (valid example: 10mm)"));
661 fl_show_object(dialog_->text_warning);
664 } else { // !s2.empty() % parameter
665 setEnabled(extra_->input_pextra_width, false);
666 setEnabled(extra_->input_pextra_widthp, true);
667 if ((lyx::atoi(s2) < 0 ) || (lyx::atoi(s2) > 100)) {
669 fl_set_object_label(dialog_->text_warning,
670 _("Warning: Invalid percent value (0-100)"));
671 fl_show_object(dialog_->text_warning);