blob: 88a53f5e51dc913c7c1ee61427352c2265e3bf15 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2020 Dirk Fauth and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.widgets.nattable.reorder.command;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
import org.eclipse.nebula.widgets.nattable.command.LayerCommandUtil;
import org.eclipse.nebula.widgets.nattable.coordinate.RowPositionCoordinate;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
/**
* Command for reordering rows.
*/
public class MultiRowReorderCommand implements ILayerCommand {
/**
* The coordinates of the rows that should be reordered
*/
private List<RowPositionCoordinate> fromRowPositionCoordinates;
/**
* The coordinate of the row to which the dragged rows should be dropped.
*
* @since 1.6
*/
protected RowPositionCoordinate toRowPositionCoordinate;
/**
* Flag to indicate if the row is dragged to the top edge of the layer.
* Needed for the special case when the reordering is performed to the
* bottom edge.
*/
private boolean reorderToTopEdge;
/**
* Flag to indicate if the carried from rows are treated as indexes, or if
* they are treated as positions.
*/
private boolean reorderByIndex = false;
/**
*
* @param layer
* The layer the positions are related to
* @param fromRowPositions
* The positions of the rows that should be reordered
* @param toRowPosition
* The position of the row to which the dragged row should be
* dropped
*/
public MultiRowReorderCommand(ILayer layer, List<Integer> fromRowPositions, int toRowPosition) {
this(layer,
fromRowPositions.stream().mapToInt(Integer::intValue).toArray(),
toRowPosition < layer.getRowCount() ? toRowPosition : toRowPosition - 1,
toRowPosition < layer.getRowCount());
}
/**
*
* @param layer
* The layer the positions are related to
* @param fromRowPositions
* The positions of the rows that should be reordered
* @param toRowPosition
* The position of the row to which the dragged row should be
* dropped
* @param reorderToTopEdge
* Flag to indicate if the row is dragged to the top edge of the
* layer
*/
public MultiRowReorderCommand(ILayer layer,
List<Integer> fromRowPositions,
int toRowPosition,
boolean reorderToTopEdge) {
this(layer,
fromRowPositions.stream().mapToInt(Integer::intValue).toArray(),
toRowPosition,
reorderToTopEdge);
}
/**
*
* @param layer
* The layer the positions are related to
* @param fromRowPositions
* The positions of the rows that should be reordered
* @param toRowPosition
* The position of the row to which the dragged row should be
* dropped
*
* @since 2.0
*/
public MultiRowReorderCommand(ILayer layer, int[] fromRowPositions, int toRowPosition) {
this(layer,
fromRowPositions,
toRowPosition < layer.getRowCount() ? toRowPosition : toRowPosition - 1,
toRowPosition < layer.getRowCount());
}
/**
*
* @param layer
* The layer the positions are related to
* @param fromRowPositions
* The positions of the rows that should be reordered
* @param toRowPosition
* The position of the row to which the dragged row should be
* dropped
* @param reorderToTopEdge
* Flag to indicate if the row is dragged to the top edge of the
* layer
*
* @since 2.0
*/
public MultiRowReorderCommand(ILayer layer,
int[] fromRowPositions,
int toRowPosition,
boolean reorderToTopEdge) {
this.fromRowPositionCoordinates = new ArrayList<>(fromRowPositions.length);
for (int fromRowPosition : fromRowPositions) {
this.fromRowPositionCoordinates.add(new RowPositionCoordinate(layer, fromRowPosition));
}
this.toRowPositionCoordinate = new RowPositionCoordinate(layer, toRowPosition);
this.reorderToTopEdge = reorderToTopEdge;
}
/**
* Constructor used for cloning purposes
*
* @param command
* The command which is base for the new one
*/
protected MultiRowReorderCommand(MultiRowReorderCommand command) {
this.fromRowPositionCoordinates = new ArrayList<>(command.fromRowPositionCoordinates);
this.toRowPositionCoordinate = command.toRowPositionCoordinate;
this.reorderToTopEdge = command.reorderToTopEdge;
}
/**
* @return The positions of the rows that should be reordered
*/
public List<Integer> getFromRowPositions() {
List<Integer> fromRowPositions = new ArrayList<>(this.fromRowPositionCoordinates.size());
for (RowPositionCoordinate fromRowPositionCoordinate : this.fromRowPositionCoordinates) {
fromRowPositions.add(fromRowPositionCoordinate.getRowPosition());
}
return fromRowPositions;
}
/**
* @return The positions of the rows that should be reordered
* @since 2.0
*/
public int[] getFromRowPositionsArray() {
return this.fromRowPositionCoordinates.stream()
.mapToInt(RowPositionCoordinate::getRowPosition)
.sorted()
.toArray();
}
/**
* @return The position of the row to which the dragged rows should be
* dropped
*/
public int getToRowPosition() {
return this.toRowPositionCoordinate.getRowPosition();
}
/**
* @return Flag to indicate if the row is dragged to the top edge of the
* layer.
*/
public boolean isReorderToTopEdge() {
return this.reorderToTopEdge;
}
/**
*
* @return <code>true</code> if the carried from rows are treated as
* indexes, <code>false</code> if they are treated as positions.
* Default is <code>false</code>.
* @since 1.6
*/
public boolean isReorderByIndex() {
return this.reorderByIndex;
}
/**
* Configure how the carried rows should be treated. By default they are
* treated as positions and converted to the local layer. Setting this value
* to <code>true</code> will treat the rows as indexes which will avoid
* conversion. This can be useful to reorder hidden rows for example.
*
* @param reorderByIndex
* <code>true</code> if the carried from columns should be
* treated as indexes, <code>false</code> if they should be
* treated as positions.
* @since 1.6
*/
public void setReorderByIndex(boolean reorderByIndex) {
this.reorderByIndex = reorderByIndex;
}
/**
* Toggles the coordinate from top edge to bottom edge and vice versa. Will
* not toggle if the coordinate is bottom edge of the last row or the top
* edge of the first row.
*
* @since 1.6
*/
public void toggleCoordinateByEdge() {
if (this.reorderToTopEdge
&& this.toRowPositionCoordinate.rowPosition > 0) {
this.toRowPositionCoordinate.rowPosition--;
this.reorderToTopEdge = false;
} else if (!this.reorderToTopEdge
&& this.toRowPositionCoordinate.rowPosition < this.toRowPositionCoordinate.getLayer().getRowCount() - 1) {
this.toRowPositionCoordinate.rowPosition++;
this.reorderToTopEdge = true;
}
}
/**
*
* @param fromPositions
* The new fromRowPositions.
*
* @since 2.0
*/
public void updateFromRowPositions(int... fromPositions) {
this.fromRowPositionCoordinates = new ArrayList<>(fromPositions.length);
for (int fromRowPosition : fromPositions) {
this.fromRowPositionCoordinates.add(
new RowPositionCoordinate(this.toRowPositionCoordinate.getLayer(), fromRowPosition));
}
}
/**
*
* @param toPosition
* The new toRowPosition.
*
* @since 2.0
*/
public void updateToRowPosition(int toPosition) {
this.toRowPositionCoordinate.rowPosition = toPosition;
}
@Override
public boolean convertToTargetLayer(ILayer targetLayer) {
List<RowPositionCoordinate> convertedFromRowPositionCoordinates =
new ArrayList<>(this.fromRowPositionCoordinates.size());
for (RowPositionCoordinate fromRowPositionCoordinate : this.fromRowPositionCoordinates) {
if (!this.reorderByIndex) {
RowPositionCoordinate convertedFromRowPositionCoordinate =
LayerCommandUtil.convertRowPositionToTargetContext(fromRowPositionCoordinate, targetLayer);
if (convertedFromRowPositionCoordinate != null) {
convertedFromRowPositionCoordinates.add(convertedFromRowPositionCoordinate);
}
} else {
convertedFromRowPositionCoordinates.add(fromRowPositionCoordinate);
}
}
RowPositionCoordinate targetToRowPositionCoordinate =
LayerCommandUtil.convertRowPositionToTargetContext(this.toRowPositionCoordinate, targetLayer);
if (!convertedFromRowPositionCoordinates.isEmpty()
&& targetToRowPositionCoordinate != null) {
this.fromRowPositionCoordinates = convertedFromRowPositionCoordinates;
this.toRowPositionCoordinate = targetToRowPositionCoordinate;
return true;
} else {
return false;
}
}
@Override
public MultiRowReorderCommand cloneCommand() {
return new MultiRowReorderCommand(this);
}
}