From 3c84267d8d56a103649494066b918130320bfc12 Mon Sep 17 00:00:00 2001 From: Scott Kostyshak Date: Mon, 24 Dec 2012 05:51:28 -0500 Subject: [PATCH] Implement move row/column in tabular inset This patch implements 'move row' and 'move column' features for tabular. The purpose is to provide a useful behavior in tabular that is consistent with PARAGRAPH_MOVE_UP and PARAGRAPH_MOVE_DOWN so that the user can, for example, do alt- to move a row up. Alternatively, icons for these features are also added to the table toolbar and context menu. If there is any selection, the feature is disabled. This is consistent with how PARAGRAPH_MOVE_UP works in other contexts. Additionally, 'move row' is disabled if there is a multi-row in the current or target row; and 'move column' is disabled if there is a multi-column in the current or target column. 'move row' moves only the left and right borders of a cell along with the row. Similarly, 'move column' moves only the the top and bottom borders. Implementing similar functionality for other insets, such as arrays and array environments, is on my TODO list. --- lib/bind/cua.bind | 7 +- lib/bind/emacs.bind | 6 +- lib/bind/mac.bind | 6 +- lib/bind/sciword.bind | 6 +- lib/bind/xemacs.bind | 6 +- .../tabular-feature_move-column-left.png | Bin 0 -> 688 bytes .../tabular-feature_move-column-right.png | Bin 0 -> 725 bytes lib/images/tabular-feature_move-row-down.png | Bin 0 -> 590 bytes lib/images/tabular-feature_move-row-up.png | Bin 0 -> 598 bytes lib/ui/stdcontext.inc | 6 +- lib/ui/stdtoolbars.inc | 4 + src/insets/InsetTabular.cpp | 139 +++++++++++++++++- src/insets/InsetTabular.h | 27 ++++ 13 files changed, 193 insertions(+), 14 deletions(-) create mode 100644 lib/images/tabular-feature_move-column-left.png create mode 100644 lib/images/tabular-feature_move-column-right.png create mode 100644 lib/images/tabular-feature_move-row-down.png create mode 100644 lib/images/tabular-feature_move-row-up.png diff --git a/lib/bind/cua.bind b/lib/bind/cua.bind index 4d6c286e42..af90fbe430 100644 --- a/lib/bind/cua.bind +++ b/lib/bind/cua.bind @@ -132,8 +132,10 @@ Format 1 # Motion group # -\bind "M-Up" "paragraph-move-up" -\bind "M-Down" "paragraph-move-down" +\bind "M-Up" "command-alternatives paragraph-move-up; inset-modify tabular move-row-up" +\bind "M-Down" "command-alternatives paragraph-move-down; inset-modify tabular move-row-down" +\bind "M-Right" "inset-modify tabular move-column-right" +\bind "M-Left" "inset-modify tabular move-column-left" \bind "C-Right" "word-right" \bind "C-Left" "word-left" \bind "C-Up" "paragraph-up" @@ -146,7 +148,6 @@ Format 1 \bind "C-~S-greater" "label-goto" \bind "C-~S-less" "bookmark-goto 0" - # # Motion + select group # diff --git a/lib/bind/emacs.bind b/lib/bind/emacs.bind index 69418a65ba..384d638ffd 100644 --- a/lib/bind/emacs.bind +++ b/lib/bind/emacs.bind @@ -148,8 +148,10 @@ Format 1 # Motion group # -\bind "M-Up" "paragraph-move-up" -\bind "M-Down" "paragraph-move-down" +\bind "M-Up" "command-alternatives paragraph-move-up; inset-modify tabular move-row-up" +\bind "M-Down" "command-alternatives paragraph-move-down; inset-modify tabular move-row-down" +\bind "M-Right" "inset-modify tabular move-column-right" +\bind "M-Left" "inset-modify tabular move-column-left" \bind "C-Right" "word-right" \bind "C-Left" "word-left" \bind "C-Up" "paragraph-up" diff --git a/lib/bind/mac.bind b/lib/bind/mac.bind index c85ec8d972..2cb306dfc1 100644 --- a/lib/bind/mac.bind +++ b/lib/bind/mac.bind @@ -358,8 +358,10 @@ Format 1 \bind "C-period" "specialchar-insert end-of-sentence" \bind "M-period" "specialchar-insert dots" \bind "Escape" "cancel" -\bind "C-M-Up" "paragraph-move-up" -\bind "C-M-Down" "paragraph-move-down" +\bind "C-M-Up" "command-alternatives paragraph-move-up; inset-modify tabular move-row-up" +\bind "C-M-Down" "command-alternatives paragraph-move-down; inset-modify tabular move-row-down" +\bind "C-M-Right" "inset-modify tabular move-column-right" +\bind "C-M-Left" "inset-modify tabular move-column-left" #\bind "F9" "meta-prefix" # Include menu and math bindings diff --git a/lib/bind/sciword.bind b/lib/bind/sciword.bind index 3367c4ea9a..75ecf2752a 100644 --- a/lib/bind/sciword.bind +++ b/lib/bind/sciword.bind @@ -217,8 +217,10 @@ Format 1 \bind_file greekkeys.bind -\bind "M-Up" "paragraph-move-up" -\bind "M-Down" "paragraph-move-down" +\bind "M-Up" "command-alternatives paragraph-move-up; inset-modify tabular move-row-up" +\bind "M-Down" "command-alternatives paragraph-move-down; inset-modify tabular move-row-down" +\bind "M-Right" "inset-modify tabular move-column-right" +\bind "M-Left" "inset-modify tabular move-column-left" \bind "S-KP_Right" "char-right-select" \bind "S-KP_Left" "char-left-select" \bind "S-KP_Up" "up-select" diff --git a/lib/bind/xemacs.bind b/lib/bind/xemacs.bind index 751199f108..77501cdf03 100644 --- a/lib/bind/xemacs.bind +++ b/lib/bind/xemacs.bind @@ -147,8 +147,10 @@ Format 1 # Motion group # -\bind "M-Up" "paragraph-move-up" -\bind "M-Down" "paragraph-move-down" +\bind "M-Up" "command-alternatives paragraph-move-up; inset-modify tabular move-row-up" +\bind "M-Down" "command-alternatives paragraph-move-down; inset-modify tabular move-row-down" +\bind "M-Right" "inset-modify tabular move-column-right" +\bind "M-Left" "inset-modify tabular move-column-left" \bind "C-Right" "word-right" \bind "C-Left" "word-left" \bind "C-Up" "paragraph-up" diff --git a/lib/images/tabular-feature_move-column-left.png b/lib/images/tabular-feature_move-column-left.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d24584f3bee3953b35cf07a79b0fe98d0a06a5 GIT binary patch literal 688 zcmV;h0#E&kP)%}Td%P}R{2m`?Ur~Vz zK6@S_;NLtaVH4fg%3Lh}$W?al$annvom~hPV2eD)yz@$_Si+yWB-6vDEmSS&mMR9^4n=957> zTF=lv5CwaZ^uh+Gf`+yp4(6?5#mbqp7mo$7tSN+)$^mViVcJ_S5d1j7(&fu&zj4~t zU~y>;dpD-y_4%}$BBeq|C3*4cH2^tjODHZrOGSMZ?>~%DTh`k83DmmYH3G6@gH0%eUq~;!%PZR<;E!Q;%omhZ(Z$}Z9 zWg&zKKw6rQi$}Nf_463Dhbq|VUrknaR&1?O!rE5jv9UF@5K>A^W9Gnmy zCv~uA$4dFHWz#ehg&L-_**Ya9!m@3;dV>i<9qZ^HnpbDpHey;ScI9t#i5_#Lv(4~un2M|grba!6IJlZwXJPyg4=RdCvfKh(xTvES)JEJLDUXby_<^KiX WP~io_uiv}?0000>&n82u(a5IoIPi|Fqa)?{HZ=T7w7rjdFOm{&U{Cy zyK^tXoH+k*46E=SaIjct-$Nk|6&21gtfT$LNdt2qzed3xw}Ewa2iTG4jLsjmw4u%S zre!vTzYQtnjNw%1rztu9HEd#5x>%;F>H;fN|6_&0V9=Bd4vm;tAP_Lju3q*NDN;F-cCQh@N%3B^cWAfqs81)^m8K0P9{lTlzeAB=f&9}?RFTR8t z2~%6*Lf5C!gpdm!n{Sg7+;8opsiE4CAD;My|J@IoZk@$be1X~$7eYuhAq73X{U*cq z7efGi`Sh91DJ$`KstozV6~{~dR__O3SNUDmrL3W*w2HmXjd)Al*zHNYeKU%t>pGgI&Reo0IT?Vs1Us2onE>Q( z?WgAGX>!sMxp-nX_M{{LbX`XiLZB+jk`DH)&Ug6~03BW3I2;b+Ig~=6s_K&d1S?%E zlR}{B;V^BTev`1dZ_vc7bg@hihtVQZvd`@@h$?);6y;?Y*p+&}N%y$@nSljg4xmXX zvFZah%WuenEZQ8b!uAi{20$sRJZHKB9*ibfiVIUG7d8A16AR9iB?!4_!5k`9yjVdR57zpXLr-4x zP)ZI(v5Ey-g{|G)nH>+okYPFrfIgmLL+*9thG%6n4Rd?;EVZBoIQMS%d9h9s0Q?9 zxXA4?3&8Qh!hh`h*DtL7Tw!%(4abW$)M)`X%RD((;n|yy967X)#Hr>LHf_rCZAeBZ~i!r!sR zgvY8YL3o?%0N?j9rIeV4p&fvs!VHl_4us1ep+LAq5;=wnGn%g6PfCduNQr5NGZ&wh zc|0}3($X?NfIGL-baX^X_1qwzIj4s86Vaka2m(RB5G+2NeB zf*`;&!tHNww;9cJVFUsFiOa-edl=1hVcWK*tM{#~uSRCuHjnORs>`!98w&P6GX}2T cZ0WZ73yYQ!w1hxI8~^|S07*qoM6N<$f^xV8%>V!Z literal 0 HcmV?d00001 diff --git a/lib/images/tabular-feature_move-row-up.png b/lib/images/tabular-feature_move-row-up.png new file mode 100644 index 0000000000000000000000000000000000000000..e27de3f769ff560b2be19db758bef8251507cc3e GIT binary patch literal 598 zcmV-c0;&CpP)*6|e>S9Yqm~}8MO31w!DHPEk@!+WyRHPPz-CLAIgopm%TI*pe&^%acuo^^5)CL`7 zlb}n22t^ScM%I~~HywsGhsj-)eK7F&yzl$I@BALWCq0;WW>LYRtZEwP&vrTB{F@9X zTAR1cre{*fl}smuKmqup$mjnh)HKch z<-<*f9A+P~A4z{&X6kW-$?Os}0UwjuC8ov(>FmD2*!6Sky4IGX>-%P2ytEA^Npd9& z9rV+AAqGJIt!u<@$B6@>racb*#G(zH>T??ubW%6Z;PrYP z`i*nL&{0fN{I|e?I+Z}33WcY3ih|Dmh65!p#WV#{ZO2H-PFeZ7$mpwa!l!zu-CJM2 zQvl{3h8=MBeUA1cLA!p#cL}#$qM=^p$^FfB04IA#Z9~I!hb*%G-qUnA-cS)Ti zp{BcqMON)osrIR?tSy$*ISjXQ@>W^dOWF1qh(s+duRFfvbZSRzAQH6{Aq29!QFg?H k5S4uo0i?d6;fmJqFaE|6Uy!420000007*qoM6N<$f+KDdr2qf` literal 0 HcmV?d00001 diff --git a/lib/ui/stdcontext.inc b/lib/ui/stdcontext.inc index 3bb9266790..f8786852f4 100644 --- a/lib/ui/stdcontext.inc +++ b/lib/ui/stdcontext.inc @@ -416,12 +416,14 @@ Menuset Item "Append Row|A" "inset-modify tabular append-row" Item "Delete Row|D" "inset-modify tabular delete-row" Item "Copy Row|o" "inset-modify tabular copy-row" - # Item "Swap Rows|S" "inset-modify tabular swap-row" # currently broken + Item "Move Row Up" "inset-modify tabular move-row-up" + Item "Move Row Down" "inset-modify tabular move-row-down" Separator Item "Append Column|p" "inset-modify tabular append-column" Item "Delete Column|e" "inset-modify tabular delete-column" Item "Copy Column|y" "inset-modify tabular copy-column" - # Item "Swap Columns|w" "inset-modify tabular swap-column" # currently broken + Item "Move Column Right|v" "inset-modify tabular move-column-right" + Item "Move Column Left" "inset-modify tabular move-column-left" Separator Item "Settings...|g" "inset-settings tabular" End diff --git a/lib/ui/stdtoolbars.inc b/lib/ui/stdtoolbars.inc index fc33c0af7f..92aaf9e628 100644 --- a/lib/ui/stdtoolbars.inc +++ b/lib/ui/stdtoolbars.inc @@ -144,6 +144,10 @@ ToolbarSet Item "Add column" "inset-modify tabular append-column" Item "Delete row" "inset-modify tabular delete-row" Item "Delete column" "inset-modify tabular delete-column" + Item "Move row up" "inset-modify tabular move-row-up" + Item "Move column left" "inset-modify tabular move-column-left" + Item "Move row down" "inset-modify tabular move-row-down" + Item "Move column right" "inset-modify tabular move-column-right" Separator Item "Set top line" "inset-modify tabular toggle-line-top" Item "Set bottom line" "inset-modify tabular toggle-line-bottom" diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index a43d45fbdf..4285e4ac44 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -13,6 +13,7 @@ * \author Jürgen Vigna * \author Uwe Stöhr * \author Edwin Leuven + * \author Scott Kostyshak * * Full author contact details are available in file CREDITS. */ @@ -115,6 +116,10 @@ TabularFeature tabularFeature[] = { Tabular::DELETE_COLUMN, "delete-column", false }, { Tabular::COPY_ROW, "copy-row", false }, { Tabular::COPY_COLUMN, "copy-column", false }, + { Tabular::MOVE_COLUMN_RIGHT, "move-column-right", false }, + { Tabular::MOVE_COLUMN_LEFT, "move-column-left", false }, + { Tabular::MOVE_ROW_DOWN, "move-row-down", false }, + { Tabular::MOVE_ROW_UP, "move-row-up", false }, { Tabular::SET_LINE_TOP, "set-line-top", true }, { Tabular::SET_LINE_BOTTOM, "set-line-bottom", true }, { Tabular::SET_LINE_LEFT, "set-line-left", true }, @@ -770,6 +775,50 @@ void Tabular::insertRow(row_type const row, bool copy) } +void Tabular::moveColumn(col_type col, ColDirection direction) +{ + if (direction == Tabular::LEFT) + col = col - 1; + + for (row_type r = 0; r < nrows(); ++r) { + std::swap(cell_info[r][col], cell_info[r][col + 1]); + std::swap(cell_info[r][col].left_line, cell_info[r][col + 1].left_line); + std::swap(cell_info[r][col].right_line, cell_info[r][col + 1].right_line); + + // FIXME track changes is broken for tabular features (#8469) + idx_type const i = cellIndex(r, col); + idx_type const j = cellIndex(r, col + 1); + if (buffer().params().trackChanges) { + cellInfo(i).inset->setChange(Change(Change::INSERTED)); + cellInfo(j).inset->setChange(Change(Change::INSERTED)); + } + } + updateIndexes(); +} + + +void Tabular::moveRow(row_type row, RowDirection direction) +{ + if (direction == Tabular::UP) + row = row - 1; + + for (col_type c = 0; c < ncols(); ++c) { + std::swap(cell_info[row][c], cell_info[row + 1][c]); + std::swap(cell_info[row][c].top_line, cell_info[row + 1][c].top_line); + std::swap(cell_info[row][c].bottom_line, cell_info[row + 1][c].bottom_line); + + // FIXME track changes is broken for tabular features (#8469) + idx_type const i = cellIndex(row, c); + idx_type const j = cellIndex(row + 1, c); + if (buffer().params().trackChanges) { + cellInfo(i).inset->setChange(Change(Change::INSERTED)); + cellInfo(j).inset->setChange(Change(Change::INSERTED)); + } + } + updateIndexes(); +} + + void Tabular::deleteColumn(col_type const col) { // Not allowed to delete last column @@ -1604,6 +1653,16 @@ bool Tabular::isMultiColumn(idx_type cell) const } +bool Tabular::hasMultiColumn(col_type c) const +{ + for (row_type r = 0; r < nrows(); ++r) { + if (isMultiColumn(cellIndex(r, c))) + return true; + } + return false; +} + + Tabular::CellData & Tabular::cellInfo(idx_type cell) const { return cell_info[cellRow(cell)][cellColumn(cell)]; @@ -1644,6 +1703,14 @@ bool Tabular::isMultiRow(idx_type cell) const || cellInfo(cell).multirow == CELL_PART_OF_MULTIROW); } +bool Tabular::hasMultiRow(row_type r) const +{ + for (col_type c = 0; c < ncols(); ++c) { + if (isMultiRow(cellIndex(r, c))) + return true; + } + return false; +} Tabular::idx_type Tabular::setMultiRow(idx_type cell, idx_type number, bool const bottom_border) @@ -4412,6 +4479,56 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd, && tabular.tabular_valignment == Tabular::LYX_VALIGN_MIDDLE); break; + case Tabular::MOVE_COLUMN_RIGHT: + case Tabular::MOVE_COLUMN_LEFT: + case Tabular::MOVE_ROW_DOWN: + case Tabular::MOVE_ROW_UP: { + if (cur.selection()) { + status.message(_("Selections not supported.")); + status.setEnabled(false); + break; + } + + if ((action == Tabular::MOVE_COLUMN_RIGHT && + tabular.ncols() == tabular.cellColumn(cur.idx()) + 1) || + (action == Tabular::MOVE_COLUMN_LEFT && + tabular.cellColumn(cur.idx()) == 0) || + (action == Tabular::MOVE_ROW_DOWN && + tabular.nrows() == tabular.cellRow(cur.idx()) + 1) || + (action == Tabular::MOVE_ROW_UP && + tabular.cellRow(cur.idx()) == 0)) { + status.setEnabled(false); + break; + } + + if (action == Tabular::MOVE_COLUMN_RIGHT || + action == Tabular::MOVE_COLUMN_LEFT) { + if (tabular.hasMultiColumn(tabular.cellColumn(cur.idx())) || + tabular.hasMultiColumn(tabular.cellColumn(cur.idx()) + + (action == Tabular::MOVE_COLUMN_RIGHT ? 1 : -1))) { + status.message(_("Multi-column in current or" + " destination column.")); + status.setEnabled(false); + break; + } + } + + if (action == Tabular::MOVE_ROW_DOWN || + action == Tabular::MOVE_ROW_UP) { + if (tabular.hasMultiRow(tabular.cellRow(cur.idx())) || + tabular.hasMultiRow(tabular.cellRow(cur.idx()) + + (action == Tabular::MOVE_ROW_DOWN ? 1 : -1))) { + status.message(_("Multi-row in current or" + " destination row.")); + status.setEnabled(false); + break; + } + } + + status.setEnabled(true); + break; + } + case Tabular::SET_DECIMAL_POINT: status.setEnabled( tabular.getAlignment(cur.idx()) == LYX_ALIGN_DECIMAL); @@ -5393,6 +5510,26 @@ void InsetTabular::tabularFeatures(Cursor & cur, cur.idx() = tabular.cellIndex(row, column); break; + case Tabular::MOVE_COLUMN_RIGHT: + tabular.moveColumn(column, Tabular::RIGHT); + cur.idx() = tabular.cellIndex(row, column + 1); + break; + + case Tabular::MOVE_COLUMN_LEFT: + tabular.moveColumn(column, Tabular::LEFT); + cur.idx() = tabular.cellIndex(row, column - 1); + break; + + case Tabular::MOVE_ROW_DOWN: + tabular.moveRow(row, Tabular::DOWN); + cur.idx() = tabular.cellIndex(row + 1, column); + break; + + case Tabular::MOVE_ROW_UP: + tabular.moveRow(row, Tabular::UP); + cur.idx() = tabular.cellIndex(row - 1, column); + break; + case Tabular::SET_LINE_TOP: case Tabular::TOGGLE_LINE_TOP: { bool lineSet = (feature == Tabular::SET_LINE_TOP) @@ -5468,7 +5605,7 @@ void InsetTabular::tabularFeatures(Cursor & cur, tabular.rightLine(cur.idx())); break; } - // we have a selection so this means we just add all this + // we have a selection so this means we just add all these // cells to form a multicolumn cell idx_type const s_start = cur.selBegin().idx(); row_type const col_start = tabular.cellColumn(s_start); diff --git a/src/insets/InsetTabular.h b/src/insets/InsetTabular.h index 80958cc8a8..707ab01aee 100644 --- a/src/insets/InsetTabular.h +++ b/src/insets/InsetTabular.h @@ -10,6 +10,7 @@ * \author Jürgen Vigna * \author Edwin Leuven * \author Uwe Stöhr + * \author Scott Kostyshak * * Full author contact details are available in file CREDITS. */ @@ -136,6 +137,14 @@ public: /// COPY_COLUMN, /// + MOVE_COLUMN_RIGHT, + /// + MOVE_COLUMN_LEFT, + /// + MOVE_ROW_DOWN, + /// + MOVE_ROW_UP, + /// SET_LINE_TOP, /// SET_LINE_BOTTOM, @@ -331,6 +340,16 @@ public: CAPTION_ANY }; + enum RowDirection { + UP, + DOWN + }; + + enum ColDirection { + RIGHT, + LEFT + }; + class ltType { public: // constructor @@ -453,6 +472,10 @@ public: /// void insertRow(row_type row, bool copy); /// + void moveColumn(col_type col, ColDirection direction); + /// + void moveRow(row_type row, RowDirection direction); + /// void appendColumn(col_type column); /// void deleteColumn(col_type column); @@ -483,6 +506,8 @@ public: /// bool isMultiColumn(idx_type cell) const; /// + bool hasMultiColumn(col_type cell) const; + /// idx_type setMultiColumn(idx_type cell, idx_type number, bool const right_border); /// @@ -494,6 +519,8 @@ public: /// bool isMultiRow(idx_type cell) const; /// + bool hasMultiRow(row_type r) const; + /// idx_type setMultiRow(idx_type cell, idx_type number, bool const bottom_border); ///