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-<up> 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.
This commit is contained in:
Scott Kostyshak 2012-12-24 05:51:28 -05:00
parent 67dcc67dae
commit 3c84267d8d
13 changed files with 193 additions and 14 deletions

View File

@ -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
#

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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"

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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);
///