/*******************************************************************************
* Copyright (c) 2004, 2008 John Krasnay and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* John Krasnay - initial API and implementation
*******************************************************************************/
package net.sf.vex.action;
import java.util.ArrayList;
import java.util.List;
import net.sf.vex.dom.Element;
import net.sf.vex.widget.IVexWidget;
/**
* Inserts one or more table rows either above or below the currently selected one(s).
* This class is meant as a base class for InsertRowAboveAction and
* InsertRowBelowAction.
*/
public class InsertRowAction extends AbstractVexAction {
/**
* Class constructor.
* @param above If true, the new rows are inserted above the currently
* selected ones, else they are inserted below.
*/
public InsertRowAction(boolean above) {
this.above = above;
}
public void run(final IVexWidget vexWidget) {
vexWidget.doWork(new Runnable() {
public void run() {
final List rowsToInsert = new ArrayList();
final List rowCellsToInsert = new ArrayList();
ActionUtils.iterateTableCells(vexWidget, new TableCellCallback() {
boolean rowSelected;
List cellsToInsert;
public void startRow(Object row, int rowIndex) {
rowSelected = ActionUtils.elementOrRangeIsPartiallySelected(vexWidget, row);
if (rowSelected) {
cellsToInsert = new ArrayList();
}
}
public void onCell(Object row, Object cell, int rowIndex, int cellIndex) {
if (rowSelected) {
cellsToInsert.add(cell);
}
}
public void endRow(Object row, int rowIndex) {
if (rowSelected) {
rowsToInsert.add(row);
rowCellsToInsert.add(cellsToInsert);
}
}
});
if (rowsToInsert.size() == 0) {
return;
}
//
// save the caret offset so that we return just inside the first
// table cell
//
// (innerOffset - outerOffset) represents the final offset of
// the caret, relative to the insertion point of the new rows
//
int outerOffset = ActionUtils.getOuterRange(rowsToInsert.get(0)).getStart();
int innerOffset;
List firstCells = (List) rowCellsToInsert.get(0);
if (firstCells.size() == 0) {
innerOffset = ActionUtils.getInnerRange(rowsToInsert.get(0)).getStart();
} else {
innerOffset = ActionUtils.getInnerRange(firstCells.get(0)).getStart();
}
int insertOffset;
if (above) {
insertOffset = ActionUtils.getOuterRange(rowsToInsert.get(0)).getStart();
} else {
Object lastRow = rowsToInsert.get(rowsToInsert.size() - 1);
insertOffset = ActionUtils.getOuterRange(lastRow).getEnd();
}
int finalOffset = insertOffset + (innerOffset - outerOffset);
vexWidget.moveTo(insertOffset);
for (int i = 0; i < rowsToInsert.size(); i++) {
Object row = rowsToInsert.get(i);
if (row instanceof Element) {
vexWidget.insertElement((Element) ((Element) row).clone());
}
List cellsToInsert = (List) rowCellsToInsert.get(i);
for (int j = 0; j < cellsToInsert.size(); j++) {
Object cell = cellsToInsert.get(j);
if (cell instanceof Element) {
vexWidget.insertElement((Element) ((Element) cell).clone());
vexWidget.moveBy(+1);
} else {
vexWidget.insertText(" ");
}
}
if (row instanceof Element) {
vexWidget.moveBy(+1);
}
}
vexWidget.moveTo(finalOffset);
}
});
}
public boolean isEnabled(IVexWidget vexWidget) {
// TODO only enable (a) if rows are selected, and (b) if not inserting
// adjacent anonymous rows
return true;
}
private boolean above;
}