X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui.nattable%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fnattable%2Foverride%2FAbstractRowHideShowLayer2.java;fp=bundles%2Forg.simantics.browsing.ui.nattable%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fnattable%2Foverride%2FAbstractRowHideShowLayer2.java;h=86b2a3d2cb6bae864aaf7c90812c6217a983cf00;hp=44f4b7c15375ab5433f417c62174cd9b4d8475da;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/override/AbstractRowHideShowLayer2.java b/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/override/AbstractRowHideShowLayer2.java index 44f4b7c15..86b2a3d2c 100644 --- a/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/override/AbstractRowHideShowLayer2.java +++ b/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/override/AbstractRowHideShowLayer2.java @@ -1,301 +1,301 @@ -/******************************************************************************* - * Copyright (c) 2012 Original authors 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: - * Original authors and others - initial API and implementation - ******************************************************************************/ -package org.simantics.browsing.ui.nattable.override; - -import java.util.ArrayList; -import java.util.Collection; - -import org.eclipse.nebula.widgets.nattable.coordinate.Range; -import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform; -import org.eclipse.nebula.widgets.nattable.layer.ILayer; -import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer; -import org.eclipse.nebula.widgets.nattable.layer.LayerUtil; -import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent; -import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent; -import org.eclipse.nebula.widgets.nattable.layer.event.VisualRefreshEvent; - -import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; - -/** - * AbstractRowHideShowLayer implementation with FastUtils hashmaps. - * - * @see org.eclipse.nebula.widgets.nattable.hideshow.AbstractRowHideShowLayer - * - * @author MLMARKO - * - */ -public abstract class AbstractRowHideShowLayer2 extends AbstractLayerTransform implements IUniqueIndexLayer { - - private Int2IntOpenHashMap cachedVisibleRowIndexOrder; - private Int2IntOpenHashMap cachedVisibleRowPositionOrder; - - private Int2IntOpenHashMap cachedHiddenRowIndexToPositionMap; - - protected final Int2IntOpenHashMap startYCache = new Int2IntOpenHashMap(); - - - public AbstractRowHideShowLayer2(IUniqueIndexLayer underlyingLayer) { - super(underlyingLayer); - } - - @Override - public void handleLayerEvent(ILayerEvent event) { - if (event instanceof IStructuralChangeEvent) { - IStructuralChangeEvent structuralChangeEvent = (IStructuralChangeEvent) event; - if (structuralChangeEvent.isVerticalStructureChanged()) { - // vertical structure has changed, update cached row information - invalidateCache(); - } - } else if (event instanceof VisualRefreshEvent) { - // visual change, e.g. font change, the startYCache needs to be - // cleared in order to re-render correctly - this.startYCache.clear(); - } - super.handleLayerEvent(event); - } - - // Horizontal features - - // Columns - - @Override - public int getColumnPositionByIndex(int columnIndex) { - return ((IUniqueIndexLayer) getUnderlyingLayer()).getColumnPositionByIndex(columnIndex); - } - - // Vertical features - - // Rows - - @Override - public int getRowCount() { - return getCachedVisibleRowIndexes().size(); - } - - @Override - public int getRowIndexByPosition(int rowPosition) { - if (rowPosition < 0 || rowPosition >= getRowCount()) { - return -1; - } - return getCachedVisibleRowPositons().get(rowPosition); - } - - @Override - public int getRowPositionByIndex(int rowIndex) { - return getCachedVisibleRowIndexes().get(rowIndex); - } - - public Collection getRowPositionsByIndexes(Collection rowIndexes) { - IntOpenHashSet rowPositions = new IntOpenHashSet(); - for (int rowIndex : rowIndexes) { - rowPositions.add(getRowPositionByIndex(rowIndex)); - } - return rowPositions; - } - - @Override - public int localToUnderlyingRowPosition(int localRowPosition) { - int rowIndex = getRowIndexByPosition(localRowPosition); - return ((IUniqueIndexLayer) getUnderlyingLayer()).getRowPositionByIndex(rowIndex); - } - - @Override - public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, int underlyingRowPosition) { - int rowIndex = getUnderlyingLayer().getRowIndexByPosition(underlyingRowPosition); - int rowPosition = getRowPositionByIndex(rowIndex); - if (rowPosition >= 0) { - return rowPosition; - } else { - if (this.cachedHiddenRowIndexToPositionMap.containsKey(rowIndex)) { - return this.cachedHiddenRowIndexToPositionMap.get(rowIndex); - } else { - return -1; - } - } - } - - @Override - public Collection underlyingToLocalRowPositions( - ILayer sourceUnderlyingLayer, Collection underlyingRowPositionRanges) { - Collection localRowPositionRanges = new ArrayList(); - - for (Range underlyingRowPositionRange : underlyingRowPositionRanges) { - int startRowPosition = getAdjustedUnderlyingToLocalStartPosition( - sourceUnderlyingLayer, - underlyingRowPositionRange.start, - underlyingRowPositionRange.end); - int endRowPosition = getAdjustedUnderlyingToLocalEndPosition( - sourceUnderlyingLayer, - underlyingRowPositionRange.end, - underlyingRowPositionRange.start); - - // teichstaedt: fixes the problem that ranges where added even if - // the corresponding startPosition weren't found in the underlying - // layer. Without that fix a bunch of ranges of kind Range [-1, 180] - // which causes strange behaviour in Freeze- and other Layers were - // returned. - if (startRowPosition > -1) { - localRowPositionRanges.add(new Range(startRowPosition, endRowPosition)); - } - } - - return localRowPositionRanges; - } - - private int getAdjustedUnderlyingToLocalStartPosition( - ILayer sourceUnderlyingLayer, - int startUnderlyingPosition, - int endUnderlyingPosition) { - int localStartRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition); - int offset = 0; - while (localStartRowPosition < 0 - && (startUnderlyingPosition + offset < endUnderlyingPosition)) { - localStartRowPosition = - underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition + offset++); - } - return localStartRowPosition; - } - - private int getAdjustedUnderlyingToLocalEndPosition( - ILayer sourceUnderlyingLayer, - int endUnderlyingPosition, - int startUnderlyingPosition) { - int localEndRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - 1); - int offset = 0; - while (localEndRowPosition < 0 - && (endUnderlyingPosition - offset > startUnderlyingPosition)) { - localEndRowPosition = - underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - offset++); - } - return localEndRowPosition + 1; - } - - // Height - - @Override - public int getHeight() { - int lastRowPosition = getRowCount() - 1; - return getStartYOfRowPosition(lastRowPosition) + getRowHeightByPosition(lastRowPosition); - } - - // Y - - @Override - public int getRowPositionByY(int y) { - return LayerUtil.getRowPositionByY(this, y); - } - - @Override - public int getStartYOfRowPosition(int localRowPosition) { - int index = this.startYCache.get(localRowPosition); - if (index >= 0) - return index; - - IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer(); - int underlyingPosition = localToUnderlyingRowPosition(localRowPosition); - if (underlyingPosition < 0) { - return -1; - } - int underlyingStartY = underlyingLayer.getStartYOfRowPosition(underlyingPosition); - if (underlyingStartY < 0) { - return -1; - } - - for (Integer hiddenIndex : getHiddenRowIndexes()) { - int hiddenPosition = underlyingLayer.getRowPositionByIndex(hiddenIndex); - // if the hidden position is -1, it is hidden in the underlying - // layertherefore the underlying layer should handle the positioning - if (hiddenPosition >= 0 && hiddenPosition <= underlyingPosition) { - underlyingStartY -= underlyingLayer.getRowHeightByPosition(hiddenPosition); - } - } - - this.startYCache.put(localRowPosition, underlyingStartY); - return underlyingStartY; - } - - // Hide/show - - /** - * Will check if the row at the specified index is hidden or not. Checks - * this layer and also the sublayers for the visibility. - * - * @param rowIndex - * The row index of the row whose visibility state should be - * checked. - * @return true if the row at the specified index is hidden, - * false if it is visible. - */ - public abstract boolean isRowIndexHidden(int rowIndex); - - /** - * Will collect and return all indexes of the rows that are hidden in this - * layer. Note: It is not intended that it also collects the row indexes of - * underlying layers. This would cause issues on calculating positions as - * every layer is responsible for those calculations itself. - * - * @return Collection of all row indexes that are hidden in this layer. - */ - public abstract Collection getHiddenRowIndexes(); - - // Cache - - /** - * Invalidate the cache to ensure that information is rebuild. - */ - protected void invalidateCache() { - this.cachedVisibleRowIndexOrder = null; - this.cachedVisibleRowPositionOrder = null; - this.cachedHiddenRowIndexToPositionMap = null; - this.startYCache.clear(); - } - - private Int2IntOpenHashMap getCachedVisibleRowIndexes() { - if (this.cachedVisibleRowIndexOrder == null) { - cacheVisibleRowIndexes(); - } - return this.cachedVisibleRowIndexOrder; - } - - private Int2IntOpenHashMap getCachedVisibleRowPositons() { - if (this.cachedVisibleRowPositionOrder == null) { - cacheVisibleRowIndexes(); - } - return this.cachedVisibleRowPositionOrder; - } - - protected void cacheVisibleRowIndexes() { - this.cachedVisibleRowIndexOrder = new Int2IntOpenHashMap(); - this.cachedVisibleRowPositionOrder = new Int2IntOpenHashMap(); - this.cachedHiddenRowIndexToPositionMap = new Int2IntOpenHashMap(); - this.startYCache.clear(); - - cachedVisibleRowPositionOrder.defaultReturnValue(-1); - cachedVisibleRowIndexOrder.defaultReturnValue(-1); - cachedHiddenRowIndexToPositionMap.defaultReturnValue(-1); - startYCache.defaultReturnValue(-1); - - ILayer underlyingLayer = getUnderlyingLayer(); - int rowPosition = 0; - for (int parentRowPosition = 0; parentRowPosition < underlyingLayer.getRowCount(); parentRowPosition++) { - int rowIndex = underlyingLayer.getRowIndexByPosition(parentRowPosition); - - if (!isRowIndexHidden(rowIndex)) { - this.cachedVisibleRowIndexOrder.put(rowIndex, rowPosition); - this.cachedVisibleRowPositionOrder.put(rowPosition, rowIndex); - rowPosition++; - } else { - this.cachedHiddenRowIndexToPositionMap.put(rowIndex, rowPosition); - } - } - } -} +/******************************************************************************* + * Copyright (c) 2012 Original authors 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: + * Original authors and others - initial API and implementation + ******************************************************************************/ +package org.simantics.browsing.ui.nattable.override; + +import java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.nebula.widgets.nattable.coordinate.Range; +import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform; +import org.eclipse.nebula.widgets.nattable.layer.ILayer; +import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer; +import org.eclipse.nebula.widgets.nattable.layer.LayerUtil; +import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent; +import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent; +import org.eclipse.nebula.widgets.nattable.layer.event.VisualRefreshEvent; + +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; + +/** + * AbstractRowHideShowLayer implementation with FastUtils hashmaps. + * + * @see org.eclipse.nebula.widgets.nattable.hideshow.AbstractRowHideShowLayer + * + * @author MLMARKO + * + */ +public abstract class AbstractRowHideShowLayer2 extends AbstractLayerTransform implements IUniqueIndexLayer { + + private Int2IntOpenHashMap cachedVisibleRowIndexOrder; + private Int2IntOpenHashMap cachedVisibleRowPositionOrder; + + private Int2IntOpenHashMap cachedHiddenRowIndexToPositionMap; + + protected final Int2IntOpenHashMap startYCache = new Int2IntOpenHashMap(); + + + public AbstractRowHideShowLayer2(IUniqueIndexLayer underlyingLayer) { + super(underlyingLayer); + } + + @Override + public void handleLayerEvent(ILayerEvent event) { + if (event instanceof IStructuralChangeEvent) { + IStructuralChangeEvent structuralChangeEvent = (IStructuralChangeEvent) event; + if (structuralChangeEvent.isVerticalStructureChanged()) { + // vertical structure has changed, update cached row information + invalidateCache(); + } + } else if (event instanceof VisualRefreshEvent) { + // visual change, e.g. font change, the startYCache needs to be + // cleared in order to re-render correctly + this.startYCache.clear(); + } + super.handleLayerEvent(event); + } + + // Horizontal features + + // Columns + + @Override + public int getColumnPositionByIndex(int columnIndex) { + return ((IUniqueIndexLayer) getUnderlyingLayer()).getColumnPositionByIndex(columnIndex); + } + + // Vertical features + + // Rows + + @Override + public int getRowCount() { + return getCachedVisibleRowIndexes().size(); + } + + @Override + public int getRowIndexByPosition(int rowPosition) { + if (rowPosition < 0 || rowPosition >= getRowCount()) { + return -1; + } + return getCachedVisibleRowPositons().get(rowPosition); + } + + @Override + public int getRowPositionByIndex(int rowIndex) { + return getCachedVisibleRowIndexes().get(rowIndex); + } + + public Collection getRowPositionsByIndexes(Collection rowIndexes) { + IntOpenHashSet rowPositions = new IntOpenHashSet(); + for (int rowIndex : rowIndexes) { + rowPositions.add(getRowPositionByIndex(rowIndex)); + } + return rowPositions; + } + + @Override + public int localToUnderlyingRowPosition(int localRowPosition) { + int rowIndex = getRowIndexByPosition(localRowPosition); + return ((IUniqueIndexLayer) getUnderlyingLayer()).getRowPositionByIndex(rowIndex); + } + + @Override + public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, int underlyingRowPosition) { + int rowIndex = getUnderlyingLayer().getRowIndexByPosition(underlyingRowPosition); + int rowPosition = getRowPositionByIndex(rowIndex); + if (rowPosition >= 0) { + return rowPosition; + } else { + if (this.cachedHiddenRowIndexToPositionMap.containsKey(rowIndex)) { + return this.cachedHiddenRowIndexToPositionMap.get(rowIndex); + } else { + return -1; + } + } + } + + @Override + public Collection underlyingToLocalRowPositions( + ILayer sourceUnderlyingLayer, Collection underlyingRowPositionRanges) { + Collection localRowPositionRanges = new ArrayList(); + + for (Range underlyingRowPositionRange : underlyingRowPositionRanges) { + int startRowPosition = getAdjustedUnderlyingToLocalStartPosition( + sourceUnderlyingLayer, + underlyingRowPositionRange.start, + underlyingRowPositionRange.end); + int endRowPosition = getAdjustedUnderlyingToLocalEndPosition( + sourceUnderlyingLayer, + underlyingRowPositionRange.end, + underlyingRowPositionRange.start); + + // teichstaedt: fixes the problem that ranges where added even if + // the corresponding startPosition weren't found in the underlying + // layer. Without that fix a bunch of ranges of kind Range [-1, 180] + // which causes strange behaviour in Freeze- and other Layers were + // returned. + if (startRowPosition > -1) { + localRowPositionRanges.add(new Range(startRowPosition, endRowPosition)); + } + } + + return localRowPositionRanges; + } + + private int getAdjustedUnderlyingToLocalStartPosition( + ILayer sourceUnderlyingLayer, + int startUnderlyingPosition, + int endUnderlyingPosition) { + int localStartRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition); + int offset = 0; + while (localStartRowPosition < 0 + && (startUnderlyingPosition + offset < endUnderlyingPosition)) { + localStartRowPosition = + underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition + offset++); + } + return localStartRowPosition; + } + + private int getAdjustedUnderlyingToLocalEndPosition( + ILayer sourceUnderlyingLayer, + int endUnderlyingPosition, + int startUnderlyingPosition) { + int localEndRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - 1); + int offset = 0; + while (localEndRowPosition < 0 + && (endUnderlyingPosition - offset > startUnderlyingPosition)) { + localEndRowPosition = + underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - offset++); + } + return localEndRowPosition + 1; + } + + // Height + + @Override + public int getHeight() { + int lastRowPosition = getRowCount() - 1; + return getStartYOfRowPosition(lastRowPosition) + getRowHeightByPosition(lastRowPosition); + } + + // Y + + @Override + public int getRowPositionByY(int y) { + return LayerUtil.getRowPositionByY(this, y); + } + + @Override + public int getStartYOfRowPosition(int localRowPosition) { + int index = this.startYCache.get(localRowPosition); + if (index >= 0) + return index; + + IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer(); + int underlyingPosition = localToUnderlyingRowPosition(localRowPosition); + if (underlyingPosition < 0) { + return -1; + } + int underlyingStartY = underlyingLayer.getStartYOfRowPosition(underlyingPosition); + if (underlyingStartY < 0) { + return -1; + } + + for (Integer hiddenIndex : getHiddenRowIndexes()) { + int hiddenPosition = underlyingLayer.getRowPositionByIndex(hiddenIndex); + // if the hidden position is -1, it is hidden in the underlying + // layertherefore the underlying layer should handle the positioning + if (hiddenPosition >= 0 && hiddenPosition <= underlyingPosition) { + underlyingStartY -= underlyingLayer.getRowHeightByPosition(hiddenPosition); + } + } + + this.startYCache.put(localRowPosition, underlyingStartY); + return underlyingStartY; + } + + // Hide/show + + /** + * Will check if the row at the specified index is hidden or not. Checks + * this layer and also the sublayers for the visibility. + * + * @param rowIndex + * The row index of the row whose visibility state should be + * checked. + * @return true if the row at the specified index is hidden, + * false if it is visible. + */ + public abstract boolean isRowIndexHidden(int rowIndex); + + /** + * Will collect and return all indexes of the rows that are hidden in this + * layer. Note: It is not intended that it also collects the row indexes of + * underlying layers. This would cause issues on calculating positions as + * every layer is responsible for those calculations itself. + * + * @return Collection of all row indexes that are hidden in this layer. + */ + public abstract Collection getHiddenRowIndexes(); + + // Cache + + /** + * Invalidate the cache to ensure that information is rebuild. + */ + protected void invalidateCache() { + this.cachedVisibleRowIndexOrder = null; + this.cachedVisibleRowPositionOrder = null; + this.cachedHiddenRowIndexToPositionMap = null; + this.startYCache.clear(); + } + + private Int2IntOpenHashMap getCachedVisibleRowIndexes() { + if (this.cachedVisibleRowIndexOrder == null) { + cacheVisibleRowIndexes(); + } + return this.cachedVisibleRowIndexOrder; + } + + private Int2IntOpenHashMap getCachedVisibleRowPositons() { + if (this.cachedVisibleRowPositionOrder == null) { + cacheVisibleRowIndexes(); + } + return this.cachedVisibleRowPositionOrder; + } + + protected void cacheVisibleRowIndexes() { + this.cachedVisibleRowIndexOrder = new Int2IntOpenHashMap(); + this.cachedVisibleRowPositionOrder = new Int2IntOpenHashMap(); + this.cachedHiddenRowIndexToPositionMap = new Int2IntOpenHashMap(); + this.startYCache.clear(); + + cachedVisibleRowPositionOrder.defaultReturnValue(-1); + cachedVisibleRowIndexOrder.defaultReturnValue(-1); + cachedHiddenRowIndexToPositionMap.defaultReturnValue(-1); + startYCache.defaultReturnValue(-1); + + ILayer underlyingLayer = getUnderlyingLayer(); + int rowPosition = 0; + for (int parentRowPosition = 0; parentRowPosition < underlyingLayer.getRowCount(); parentRowPosition++) { + int rowIndex = underlyingLayer.getRowIndexByPosition(parentRowPosition); + + if (!isRowIndexHidden(rowIndex)) { + this.cachedVisibleRowIndexOrder.put(rowIndex, rowPosition); + this.cachedVisibleRowPositionOrder.put(rowPosition, rowIndex); + rowPosition++; + } else { + this.cachedHiddenRowIndexToPositionMap.put(rowIndex, rowPosition); + } + } + } +}