blob: cd749b1b3c01f19e6c86d6f3f5422580e7bce2f9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2020 Original authors 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:
* Original authors and others - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.reorder.event;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.collections.api.list.primitive.MutableIntList;
import org.eclipse.collections.impl.factory.primitive.IntLists;
import org.eclipse.nebula.widgets.nattable.coordinate.PositionUtil;
import org.eclipse.nebula.widgets.nattable.coordinate.Range;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.event.ColumnStructuralChangeEvent;
import org.eclipse.nebula.widgets.nattable.layer.event.StructuralDiff;
import org.eclipse.nebula.widgets.nattable.layer.event.StructuralDiff.DiffTypeEnum;
import org.eclipse.nebula.widgets.nattable.util.ArrayUtil;
/**
* Event indicating that one or multiple columns are moved to a new position.
*/
public class ColumnReorderEvent extends ColumnStructuralChangeEvent {
private ILayer beforeLayer;
private Collection<Range> beforeFromColumnPositionRanges;
private MutableIntList beforeFromColumnIndexes;
private int beforeToColumnPosition;
private int beforeToColumnIndex;
private boolean reorderToLeftEdge;
/**
*
* @param layer
* The layer to which the column positions match.
* @param beforeFromColumnPosition
* The column position that was reordered, before the reorder
* operation was performed.
* @param beforeFromColumnIndex
* The index of the reordered position.
* @param beforeToColumnPosition
* The position of the column to which the reorder operation was
* performed, before the reorder operation was performed
* @param beforeToColumnIndex
* The index of the column to which the reorder operation was
* performed.
* @param reorderToLeftEdge
* whether the reorder operation was performed to the left or the
* right edge.
*
* @since 1.6
*/
public ColumnReorderEvent(ILayer layer,
int beforeFromColumnPosition,
int beforeFromColumnIndex,
int beforeToColumnPosition,
int beforeToColumnIndex,
boolean reorderToLeftEdge) {
this(layer,
new int[] { beforeFromColumnPosition },
new int[] { beforeFromColumnIndex },
beforeToColumnPosition,
beforeToColumnIndex,
reorderToLeftEdge);
}
/**
*
* @param layer
* The layer to which the column positions match.
* @param beforeFromColumnPositions
* The column positions that were reordered, before the reorder
* operation was performed.
* @param beforeFromColumnIndexes
* The indexes of the reordered positions.
* @param beforeToColumnPosition
* The position of the column to which the reorder operation was
* performed, before the reorder operation was performed
* @param beforeToColumnIndex
* The index of the column to which the reorder operation was
* performed.
* @param reorderToLeftEdge
* whether the reorder operation was performed to the left or the
* right edge.
*
* @since 1.6
*/
public ColumnReorderEvent(ILayer layer,
List<Integer> beforeFromColumnPositions,
List<Integer> beforeFromColumnIndexes,
int beforeToColumnPosition,
int beforeToColumnIndex,
boolean reorderToLeftEdge) {
this(layer,
beforeFromColumnPositions.stream().mapToInt(Integer::intValue).toArray(),
beforeFromColumnIndexes.stream().mapToInt(Integer::intValue).toArray(),
beforeToColumnPosition,
beforeToColumnIndex,
reorderToLeftEdge);
}
/**
*
* @param layer
* The layer to which the column positions match.
* @param beforeFromColumnPositions
* The column positions that were reordered, before the reorder
* operation was performed.
* @param beforeFromColumnIndexes
* The indexes of the reordered positions.
* @param beforeToColumnPosition
* The position of the column to which the reorder operation was
* performed, before the reorder operation was performed
* @param beforeToColumnIndex
* The index of the column to which the reorder operation was
* performed.
* @param reorderToLeftEdge
* whether the reorder operation was performed to the left or the
* right edge.
*
* @since 2.0
*/
public ColumnReorderEvent(ILayer layer,
int[] beforeFromColumnPositions,
int[] beforeFromColumnIndexes,
int beforeToColumnPosition,
int beforeToColumnIndex,
boolean reorderToLeftEdge) {
super(layer);
this.beforeLayer = layer;
this.beforeFromColumnPositionRanges = PositionUtil.getRanges(beforeFromColumnPositions);
this.beforeFromColumnIndexes = IntLists.mutable.of(beforeFromColumnIndexes);
this.beforeToColumnPosition = beforeToColumnPosition;
this.beforeToColumnIndex = beforeToColumnIndex;
this.reorderToLeftEdge = reorderToLeftEdge;
MutableIntList allColumnPositions = IntLists.mutable.of(beforeFromColumnPositions);
allColumnPositions.add(beforeToColumnPosition);
setColumnPositionRanges(PositionUtil.getRanges(allColumnPositions.toSortedArray()));
}
/**
* Constructor for internal use to clone this event.
*
* @param event
* The event out of which the new one should be created
*/
public ColumnReorderEvent(ColumnReorderEvent event) {
super(event);
this.beforeLayer = event.beforeLayer;
this.beforeFromColumnPositionRanges = new ArrayList<Range>(event.beforeFromColumnPositionRanges);
this.beforeFromColumnIndexes = IntLists.mutable.ofAll(event.beforeFromColumnIndexes);
this.beforeToColumnPosition = event.beforeToColumnPosition;
this.beforeToColumnIndex = event.beforeToColumnIndex;
this.reorderToLeftEdge = event.reorderToLeftEdge;
}
/**
*
* @return The indexes of the reordered columns.
* @since 1.6
*/
public Collection<Integer> getBeforeFromColumnIndexes() {
return ArrayUtil.asIntegerList(this.beforeFromColumnIndexes.toSortedArray());
}
/**
*
* @return The indexes of the reordered columns.
* @since 2.0
*/
public int[] getBeforeFromColumnIndexesArray() {
return this.beforeFromColumnIndexes.toSortedArray();
}
/**
*
* @return The position ranges of the reordered columns.
*/
public Collection<Range> getBeforeFromColumnPositionRanges() {
return this.beforeFromColumnPositionRanges;
}
/**
*
* @return The position of the column to which the reorder operation was
* performed.
*/
public int getBeforeToColumnPosition() {
return this.beforeToColumnPosition;
}
/**
*
* @return The index of the column to which the reorder operation was
* performed.
* @since 1.6
*/
public int getBeforeToColumnIndex() {
return this.beforeToColumnIndex;
}
/**
* Setter for the beforeToColumnIndex that needs to be called used in case a
* reorder operation was performed to a hidden column.
*
* @param beforeIndex
* The index of the column to which the reorder operation was
* performed.
* @since 1.6
*/
public void setBeforeToColumnIndex(int beforeIndex) {
this.beforeToColumnIndex = beforeIndex;
}
/**
*
* @return <code>true</code> if the columns were reordered to the left edge
* of the toColumnPosition, <code>false</code> if the reorder
* operation was performed on the right edge (e.g. at the end of a
* table)
*/
public boolean isReorderToLeftEdge() {
return this.reorderToLeftEdge;
}
@Override
public Collection<StructuralDiff> getColumnDiffs() {
Collection<StructuralDiff> columnDiffs = new ArrayList<StructuralDiff>();
Collection<Range> beforeFromColumnPositionRanges = getBeforeFromColumnPositionRanges();
final int beforeToColumnPosition = (this.reorderToLeftEdge)
? this.beforeToColumnPosition
: (this.beforeToColumnPosition + 1);
int afterAddColumnPosition = beforeToColumnPosition;
for (Range beforeFromColumnPositionRange : beforeFromColumnPositionRanges) {
if (beforeFromColumnPositionRange.start < beforeToColumnPosition) {
afterAddColumnPosition -=
Math.min(beforeFromColumnPositionRange.end, beforeToColumnPosition) - beforeFromColumnPositionRange.start;
} else {
break;
}
}
int cumulativeAddSize = 0;
for (Range beforeFromColumnPositionRange : beforeFromColumnPositionRanges) {
cumulativeAddSize += beforeFromColumnPositionRange.size();
}
int offset = 0;
for (Range beforeFromColumnPositionRange : beforeFromColumnPositionRanges) {
int afterDeleteColumnPosition = beforeFromColumnPositionRange.start - offset;
if (afterAddColumnPosition < afterDeleteColumnPosition) {
afterDeleteColumnPosition += cumulativeAddSize;
}
columnDiffs.add(new StructuralDiff(
DiffTypeEnum.DELETE,
beforeFromColumnPositionRange,
new Range(afterDeleteColumnPosition, afterDeleteColumnPosition)));
offset += beforeFromColumnPositionRange.size();
}
Range beforeAddRange = new Range(beforeToColumnPosition, beforeToColumnPosition);
offset = 0;
for (Range beforeFromColumnPositionRange : beforeFromColumnPositionRanges) {
int size = beforeFromColumnPositionRange.size();
columnDiffs.add(new StructuralDiff(
DiffTypeEnum.ADD,
beforeAddRange,
new Range(afterAddColumnPosition + offset, afterAddColumnPosition + offset + size)));
offset += size;
}
return columnDiffs;
}
/**
* This method is intended to be used for position conversion of the before
* positions. The locally stored before positions are the positions of the
* reordered columns positions <b>before</b> the reorder is applied. Needed
* in case the conversion needs to be done before other states in the given
* layer are updated, and therefore the local before position cannot be
* determined anymore.
*
* @param layer
* The layer that performed the conversion of the before
* positions.
* @param fromColumnPositionRanges
* The converted column position ranges that were reordered
* before the reorder happened.
* @param toColumnPosition
* The converted column position to which a reorder happened
* before the reordering was performed.
*
* @since 1.6
*/
public void setConvertedBeforePositions(ILayer layer, Collection<Range> fromColumnPositionRanges, int toColumnPosition) {
this.beforeLayer = layer;
this.beforeFromColumnPositionRanges = fromColumnPositionRanges;
this.beforeToColumnPosition = toColumnPosition;
}
@Override
public boolean convertToLocal(ILayer targetLayer) {
// if the conversion was done before, e.g. by an
// AbstractColumnHideShowLayer, we don't need to perform the conversion
// again
if (this.beforeLayer != targetLayer) {
this.beforeFromColumnPositionRanges =
targetLayer.underlyingToLocalColumnPositions(getLayer(), this.beforeFromColumnPositionRanges);
this.beforeToColumnPosition =
targetLayer.underlyingToLocalColumnPosition(getLayer(), this.beforeToColumnPosition);
this.beforeLayer = targetLayer;
}
if (this.beforeToColumnPosition >= 0) {
return super.convertToLocal(targetLayer);
} else {
return false;
}
}
@Override
public ColumnReorderEvent cloneEvent() {
return new ColumnReorderEvent(this);
}
}