1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 2000 The LyX Team.
10 *======================================================*/
15 #pragma implementation
18 #include "lyx_gui_misc.h"
20 #include FORMS_H_LOCATION
21 #include XPM_H_LOCATION
23 #include "FormParagraph.h"
24 #include "form_paragraph.h"
25 #include "xform_macros.h"
27 #include "ButtonController.h"
30 #include "BufferView.h"
34 #ifdef SIGC_CXX_NAMESPACES
38 #ifdef CXX_WORKING_NAMESPACES
39 using Liason::setMinibuffer;
42 C_RETURNCB(FormParagraph, WMHideCB)
43 C_GENERICCB(FormParagraph, InputCB)
44 C_GENERICCB(FormParagraph, OKCB)
45 C_GENERICCB(FormParagraph, ApplyCB)
46 C_GENERICCB(FormParagraph, CancelCB)
47 C_GENERICCB(FormParagraph, RestoreCB)
48 C_GENERICCB(FormParagraph, VSpaceCB)
50 FormParagraph::FormParagraph(LyXView * lv, Dialogs * d)
51 : dialog_(0), general_(0), extra_(0),
52 lv_(lv), d_(d), u_(0), h_(0),
53 status(POPUP_UNMODIFIED) ,
54 bc_(new ButtonController<NoRepeatedApplyReadOnlyPolicy>(_("Cancel"),
57 // let the popup be shown
58 // This is a permanent connection so we won't bother
59 // storing a copy because we won't be disconnecting.
60 d->showLayoutParagraph.connect(slot(this, &FormParagraph::show));
64 FormParagraph::~FormParagraph()
71 void FormParagraph::build()
74 dialog_ = build_tabbed_paragraph();
76 // manage the restore, ok, apply and cancel/close buttons
77 bc_->setOK(dialog_->button_ok);
78 bc_->setApply(dialog_->button_apply);
79 bc_->setCancel(dialog_->button_cancel);
80 bc_->setUndoAll(dialog_->button_restore);
83 // the general paragraph data form
84 general_ = build_paragraph_general();
86 fl_addto_choice(general_->choice_space_above,
87 _(" None | Defskip | Smallskip "
88 "| Medskip | Bigskip | VFill | Length "));
89 fl_addto_choice(general_->choice_space_below,
90 _(" None | Defskip | Smallskip "
91 "| Medskip | Bigskip | VFill | Length "));
93 fl_set_input_return(general_->input_space_above, FL_RETURN_CHANGED);
94 fl_set_input_return(general_->input_space_below, FL_RETURN_CHANGED);
95 fl_set_input_return(general_->input_labelwidth, FL_RETURN_CHANGED);
97 bc_->addReadOnly (general_->radio_align_right);
98 bc_->addReadOnly (general_->radio_align_left);
99 bc_->addReadOnly (general_->radio_align_block);
100 bc_->addReadOnly (general_->radio_align_center);
101 bc_->addReadOnly (general_->check_lines_top);
102 bc_->addReadOnly (general_->check_lines_bottom);
103 bc_->addReadOnly (general_->check_pagebreaks_top);
104 bc_->addReadOnly (general_->check_pagebreaks_bottom);
105 bc_->addReadOnly (general_->choice_space_above);
106 bc_->addReadOnly (general_->input_space_above);
107 bc_->addReadOnly (general_->check_space_above);
108 bc_->addReadOnly (general_->choice_space_below);
109 bc_->addReadOnly (general_->input_space_below);
110 bc_->addReadOnly (general_->check_space_below);
111 bc_->addReadOnly (general_->check_noindent);
112 bc_->addReadOnly (general_->input_labelwidth);
114 // the document class form
115 extra_ = build_paragraph_extra();
117 fl_set_input_return(extra_->input_pextra_width, FL_RETURN_CHANGED);
118 fl_set_input_return(extra_->input_pextra_widthp, FL_RETURN_CHANGED);
120 bc_->addReadOnly (extra_->radio_pextra_indent);
121 bc_->addReadOnly (extra_->radio_pextra_minipage);
122 bc_->addReadOnly (extra_->radio_pextra_floatflt);
123 bc_->addReadOnly (extra_->input_pextra_width);
124 bc_->addReadOnly (extra_->input_pextra_widthp);
125 bc_->addReadOnly (extra_->radio_pextra_top);
126 bc_->addReadOnly (extra_->radio_pextra_middle);
127 bc_->addReadOnly (extra_->radio_pextra_bottom);
128 bc_->addReadOnly (extra_->radio_pextra_hfill);
129 bc_->addReadOnly (extra_->radio_pextra_startmp);
131 // now make them fit together
132 fl_set_form_atclose(dialog_->form, C_FormParagraphWMHideCB, 0);
133 fl_addto_tabfolder(dialog_->tabbed_folder,_("General"), general_->form);
134 fl_addto_tabfolder(dialog_->tabbed_folder,_("Extra"), extra_->form);
138 void FormParagraph::show()
143 update(); // make sure its up-to-date
144 if (dialog_->form->visible) {
145 fl_raise_form(dialog_->form);
147 fl_show_form(dialog_->form, FL_PLACE_MOUSE | FL_FREE_SIZE,
148 FL_TRANSIENT, _("Paragraph Layout"));
149 u_ = d_->updateBufferDependent.connect(
150 slot(this, &FormParagraph::update));
151 h_ = d_->hideBufferDependent.connect(
152 slot(this, &FormParagraph::hide));
157 void FormParagraph::hide()
159 if (dialog_->form->visible) {
160 fl_hide_form(dialog_->form);
167 void FormParagraph::apply()
169 if (!lv_->view()->available() || !dialog_)
175 lv_->view()->update(BufferView::SELECT | BufferView::FITCUR |
177 lv_->buffer()->markDirty();
178 setMinibuffer(lv_, _("Paragraph layout set"));
182 void FormParagraph::general_apply()
184 VSpace space_top, space_bottom;
186 string labelwidthstring;
189 // If a vspace kind is "Length" but there's no text in
190 // the input field, reset the kind to "None".
191 if ((fl_get_choice (general_->choice_space_above) == 7) &&
192 !*(fl_get_input (general_->input_space_above)))
194 fl_set_choice (general_->choice_space_above, 1);
196 if ((fl_get_choice (general_->choice_space_below) == 7) &&
197 !*(fl_get_input (general_->input_space_below)))
199 fl_set_choice (general_->choice_space_below, 1);
202 bool line_top = fl_get_button(general_->check_lines_top);
203 bool line_bottom = fl_get_button(general_->check_lines_bottom);
204 bool pagebreak_top = fl_get_button(general_->check_pagebreaks_top);
205 bool pagebreak_bottom = fl_get_button(general_->check_pagebreaks_bottom);
207 switch (fl_get_choice (general_->choice_space_above)) {
209 space_top = VSpace(VSpace::NONE);
212 space_top = VSpace(VSpace::DEFSKIP);
215 space_top = VSpace(VSpace::SMALLSKIP);
218 space_top = VSpace(VSpace::MEDSKIP);
221 space_top = VSpace(VSpace::BIGSKIP);
224 space_top = VSpace(VSpace::VFILL);
227 space_top = VSpace(LyXGlueLength(fl_get_input(general_->input_space_above)));
230 if (fl_get_button (general_->check_space_above))
231 space_top.setKeep (true);
232 switch (fl_get_choice (general_->choice_space_below)) {
234 space_bottom = VSpace(VSpace::NONE);
237 space_bottom = VSpace(VSpace::DEFSKIP);
240 space_bottom = VSpace(VSpace::SMALLSKIP);
243 space_bottom = VSpace(VSpace::MEDSKIP);
246 space_bottom = VSpace(VSpace::BIGSKIP);
249 space_bottom = VSpace(VSpace::VFILL);
252 space_bottom = VSpace(LyXGlueLength(fl_get_input(general_->input_space_below)));
255 if (fl_get_button (general_->check_space_below))
256 space_bottom.setKeep (true);
258 if (fl_get_button(general_->radio_align_left))
259 align = LYX_ALIGN_LEFT;
260 else if (fl_get_button(general_->radio_align_right))
261 align = LYX_ALIGN_RIGHT;
262 else if (fl_get_button(general_->radio_align_center))
263 align = LYX_ALIGN_CENTER;
265 align = LYX_ALIGN_BLOCK;
267 labelwidthstring = fl_get_input(general_->input_labelwidth);
268 noindent = fl_get_button(general_->check_noindent);
271 if (lv_->view()->the_locking_inset)
272 text = lv_->view()->the_locking_inset->getLyXText(lv_->view());
274 text = lv_->view()->text;
275 text->SetParagraph(lv_->view(), line_top, line_bottom, pagebreak_top,
276 pagebreak_bottom, space_top, space_bottom, align,
277 labelwidthstring, noindent);
281 void FormParagraph::extra_apply()
283 char const * width = fl_get_input(extra_->input_pextra_width);
284 char const * widthp = fl_get_input(extra_->input_pextra_widthp);
285 LyXText * text = lv_->view()->text;
286 int type = LyXParagraph::PEXTRA_NONE;
287 LyXParagraph::MINIPAGE_ALIGNMENT
288 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
291 start_minipage = false;
293 if (fl_get_button(extra_->radio_pextra_indent)) {
294 type = LyXParagraph::PEXTRA_INDENT;
295 } else if (fl_get_button(extra_->radio_pextra_minipage)) {
296 type = LyXParagraph::PEXTRA_MINIPAGE;
297 hfill = fl_get_button(extra_->radio_pextra_hfill);
298 start_minipage = fl_get_button(extra_->radio_pextra_startmp);
299 if (fl_get_button(extra_->radio_pextra_top))
300 alignment = LyXParagraph::MINIPAGE_ALIGN_TOP;
301 else if (fl_get_button(extra_->radio_pextra_middle))
302 alignment = LyXParagraph::MINIPAGE_ALIGN_MIDDLE;
303 else if (fl_get_button(extra_->radio_pextra_bottom))
304 alignment = LyXParagraph::MINIPAGE_ALIGN_BOTTOM;
305 } else if (fl_get_button(extra_->radio_pextra_floatflt)) {
306 type = LyXParagraph::PEXTRA_FLOATFLT;
308 text->SetParagraphExtraOpt(lv_->view(), type, width, widthp, alignment,
309 hfill, start_minipage);
313 void FormParagraph::cancel()
318 void FormParagraph::update()
328 void FormParagraph::general_update()
333 Buffer * buf = lv_->view()->buffer();
336 if (lv_->view()->the_locking_inset)
337 text = lv_->view()->the_locking_inset->getLyXText(lv_->view());
339 text = lv_->view()->text;
341 fl_set_input(general_->input_labelwidth,
342 text->cursor.par()->GetLabelWidthString().c_str());
343 fl_set_button(general_->radio_align_right, 0);
344 fl_set_button(general_->radio_align_left, 0);
345 fl_set_button(general_->radio_align_center, 0);
346 fl_set_button(general_->radio_align_block, 0);
348 int align = text->cursor.par()->GetAlign();
349 if (align == LYX_ALIGN_LAYOUT)
350 align = textclasslist.Style(buf->params.textclass,
351 text->cursor.par()->GetLayout()).align;
354 case LYX_ALIGN_RIGHT:
355 fl_set_button(general_->radio_align_right, 1);
358 fl_set_button(general_->radio_align_left, 1);
360 case LYX_ALIGN_CENTER:
361 fl_set_button(general_->radio_align_center, 1);
364 fl_set_button(general_->radio_align_block, 1);
369 fl_set_button(general_->check_lines_top,
370 text->cursor.par()->FirstPhysicalPar()->line_top);
372 fl_set_button(general_->check_lines_bottom,
373 text->cursor.par()->FirstPhysicalPar()->line_bottom);
375 fl_set_button(general_->check_pagebreaks_top,
376 text->cursor.par()->FirstPhysicalPar()->pagebreak_top);
378 fl_set_button(general_->check_pagebreaks_bottom,
379 text->cursor.par()->FirstPhysicalPar()->pagebreak_bottom);
380 fl_set_button(general_->check_noindent,
381 text->cursor.par()->FirstPhysicalPar()->noindent);
383 fl_set_button(general_->check_lines_top,
384 text->cursor.par()->line_top);
385 fl_set_button(general_->check_lines_bottom,
386 text->cursor.par()->line_bottom);
387 fl_set_button(general_->check_pagebreaks_top,
388 text->cursor.par()->pagebreak_top);
389 fl_set_button(general_->check_pagebreaks_bottom,
390 text->cursor.par()->pagebreak_bottom);
391 fl_set_button(general_->check_noindent,
392 text->cursor.par()->noindent);
394 fl_set_input (general_->input_space_above, "");
397 switch (text->cursor.par()->FirstPhysicalPar()->added_space_top.kind()) {
399 switch (text->cursor.par()->added_space_top.kind()) {
403 fl_set_choice (general_->choice_space_above, 1);
405 case VSpace::DEFSKIP:
406 fl_set_choice (general_->choice_space_above, 2);
408 case VSpace::SMALLSKIP:
409 fl_set_choice (general_->choice_space_above, 3);
411 case VSpace::MEDSKIP:
412 fl_set_choice (general_->choice_space_above, 4);
414 case VSpace::BIGSKIP:
415 fl_set_choice (general_->choice_space_above, 5);
418 fl_set_choice (general_->choice_space_above, 6);
421 fl_set_choice (general_->choice_space_above, 7);
423 fl_set_input (general_->input_space_above,
424 text->cursor.par()->FirstPhysicalPar()->
425 added_space_top.length().asString().c_str());
427 fl_set_input (general_->input_space_above, text->cursor.par()->
428 added_space_top.length().asString().c_str());
433 fl_set_button(general_->check_space_above,
434 text->cursor.par()->FirstPhysicalPar()->
435 added_space_top.keep());
436 fl_set_input(general_->input_space_below, "");
437 switch (text->cursor.par()->FirstPhysicalPar()->
438 added_space_bottom.kind()) {
440 fl_set_button (general_->check_space_above,
441 text->cursor.par()->added_space_top.keep());
442 fl_set_input (general_->input_space_below, "");
443 switch (text->cursor.par()->added_space_bottom.kind()) {
446 fl_set_choice (general_->choice_space_below, 1);
448 case VSpace::DEFSKIP:
449 fl_set_choice (general_->choice_space_below, 2);
451 case VSpace::SMALLSKIP:
452 fl_set_choice (general_->choice_space_below, 3);
454 case VSpace::MEDSKIP:
455 fl_set_choice (general_->choice_space_below, 4);
457 case VSpace::BIGSKIP:
458 fl_set_choice (general_->choice_space_below, 5);
461 fl_set_choice (general_->choice_space_below, 6);
464 fl_set_choice (general_->choice_space_below, 7);
466 fl_set_input (general_->input_space_below,
467 text->cursor.par()->FirstPhysicalPar()->
468 added_space_bottom.length().asString().c_str());
471 fl_set_button(general_->check_space_below,
472 text->cursor.par()->FirstPhysicalPar()->
473 added_space_bottom.keep());
474 fl_set_button(general_->check_noindent,
475 text->cursor.par()->FirstPhysicalPar()->noindent);
477 fl_set_input(general_->input_space_below, text->cursor.par()->
478 added_space_bottom.length().asString().c_str());
481 fl_set_button(general_->check_space_below,
482 text->cursor.par()->added_space_bottom.keep());
483 fl_set_button(general_->check_noindent,
484 text->cursor.par()->noindent);
489 void FormParagraph::extra_update()
491 if (!lv_->view()->available() || !extra_)
494 LyXParagraph * par = lv_->view()->text->cursor.par();
496 fl_activate_object(extra_->input_pextra_width);
497 fl_activate_object(extra_->input_pextra_widthp);
498 fl_set_input(extra_->input_pextra_width,
499 par->pextra_width.c_str());
500 fl_set_input(extra_->input_pextra_widthp,
501 par->pextra_widthp.c_str());
502 switch(par->pextra_alignment) {
503 case LyXParagraph::MINIPAGE_ALIGN_TOP:
504 fl_set_button(extra_->radio_pextra_top, 1);
506 case LyXParagraph::MINIPAGE_ALIGN_MIDDLE:
507 fl_set_button(extra_->radio_pextra_middle, 1);
509 case LyXParagraph::MINIPAGE_ALIGN_BOTTOM:
510 fl_set_button(extra_->radio_pextra_bottom, 1);
513 fl_set_button(extra_->radio_pextra_hfill,
515 fl_set_button(extra_->radio_pextra_startmp,
516 par->pextra_start_minipage);
517 // CheckInputWidth();
518 if (par->pextra_type == LyXParagraph::PEXTRA_INDENT) {
519 fl_set_button(extra_->radio_pextra_indent, 1);
520 fl_set_button(extra_->radio_pextra_minipage, 0);
521 fl_set_button(extra_->radio_pextra_floatflt, 0);
522 fl_deactivate_object(extra_->radio_pextra_top);
523 fl_deactivate_object(extra_->radio_pextra_middle);
524 fl_deactivate_object(extra_->radio_pextra_bottom);
525 } else if (par->pextra_type == LyXParagraph::PEXTRA_MINIPAGE) {
526 fl_set_button(extra_->radio_pextra_indent, 0);
527 fl_set_button(extra_->radio_pextra_minipage, 1);
528 fl_set_button(extra_->radio_pextra_floatflt, 0);
529 fl_activate_object(extra_->radio_pextra_top);
530 fl_activate_object(extra_->radio_pextra_middle);
531 fl_activate_object(extra_->radio_pextra_bottom);
532 } else if (par->pextra_type == LyXParagraph::PEXTRA_FLOATFLT) {
533 fl_set_button(extra_->radio_pextra_indent, 0);
534 fl_set_button(extra_->radio_pextra_minipage, 0);
535 fl_set_button(extra_->radio_pextra_floatflt, 1);
536 fl_deactivate_object(extra_->radio_pextra_top);
537 fl_deactivate_object(extra_->radio_pextra_middle);
538 fl_deactivate_object(extra_->radio_pextra_bottom);
540 fl_set_button(extra_->radio_pextra_indent, 0);
541 fl_set_button(extra_->radio_pextra_minipage, 0);
542 fl_deactivate_object(extra_->input_pextra_width);
543 fl_deactivate_object(extra_->input_pextra_widthp);
544 fl_deactivate_object(extra_->radio_pextra_top);
545 fl_deactivate_object(extra_->radio_pextra_middle);
546 fl_deactivate_object(extra_->radio_pextra_bottom);
548 // if (par->pextra_type == LyXParagraph::PEXTRA_NONE)
549 // ActivateParagraphExtraButtons();
551 fl_hide_object(extra_->text_warning);
555 void FormParagraph::free()
560 // fl_free_form(general_->form);
565 // fl_free_form(extra_->form);
569 // fl_free_form(dialog_->form);
576 int FormParagraph::WMHideCB(FL_FORM * form, void *)
578 // Ensure that the signals (u and h) are disconnected even if the
579 // window manager is used to close the popup.
580 FormParagraph * pre = static_cast<FormParagraph*>(form->u_vdata);
587 void FormParagraph::OKCB(FL_OBJECT * ob, long)
589 FormParagraph * pre = static_cast<FormParagraph*>(ob->form->u_vdata);
596 void FormParagraph::ApplyCB(FL_OBJECT * ob, long)
598 FormParagraph * pre = static_cast<FormParagraph*>(ob->form->u_vdata);
604 void FormParagraph::CancelCB(FL_OBJECT * ob, long)
606 FormParagraph * pre = static_cast<FormParagraph*>(ob->form->u_vdata);
613 void FormParagraph::RestoreCB(FL_OBJECT * ob, long)
615 FormParagraph * pre = static_cast<FormParagraph*>(ob->form->u_vdata);
621 void FormParagraph::InputCB(FL_OBJECT * ob, long)
623 FormParagraph * pre = static_cast<FormParagraph*>(ob->form->u_vdata);
624 pre->bc_->valid(pre->CheckParagraphInput(ob,0));
628 void FormParagraph::VSpaceCB(FL_OBJECT * ob, long)
630 FormParagraph * pre = static_cast<FormParagraph*>(ob->form->u_vdata);
631 pre->bc_->valid(pre->CheckParagraphInput(ob,0));
635 bool FormParagraph::CheckParagraphInput(FL_OBJECT * ob, long)
639 fl_hide_object(extra_->text_warning);
642 // first the general form
644 // "Synchronize" the choices and input fields, making it
645 // impossible to commit senseless data.
646 if (ob == general_->choice_space_above) {
647 if (fl_get_choice (general_->choice_space_above) != 7)
648 fl_set_input (general_->input_space_above, "");
649 } else if (ob == general_->choice_space_below) {
650 if (fl_get_choice (general_->choice_space_below) != 7)
651 fl_set_input (general_->input_space_below, "");
654 string input = fl_get_input (general_->input_space_above);
657 fl_set_choice (general_->choice_space_above, 1);
658 } else if (isValidGlueLength (input)) {
659 fl_set_choice (general_->choice_space_above, 7);
661 fl_set_choice (general_->choice_space_above, 7);
665 input = fl_get_input (general_->input_space_below);
668 fl_set_choice (general_->choice_space_below, 1);
669 } else if (isValidGlueLength (input)) {
670 fl_set_choice (general_->choice_space_below, 7);
672 fl_set_choice (general_->choice_space_below, 7);
676 // then the extra form
678 string s1 = fl_get_input(extra_->input_pextra_width);
679 string s2 = fl_get_input(extra_->input_pextra_widthp);
680 if (s1.empty() && s2.empty()) {
681 fl_activate_object(extra_->input_pextra_width);
682 fl_activate_object(extra_->input_pextra_widthp);
683 fl_hide_object(extra_->text_warning);
686 if (!s1.empty()) { // LyXLength parameter
687 fl_activate_object(extra_->input_pextra_width);
688 fl_deactivate_object(extra_->input_pextra_widthp);
689 if (!isValidLength(s1)) {
690 fl_set_object_label(extra_->text_warning,
691 _("Warning: Invalid Length (valid example: 10mm)"));
692 fl_show_object(extra_->text_warning);
695 } else { // !s2.empty() % parameter
696 fl_deactivate_object(extra_->input_pextra_width);
697 fl_activate_object(extra_->input_pextra_widthp);
698 if ((atoi(s2.c_str()) < 0 ) || (atoi(s2.c_str()) > 100)) {
700 fl_set_object_label(extra_->text_warning,
701 _("Warning: Invalid percent value (0-100)"));
702 fl_show_object(extra_->text_warning);