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 // Workaround dumb xforms sizing bug
74 // Manage the ok, apply, restore and cancel/close buttons
75 bc_.setOK(dialog_->button_ok);
76 bc_.setApply(dialog_->button_apply);
77 bc_.setCancel(dialog_->button_cancel);
78 bc_.setUndoAll(dialog_->button_restore);
81 // the general paragraph data form
82 general_.reset(build_paragraph_general());
84 fl_addto_choice(general_->choice_space_above,
85 _(" None | Defskip | Smallskip "
86 "| Medskip | Bigskip | VFill | Length "));
87 fl_addto_choice(general_->choice_space_below,
88 _(" None | Defskip | Smallskip "
89 "| Medskip | Bigskip | VFill | Length "));
91 fl_set_input_return(general_->input_space_above, FL_RETURN_CHANGED);
92 fl_set_input_return(general_->input_space_below, FL_RETURN_CHANGED);
93 fl_set_input_return(general_->input_labelwidth, FL_RETURN_CHANGED);
95 bc_.addReadOnly (general_->radio_align_right);
96 bc_.addReadOnly (general_->radio_align_left);
97 bc_.addReadOnly (general_->radio_align_block);
98 bc_.addReadOnly (general_->radio_align_center);
99 bc_.addReadOnly (general_->check_lines_top);
100 bc_.addReadOnly (general_->check_lines_bottom);
101 bc_.addReadOnly (general_->check_pagebreaks_top);
102 bc_.addReadOnly (general_->check_pagebreaks_bottom);
103 bc_.addReadOnly (general_->choice_space_above);
104 bc_.addReadOnly (general_->input_space_above);
105 bc_.addReadOnly (general_->check_space_above);
106 bc_.addReadOnly (general_->choice_space_below);
107 bc_.addReadOnly (general_->input_space_below);
108 bc_.addReadOnly (general_->check_space_below);
109 bc_.addReadOnly (general_->check_noindent);
110 bc_.addReadOnly (general_->input_labelwidth);
113 // the document class form
114 extra_.reset(build_paragraph_extra());
116 fl_set_input_return(extra_->input_pextra_width, FL_RETURN_CHANGED);
117 fl_set_input_return(extra_->input_pextra_widthp, FL_RETURN_CHANGED);
119 bc_.addReadOnly (extra_->radio_pextra_indent);
120 bc_.addReadOnly (extra_->radio_pextra_minipage);
121 bc_.addReadOnly (extra_->radio_pextra_floatflt);
122 bc_.addReadOnly (extra_->radio_pextra_hfill);
123 bc_.addReadOnly (extra_->radio_pextra_startmp);
126 // now make them fit together
127 fl_addto_tabfolder(dialog_->tabbed_folder,_("General"), general_->form);
129 fl_addto_tabfolder(dialog_->tabbed_folder,_("Extra"), extra_->form);
134 void FormParagraph::apply()
136 if (!lv_->view()->available() || !dialog_.get())
144 lv_->view()->update(lv_->view()->text,
145 BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
146 lv_->buffer()->markDirty();
147 setMinibuffer(lv_, _("Paragraph layout set"));
151 void FormParagraph::update()
160 bc_.readOnly(lv_->buffer()->isReadonly());
164 void FormParagraph::general_apply()
166 VSpace space_top, space_bottom;
168 string labelwidthstring;
171 // If a vspace kind is "Length" but there's no text in
172 // the input field, reset the kind to "None".
173 if ((fl_get_choice (general_->choice_space_above) == 7) &&
174 !*(fl_get_input (general_->input_space_above)))
176 fl_set_choice (general_->choice_space_above, 1);
178 if ((fl_get_choice (general_->choice_space_below) == 7) &&
179 !*(fl_get_input (general_->input_space_below)))
181 fl_set_choice (general_->choice_space_below, 1);
184 bool line_top = fl_get_button(general_->check_lines_top);
185 bool line_bottom = fl_get_button(general_->check_lines_bottom);
186 bool pagebreak_top = fl_get_button(general_->check_pagebreaks_top);
187 bool pagebreak_bottom = fl_get_button(general_->check_pagebreaks_bottom);
189 switch (fl_get_choice (general_->choice_space_above)) {
191 space_top = VSpace(VSpace::NONE);
194 space_top = VSpace(VSpace::DEFSKIP);
197 space_top = VSpace(VSpace::SMALLSKIP);
200 space_top = VSpace(VSpace::MEDSKIP);
203 space_top = VSpace(VSpace::BIGSKIP);
206 space_top = VSpace(VSpace::VFILL);
210 VSpace(LyXGlueLength(fl_get_input(general_->input_space_above)));
213 if (fl_get_button (general_->check_space_above))
214 space_top.setKeep (true);
215 switch (fl_get_choice (general_->choice_space_below)) {
217 space_bottom = VSpace(VSpace::NONE);
220 space_bottom = VSpace(VSpace::DEFSKIP);
223 space_bottom = VSpace(VSpace::SMALLSKIP);
226 space_bottom = VSpace(VSpace::MEDSKIP);
229 space_bottom = VSpace(VSpace::BIGSKIP);
232 space_bottom = VSpace(VSpace::VFILL);
236 VSpace(LyXGlueLength(fl_get_input(general_->input_space_below)));
239 if (fl_get_button (general_->check_space_below))
240 space_bottom.setKeep (true);
242 if (fl_get_button(general_->radio_align_left))
243 align = LYX_ALIGN_LEFT;
244 else if (fl_get_button(general_->radio_align_right))
245 align = LYX_ALIGN_RIGHT;
246 else if (fl_get_button(general_->radio_align_center))
247 align = LYX_ALIGN_CENTER;
249 align = LYX_ALIGN_BLOCK;
251 labelwidthstring = fl_get_input(general_->input_labelwidth);
252 noindent = fl_get_button(general_->check_noindent);
255 if (lv_->view()->theLockingInset())
256 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
258 text = lv_->view()->text;
259 text->SetParagraph(lv_->view(), line_top, line_bottom, pagebreak_top,
260 pagebreak_bottom, space_top, space_bottom, align,
261 labelwidthstring, noindent);
266 void FormParagraph::extra_apply()
268 char const * width = fl_get_input(extra_->input_pextra_width);
269 char const * widthp = fl_get_input(extra_->input_pextra_widthp);
270 LyXText * text = lv_->view()->text;
271 int type = LyXParagraph::PEXTRA_NONE;
272 LyXParagraph::MINIPAGE_ALIGNMENT
273 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
276 start_minipage = false;
278 if (fl_get_button(extra_->radio_pextra_indent)) {
279 type = LyXParagraph::PEXTRA_INDENT;
280 } else if (fl_get_button(extra_->radio_pextra_minipage)) {
281 type = LyXParagraph::PEXTRA_MINIPAGE;
282 hfill = fl_get_button(extra_->radio_pextra_hfill);
283 start_minipage = fl_get_button(extra_->radio_pextra_startmp);
284 if (fl_get_button(extra_->radio_pextra_top))
285 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
286 else if (fl_get_button(extra_->radio_pextra_middle))
287 alignment = LyXParagraph::MINIPAGE_ALIGN_MIDDLE;
288 else if (fl_get_button(extra_->radio_pextra_bottom))
289 alignment = LyXParagraph::MINIPAGE_ALIGN_BOTTOM;
290 } else if (fl_get_button(extra_->radio_pextra_floatflt)) {
291 type = LyXParagraph::PEXTRA_FLOATFLT;
293 text->SetParagraphExtraOpt(lv_->view(), type, width, widthp, alignment,
294 hfill, start_minipage);
299 void FormParagraph::general_update()
304 Buffer * buf = lv_->view()->buffer();
307 if (lv_->view()->theLockingInset())
308 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
310 text = lv_->view()->text;
312 fl_set_input(general_->input_labelwidth,
313 text->cursor.par()->GetLabelWidthString().c_str());
314 fl_set_button(general_->radio_align_right, 0);
315 fl_set_button(general_->radio_align_left, 0);
316 fl_set_button(general_->radio_align_center, 0);
317 fl_set_button(general_->radio_align_block, 0);
319 int align = text->cursor.par()->GetAlign();
320 if (align == LYX_ALIGN_LAYOUT)
321 align = textclasslist.Style(buf->params.textclass,
322 text->cursor.par()->GetLayout()).align;
325 case LYX_ALIGN_RIGHT:
326 fl_set_button(general_->radio_align_right, 1);
329 fl_set_button(general_->radio_align_left, 1);
331 case LYX_ALIGN_CENTER:
332 fl_set_button(general_->radio_align_center, 1);
335 fl_set_button(general_->radio_align_block, 1);
340 fl_set_button(general_->check_lines_top,
341 text->cursor.par()->FirstPhysicalPar()->params.lineTop());
343 fl_set_button(general_->check_lines_bottom,
344 text->cursor.par()->FirstPhysicalPar()->params.lineBottom());
346 fl_set_button(general_->check_pagebreaks_top,
347 text->cursor.par()->FirstPhysicalPar()->params.pagebreakTop());
349 fl_set_button(general_->check_pagebreaks_bottom,
350 text->cursor.par()->FirstPhysicalPar()->params.pagebreakBottom());
351 fl_set_button(general_->check_noindent,
352 text->cursor.par()->FirstPhysicalPar()->params.noindent());
354 fl_set_button(general_->check_lines_top,
355 text->cursor.par()->params.lineTop());
356 fl_set_button(general_->check_lines_bottom,
357 text->cursor.par()->params.lineBottom());
358 fl_set_button(general_->check_pagebreaks_top,
359 text->cursor.par()->params.pagebreakTop());
360 fl_set_button(general_->check_pagebreaks_bottom,
361 text->cursor.par()->params.pagebreakBottom());
362 fl_set_button(general_->check_noindent,
363 text->cursor.par()->params.noindent());
365 fl_set_input (general_->input_space_above, "");
368 switch (text->cursor.par()->FirstPhysicalPar()->params.spaceTop().kind()) {
370 switch (text->cursor.par()->params.spaceTop().kind()) {
374 fl_set_choice (general_->choice_space_above, 1);
376 case VSpace::DEFSKIP:
377 fl_set_choice (general_->choice_space_above, 2);
379 case VSpace::SMALLSKIP:
380 fl_set_choice (general_->choice_space_above, 3);
382 case VSpace::MEDSKIP:
383 fl_set_choice (general_->choice_space_above, 4);
385 case VSpace::BIGSKIP:
386 fl_set_choice (general_->choice_space_above, 5);
389 fl_set_choice (general_->choice_space_above, 6);
392 fl_set_choice (general_->choice_space_above, 7);
394 fl_set_input(general_->input_space_above,
395 text->cursor.par()->FirstPhysicalPar()->
396 params.spaceTop().length().asString().c_str());
398 fl_set_input(general_->input_space_above, text->cursor.par()->
399 params.spaceTop().length().asString().c_str());
404 fl_set_button(general_->check_space_above,
405 text->cursor.par()->FirstPhysicalPar()->
406 params.spaceTop().keep());
407 fl_set_input(general_->input_space_below, "");
408 switch (text->cursor.par()->FirstPhysicalPar()->
409 params.spaceBottom().kind()) {
411 fl_set_button (general_->check_space_above,
412 text->cursor.par()->params.spaceTop().keep());
413 fl_set_input (general_->input_space_below, "");
414 switch (text->cursor.par()->params.spaceBottom().kind()) {
417 fl_set_choice (general_->choice_space_below, 1);
419 case VSpace::DEFSKIP:
420 fl_set_choice (general_->choice_space_below, 2);
422 case VSpace::SMALLSKIP:
423 fl_set_choice (general_->choice_space_below, 3);
425 case VSpace::MEDSKIP:
426 fl_set_choice (general_->choice_space_below, 4);
428 case VSpace::BIGSKIP:
429 fl_set_choice (general_->choice_space_below, 5);
432 fl_set_choice (general_->choice_space_below, 6);
435 fl_set_choice (general_->choice_space_below, 7);
437 fl_set_input(general_->input_space_below,
438 text->cursor.par()->FirstPhysicalPar()->
439 params.spaceBottom().length().asString().c_str());
442 fl_set_button(general_->check_space_below,
443 text->cursor.par()->FirstPhysicalPar()->
444 params.spaceBottom().keep());
445 fl_set_button(general_->check_noindent,
446 text->cursor.par()->FirstPhysicalPar()->params.noindent());
448 bool const enable = (!text->cursor.par()->FirstPhysicalPar()->InInset());
450 setEnabled(general_->check_pagebreaks_top, enable);
451 setEnabled(general_->check_pagebreaks_bottom, enable);
454 fl_set_button(general_->check_pagebreaks_top, 0);
455 fl_set_button(general_->check_pagebreaks_bottom, 0);
459 fl_set_input(general_->input_space_below, text->cursor.par()->
460 params.spaceBottom().length().asString().c_str());
463 fl_set_button(general_->check_space_below,
464 text->cursor.par()->params.spaceBottom().keep());
465 fl_set_button(general_->check_noindent,
466 text->cursor.par()->params.noindent());
472 void FormParagraph::extra_update()
474 if (!lv_->view()->available() || !extra_.get())
477 LyXParagraph * par = lv_->view()->text->cursor.par();
479 setEnabled(extra_->input_pextra_width, true);
480 setEnabled(extra_->input_pextra_widthp, true);
482 fl_set_input(extra_->input_pextra_width,
483 par->params.pextraWidth().c_str());
484 fl_set_input(extra_->input_pextra_widthp,
485 par->params.pextraWidthp().c_str());
486 switch (par->params.pextraAlignment()) {
487 case LyXParagraph::MINIPAGE_ALIGN_TOP:
488 fl_set_button(extra_->radio_pextra_top, 1);
490 case LyXParagraph::MINIPAGE_ALIGN_MIDDLE:
491 fl_set_button(extra_->radio_pextra_middle, 1);
493 case LyXParagraph::MINIPAGE_ALIGN_BOTTOM:
494 fl_set_button(extra_->radio_pextra_bottom, 1);
497 fl_set_button(extra_->radio_pextra_hfill,
498 par->params.pextraHfill());
499 fl_set_button(extra_->radio_pextra_startmp,
500 par->params.pextraStartMinipage());
501 if (par->params.pextraType() == LyXParagraph::PEXTRA_INDENT) {
502 fl_set_button(extra_->radio_pextra_indent, 1);
503 fl_set_button(extra_->radio_pextra_minipage, 0);
504 fl_set_button(extra_->radio_pextra_floatflt, 0);
505 setEnabled(extra_->radio_pextra_top, false);
506 setEnabled(extra_->radio_pextra_middle, false);
507 setEnabled(extra_->radio_pextra_bottom, false);
508 input(extra_->radio_pextra_indent, 0);
509 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE) {
510 fl_set_button(extra_->radio_pextra_indent, 0);
511 fl_set_button(extra_->radio_pextra_minipage, 1);
512 fl_set_button(extra_->radio_pextra_floatflt, 0);
513 setEnabled(extra_->radio_pextra_top, true);
514 setEnabled(extra_->radio_pextra_middle, true);
515 setEnabled(extra_->radio_pextra_bottom, true);
516 input(extra_->radio_pextra_minipage, 0);
517 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_FLOATFLT) {
518 fl_set_button(extra_->radio_pextra_indent, 0);
519 fl_set_button(extra_->radio_pextra_minipage, 0);
520 fl_set_button(extra_->radio_pextra_floatflt, 1);
521 setEnabled(extra_->radio_pextra_top, false);
522 setEnabled(extra_->radio_pextra_middle, false);
523 setEnabled(extra_->radio_pextra_bottom, false);
524 input(extra_->radio_pextra_floatflt, 0);
526 fl_set_button(extra_->radio_pextra_indent, 0);
527 fl_set_button(extra_->radio_pextra_minipage, 0);
528 fl_set_button(extra_->radio_pextra_floatflt, 0);
529 setEnabled(extra_->input_pextra_width, false);
530 setEnabled(extra_->input_pextra_widthp, false);
531 setEnabled(extra_->radio_pextra_top, false);
532 setEnabled(extra_->radio_pextra_middle, false);
533 setEnabled(extra_->radio_pextra_bottom, false);
536 fl_hide_object(dialog_->text_warning);
541 bool FormParagraph::input(FL_OBJECT * ob, long)
545 fl_hide_object(dialog_->text_warning);
547 // First check the buttons which are exclusive and you have to
548 // check only the actuall de/activated button.
550 // general form first
552 // "Synchronize" the choices and input fields, making it
553 // impossible to commit senseless data.
555 if (fl_get_choice (general_->choice_space_above) != 7)
556 fl_set_input (general_->input_space_above, "");
558 if (fl_get_choice (general_->choice_space_below) != 7)
559 fl_set_input (general_->input_space_below, "");
563 // then the extra form
565 if (ob == extra_->radio_pextra_indent) {
566 bool const enable = (fl_get_button(extra_->radio_pextra_indent) != 0);
569 fl_set_button(extra_->radio_pextra_minipage, 0);
570 fl_set_button(extra_->radio_pextra_floatflt, 0);
573 setEnabled(extra_->input_pextra_width, enable);
574 setEnabled(extra_->input_pextra_widthp, enable);
576 setEnabled(extra_->radio_pextra_top, false);
577 setEnabled(extra_->radio_pextra_middle, false);
578 setEnabled(extra_->radio_pextra_bottom, false);
579 setEnabled(extra_->radio_pextra_hfill, false);
580 setEnabled(extra_->radio_pextra_startmp, false);
582 } else if (ob == extra_->radio_pextra_minipage) {
583 bool const enable = (fl_get_button(extra_->radio_pextra_minipage) != 0);
586 fl_set_button(extra_->radio_pextra_indent, 0);
587 fl_set_button(extra_->radio_pextra_floatflt, 0);
590 setEnabled(extra_->input_pextra_width, enable);
591 setEnabled(extra_->input_pextra_widthp, enable);
592 setEnabled(extra_->radio_pextra_top, enable);
593 setEnabled(extra_->radio_pextra_middle, enable);
594 setEnabled(extra_->radio_pextra_bottom, enable);
595 setEnabled(extra_->radio_pextra_hfill, enable);
596 setEnabled(extra_->radio_pextra_startmp, enable);
597 } else if (ob == extra_->radio_pextra_floatflt) {
598 bool const enable = (fl_get_button(extra_->radio_pextra_floatflt) != 0);
601 fl_set_button(extra_->radio_pextra_indent, 0);
602 fl_set_button(extra_->radio_pextra_minipage, 0);
605 setEnabled(extra_->input_pextra_width, enable);
606 setEnabled(extra_->input_pextra_widthp, enable);
608 setEnabled(extra_->radio_pextra_top, false);
609 setEnabled(extra_->radio_pextra_middle, false);
610 setEnabled(extra_->radio_pextra_bottom, false);
611 setEnabled(extra_->radio_pextra_hfill, false);
612 setEnabled(extra_->radio_pextra_startmp, false);
617 // first the general form
619 string input = fl_get_input (general_->input_space_above);
620 bool invalid = false;
622 if (fl_get_choice(general_->choice_space_above)==7)
623 invalid = !input.empty() && !isValidGlueLength(input);
625 input = fl_get_input (general_->input_space_below);
627 if (fl_get_choice(general_->choice_space_below)==7)
628 invalid = invalid || (!input.empty() && !isValidGlueLength(input));
630 if (ob == general_->input_space_above || ob == general_->input_space_below) {
632 fl_set_object_label(dialog_->text_warning,
633 _("Warning: Invalid Length (valid example: 10mm)"));
634 fl_show_object(dialog_->text_warning);
637 fl_hide_object(dialog_->text_warning);
644 // then the extra form
646 int n = fl_get_button(extra_->radio_pextra_indent) +
647 fl_get_button(extra_->radio_pextra_minipage) +
648 fl_get_button(extra_->radio_pextra_floatflt);
649 string s1 = fl_get_input(extra_->input_pextra_width);
650 string s2 = fl_get_input(extra_->input_pextra_widthp);
651 if (!n) { // no button pressed both should be deactivated now
652 setEnabled(extra_->input_pextra_width, false);
653 setEnabled(extra_->input_pextra_widthp, false);
654 fl_hide_object(dialog_->text_warning);
655 } else if (s1.empty() && s2.empty()) {
656 setEnabled(extra_->input_pextra_width, true);
657 setEnabled(extra_->input_pextra_widthp, true);
658 fl_hide_object(dialog_->text_warning);
660 } else if (!s1.empty()) { // LyXLength parameter
661 setEnabled(extra_->input_pextra_width, true);
662 setEnabled(extra_->input_pextra_widthp, false);
663 if (!isValidLength(s1)) {
664 fl_set_object_label(dialog_->text_warning,
665 _("Warning: Invalid Length (valid example: 10mm)"));
666 fl_show_object(dialog_->text_warning);
669 } else { // !s2.empty() % parameter
670 setEnabled(extra_->input_pextra_width, false);
671 setEnabled(extra_->input_pextra_widthp, true);
672 if ((lyx::atoi(s2) < 0 ) || (lyx::atoi(s2) > 100)) {
674 fl_set_object_label(dialog_->text_warning,
675 _("Warning: Invalid percent value (0-100)"));
676 fl_show_object(dialog_->text_warning);