| /******************************************************************************* |
| * Copyright (c) 2012, 2020 Original authors and others. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Original authors and others - initial API and implementation (DimensionallyDependentLayer) |
| * Stephan Wahlbrink - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.grid.layer; |
| |
| import org.eclipse.nebula.widgets.nattable.command.ILayerCommand; |
| import org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform; |
| import org.eclipse.nebula.widgets.nattable.layer.ILayer; |
| import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer; |
| import org.eclipse.nebula.widgets.nattable.layer.LayerUtil; |
| |
| /** |
| * <p> |
| * A DimensionallyDependentIndexLayer is a layer whose horizontal and vertical |
| * dimensions are dependent on the horizontal and vertical dimensions of other |
| * layers. A DimensionallyDependentIndexLayer takes three constructor |
| * parameters: the horizontal layer that the DimensionallyDependentIndexLayer's |
| * horizontal dimension is linked to, the vertical layer that the |
| * DimensionallyDependentIndexLayer is linked to, and a base layer to which all |
| * non-dimensionally related ILayer method calls will be delegated to (e.g. |
| * command, event methods) |
| * </p> |
| * <p> |
| * Prime examples of dimensionally dependent layers are the column header and |
| * row header layers. For example, the column header layer's horizontal |
| * dimension is linked to the body layer's horizontal dimension. This means that |
| * whatever columns are shown in the body area will also be shown in the column |
| * header area, and vice versa. Note that the column header layer maintains its |
| * own vertical dimension, however, so it's vertical layer dependency would be a |
| * separate data layer. The same is true for the row header layer, only with the |
| * vertical instead of the horizontal dimension. The constructors for the column |
| * header and row header layers would therefore look something like this: |
| * </p> |
| * |
| * <pre> |
| * ILayer columnHeaderLayer = new DimensionallyDependentIndexLayer( |
| * columnHeaderRowDataLayer, bodyLayer, columnHeaderRowDataLayer); |
| * ILayer rowHeaderLayer = new DimensionallyDependentIndexLayer( |
| * rowHeaderColumnDataLayer, bodyLayer, rowHeaderColumnDataLayer); |
| * </pre> |
| * <p> |
| * In contrast to {@link DimensionallyDependentLayer}, this class: |
| * </p> |
| * <ul> |
| * <li>implements {@link IUniqueIndexLayer};</li> |
| * <li>provides conversion of local and underlying positions based on the unique |
| * index (reliable);</li> |
| * <li>provides an implementation of {@link #getCellByPosition(int, int)} which |
| * e.g. fully supports spanned cells;</li> |
| * <li>requires that the layers, the horizontal and vertical dimension are |
| * linked to, implements {@link IUniqueIndexLayer} too.</li> |
| * </ul> |
| */ |
| public class DimensionallyDependentIndexLayer extends |
| AbstractIndexLayerTransform { |
| |
| private IUniqueIndexLayer horizontalLayerDependency; |
| private IUniqueIndexLayer verticalLayerDependency; |
| |
| /** |
| * Creates a new DimensionallyDependentIndexLayer. |
| * |
| * @param baseLayer |
| * the underlying base layer |
| * @param horizontalLayerDependency |
| * the layer, the horizontal dimension is linked to |
| * @param verticalLayerDependency |
| * the layer, the vertical dimension is linked to |
| */ |
| public DimensionallyDependentIndexLayer(IUniqueIndexLayer baseLayer, |
| IUniqueIndexLayer horizontalLayerDependency, |
| IUniqueIndexLayer verticalLayerDependency) { |
| super(baseLayer); |
| |
| setHorizontalLayerDependency(horizontalLayerDependency); |
| setVerticalLayerDependency(verticalLayerDependency); |
| } |
| |
| /** |
| * Creates a new DimensionallyDependentIndexLayer. |
| * |
| * @param baseLayer |
| * the underlying base layer |
| */ |
| protected DimensionallyDependentIndexLayer(IUniqueIndexLayer baseLayer) { |
| super(baseLayer); |
| } |
| |
| // Dependent layer accessors |
| |
| protected void setHorizontalLayerDependency( |
| IUniqueIndexLayer horizontalLayerDependency) { |
| this.horizontalLayerDependency = horizontalLayerDependency; |
| |
| // horizontalLayerDependency.addLayerListener(new ILayerListener() { |
| // |
| // public void handleLayerEvent(ILayerEvent event) { |
| // if (event instanceof IStructuralChangeEvent) { |
| // // TODO refresh horizontal structure |
| // } |
| // } |
| // |
| // }); |
| } |
| |
| protected void setVerticalLayerDependency( |
| IUniqueIndexLayer verticalLayerDependency) { |
| this.verticalLayerDependency = verticalLayerDependency; |
| |
| // verticalLayerDependency.addLayerListener(new ILayerListener() { |
| // |
| // public void handleLayerEvent(ILayerEvent event) { |
| // if (event instanceof IStructuralChangeEvent) { |
| // // TODO refresh vertical structure |
| // } |
| // } |
| // |
| // }); |
| } |
| |
| public ILayer getHorizontalLayerDependency() { |
| return this.horizontalLayerDependency; |
| } |
| |
| public ILayer getVerticalLayerDependency() { |
| return this.verticalLayerDependency; |
| } |
| |
| public IUniqueIndexLayer getBaseLayer() { |
| return getUnderlyingLayer(); |
| } |
| |
| // Commands |
| |
| @Override |
| public boolean doCommand(ILayerCommand command) { |
| // Invoke command handler(s) on the Dimensionally dependent layer |
| ILayerCommand clonedCommand = command.cloneCommand(); |
| if (super.doCommand(command)) { |
| return true; |
| } |
| |
| clonedCommand = command.cloneCommand(); |
| if (this.horizontalLayerDependency.doCommand(clonedCommand)) { |
| return true; |
| } |
| |
| clonedCommand = command.cloneCommand(); |
| if (this.verticalLayerDependency.doCommand(clonedCommand)) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // Horizontal features |
| |
| // Columns |
| |
| @Override |
| public int getColumnCount() { |
| return this.horizontalLayerDependency.getColumnCount(); |
| } |
| |
| @Override |
| public int getPreferredColumnCount() { |
| return this.horizontalLayerDependency.getPreferredColumnCount(); |
| } |
| |
| @Override |
| public int getColumnIndexByPosition(int columnPosition) { |
| return this.horizontalLayerDependency |
| .getColumnIndexByPosition(columnPosition); |
| } |
| |
| @Override |
| public int getColumnPositionByIndex(int columnIndex) { |
| return this.horizontalLayerDependency.getColumnPositionByIndex(columnIndex); |
| } |
| |
| @Override |
| public int localToUnderlyingColumnPosition(int localColumnPosition) { |
| return LayerUtil.convertColumnPosition(this, localColumnPosition, |
| getUnderlyingLayer()); |
| } |
| |
| @Override |
| public int underlyingToLocalColumnPosition(ILayer sourceUnderlyingLayer, |
| int underlyingColumnPosition) { |
| return LayerUtil.convertColumnPosition(sourceUnderlyingLayer, |
| underlyingColumnPosition, this); |
| } |
| |
| // Width |
| |
| @Override |
| public int getWidth() { |
| return this.horizontalLayerDependency.getWidth(); |
| } |
| |
| @Override |
| public int getPreferredWidth() { |
| return this.horizontalLayerDependency.getPreferredWidth(); |
| } |
| |
| @Override |
| public int getColumnWidthByPosition(int columnPosition) { |
| return this.horizontalLayerDependency |
| .getColumnWidthByPosition(columnPosition); |
| } |
| |
| // Column resize |
| |
| @Override |
| public boolean isColumnPositionResizable(int columnPosition) { |
| return this.horizontalLayerDependency |
| .isColumnPositionResizable(columnPosition); |
| } |
| |
| // X |
| |
| @Override |
| public int getColumnPositionByX(int x) { |
| return this.horizontalLayerDependency.getColumnPositionByX(x); |
| } |
| |
| @Override |
| public int getStartXOfColumnPosition(int columnPosition) { |
| return this.horizontalLayerDependency |
| .getStartXOfColumnPosition(columnPosition); |
| } |
| |
| // Vertical features |
| |
| // Rows |
| |
| @Override |
| public int getRowCount() { |
| return this.verticalLayerDependency.getRowCount(); |
| } |
| |
| @Override |
| public int getPreferredRowCount() { |
| return this.verticalLayerDependency.getPreferredRowCount(); |
| } |
| |
| @Override |
| public int getRowIndexByPosition(int rowPosition) { |
| return this.verticalLayerDependency.getRowIndexByPosition(rowPosition); |
| } |
| |
| @Override |
| public int getRowPositionByIndex(int rowIndex) { |
| return this.verticalLayerDependency.getRowPositionByIndex(rowIndex); |
| } |
| |
| @Override |
| public int localToUnderlyingRowPosition(int localRowPosition) { |
| return LayerUtil.convertRowPosition(this, localRowPosition, |
| getUnderlyingLayer()); |
| } |
| |
| @Override |
| public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, |
| int underlyingRowPosition) { |
| return LayerUtil.convertRowPosition(sourceUnderlyingLayer, |
| underlyingRowPosition, this); |
| } |
| |
| // Height |
| |
| @Override |
| public int getHeight() { |
| return this.verticalLayerDependency.getHeight(); |
| } |
| |
| @Override |
| public int getPreferredHeight() { |
| return this.verticalLayerDependency.getPreferredHeight(); |
| } |
| |
| @Override |
| public int getRowHeightByPosition(int rowPosition) { |
| return this.verticalLayerDependency.getRowHeightByPosition(rowPosition); |
| } |
| |
| // Row resize |
| |
| @Override |
| public boolean isRowPositionResizable(int rowPosition) { |
| return this.verticalLayerDependency.isRowPositionResizable(rowPosition); |
| } |
| |
| // Y |
| |
| @Override |
| public int getRowPositionByY(int y) { |
| return this.verticalLayerDependency.getRowPositionByY(y); |
| } |
| |
| @Override |
| public int getStartYOfRowPosition(int rowPosition) { |
| return this.verticalLayerDependency.getStartYOfRowPosition(rowPosition); |
| } |
| |
| } |