1 /*******************************************************************************
\r
2 * Copyright (c) 2012 Original authors and others.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * Original authors and others - initial API and implementation
\r
10 ******************************************************************************/
\r
11 package org.simantics.browsing.ui.nattable.override;
\r
13 import java.util.ArrayList;
\r
14 import java.util.Collection;
\r
16 import org.eclipse.nebula.widgets.nattable.coordinate.Range;
\r
17 import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
\r
18 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
\r
19 import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
\r
20 import org.eclipse.nebula.widgets.nattable.layer.LayerUtil;
\r
21 import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;
\r
22 import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent;
\r
23 import org.eclipse.nebula.widgets.nattable.layer.event.VisualRefreshEvent;
\r
25 import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
\r
26 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
\r
29 * AbstractRowHideShowLayer implementation with FastUtils hashmaps.
\r
31 * @see org.eclipse.nebula.widgets.nattable.hideshow.AbstractRowHideShowLayer
\r
36 public abstract class AbstractRowHideShowLayer2 extends AbstractLayerTransform implements IUniqueIndexLayer {
\r
38 private Int2IntOpenHashMap cachedVisibleRowIndexOrder;
\r
39 private Int2IntOpenHashMap cachedVisibleRowPositionOrder;
\r
41 private Int2IntOpenHashMap cachedHiddenRowIndexToPositionMap;
\r
43 protected final Int2IntOpenHashMap startYCache = new Int2IntOpenHashMap();
\r
46 public AbstractRowHideShowLayer2(IUniqueIndexLayer underlyingLayer) {
\r
47 super(underlyingLayer);
\r
51 public void handleLayerEvent(ILayerEvent event) {
\r
52 if (event instanceof IStructuralChangeEvent) {
\r
53 IStructuralChangeEvent structuralChangeEvent = (IStructuralChangeEvent) event;
\r
54 if (structuralChangeEvent.isVerticalStructureChanged()) {
\r
55 // vertical structure has changed, update cached row information
\r
58 } else if (event instanceof VisualRefreshEvent) {
\r
59 // visual change, e.g. font change, the startYCache needs to be
\r
60 // cleared in order to re-render correctly
\r
61 this.startYCache.clear();
\r
63 super.handleLayerEvent(event);
\r
66 // Horizontal features
\r
71 public int getColumnPositionByIndex(int columnIndex) {
\r
72 return ((IUniqueIndexLayer) getUnderlyingLayer()).getColumnPositionByIndex(columnIndex);
\r
75 // Vertical features
\r
80 public int getRowCount() {
\r
81 return getCachedVisibleRowIndexes().size();
\r
85 public int getRowIndexByPosition(int rowPosition) {
\r
86 if (rowPosition < 0 || rowPosition >= getRowCount()) {
\r
89 return getCachedVisibleRowPositons().get(rowPosition);
\r
93 public int getRowPositionByIndex(int rowIndex) {
\r
94 return getCachedVisibleRowIndexes().get(rowIndex);
\r
97 public Collection<Integer> getRowPositionsByIndexes(Collection<Integer> rowIndexes) {
\r
98 IntOpenHashSet rowPositions = new IntOpenHashSet();
\r
99 for (int rowIndex : rowIndexes) {
\r
100 rowPositions.add(getRowPositionByIndex(rowIndex));
\r
102 return rowPositions;
\r
106 public int localToUnderlyingRowPosition(int localRowPosition) {
\r
107 int rowIndex = getRowIndexByPosition(localRowPosition);
\r
108 return ((IUniqueIndexLayer) getUnderlyingLayer()).getRowPositionByIndex(rowIndex);
\r
112 public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, int underlyingRowPosition) {
\r
113 int rowIndex = getUnderlyingLayer().getRowIndexByPosition(underlyingRowPosition);
\r
114 int rowPosition = getRowPositionByIndex(rowIndex);
\r
115 if (rowPosition >= 0) {
\r
116 return rowPosition;
\r
118 if (this.cachedHiddenRowIndexToPositionMap.containsKey(rowIndex)) {
\r
119 return this.cachedHiddenRowIndexToPositionMap.get(rowIndex);
\r
127 public Collection<Range> underlyingToLocalRowPositions(
\r
128 ILayer sourceUnderlyingLayer, Collection<Range> underlyingRowPositionRanges) {
\r
129 Collection<Range> localRowPositionRanges = new ArrayList<Range>();
\r
131 for (Range underlyingRowPositionRange : underlyingRowPositionRanges) {
\r
132 int startRowPosition = getAdjustedUnderlyingToLocalStartPosition(
\r
133 sourceUnderlyingLayer,
\r
134 underlyingRowPositionRange.start,
\r
135 underlyingRowPositionRange.end);
\r
136 int endRowPosition = getAdjustedUnderlyingToLocalEndPosition(
\r
137 sourceUnderlyingLayer,
\r
138 underlyingRowPositionRange.end,
\r
139 underlyingRowPositionRange.start);
\r
141 // teichstaedt: fixes the problem that ranges where added even if
\r
142 // the corresponding startPosition weren't found in the underlying
\r
143 // layer. Without that fix a bunch of ranges of kind Range [-1, 180]
\r
144 // which causes strange behaviour in Freeze- and other Layers were
\r
146 if (startRowPosition > -1) {
\r
147 localRowPositionRanges.add(new Range(startRowPosition, endRowPosition));
\r
151 return localRowPositionRanges;
\r
154 private int getAdjustedUnderlyingToLocalStartPosition(
\r
155 ILayer sourceUnderlyingLayer,
\r
156 int startUnderlyingPosition,
\r
157 int endUnderlyingPosition) {
\r
158 int localStartRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition);
\r
160 while (localStartRowPosition < 0
\r
161 && (startUnderlyingPosition + offset < endUnderlyingPosition)) {
\r
162 localStartRowPosition =
\r
163 underlyingToLocalRowPosition(sourceUnderlyingLayer, startUnderlyingPosition + offset++);
\r
165 return localStartRowPosition;
\r
168 private int getAdjustedUnderlyingToLocalEndPosition(
\r
169 ILayer sourceUnderlyingLayer,
\r
170 int endUnderlyingPosition,
\r
171 int startUnderlyingPosition) {
\r
172 int localEndRowPosition = underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - 1);
\r
174 while (localEndRowPosition < 0
\r
175 && (endUnderlyingPosition - offset > startUnderlyingPosition)) {
\r
176 localEndRowPosition =
\r
177 underlyingToLocalRowPosition(sourceUnderlyingLayer, endUnderlyingPosition - offset++);
\r
179 return localEndRowPosition + 1;
\r
185 public int getHeight() {
\r
186 int lastRowPosition = getRowCount() - 1;
\r
187 return getStartYOfRowPosition(lastRowPosition) + getRowHeightByPosition(lastRowPosition);
\r
193 public int getRowPositionByY(int y) {
\r
194 return LayerUtil.getRowPositionByY(this, y);
\r
198 public int getStartYOfRowPosition(int localRowPosition) {
\r
199 int index = this.startYCache.get(localRowPosition);
\r
203 IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer();
\r
204 int underlyingPosition = localToUnderlyingRowPosition(localRowPosition);
\r
205 if (underlyingPosition < 0) {
\r
208 int underlyingStartY = underlyingLayer.getStartYOfRowPosition(underlyingPosition);
\r
209 if (underlyingStartY < 0) {
\r
213 for (Integer hiddenIndex : getHiddenRowIndexes()) {
\r
214 int hiddenPosition = underlyingLayer.getRowPositionByIndex(hiddenIndex);
\r
215 // if the hidden position is -1, it is hidden in the underlying
\r
216 // layertherefore the underlying layer should handle the positioning
\r
217 if (hiddenPosition >= 0 && hiddenPosition <= underlyingPosition) {
\r
218 underlyingStartY -= underlyingLayer.getRowHeightByPosition(hiddenPosition);
\r
222 this.startYCache.put(localRowPosition, underlyingStartY);
\r
223 return underlyingStartY;
\r
229 * Will check if the row at the specified index is hidden or not. Checks
\r
230 * this layer and also the sublayers for the visibility.
\r
233 * The row index of the row whose visibility state should be
\r
235 * @return <code>true</code> if the row at the specified index is hidden,
\r
236 * <code>false</code> if it is visible.
\r
238 public abstract boolean isRowIndexHidden(int rowIndex);
\r
241 * Will collect and return all indexes of the rows that are hidden in this
\r
242 * layer. Note: It is not intended that it also collects the row indexes of
\r
243 * underlying layers. This would cause issues on calculating positions as
\r
244 * every layer is responsible for those calculations itself.
\r
246 * @return Collection of all row indexes that are hidden in this layer.
\r
248 public abstract Collection<Integer> getHiddenRowIndexes();
\r
253 * Invalidate the cache to ensure that information is rebuild.
\r
255 protected void invalidateCache() {
\r
256 this.cachedVisibleRowIndexOrder = null;
\r
257 this.cachedVisibleRowPositionOrder = null;
\r
258 this.cachedHiddenRowIndexToPositionMap = null;
\r
259 this.startYCache.clear();
\r
262 private Int2IntOpenHashMap getCachedVisibleRowIndexes() {
\r
263 if (this.cachedVisibleRowIndexOrder == null) {
\r
264 cacheVisibleRowIndexes();
\r
266 return this.cachedVisibleRowIndexOrder;
\r
269 private Int2IntOpenHashMap getCachedVisibleRowPositons() {
\r
270 if (this.cachedVisibleRowPositionOrder == null) {
\r
271 cacheVisibleRowIndexes();
\r
273 return this.cachedVisibleRowPositionOrder;
\r
276 protected void cacheVisibleRowIndexes() {
\r
277 this.cachedVisibleRowIndexOrder = new Int2IntOpenHashMap();
\r
278 this.cachedVisibleRowPositionOrder = new Int2IntOpenHashMap();
\r
279 this.cachedHiddenRowIndexToPositionMap = new Int2IntOpenHashMap();
\r
280 this.startYCache.clear();
\r
282 cachedVisibleRowPositionOrder.defaultReturnValue(-1);
\r
283 cachedVisibleRowIndexOrder.defaultReturnValue(-1);
\r
284 cachedHiddenRowIndexToPositionMap.defaultReturnValue(-1);
\r
285 startYCache.defaultReturnValue(-1);
\r
287 ILayer underlyingLayer = getUnderlyingLayer();
\r
288 int rowPosition = 0;
\r
289 for (int parentRowPosition = 0; parentRowPosition < underlyingLayer.getRowCount(); parentRowPosition++) {
\r
290 int rowIndex = underlyingLayer.getRowIndexByPosition(parentRowPosition);
\r
292 if (!isRowIndexHidden(rowIndex)) {
\r
293 this.cachedVisibleRowIndexOrder.put(rowIndex, rowPosition);
\r
294 this.cachedVisibleRowPositionOrder.put(rowPosition, rowIndex);
\r
297 this.cachedHiddenRowIndexToPositionMap.put(rowIndex, rowPosition);
\r