| /******************************************************************************* |
| * 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 |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.layer; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.Properties; |
| |
| import org.eclipse.nebula.widgets.nattable.command.ILayerCommand; |
| import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; |
| import org.eclipse.nebula.widgets.nattable.coordinate.Range; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.IConfigLabelAccumulator; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.TranslatedLayerCell; |
| import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent; |
| import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter; |
| import org.eclipse.nebula.widgets.nattable.painter.layer.ILayerPainter; |
| import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry; |
| import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider; |
| |
| /** |
| * Abstract base class for layers that expose transformed views of an underlying |
| * layer. By default the AbstractLayerTransform behaves as an identity transform |
| * of its underlying layer; that is, it exposes its underlying layer as is |
| * without any changes. Subclasses are expected to override methods in this |
| * class to implement specific kinds of layer transformations. |
| */ |
| public abstract class AbstractLayerTransform extends AbstractLayer { |
| |
| protected ILayer underlyingLayer; |
| |
| public AbstractLayerTransform() { |
| } |
| |
| public AbstractLayerTransform(ILayer underlyingLayer) { |
| setUnderlyingLayer(underlyingLayer); |
| } |
| |
| protected void setUnderlyingLayer(ILayer underlyingLayer) { |
| this.underlyingLayer = underlyingLayer; |
| this.underlyingLayer.setClientAreaProvider(getClientAreaProvider()); |
| this.underlyingLayer.addLayerListener(this); |
| } |
| |
| protected ILayer getUnderlyingLayer() { |
| return this.underlyingLayer; |
| } |
| |
| // Dispose |
| |
| @Override |
| public void dispose() { |
| this.underlyingLayer.dispose(); |
| } |
| |
| // Persistence |
| |
| @Override |
| public void saveState(String prefix, Properties properties) { |
| super.saveState(prefix, properties); |
| this.underlyingLayer.saveState(prefix, properties); |
| } |
| |
| /** |
| * Underlying layers <i>must</i> load state first. If this is not done, |
| * {@link IStructuralChangeEvent} from underlying layers will reset caches |
| * after state has been loaded |
| */ |
| @Override |
| public void loadState(String prefix, Properties properties) { |
| super.loadState(prefix, properties); |
| this.underlyingLayer.loadState(prefix, properties); |
| } |
| |
| // Configuration |
| |
| @Override |
| public void configure(IConfigRegistry configRegistry, UiBindingRegistry uiBindingRegistry) { |
| this.underlyingLayer.configure(configRegistry, uiBindingRegistry); |
| super.configure(configRegistry, uiBindingRegistry); |
| } |
| |
| @Override |
| public ILayerPainter getLayerPainter() { |
| return this.underlyingLayer.getLayerPainter(); |
| } |
| |
| // Command |
| |
| @Override |
| public boolean doCommand(ILayerCommand command) { |
| if (super.doCommand(command)) { |
| return true; |
| } |
| |
| if (this.underlyingLayer != null) { |
| return this.underlyingLayer.doCommand(command); |
| } |
| |
| return false; |
| } |
| |
| // Client area |
| |
| @Override |
| public void setClientAreaProvider(IClientAreaProvider clientAreaProvider) { |
| super.setClientAreaProvider(clientAreaProvider); |
| if (getUnderlyingLayer() != null) { |
| getUnderlyingLayer().setClientAreaProvider(clientAreaProvider); |
| } |
| } |
| |
| // Horizontal features |
| |
| // Columns |
| |
| @Override |
| public int getColumnCount() { |
| return this.underlyingLayer.getColumnCount(); |
| } |
| |
| @Override |
| public int getPreferredColumnCount() { |
| return this.underlyingLayer.getPreferredColumnCount(); |
| } |
| |
| @Override |
| public int getColumnIndexByPosition(int columnPosition) { |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| return this.underlyingLayer.getColumnIndexByPosition(underlyingColumnPosition); |
| } |
| |
| @Override |
| public int localToUnderlyingColumnPosition(int localColumnPosition) { |
| return localColumnPosition; |
| } |
| |
| @Override |
| public int underlyingToLocalColumnPosition(ILayer sourceUnderlyingLayer, int underlyingColumnPosition) { |
| return underlyingColumnPosition; |
| } |
| |
| @Override |
| public Collection<Range> underlyingToLocalColumnPositions( |
| ILayer sourceUnderlyingLayer, Collection<Range> underlyingColumnPositionRanges) { |
| Collection<Range> localColumnPositionRanges = new ArrayList<>(underlyingColumnPositionRanges.size()); |
| |
| for (Range underlyingColumnPositionRange : underlyingColumnPositionRanges) { |
| localColumnPositionRanges.add(new Range( |
| underlyingToLocalColumnPosition(sourceUnderlyingLayer, underlyingColumnPositionRange.start), |
| underlyingToLocalColumnPosition(sourceUnderlyingLayer, underlyingColumnPositionRange.end))); |
| } |
| |
| return localColumnPositionRanges; |
| } |
| |
| // Width |
| |
| @Override |
| public int getWidth() { |
| return this.underlyingLayer.getWidth(); |
| } |
| |
| @Override |
| public int getPreferredWidth() { |
| return this.underlyingLayer.getPreferredWidth(); |
| } |
| |
| @Override |
| public int getColumnWidthByPosition(int columnPosition) { |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| return this.underlyingLayer.getColumnWidthByPosition(underlyingColumnPosition); |
| } |
| |
| // Column resize |
| |
| @Override |
| public boolean isColumnPositionResizable(int columnPosition) { |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| return this.underlyingLayer.isColumnPositionResizable(underlyingColumnPosition); |
| } |
| |
| // X |
| |
| @Override |
| public int getColumnPositionByX(int x) { |
| return this.underlyingLayer.getColumnPositionByX(x); |
| } |
| |
| @Override |
| public int getStartXOfColumnPosition(int columnPosition) { |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| return this.underlyingLayer.getStartXOfColumnPosition(underlyingColumnPosition); |
| } |
| |
| // Underlying |
| |
| @Override |
| public Collection<ILayer> getUnderlyingLayersByColumnPosition(int columnPosition) { |
| Collection<ILayer> underlyingLayers = new HashSet<>(); |
| underlyingLayers.add(this.underlyingLayer); |
| return underlyingLayers; |
| } |
| |
| // Vertical features |
| |
| // Rows |
| |
| @Override |
| public int getRowCount() { |
| return this.underlyingLayer.getRowCount(); |
| } |
| |
| @Override |
| public int getPreferredRowCount() { |
| return this.underlyingLayer.getPreferredRowCount(); |
| } |
| |
| @Override |
| public int getRowIndexByPosition(int rowPosition) { |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| return this.underlyingLayer.getRowIndexByPosition(underlyingRowPosition); |
| } |
| |
| @Override |
| public int localToUnderlyingRowPosition(int localRowPosition) { |
| return localRowPosition; |
| } |
| |
| @Override |
| public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, int underlyingRowPosition) { |
| return underlyingRowPosition; |
| } |
| |
| @Override |
| public Collection<Range> underlyingToLocalRowPositions( |
| ILayer sourceUnderlyingLayer, |
| Collection<Range> underlyingRowPositionRanges) { |
| Collection<Range> localRowPositionRanges = new ArrayList<>(underlyingRowPositionRanges.size()); |
| |
| for (Range underlyingRowPositionRange : underlyingRowPositionRanges) { |
| localRowPositionRanges.add(new Range( |
| underlyingToLocalRowPosition(sourceUnderlyingLayer, underlyingRowPositionRange.start), |
| underlyingToLocalRowPosition(sourceUnderlyingLayer, underlyingRowPositionRange.end))); |
| } |
| |
| return localRowPositionRanges; |
| } |
| |
| // Height |
| |
| @Override |
| public int getHeight() { |
| return this.underlyingLayer.getHeight(); |
| } |
| |
| @Override |
| public int getPreferredHeight() { |
| return this.underlyingLayer.getPreferredHeight(); |
| } |
| |
| @Override |
| public int getRowHeightByPosition(int rowPosition) { |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| return this.underlyingLayer.getRowHeightByPosition(underlyingRowPosition); |
| } |
| |
| // Row resize |
| |
| @Override |
| public boolean isRowPositionResizable(int rowPosition) { |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| return this.underlyingLayer.isRowPositionResizable(underlyingRowPosition); |
| } |
| |
| // Y |
| |
| @Override |
| public int getRowPositionByY(int y) { |
| return this.underlyingLayer.getRowPositionByY(y); |
| } |
| |
| @Override |
| public int getStartYOfRowPosition(int rowPosition) { |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| return this.underlyingLayer.getStartYOfRowPosition(underlyingRowPosition); |
| } |
| |
| // Underlying |
| |
| @Override |
| public Collection<ILayer> getUnderlyingLayersByRowPosition(int rowPosition) { |
| Collection<ILayer> underlyingLayers = new HashSet<>(); |
| underlyingLayers.add(this.underlyingLayer); |
| return underlyingLayers; |
| } |
| |
| // Cell features |
| |
| @Override |
| public ILayerCell getCellByPosition(int columnPosition, int rowPosition) { |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| ILayerCell cell = this.underlyingLayer.getCellByPosition(underlyingColumnPosition, underlyingRowPosition); |
| if (cell != null) { |
| cell = new TranslatedLayerCell(cell, this, |
| underlyingToLocalColumnPosition(this.underlyingLayer, cell.getOriginColumnPosition()), |
| underlyingToLocalRowPosition(this.underlyingLayer, cell.getOriginRowPosition()), |
| underlyingToLocalColumnPosition(this.underlyingLayer, cell.getColumnPosition()), |
| underlyingToLocalRowPosition(this.underlyingLayer, cell.getRowPosition())); |
| } |
| return cell; |
| } |
| |
| @Override |
| public String getDisplayModeByPosition(int columnPosition, int rowPosition) { |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| return this.underlyingLayer.getDisplayModeByPosition(underlyingColumnPosition, underlyingRowPosition); |
| } |
| |
| @Override |
| public LabelStack getConfigLabelsByPosition(int columnPosition, int rowPosition) { |
| LabelStack configLabels = null; |
| |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| if (underlyingColumnPosition != -1 && underlyingRowPosition != -1) { |
| configLabels = this.underlyingLayer.getConfigLabelsByPosition(underlyingColumnPosition, underlyingRowPosition); |
| |
| IConfigLabelAccumulator configLabelAccumulator = getConfigLabelAccumulator(); |
| if (configLabelAccumulator != null) { |
| configLabelAccumulator.accumulateConfigLabels(configLabels, columnPosition, rowPosition); |
| } |
| } else { |
| // the the layer-position-transformation returned -1 for the |
| // underlying position, it is not possible the get the LabelStack |
| // from the underlying layer. In this case we simply create a new |
| // LabelStack. |
| configLabels = new LabelStack(); |
| } |
| |
| String regionName = getRegionName(); |
| if (regionName != null) { |
| configLabels.addLabel(regionName); |
| } |
| |
| return configLabels; |
| } |
| |
| @Override |
| public Object getDataValueByPosition(int columnPosition, int rowPosition) { |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| return this.underlyingLayer.getDataValueByPosition(underlyingColumnPosition, underlyingRowPosition); |
| } |
| |
| @Override |
| public ICellPainter getCellPainter( |
| int columnPosition, int rowPosition, |
| ILayerCell cell, IConfigRegistry configRegistry) { |
| return this.underlyingLayer.getCellPainter(columnPosition, rowPosition, cell, configRegistry); |
| } |
| |
| // IRegionResolver |
| |
| @Override |
| public LabelStack getRegionLabelsByXY(int x, int y) { |
| LabelStack regionLabels = this.underlyingLayer.getRegionLabelsByXY(x, y); |
| String regionName = getRegionName(); |
| if (regionName != null) { |
| regionLabels.addLabel(regionName); |
| } |
| return regionLabels; |
| } |
| |
| @Override |
| public ILayer getUnderlyingLayerByPosition(int columnPosition, int rowPosition) { |
| return this.underlyingLayer; |
| } |
| |
| @Override |
| public boolean isDynamicSizeLayer() { |
| return this.underlyingLayer.isDynamicSizeLayer(); |
| } |
| |
| } |