| package org.eclipse.nebula.widgets.nattable.core.layer.axis.impl.reorder |
| |
| import java.io.Serializable |
| import java.math.BigDecimal |
| import java.util.HashMap |
| import java.util.TreeMap |
| import org.eclipse.nebula.widgets.nattable.core.layer.axis.Axis |
| import org.eclipse.nebula.widgets.nattable.core.layer.axis.impl.AbstractAxis |
| |
| import static extension org.eclipse.nebula.widgets.nattable.core.layer.axis.AxisInvariants.* |
| import static extension org.eclipse.nebula.widgets.nattable.core.math.BigDecimalExtensions.* |
| |
| /** |
| * An axis that allows reordering of its segments. |
| * <p> |
| * NOTE: This axis implementation is not performant for large numbers (e.g. thousands) of segments. |
| */ |
| class ReorderAxis extends AbstractAxis { |
| |
| val reorderedSegmentPositionToIdMap = new TreeMap<Long, Serializable> |
| val reorderedSegmentIdToPositionMap = new HashMap<Serializable, Long> |
| val segmentPositionToStartPixelMap = new TreeMap<Long, BigDecimal> |
| |
| Axis underlyingAxis |
| |
| new() {} |
| |
| new(Axis underlyingAxis) { |
| setUnderlyingAxis(underlyingAxis) |
| } |
| |
| def void setUnderlyingAxis(Axis underlyingAxis) { |
| this.underlyingAxis = underlyingAxis |
| |
| var segmentPosition = 0L |
| while (segmentPosition < underlyingAxis.segmentCount) { |
| reorderedSegmentPositionToIdMap.put(segmentPosition, underlyingAxis.getIdOfSegmentPosition(segmentPosition)) |
| reorderedSegmentIdToPositionMap.put(underlyingAxis.getIdOfSegmentPosition(segmentPosition), segmentPosition) |
| |
| segmentPosition = segmentPosition + 1 |
| } |
| } |
| |
| // Axis interface |
| |
| override getSegmentCount() { |
| underlyingAxis.segmentCount |
| } |
| |
| override getStartPixelOfSegmentPosition(long segmentPosition) { |
| val startPixel = segmentPositionToStartPixelMap.get(segmentPosition) |
| if (startPixel != null) |
| return startPixel |
| else { |
| var aggregateSize = new BigDecimal(0.0) |
| |
| var position = 0L |
| while (position < segmentPosition) { |
| val segmentId = reorderedSegmentPositionToIdMap.get(position) |
| val underlyingSegmentPosition = underlyingAxis.getSegmentPositionOfId(segmentId) |
| aggregateSize = aggregateSize + underlyingAxis.getPixelSizeOfSegmentPosition(underlyingSegmentPosition) |
| |
| position = position + 1 |
| } |
| |
| segmentPositionToStartPixelMap.put(segmentPosition, aggregateSize) |
| return aggregateSize |
| } |
| } |
| |
| override getSegmentPositionOfPixelLocation(BigDecimal pixelLocation) { |
| if (pixelLocation < new BigDecimal(0)) return -1 |
| |
| var segmentPosition = 0L |
| while (segmentPosition <= segmentCount) { |
| val startPixel = getStartPixelOfSegmentPosition(segmentPosition) |
| if (startPixel > pixelLocation) |
| return segmentPosition - 1 |
| |
| segmentPosition = segmentPosition + 1 |
| } |
| |
| return segmentCount |
| } |
| |
| override getIdOfSegmentPosition(long segmentPosition) { |
| reorderedSegmentPositionToIdMap.get(segmentPosition) |
| } |
| |
| override getSegmentPositionOfId(Serializable segmentId) { |
| reorderedSegmentIdToPositionMap.get(segmentId) |
| } |
| |
| // |
| |
| /** |
| * Moves a segment from a given position to a new position. |
| * @param fromSegmentPosition The segment position to move. |
| * @param toSegmentPosition The new position to move the segment to. |
| */ |
| def void reorderSegmentPosition(long fromSegmentPosition, long toSegmentPosition) { |
| val segmentId = reorderedSegmentPositionToIdMap.get(fromSegmentPosition) |
| |
| reorderedSegmentPositionToIdMap.remove(fromSegmentPosition) |
| reorderedSegmentIdToPositionMap.remove(segmentId) |
| |
| reorderedSegmentPositionToIdMap.put(toSegmentPosition, segmentId) |
| reorderedSegmentIdToPositionMap.put(segmentId, toSegmentPosition) |
| |
| segmentPositionToStartPixelMap.clear |
| } |
| |
| } |