3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS
14 #pragma implementation
17 #include "ControlTabular.h"
18 #include "insets/insettabular.h"
20 #include "support/lstrings.h"
22 #include "QTabularDialog.h"
26 #include <qpushbutton.h>
27 #include <qlineedit.h>
28 #include <qcheckbox.h>
30 typedef Qt2CB<ControlTabular, Qt2DB<QTabularDialog> > base_class;
33 : base_class(_("LyX: Edit Table"))
38 void QTabular::build_dialog()
40 dialog_.reset(new QTabularDialog(this));
42 bc().setCancel(dialog_->closePB);
46 bool QTabular::isValid()
52 void QTabular::update_contents()
54 LyXTabular * tabular(controller().tabular());
55 int cell(controller().inset()->getActCell());
57 int row(tabular->row_of_cell(cell));
58 int col(tabular->column_of_cell(cell));
60 dialog_->tabularRowED->setText(tostr(row + 1).c_str());
61 dialog_->tabularColumnED->setText(tostr(col + 1).c_str());
63 bool const multicol(tabular->IsMultiColumn(cell));
65 dialog_->MulticolumnCB->setChecked(multicol);
67 dialog_->rotateCellCB->setChecked(tabular->GetRotateCell(cell));
68 dialog_->rotateTabularCB->setChecked(tabular->GetRotateTabular());
70 dialog_->LongtabularCB->setChecked(tabular->IsLongTabular());
73 if (tabular->IsMultiColumn(cell)) {
74 fl_set_button(cell_options_->check_border_top,
75 tabular->TopLine(cell)?1:0);
76 setEnabled(cell_options_->check_border_top, true);
77 fl_set_button(cell_options_->check_border_bottom,
78 tabular->BottomLine(cell)?1:0);
79 setEnabled(cell_options_->check_border_bottom, true);
80 // pay attention to left/right lines they are only allowed
81 // to set if we are in first/last cell of row or if the left/right
82 // cell is also a multicolumn.
83 if (tabular->IsFirstCellInRow(cell) ||
84 tabular->IsMultiColumn(cell-1)) {
85 fl_set_button(cell_options_->check_border_left,
86 tabular->LeftLine(cell)?1:0);
87 setEnabled(cell_options_->check_border_left, true);
89 fl_set_button(cell_options_->check_border_left, 0);
90 setEnabled(cell_options_->check_border_left, false);
92 if (tabular->IsLastCellInRow(cell) ||
93 tabular->IsMultiColumn(cell+1)) {
94 fl_set_button(cell_options_->check_border_right,
95 tabular->RightLine(cell)?1:0);
96 setEnabled(cell_options_->check_border_right, true);
98 fl_set_button(cell_options_->check_border_right, 0);
99 setEnabled(cell_options_->check_border_right, false);
101 pwidth = tabular->GetMColumnPWidth(cell);
102 align = tabular->GetAlignment(cell);
103 if (align == LYX_ALIGN_LEFT)
104 fl_set_button(cell_options_->radio_align_left, 1);
105 else if (align == LYX_ALIGN_RIGHT)
106 fl_set_button(cell_options_->radio_align_right, 1);
108 fl_set_button(cell_options_->radio_align_center, 1);
110 align = tabular->GetVAlignment(cell);
111 fl_set_button(cell_options_->radio_valign_top, 0);
112 fl_set_button(cell_options_->radio_valign_bottom, 0);
113 fl_set_button(cell_options_->radio_valign_center, 0);
114 if (pwidth.zero() || (align == LyXTabular::LYX_VALIGN_CENTER))
115 fl_set_button(cell_options_->radio_valign_center, 1);
116 else if (align == LyXTabular::LYX_VALIGN_BOTTOM)
117 fl_set_button(cell_options_->radio_valign_bottom, 1);
119 fl_set_button(cell_options_->radio_valign_top, 1);
121 special = tabular->GetAlignSpecial(cell, LyXTabular::SET_SPECIAL_MULTI);
122 fl_set_input(cell_options_->input_special_multialign, special.c_str());
123 bool const metric(controller().metric());
124 string const default_unit = metric ? "cm" : "in";
125 updateWidgetsFromLength(cell_options_->input_mcolumn_width,
126 cell_options_->choice_value_mcolumn_width,
127 pwidth, default_unit);
129 if (bc().bp().isReadOnly()) {
130 setEnabled(cell_options_->input_special_multialign, true);
131 setEnabled(cell_options_->input_mcolumn_width, true);
132 setEnabled(cell_options_->choice_value_mcolumn_width, true);
135 setEnabled(cell_options_->radio_valign_top, !pwidth.zero());
136 setEnabled(cell_options_->radio_valign_bottom, !pwidth.zero());
137 setEnabled(cell_options_->radio_valign_center, !pwidth.zero());
139 setEnabled(cell_options_->radio_align_left, true);
140 setEnabled(cell_options_->radio_align_right, true);
141 setEnabled(cell_options_->radio_align_center, true);
143 fl_set_button(cell_options_->check_border_top, 0);
144 setEnabled(cell_options_->check_border_top, false);
146 fl_set_button(cell_options_->check_border_bottom, 0);
147 setEnabled(cell_options_->check_border_bottom, false);
149 fl_set_button(cell_options_->check_border_left, 0);
150 setEnabled(cell_options_->check_border_left, false);
152 fl_set_button(cell_options_->check_border_right, 0);
153 setEnabled(cell_options_->check_border_right, false);
155 fl_set_button(cell_options_->radio_align_left, 0);
156 setEnabled(cell_options_->radio_align_left, false);
158 fl_set_button(cell_options_->radio_align_right, 0);
159 setEnabled(cell_options_->radio_align_right, false);
161 fl_set_button(cell_options_->radio_align_center, 0);
162 setEnabled(cell_options_->radio_align_center, false);
164 fl_set_button(cell_options_->radio_valign_top, 0);
165 setEnabled(cell_options_->radio_valign_top, false);
167 fl_set_button(cell_options_->radio_valign_bottom, 0);
168 setEnabled(cell_options_->radio_valign_bottom, false);
170 fl_set_button(cell_options_->radio_valign_center, 0);
171 setEnabled(cell_options_->radio_valign_center, false);
173 fl_set_input(cell_options_->input_special_multialign, "");
174 setEnabled(cell_options_->input_special_multialign, false);
176 fl_set_input(cell_options_->input_mcolumn_width, "");
177 setEnabled(cell_options_->input_mcolumn_width, false);
178 setEnabled(cell_options_->choice_value_mcolumn_width, false);
180 if (tabular->TopLine(cell, true))
181 fl_set_button(column_options_->check_border_top, 1);
183 fl_set_button(column_options_->check_border_top, 0);
184 if (tabular->BottomLine(cell, true))
185 fl_set_button(column_options_->check_border_bottom, 1);
187 fl_set_button(column_options_->check_border_bottom, 0);
188 if (tabular->LeftLine(cell, true))
189 fl_set_button(column_options_->check_border_left, 1);
191 fl_set_button(column_options_->check_border_left, 0);
192 if (tabular->RightLine(cell, true))
193 fl_set_button(column_options_->check_border_right, 1);
195 fl_set_button(column_options_->check_border_right, 0);
196 special = tabular->GetAlignSpecial(cell, LyXTabular::SET_SPECIAL_COLUMN);
197 fl_set_input(column_options_->input_special_alignment, special.c_str());
199 bool const isReadonly = bc().bp().isReadOnly();
200 setEnabled(column_options_->input_special_alignment, !isReadonly);
202 pwidth = tabular->GetColumnPWidth(cell);
203 bool const metric = lyxrc.default_papersize > BufferParams::PAPER_EXECUTIVEPAPER;
204 string const default_unit = metric ? "cm" : "in";
205 updateWidgetsFromLength(column_options_->input_column_width,
206 column_options_->choice_value_column_width,
207 pwidth, default_unit);
208 setEnabled(column_options_->input_column_width, !isReadonly);
209 setEnabled(column_options_->choice_value_column_width, !isReadonly);
211 setEnabled(cell_options_->check_useminipage, !pwidth.zero());
212 if (!pwidth.zero()) {
213 if (tabular->GetUsebox(cell) == 2)
214 fl_set_button(cell_options_->check_useminipage, 1);
216 fl_set_button(cell_options_->check_useminipage, 0);
218 fl_set_button(cell_options_->check_useminipage, 0);
220 align = tabular->GetAlignment(cell, true);
221 fl_set_button(column_options_->radio_align_left, 0);
222 fl_set_button(column_options_->radio_align_right, 0);
223 fl_set_button(column_options_->radio_align_center, 0);
224 if (align == LYX_ALIGN_LEFT)
225 fl_set_button(column_options_->radio_align_left, 1);
226 else if (align == LYX_ALIGN_RIGHT)
227 fl_set_button(column_options_->radio_align_right, 1);
229 fl_set_button(column_options_->radio_align_center, 1);
230 align = tabular->GetVAlignment(cell, true);
231 fl_set_button(column_options_->radio_valign_top, 0);
232 fl_set_button(column_options_->radio_valign_bottom, 0);
233 fl_set_button(column_options_->radio_valign_center, 0);
234 if (pwidth.zero() || (align == LyXTabular::LYX_VALIGN_CENTER))
235 fl_set_button(column_options_->radio_valign_center, 1);
236 else if (align == LyXTabular::LYX_VALIGN_BOTTOM)
237 fl_set_button(column_options_->radio_valign_bottom, 1);
239 fl_set_button(column_options_->radio_valign_top, 1);
241 setEnabled(column_options_->radio_align_left, true);
242 setEnabled(column_options_->radio_align_right, true);
243 setEnabled(column_options_->radio_align_center, true);
244 setEnabled(column_options_->radio_valign_top, !pwidth.zero());
245 setEnabled(column_options_->radio_valign_bottom, !pwidth.zero());
246 setEnabled(column_options_->radio_valign_center, !pwidth.zero());
248 if ( is a long tabular ) {
249 LyXTabular::ltType ltt;
251 bool row_set = tabular->GetRowOfLTHead(row, ltt);
252 fl_set_button(longtable_options_->check_lt_head, row_set);
254 fl_set_button(longtable_options_->check_head_2border_above,
256 fl_set_button(longtable_options_->check_head_2border_above,
260 setEnabled(longtable_options_->check_head_2border_above, 0);
261 setEnabled(longtable_options_->check_head_2border_below, 0);
262 fl_set_button(longtable_options_->check_head_2border_above,0);
263 fl_set_button(longtable_options_->check_head_2border_above,0);
264 fl_set_button(longtable_options_->check_1head_empty,0);
265 setEnabled(longtable_options_->check_1head_empty, 0);
269 row_set = tabular->GetRowOfLTFirstHead(row, ltt);
270 fl_set_button(longtable_options_->check_lt_firsthead, row_set);
271 if (ltt.set && (!ltt.empty || !use_empty)) {
272 fl_set_button(longtable_options_->check_1head_2border_above,
274 fl_set_button(longtable_options_->check_1head_2border_above,
277 setEnabled(longtable_options_->check_1head_2border_above, 0);
278 setEnabled(longtable_options_->check_1head_2border_below, 0);
279 fl_set_button(longtable_options_->check_1head_2border_above,0);
280 fl_set_button(longtable_options_->check_1head_2border_above,0);
282 fl_set_button(longtable_options_->check_1head_empty,ltt.empty);
284 setEnabled(longtable_options_->check_lt_firsthead, 0);
288 row_set = tabular->GetRowOfLTFoot(row, ltt);
289 fl_set_button(longtable_options_->check_lt_foot, row_set);
291 fl_set_button(longtable_options_->check_foot_2border_above,
293 fl_set_button(longtable_options_->check_foot_2border_above,
297 setEnabled(longtable_options_->check_foot_2border_above, 0);
298 setEnabled(longtable_options_->check_foot_2border_below, 0);
299 fl_set_button(longtable_options_->check_foot_2border_above,0);
300 fl_set_button(longtable_options_->check_foot_2border_above,0);
301 fl_set_button(longtable_options_->check_lastfoot_empty, 0);
302 setEnabled(longtable_options_->check_lastfoot_empty, 0);
306 row_set = tabular->GetRowOfLTLastFoot(row, ltt);
307 fl_set_button(longtable_options_->check_lt_lastfoot, row_set);
308 if (ltt.set && (!ltt.empty || !use_empty)) {
309 fl_set_button(longtable_options_->check_lastfoot_2border_above,
311 fl_set_button(longtable_options_->check_lastfoot_2border_above,
314 setEnabled(longtable_options_->check_lastfoot_2border_above,0);
315 setEnabled(longtable_options_->check_lastfoot_2border_below,0);
316 fl_set_button(longtable_options_->check_lastfoot_2border_above, 0);
317 fl_set_button(longtable_options_->check_lastfoot_2border_above, 0);
319 fl_set_button(longtable_options_->check_lastfoot_empty,
322 setEnabled(longtable_options_->check_lt_lastfoot, 0);
325 fl_set_button(longtable_options_->check_lt_newpage,
326 tabular->GetLTNewPage(row));
328 fl_set_button(longtable_options_->check_lt_firsthead, 0);
329 fl_set_button(longtable_options_->check_1head_2border_above, 0);
330 fl_set_button(longtable_options_->check_1head_2border_above, 0);
331 fl_set_button(longtable_options_->check_1head_empty, 0);
332 fl_set_button(longtable_options_->check_lt_head, 0);
333 fl_set_button(longtable_options_->check_head_2border_above, 0);
334 fl_set_button(longtable_options_->check_head_2border_above, 0);
335 fl_set_button(longtable_options_->check_lt_foot, 0);
336 fl_set_button(longtable_options_->check_foot_2border_above, 0);
337 fl_set_button(longtable_options_->check_foot_2border_above, 0);
338 fl_set_button(longtable_options_->check_lt_lastfoot, 0);
339 fl_set_button(longtable_options_->check_lastfoot_2border_above, 0);
340 fl_set_button(longtable_options_->check_lastfoot_2border_above, 0);
341 fl_set_button(longtable_options_->check_lastfoot_empty, 0);
342 fl_set_button(longtable_options_->check_lt_newpage, 0);
349 ButtonPolicy::SMInput FormTabular::input(FL_OBJECT * ob, long)
352 LyXTabular::Feature num = LyXTabular::LAST_ACTION;
355 InsetTabular * inset(controller().inset());
356 LyXTabular * tabular(controller().tabular());
358 int cell = inset->getActCell();
360 // ugly hack to auto-apply the stuff that hasn't been
361 // yet. don't let this continue to exist ...
362 if (ob == dialog_->button_close) {
365 getLengthFromWidgets(column_options_->input_column_width,
366 column_options_->choice_value_column_width);
368 LyXLength llen = tabular->GetColumnPWidth(cell);
370 str2 = llen.asString();
372 input(column_options_->input_column_width, 0);
373 str1 = getLengthFromWidgets(cell_options_->input_mcolumn_width,
374 cell_options_->choice_value_mcolumn_width);
375 llen = tabular->GetMColumnPWidth(cell);
379 str2 = llen.asString();
381 input(cell_options_->input_mcolumn_width, 0);
382 str1 = getString(column_options_->input_special_alignment);
383 str2 = tabular->GetAlignSpecial(cell, LyXTabular::SET_SPECIAL_COLUMN);
385 input(column_options_->input_special_alignment, 0);
386 str1 = getString(cell_options_->input_special_multialign);
387 str2 = tabular->GetAlignSpecial(cell, LyXTabular::SET_SPECIAL_MULTI);
389 input(cell_options_->input_special_multialign, 0);
392 controller().OKButton();
393 return ButtonPolicy::SMI_VALID;
396 if (actCell_ != cell) {
398 postWarning(_("Wrong Cursor position, updated window"));
399 return ButtonPolicy::SMI_VALID;
402 // No point in processing directives that you can't do anything with
403 // anyhow, so exit now if the buffer is read-only.
404 if (bc().bp().isReadOnly()) {
406 return ButtonPolicy::SMI_VALID;
409 if ((ob == column_options_->input_column_width) ||
410 (ob == column_options_->choice_value_column_width)) {
412 getLengthFromWidgets(column_options_->input_column_width,
413 column_options_->choice_value_column_width);
414 controller().set(LyXTabular::SET_PWIDTH, str);
416 //check if the input is valid
417 string const input = getString(column_options_->input_column_width);
418 if (!input.empty() && !isValidLength(input) && !isStrDbl(input)) {
419 postWarning(_("Invalid Length (valid example: 10mm)"));
420 return ButtonPolicy::SMI_INVALID;
423 update(); // update for alignment
424 return ButtonPolicy::SMI_VALID;
427 if ((ob == cell_options_->input_mcolumn_width) ||
428 (ob == cell_options_->choice_value_mcolumn_width)) {
430 getLengthFromWidgets(cell_options_->input_mcolumn_width,
431 cell_options_->choice_value_mcolumn_width);
432 controller().set(LyXTabular::SET_MPWIDTH, str);
434 //check if the input is valid
435 string const input = getString(cell_options_->input_mcolumn_width);
436 if (!input.empty() && !isValidLength(input) && !isStrDbl(input)) {
437 postWarning(_("Invalid Length (valid example: 10mm)"));
438 return ButtonPolicy::SMI_INVALID;
440 update(); // update for alignment
441 return ButtonPolicy::SMI_VALID;
444 if (ob == tabular_options_->button_set_borders)
445 num = LyXTabular::SET_ALL_LINES;
446 else if (ob == tabular_options_->button_unset_borders)
447 num = LyXTabular::UNSET_ALL_LINES;
448 else if (ob == column_options_->check_border_top)
449 num = LyXTabular::TOGGLE_LINE_TOP;
450 else if (ob == column_options_->check_border_bottom)
451 num = LyXTabular::TOGGLE_LINE_BOTTOM;
452 else if (ob == column_options_->check_border_left)
453 num = LyXTabular::TOGGLE_LINE_LEFT;
454 else if (ob == column_options_->check_border_right)
455 num = LyXTabular::TOGGLE_LINE_RIGHT;
456 else if (ob == column_options_->radio_align_left)
457 num = LyXTabular::ALIGN_LEFT;
458 else if (ob == column_options_->radio_align_right)
459 num = LyXTabular::ALIGN_RIGHT;
460 else if (ob == column_options_->radio_align_center)
461 num = LyXTabular::ALIGN_CENTER;
462 else if (ob == column_options_->radio_valign_top)
463 num = LyXTabular::VALIGN_TOP;
464 else if (ob == column_options_->radio_valign_bottom)
465 num = LyXTabular::VALIGN_BOTTOM;
466 else if (ob == column_options_->radio_valign_center)
467 num = LyXTabular::VALIGN_CENTER;
468 else if (ob == cell_options_->check_multicolumn)
469 num = LyXTabular::MULTICOLUMN;
470 else if (ob == tabular_options_->check_longtable) {
471 if (fl_get_button(tabular_options_->check_longtable))
472 num = LyXTabular::SET_LONGTABULAR;
474 num = LyXTabular::UNSET_LONGTABULAR;
475 } else if (ob == tabular_options_->check_rotate_tabular) {
476 s = fl_get_button(tabular_options_->check_rotate_tabular);
478 num = LyXTabular::SET_ROTATE_TABULAR;
480 num = LyXTabular::UNSET_ROTATE_TABULAR;
481 } else if (ob == cell_options_->check_rotate_cell) {
482 s = fl_get_button(cell_options_->check_rotate_cell);
484 num = LyXTabular::SET_ROTATE_CELL;
486 num = LyXTabular::UNSET_ROTATE_CELL;
487 } else if (ob == cell_options_->check_useminipage) {
488 num = LyXTabular::SET_USEBOX;
490 } else if ((ob == longtable_options_->check_lt_firsthead) ||
491 (ob == longtable_options_->check_1head_2border_above) ||
492 (ob == longtable_options_->check_1head_2border_below) ||
493 (ob == longtable_options_->check_1head_empty) ||
494 (ob == longtable_options_->check_lt_head) ||
495 (ob == longtable_options_->check_head_2border_above) ||
496 (ob == longtable_options_->check_head_2border_below) ||
497 (ob == longtable_options_->check_lt_foot) ||
498 (ob == longtable_options_->check_foot_2border_above) ||
499 (ob == longtable_options_->check_foot_2border_below) ||
500 (ob == longtable_options_->check_lt_lastfoot) ||
501 (ob == longtable_options_->check_lastfoot_2border_above) ||
502 (ob == longtable_options_->check_lastfoot_2border_below) ||
503 (ob == longtable_options_->check_lastfoot_empty)) {
504 num = static_cast<LyXTabular::Feature>(checkLongtableOptions(ob, special));
505 } else if (ob == longtable_options_->check_lt_newpage) {
506 num = LyXTabular::SET_LTNEWPAGE;
507 } else if (ob == column_options_->input_special_alignment) {
508 special = getString(column_options_->input_special_alignment);
509 num = LyXTabular::SET_SPECIAL_COLUMN;
510 } else if (ob == cell_options_->input_special_multialign) {
511 special = getString(cell_options_->input_special_multialign);
512 num = LyXTabular::SET_SPECIAL_MULTI;
513 } else if (ob == cell_options_->check_border_top)
514 num = LyXTabular::M_TOGGLE_LINE_TOP;
515 else if (ob == cell_options_->check_border_bottom)
516 num = LyXTabular::M_TOGGLE_LINE_BOTTOM;
517 else if (ob == cell_options_->check_border_left)
518 num = LyXTabular::M_TOGGLE_LINE_LEFT;
519 else if (ob == cell_options_->check_border_right)
520 num = LyXTabular::M_TOGGLE_LINE_RIGHT;
521 else if (ob == cell_options_->radio_align_left)
522 num = LyXTabular::M_ALIGN_LEFT;
523 else if (ob == cell_options_->radio_align_right)
524 num = LyXTabular::M_ALIGN_RIGHT;
525 else if (ob == cell_options_->radio_align_center)
526 num = LyXTabular::M_ALIGN_CENTER;
527 else if (ob == cell_options_->radio_valign_top)
528 num = LyXTabular::M_VALIGN_TOP;
529 else if (ob == cell_options_->radio_valign_bottom)
530 num = LyXTabular::M_VALIGN_BOTTOM;
531 else if (ob == cell_options_->radio_valign_center)
532 num = LyXTabular::M_VALIGN_CENTER;
534 return ButtonPolicy::SMI_VALID;
536 controller().set(num, special);
539 return ButtonPolicy::SMI_VALID;
543 int FormTabular::checkLongtableOptions(FL_OBJECT * ob, string & special)
545 bool flag = fl_get_button(ob);
546 if ((ob == longtable_options_->check_1head_2border_above) ||
547 (ob == longtable_options_->check_head_2border_above) ||
548 (ob == longtable_options_->check_foot_2border_above) ||
549 (ob == longtable_options_->check_lastfoot_2border_above)) {
550 special = "dl_above";
551 } else if ((ob == longtable_options_->check_1head_2border_below) ||
552 (ob == longtable_options_->check_head_2border_below) ||
553 (ob == longtable_options_->check_foot_2border_below) ||
554 (ob == longtable_options_->check_lastfoot_2border_below)) {
555 special = "dl_below";
556 } else if ((ob == longtable_options_->check_1head_empty) ||
557 (ob == longtable_options_->check_lastfoot_empty)) {
562 if ((ob == longtable_options_->check_lt_firsthead) ||
563 (ob == longtable_options_->check_1head_2border_above) ||
564 (ob == longtable_options_->check_1head_2border_below) ||
565 (ob == longtable_options_->check_1head_empty)) {
566 return (flag ? LyXTabular::SET_LTFIRSTHEAD :
567 LyXTabular::UNSET_LTFIRSTHEAD);
568 } else if ((ob == longtable_options_->check_lt_head) ||
569 (ob == longtable_options_->check_head_2border_above) ||
570 (ob == longtable_options_->check_head_2border_below)) {
571 return (flag ? LyXTabular::SET_LTHEAD : LyXTabular::UNSET_LTHEAD);
572 } else if ((ob == longtable_options_->check_lt_foot) ||
573 (ob == longtable_options_->check_foot_2border_above) ||
574 (ob == longtable_options_->check_foot_2border_below)) {
575 return (flag ? LyXTabular::SET_LTFOOT : LyXTabular::UNSET_LTFOOT);
576 } else if ((ob == longtable_options_->check_lt_lastfoot) ||
577 (ob == longtable_options_->check_lastfoot_2border_above) ||
578 (ob == longtable_options_->check_lastfoot_2border_below) ||
579 (ob == longtable_options_->check_lastfoot_empty)) {
580 return (flag ? LyXTabular::SET_LTLASTFOOT :
581 LyXTabular::UNSET_LTLASTFOOT);
584 return LyXTabular::LAST_ACTION;