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 #ifdef CXX_WORKING_NAMESPACES
30 using Liason::setMinibuffer;
33 FormParagraph::FormParagraph(LyXView * lv, Dialogs * d)
34 : FormBaseBD(lv, d, _("Paragraph Layout"),
35 new NoRepeatedApplyReadOnlyPolicy),
36 dialog_(0), general_(0), extra_(0)
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 FormParagraph::~FormParagraph()
53 void FormParagraph::redraw()
55 if( form() && form()->visible )
56 fl_redraw_form( form() );
60 FL_FORM * outer_form = fl_get_active_folder(dialog_->tabbed_folder);
61 if (outer_form && outer_form->visible)
62 fl_redraw_form( outer_form );
66 FL_FORM * FormParagraph::form() const
68 if (dialog_) return dialog_->form;
73 void FormParagraph::build()
76 dialog_ = build_tabbed_paragraph();
78 // Workaround dumb xforms sizing bug
82 // Manage the ok, apply, restore and cancel/close buttons
83 bc_.setOK(dialog_->button_ok);
84 bc_.setApply(dialog_->button_apply);
85 bc_.setCancel(dialog_->button_cancel);
86 bc_.setUndoAll(dialog_->button_restore);
89 // the general paragraph data form
90 general_ = build_paragraph_general();
92 fl_addto_choice(general_->choice_space_above,
93 _(" None | Defskip | Smallskip "
94 "| Medskip | Bigskip | VFill | Length "));
95 fl_addto_choice(general_->choice_space_below,
96 _(" None | Defskip | Smallskip "
97 "| Medskip | Bigskip | VFill | Length "));
99 fl_set_input_return(general_->input_space_above, FL_RETURN_CHANGED);
100 fl_set_input_return(general_->input_space_below, FL_RETURN_CHANGED);
101 fl_set_input_return(general_->input_labelwidth, FL_RETURN_CHANGED);
103 bc_.addReadOnly (general_->radio_align_right);
104 bc_.addReadOnly (general_->radio_align_left);
105 bc_.addReadOnly (general_->radio_align_block);
106 bc_.addReadOnly (general_->radio_align_center);
107 bc_.addReadOnly (general_->check_lines_top);
108 bc_.addReadOnly (general_->check_lines_bottom);
109 bc_.addReadOnly (general_->check_pagebreaks_top);
110 bc_.addReadOnly (general_->check_pagebreaks_bottom);
111 bc_.addReadOnly (general_->choice_space_above);
112 bc_.addReadOnly (general_->input_space_above);
113 bc_.addReadOnly (general_->check_space_above);
114 bc_.addReadOnly (general_->choice_space_below);
115 bc_.addReadOnly (general_->input_space_below);
116 bc_.addReadOnly (general_->check_space_below);
117 bc_.addReadOnly (general_->check_noindent);
118 bc_.addReadOnly (general_->input_labelwidth);
120 // the document class form
121 extra_ = build_paragraph_extra();
123 fl_set_input_return(extra_->input_pextra_width, FL_RETURN_CHANGED);
124 fl_set_input_return(extra_->input_pextra_widthp, FL_RETURN_CHANGED);
126 bc_.addReadOnly (extra_->radio_pextra_indent);
127 bc_.addReadOnly (extra_->radio_pextra_minipage);
128 bc_.addReadOnly (extra_->radio_pextra_floatflt);
129 bc_.addReadOnly (extra_->radio_pextra_hfill);
130 bc_.addReadOnly (extra_->radio_pextra_startmp);
132 // now make them fit together
133 fl_addto_tabfolder(dialog_->tabbed_folder,_("General"), general_->form);
134 fl_addto_tabfolder(dialog_->tabbed_folder,_("Extra"), extra_->form);
138 void FormParagraph::apply()
140 if (!lv_->view()->available() || !dialog_)
146 lv_->view()->update(lv_->view()->text,
147 BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
148 lv_->buffer()->markDirty();
149 setMinibuffer(lv_, _("Paragraph layout set"));
153 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);
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);
297 void FormParagraph::general_update()
302 Buffer * buf = lv_->view()->buffer();
305 if (lv_->view()->theLockingInset())
306 text = lv_->view()->theLockingInset()->getLyXText(lv_->view());
308 text = lv_->view()->text;
310 fl_set_input(general_->input_labelwidth,
311 text->cursor.par()->GetLabelWidthString().c_str());
312 fl_set_button(general_->radio_align_right, 0);
313 fl_set_button(general_->radio_align_left, 0);
314 fl_set_button(general_->radio_align_center, 0);
315 fl_set_button(general_->radio_align_block, 0);
317 int align = text->cursor.par()->GetAlign();
318 if (align == LYX_ALIGN_LAYOUT)
319 align = textclasslist.Style(buf->params.textclass,
320 text->cursor.par()->GetLayout()).align;
323 case LYX_ALIGN_RIGHT:
324 fl_set_button(general_->radio_align_right, 1);
327 fl_set_button(general_->radio_align_left, 1);
329 case LYX_ALIGN_CENTER:
330 fl_set_button(general_->radio_align_center, 1);
333 fl_set_button(general_->radio_align_block, 1);
338 fl_set_button(general_->check_lines_top,
339 text->cursor.par()->FirstPhysicalPar()->params.lineTop());
341 fl_set_button(general_->check_lines_bottom,
342 text->cursor.par()->FirstPhysicalPar()->params.lineBottom());
344 fl_set_button(general_->check_pagebreaks_top,
345 text->cursor.par()->FirstPhysicalPar()->params.pagebreakTop());
347 fl_set_button(general_->check_pagebreaks_bottom,
348 text->cursor.par()->FirstPhysicalPar()->params.pagebreakBottom());
349 fl_set_button(general_->check_noindent,
350 text->cursor.par()->FirstPhysicalPar()->params.noindent());
352 fl_set_button(general_->check_lines_top,
353 text->cursor.par()->params.lineTop());
354 fl_set_button(general_->check_lines_bottom,
355 text->cursor.par()->params.lineBottom());
356 fl_set_button(general_->check_pagebreaks_top,
357 text->cursor.par()->params.pagebreakTop());
358 fl_set_button(general_->check_pagebreaks_bottom,
359 text->cursor.par()->params.pagebreakBottom());
360 fl_set_button(general_->check_noindent,
361 text->cursor.par()->params.noindent());
363 fl_set_input (general_->input_space_above, "");
366 switch (text->cursor.par()->FirstPhysicalPar()->params.spaceTop().kind()) {
368 switch (text->cursor.par()->params.spaceTop().kind()) {
372 fl_set_choice (general_->choice_space_above, 1);
374 case VSpace::DEFSKIP:
375 fl_set_choice (general_->choice_space_above, 2);
377 case VSpace::SMALLSKIP:
378 fl_set_choice (general_->choice_space_above, 3);
380 case VSpace::MEDSKIP:
381 fl_set_choice (general_->choice_space_above, 4);
383 case VSpace::BIGSKIP:
384 fl_set_choice (general_->choice_space_above, 5);
387 fl_set_choice (general_->choice_space_above, 6);
390 fl_set_choice (general_->choice_space_above, 7);
392 fl_set_input(general_->input_space_above,
393 text->cursor.par()->FirstPhysicalPar()->
394 params.spaceTop().length().asString().c_str());
396 fl_set_input(general_->input_space_above, text->cursor.par()->
397 params.spaceTop().length().asString().c_str());
402 fl_set_button(general_->check_space_above,
403 text->cursor.par()->FirstPhysicalPar()->
404 params.spaceTop().keep());
405 fl_set_input(general_->input_space_below, "");
406 switch (text->cursor.par()->FirstPhysicalPar()->
407 params.spaceBottom().kind()) {
409 fl_set_button (general_->check_space_above,
410 text->cursor.par()->params.spaceTop().keep());
411 fl_set_input (general_->input_space_below, "");
412 switch (text->cursor.par()->params.spaceBottom().kind()) {
415 fl_set_choice (general_->choice_space_below, 1);
417 case VSpace::DEFSKIP:
418 fl_set_choice (general_->choice_space_below, 2);
420 case VSpace::SMALLSKIP:
421 fl_set_choice (general_->choice_space_below, 3);
423 case VSpace::MEDSKIP:
424 fl_set_choice (general_->choice_space_below, 4);
426 case VSpace::BIGSKIP:
427 fl_set_choice (general_->choice_space_below, 5);
430 fl_set_choice (general_->choice_space_below, 6);
433 fl_set_choice (general_->choice_space_below, 7);
435 fl_set_input(general_->input_space_below,
436 text->cursor.par()->FirstPhysicalPar()->
437 params.spaceBottom().length().asString().c_str());
440 fl_set_button(general_->check_space_below,
441 text->cursor.par()->FirstPhysicalPar()->
442 params.spaceBottom().keep());
443 fl_set_button(general_->check_noindent,
444 text->cursor.par()->FirstPhysicalPar()->params.noindent());
446 bool const enable = (!text->cursor.par()->FirstPhysicalPar()->InInset());
448 setEnabled(general_->check_pagebreaks_top, enable);
449 setEnabled(general_->check_pagebreaks_bottom, enable);
452 fl_set_button(general_->check_pagebreaks_top, 0);
453 fl_set_button(general_->check_pagebreaks_bottom, 0);
457 fl_set_input(general_->input_space_below, text->cursor.par()->
458 params.spaceBottom().length().asString().c_str());
461 fl_set_button(general_->check_space_below,
462 text->cursor.par()->params.spaceBottom().keep());
463 fl_set_button(general_->check_noindent,
464 text->cursor.par()->params.noindent());
469 void FormParagraph::extra_update()
471 if (!lv_->view()->available() || !extra_)
474 LyXParagraph * par = lv_->view()->text->cursor.par();
476 setEnabled(extra_->input_pextra_width, true);
477 setEnabled(extra_->input_pextra_widthp, true);
479 fl_set_input(extra_->input_pextra_width,
480 par->params.pextraWidth().c_str());
481 fl_set_input(extra_->input_pextra_widthp,
482 par->params.pextraWidthp().c_str());
483 switch (par->params.pextraAlignment()) {
484 case LyXParagraph::MINIPAGE_ALIGN_TOP:
485 fl_set_button(extra_->radio_pextra_top, 1);
487 case LyXParagraph::MINIPAGE_ALIGN_MIDDLE:
488 fl_set_button(extra_->radio_pextra_middle, 1);
490 case LyXParagraph::MINIPAGE_ALIGN_BOTTOM:
491 fl_set_button(extra_->radio_pextra_bottom, 1);
494 fl_set_button(extra_->radio_pextra_hfill,
495 par->params.pextraHfill());
496 fl_set_button(extra_->radio_pextra_startmp,
497 par->params.pextraStartMinipage());
498 if (par->params.pextraType() == LyXParagraph::PEXTRA_INDENT) {
499 fl_set_button(extra_->radio_pextra_indent, 1);
500 fl_set_button(extra_->radio_pextra_minipage, 0);
501 fl_set_button(extra_->radio_pextra_floatflt, 0);
502 setEnabled(extra_->radio_pextra_top, false);
503 setEnabled(extra_->radio_pextra_middle, false);
504 setEnabled(extra_->radio_pextra_bottom, false);
505 input(extra_->radio_pextra_indent, 0);
506 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE) {
507 fl_set_button(extra_->radio_pextra_indent, 0);
508 fl_set_button(extra_->radio_pextra_minipage, 1);
509 fl_set_button(extra_->radio_pextra_floatflt, 0);
510 setEnabled(extra_->radio_pextra_top, true);
511 setEnabled(extra_->radio_pextra_middle, true);
512 setEnabled(extra_->radio_pextra_bottom, true);
513 input(extra_->radio_pextra_minipage, 0);
514 } else if (par->params.pextraType() == LyXParagraph::PEXTRA_FLOATFLT) {
515 fl_set_button(extra_->radio_pextra_indent, 0);
516 fl_set_button(extra_->radio_pextra_minipage, 0);
517 fl_set_button(extra_->radio_pextra_floatflt, 1);
518 setEnabled(extra_->radio_pextra_top, false);
519 setEnabled(extra_->radio_pextra_middle, false);
520 setEnabled(extra_->radio_pextra_bottom, false);
521 input(extra_->radio_pextra_floatflt, 0);
523 fl_set_button(extra_->radio_pextra_indent, 0);
524 fl_set_button(extra_->radio_pextra_minipage, 0);
525 fl_set_button(extra_->radio_pextra_floatflt, 0);
526 setEnabled(extra_->input_pextra_width, false);
527 setEnabled(extra_->input_pextra_widthp, false);
528 setEnabled(extra_->radio_pextra_top, false);
529 setEnabled(extra_->radio_pextra_middle, false);
530 setEnabled(extra_->radio_pextra_bottom, false);
533 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, "");
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);
611 // first the general form
613 string input = fl_get_input (general_->input_space_above);
614 bool invalid = false;
616 if (fl_get_choice(general_->choice_space_above)==7)
617 invalid = !input.empty() && !isValidGlueLength(input);
619 input = fl_get_input (general_->input_space_below);
621 if (fl_get_choice(general_->choice_space_below)==7)
622 invalid = invalid || (!input.empty() && !isValidGlueLength(input));
624 if (ob == general_->input_space_above || ob == general_->input_space_below) {
626 fl_set_object_label(dialog_->text_warning,
627 _("Warning: Invalid Length (valid example: 10mm)"));
628 fl_show_object(dialog_->text_warning);
631 fl_hide_object(dialog_->text_warning);
637 // then the extra form
639 int n = fl_get_button(extra_->radio_pextra_indent) +
640 fl_get_button(extra_->radio_pextra_minipage) +
641 fl_get_button(extra_->radio_pextra_floatflt);
642 string s1 = fl_get_input(extra_->input_pextra_width);
643 string s2 = fl_get_input(extra_->input_pextra_widthp);
644 if (!n) { // no button pressed both should be deactivated now
645 setEnabled(extra_->input_pextra_width, false);
646 setEnabled(extra_->input_pextra_widthp, false);
647 fl_hide_object(dialog_->text_warning);
648 } else if (s1.empty() && s2.empty()) {
649 setEnabled(extra_->input_pextra_width, true);
650 setEnabled(extra_->input_pextra_widthp, true);
651 fl_hide_object(dialog_->text_warning);
653 } else if (!s1.empty()) { // LyXLength parameter
654 setEnabled(extra_->input_pextra_width, true);
655 setEnabled(extra_->input_pextra_widthp, false);
656 if (!isValidLength(s1)) {
657 fl_set_object_label(dialog_->text_warning,
658 _("Warning: Invalid Length (valid example: 10mm)"));
659 fl_show_object(dialog_->text_warning);
662 } else { // !s2.empty() % parameter
663 setEnabled(extra_->input_pextra_width, false);
664 setEnabled(extra_->input_pextra_widthp, true);
665 if ((lyx::atoi(s2) < 0 ) || (lyx::atoi(s2) > 100)) {
667 fl_set_object_label(dialog_->text_warning,
668 _("Warning: Invalid percent value (0-100)"));
669 fl_show_object(dialog_->text_warning);