blob: 1b32633f5017b1d6669f5975c596a47532ad2667 [file] [log] [blame]
package org.eclipse.nebula.widgets.nattable.core.layer.axis.impl.hideshow
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 segments to be hidden and later shown again.
* <p>
* NOTE: This axis implementation is not performant for large numbers (e.g. thousands) of segments.
*/
class HideShowAxis extends AbstractAxis {
val hiddenSegmentPositionToIdMap = new TreeMap<Long, Serializable>
val segmentPositionToStartPixelMap = new HashMap<Long, BigDecimal>
Axis underlyingAxis
new() {}
new(Axis underlyingAxis) {
setUnderlyingAxis(underlyingAxis)
}
def void setUnderlyingAxis(Axis underlyingAxis) {
this.underlyingAxis = underlyingAxis
}
// Axis interface
override getSegmentCount() {
underlyingAxis.segmentCount - hiddenSegmentPositionToIdMap.size
}
override getStartPixelOfSegmentPosition(long segmentPosition) {
val startPixel = segmentPositionToStartPixelMap.get(segmentPosition)
if (startPixel != null)
return startPixel
else {
var aggregateSize = new BigDecimal(0.0)
for (position : 0 ..< segmentPosition) {
val segmentId = getIdOfSegmentPosition(position)
val underlyingSegmentPosition = underlyingAxis.getSegmentPositionOfId(segmentId)
aggregateSize = aggregateSize + underlyingAxis.getPixelSizeOfSegmentPosition(underlyingSegmentPosition)
}
segmentPositionToStartPixelMap.put(segmentPosition, aggregateSize)
return aggregateSize
}
}
override getSegmentPositionOfPixelLocation(BigDecimal pixelLocation) {
if (pixelLocation < new BigDecimal(0)) return -1
for (segmentPosition : 0 .. segmentCount) {
val startPixel = getStartPixelOfSegmentPosition(segmentPosition)
if (startPixel > pixelLocation)
return segmentPosition - 1
}
return segmentCount
}
// TODO Optimize. Cache?
override getIdOfSegmentPosition(long segmentPosition) {
var numHiddenSegments = 0L
var fromPosition = 0L
var toPosition = segmentPosition
while (toPosition < underlyingAxis.segmentCount) {
var numHiddenSegmentsAtOrBeforeToPosition = hiddenSegmentPositionToIdMap.subMap(fromPosition, toPosition + 1).size
if (numHiddenSegmentsAtOrBeforeToPosition == 0)
return underlyingAxis.getIdOfSegmentPosition(segmentPosition + numHiddenSegments)
else {
numHiddenSegments = numHiddenSegments + numHiddenSegmentsAtOrBeforeToPosition
fromPosition = toPosition + 1
toPosition = toPosition + numHiddenSegmentsAtOrBeforeToPosition
}
}
null
}
override getSegmentPositionOfId(Serializable segmentId) {
val underlyingSegmentPosition = underlyingAxis.getSegmentPositionOfId(segmentId)
underlyingSegmentPosition - hiddenSegmentPositionToIdMap.subMap(0L, underlyingSegmentPosition).size
}
//
def hideSegmentId(Serializable segmentId) {
val underlyingSegmentPosition = underlyingAxis.getSegmentPositionOfId(segmentId)
if (underlyingAxis.containsSegmentPosition(underlyingSegmentPosition)) {
hiddenSegmentPositionToIdMap.put(underlyingSegmentPosition, segmentId)
segmentPositionToStartPixelMap.clear
}
}
def showSegmentId(Serializable segmentId) {
val underlyingSegmentPosition = underlyingAxis.getSegmentPositionOfId(segmentId)
if (underlyingAxis.containsSegmentPosition(underlyingSegmentPosition)) {
val mapping = hiddenSegmentPositionToIdMap.remove(underlyingSegmentPosition)
if (mapping != null)
segmentPositionToStartPixelMap.clear
}
}
}