]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/override/AbstractRowHideShowLayer2.java
Sync git svn branch with SVN repository r33144.
[simantics/platform.git] / bundles / org.simantics.browsing.ui.nattable / src / org / simantics / browsing / ui / nattable / override / AbstractRowHideShowLayer2.java
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
new file mode 100644 (file)
index 0000000..44f4b7c
--- /dev/null
@@ -0,0 +1,301 @@
+/*******************************************************************************\r
+ * Copyright (c) 2012 Original authors and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *     Original authors and others - initial API and implementation\r
+ ******************************************************************************/\r
+package org.simantics.browsing.ui.nattable.override;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.eclipse.nebula.widgets.nattable.coordinate.Range;\r
+import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;\r
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;\r
+import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;\r
+import org.eclipse.nebula.widgets.nattable.layer.LayerUtil;\r
+import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;\r
+import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent;\r
+import org.eclipse.nebula.widgets.nattable.layer.event.VisualRefreshEvent;\r
+\r
+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;\r
+import it.unimi.dsi.fastutil.ints.IntOpenHashSet;\r
+\r
+/**\r
+ * AbstractRowHideShowLayer implementation with FastUtils hashmaps.\r
+ * \r
+ * @see org.eclipse.nebula.widgets.nattable.hideshow.AbstractRowHideShowLayer\r
+ * \r
+ * @author MLMARKO\r
+ *\r
+ */\r
+public abstract class AbstractRowHideShowLayer2 extends AbstractLayerTransform implements IUniqueIndexLayer {\r
+\r
+       private Int2IntOpenHashMap cachedVisibleRowIndexOrder;\r
+       private Int2IntOpenHashMap cachedVisibleRowPositionOrder;\r
+       \r
+       private Int2IntOpenHashMap cachedHiddenRowIndexToPositionMap;\r
+\r
+       protected final Int2IntOpenHashMap startYCache = new Int2IntOpenHashMap();      \r
+       \r
+       \r
+       public AbstractRowHideShowLayer2(IUniqueIndexLayer underlyingLayer) {\r
+               super(underlyingLayer);\r
+       }\r
+       \r
+        @Override\r
+           public void handleLayerEvent(ILayerEvent event) {\r
+               if (event instanceof IStructuralChangeEvent) {\r
+                   IStructuralChangeEvent structuralChangeEvent = (IStructuralChangeEvent) event;\r
+                   if (structuralChangeEvent.isVerticalStructureChanged()) {\r
+                       // vertical structure has changed, update cached row information\r
+                       invalidateCache();\r
+                   }\r
+               } else if (event instanceof VisualRefreshEvent) {\r
+                   // visual change, e.g. font change, the startYCache needs to be\r
+                   // cleared in order to re-render correctly\r
+                   this.startYCache.clear();\r
+               }\r
+               super.handleLayerEvent(event);\r
+           }\r
+\r
+           // Horizontal features\r
+\r
+           // Columns\r
+\r
+           @Override\r
+           public int getColumnPositionByIndex(int columnIndex) {\r
+               return ((IUniqueIndexLayer) getUnderlyingLayer()).getColumnPositionByIndex(columnIndex);\r
+           }\r
+\r
+           // Vertical features\r
+\r
+           // Rows\r
+\r
+           @Override\r
+           public int getRowCount() {\r
+               return getCachedVisibleRowIndexes().size();\r
+           }\r
+\r
+           @Override\r
+           public int getRowIndexByPosition(int rowPosition) {\r
+               if (rowPosition < 0 || rowPosition >= getRowCount()) {\r
+                   return -1;\r
+               }\r
+               return getCachedVisibleRowPositons().get(rowPosition);\r
+           }\r
+\r
+           @Override\r
+           public int getRowPositionByIndex(int rowIndex) {\r
+               return getCachedVisibleRowIndexes().get(rowIndex);\r
+           }\r
+\r
+           public Collection<Integer> getRowPositionsByIndexes(Collection<Integer> rowIndexes) {\r
+               IntOpenHashSet rowPositions = new IntOpenHashSet();\r
+               for (int rowIndex : rowIndexes) {\r
+                   rowPositions.add(getRowPositionByIndex(rowIndex));\r
+               }\r
+               return rowPositions;\r
+           }\r
+\r
+           @Override\r
+           public int localToUnderlyingRowPosition(int localRowPosition) {\r
+               int rowIndex = getRowIndexByPosition(localRowPosition);\r
+               return ((IUniqueIndexLayer) getUnderlyingLayer()).getRowPositionByIndex(rowIndex);\r
+           }\r
+\r
+           @Override\r
+           public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, int underlyingRowPosition) {\r
+               int rowIndex = getUnderlyingLayer().getRowIndexByPosition(underlyingRowPosition);\r
+               int rowPosition = getRowPositionByIndex(rowIndex);\r
+               if (rowPosition >= 0) {\r
+                   return rowPosition;\r
+               } else {\r
+                       if (this.cachedHiddenRowIndexToPositionMap.containsKey(rowIndex)) {\r
+                     return this.cachedHiddenRowIndexToPositionMap.get(rowIndex);\r
+                   } else {\r
+                       return -1;\r
+                   }\r
+               }\r
+           }\r
+\r
+           @Override\r
+           public Collection<Range> underlyingToLocalRowPositions(\r
+                   ILayer sourceUnderlyingLayer, Collection<Range> underlyingRowPositionRanges) {\r
+               Collection<Range> localRowPositionRanges = new ArrayList<Range>();\r
+\r
+               for (Range underlyingRowPositionRange : underlyingRowPositionRanges) {\r
+                   int startRowPosition = getAdjustedUnderlyingToLocalStartPosition(\r
+                           sourceUnderlyingLayer,\r
+                           underlyingRowPositionRange.start,\r
+                           underlyingRowPositionRange.end);\r
+                   int endRowPosition = getAdjustedUnderlyingToLocalEndPosition(\r
+                           sourceUnderlyingLayer,\r
+                           underlyingRowPositionRange.end,\r
+                           underlyingRowPositionRange.start);\r
+\r
+                   // teichstaedt: fixes the problem that ranges where added even if\r
+                   // the corresponding startPosition weren't found in the underlying\r
+                   // layer. Without that fix a bunch of ranges of kind Range [-1, 180]\r
+                   // which causes strange behaviour in Freeze- and other Layers were\r
+                   // returned.\r
+                   if (startRowPosition > -1) {\r
+                       localRowPositionRanges.add(new Range(startRowPosition, endRowPosition));\r
+                   }\r
+               }\r
+\r
+               return localRowPositionRanges;\r
+           }\r
+\r
+           private int getAdjustedUnderlyingToLocalStartPosition(\r
+                   ILayer sourceUnderlyingLayer,\r
+                   int startUnderlyingPosition,\r
+                   int endUnderlyingPosition) {\r
+               int localStartRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition);\r
+               int offset = 0;\r
+               while (localStartRowPosition < 0\r
+                       && (startUnderlyingPosition + offset < endUnderlyingPosition)) {\r
+                   localStartRowPosition =\r
+                           underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition + offset++);\r
+               }\r
+               return localStartRowPosition;\r
+           }\r
+\r
+           private int getAdjustedUnderlyingToLocalEndPosition(\r
+                   ILayer sourceUnderlyingLayer,\r
+                   int endUnderlyingPosition,\r
+                   int startUnderlyingPosition) {\r
+               int localEndRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - 1);\r
+               int offset = 0;\r
+               while (localEndRowPosition < 0\r
+                       && (endUnderlyingPosition - offset > startUnderlyingPosition)) {\r
+                   localEndRowPosition =\r
+                           underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - offset++);\r
+               }\r
+               return localEndRowPosition + 1;\r
+           }\r
+\r
+           // Height\r
+\r
+           @Override\r
+           public int getHeight() {\r
+               int lastRowPosition = getRowCount() - 1;\r
+               return getStartYOfRowPosition(lastRowPosition) + getRowHeightByPosition(lastRowPosition);\r
+           }\r
+\r
+           // Y\r
+\r
+           @Override\r
+           public int getRowPositionByY(int y) {\r
+               return LayerUtil.getRowPositionByY(this, y);\r
+           }\r
+\r
+           @Override\r
+           public int getStartYOfRowPosition(int localRowPosition) {\r
+               int index = this.startYCache.get(localRowPosition);\r
+               if (index >= 0)\r
+                       return index;\r
+\r
+               IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer();\r
+               int underlyingPosition = localToUnderlyingRowPosition(localRowPosition);\r
+               if (underlyingPosition < 0) {\r
+                   return -1;\r
+               }\r
+               int underlyingStartY = underlyingLayer.getStartYOfRowPosition(underlyingPosition);\r
+               if (underlyingStartY < 0) {\r
+                   return -1;\r
+               }\r
+\r
+               for (Integer hiddenIndex : getHiddenRowIndexes()) {\r
+                   int hiddenPosition = underlyingLayer.getRowPositionByIndex(hiddenIndex);\r
+                   // if the hidden position is -1, it is hidden in the underlying\r
+                   // layertherefore the underlying layer should handle the positioning\r
+                   if (hiddenPosition >= 0 && hiddenPosition <= underlyingPosition) {\r
+                       underlyingStartY -= underlyingLayer.getRowHeightByPosition(hiddenPosition);\r
+                   }\r
+               }\r
+\r
+               this.startYCache.put(localRowPosition, underlyingStartY);\r
+               return underlyingStartY;\r
+           }\r
+\r
+           // Hide/show\r
+\r
+           /**\r
+            * Will check if the row at the specified index is hidden or not. Checks\r
+            * this layer and also the sublayers for the visibility.\r
+            *\r
+            * @param rowIndex\r
+            *            The row index of the row whose visibility state should be\r
+            *            checked.\r
+            * @return <code>true</code> if the row at the specified index is hidden,\r
+            *         <code>false</code> if it is visible.\r
+            */\r
+           public abstract boolean isRowIndexHidden(int rowIndex);\r
+\r
+           /**\r
+            * Will collect and return all indexes of the rows that are hidden in this\r
+            * layer. Note: It is not intended that it also collects the row indexes of\r
+            * underlying layers. This would cause issues on calculating positions as\r
+            * every layer is responsible for those calculations itself.\r
+            *\r
+            * @return Collection of all row indexes that are hidden in this layer.\r
+            */\r
+           public abstract Collection<Integer> getHiddenRowIndexes();\r
+\r
+           // Cache\r
+\r
+           /**\r
+            * Invalidate the cache to ensure that information is rebuild.\r
+            */\r
+           protected void invalidateCache() {\r
+               this.cachedVisibleRowIndexOrder = null;\r
+               this.cachedVisibleRowPositionOrder = null;\r
+               this.cachedHiddenRowIndexToPositionMap = null;\r
+               this.startYCache.clear();\r
+           }\r
+\r
+           private Int2IntOpenHashMap getCachedVisibleRowIndexes() {\r
+               if (this.cachedVisibleRowIndexOrder == null) {\r
+                   cacheVisibleRowIndexes();\r
+               }\r
+               return this.cachedVisibleRowIndexOrder;\r
+           }\r
+\r
+           private Int2IntOpenHashMap getCachedVisibleRowPositons() {\r
+               if (this.cachedVisibleRowPositionOrder == null) {\r
+                   cacheVisibleRowIndexes();\r
+               }\r
+               return this.cachedVisibleRowPositionOrder;\r
+           }\r
+\r
+           protected void cacheVisibleRowIndexes() {\r
+               this.cachedVisibleRowIndexOrder = new Int2IntOpenHashMap();\r
+               this.cachedVisibleRowPositionOrder = new Int2IntOpenHashMap();\r
+               this.cachedHiddenRowIndexToPositionMap = new Int2IntOpenHashMap();\r
+               this.startYCache.clear();\r
+               \r
+               cachedVisibleRowPositionOrder.defaultReturnValue(-1);\r
+               cachedVisibleRowIndexOrder.defaultReturnValue(-1);\r
+               cachedHiddenRowIndexToPositionMap.defaultReturnValue(-1);\r
+               startYCache.defaultReturnValue(-1);\r
+\r
+               ILayer underlyingLayer = getUnderlyingLayer();\r
+               int rowPosition = 0;\r
+               for (int parentRowPosition = 0; parentRowPosition < underlyingLayer.getRowCount(); parentRowPosition++) {\r
+                   int rowIndex = underlyingLayer.getRowIndexByPosition(parentRowPosition);\r
+\r
+                   if (!isRowIndexHidden(rowIndex)) {\r
+                       this.cachedVisibleRowIndexOrder.put(rowIndex, rowPosition);\r
+                       this.cachedVisibleRowPositionOrder.put(rowPosition, rowIndex);\r
+                       rowPosition++;\r
+                   } else {\r
+                       this.cachedHiddenRowIndexToPositionMap.put(rowIndex, rowPosition);\r
+                   }\r
+               }\r
+           }\r
+}\r