| /*=============================================================================# |
| # Copyright (c) 2012, 2021 Original NatTable 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 NatTable authors and others - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ecommons.waltable.freeze; |
| |
| import static org.eclipse.statet.ecommons.waltable.coordinate.Orientation.HORIZONTAL; |
| import static org.eclipse.statet.ecommons.waltable.coordinate.Orientation.VERTICAL; |
| import static org.eclipse.statet.ecommons.waltable.painter.cell.GraphicsUtils.safe; |
| |
| import java.util.Properties; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.GC; |
| |
| import org.eclipse.statet.ecommons.waltable.command.ILayerCommand; |
| import org.eclipse.statet.ecommons.waltable.config.IConfigRegistry; |
| import org.eclipse.statet.ecommons.waltable.coordinate.PositionCoordinate; |
| import org.eclipse.statet.ecommons.waltable.freeze.config.DefaultFreezeGridBindings; |
| import org.eclipse.statet.ecommons.waltable.grid.ClientAreaResizeCommand; |
| import org.eclipse.statet.ecommons.waltable.grid.layer.DimensionallyDependentLayer; |
| import org.eclipse.statet.ecommons.waltable.layer.AbstractLayer; |
| import org.eclipse.statet.ecommons.waltable.layer.CompositeLayer; |
| import org.eclipse.statet.ecommons.waltable.layer.ILayer; |
| import org.eclipse.statet.ecommons.waltable.painter.layer.ILayerPainter; |
| import org.eclipse.statet.ecommons.waltable.persistence.IPersistable; |
| import org.eclipse.statet.ecommons.waltable.selection.SelectionLayer; |
| import org.eclipse.statet.ecommons.waltable.style.DisplayMode; |
| import org.eclipse.statet.ecommons.waltable.util.GUIHelper; |
| import org.eclipse.statet.ecommons.waltable.viewport.ViewportLayer; |
| import org.eclipse.statet.ecommons.waltable.viewport.ViewportSelectDimPositionsCommandHandler; |
| |
| |
| public class CompositeFreezeLayer extends CompositeLayer { |
| |
| |
| private final FreezeLayer freezeLayer; |
| private final ViewportLayer viewportLayer; |
| private final SelectionLayer selectionLayer; |
| |
| |
| public CompositeFreezeLayer(final FreezeLayer freezeLayer, final ViewportLayer viewportLayer, final SelectionLayer selectionLayer) { |
| this(freezeLayer, viewportLayer, selectionLayer, true); |
| } |
| |
| public CompositeFreezeLayer(final FreezeLayer freezeLayer, final ViewportLayer viewportLayer, final SelectionLayer selectionLayer, |
| final boolean useDefaultConfiguration) { |
| super(2, 2); |
| this.freezeLayer= freezeLayer; |
| this.viewportLayer= viewportLayer; |
| this.selectionLayer= selectionLayer; |
| |
| setChildLayer("FROZEN_REGION", freezeLayer, 0, 0); //$NON-NLS-1$ |
| setChildLayer("FROZEN_ROW_REGION", new DimensionallyDependentLayer(viewportLayer.getScrollableLayer(), viewportLayer, freezeLayer), 1, 0); //$NON-NLS-1$ |
| setChildLayer("FROZEN_COLUMN_REGION", new DimensionallyDependentLayer(viewportLayer.getScrollableLayer(), freezeLayer, viewportLayer), 0, 1); //$NON-NLS-1$ |
| setChildLayer("NONFROZEN_REGION", viewportLayer, 1, 1); //$NON-NLS-1$ |
| |
| registerCommandHandlers(); |
| |
| if (useDefaultConfiguration) { |
| addConfiguration(new DefaultFreezeGridBindings()); |
| } |
| } |
| |
| |
| @Override |
| protected ILayerPainter createPainter() { |
| return new FreezableLayerPainter(); |
| } |
| |
| |
| public boolean isFrozen() { |
| return this.freezeLayer.isFrozen(); |
| } |
| |
| @Override |
| public ILayerPainter getLayerPainter() { |
| return this.layerPainter; |
| } |
| |
| @Override |
| protected void registerCommandHandlers() { |
| registerCommandHandler(new FreezeCommandHandler(this.freezeLayer, this.viewportLayer, this.selectionLayer)); |
| |
| final AbstractLayer frozenRowLayer= (AbstractLayer) getChildLayerByLayoutCoordinate(1, 0); |
| frozenRowLayer.registerCommandHandler(new ViewportSelectDimPositionsCommandHandler( |
| frozenRowLayer, VERTICAL )); |
| |
| final AbstractLayer frozenColumnLayer= (AbstractLayer) getChildLayerByLayoutCoordinate(0, 1); |
| frozenColumnLayer.registerCommandHandler(new ViewportSelectDimPositionsCommandHandler( |
| frozenRowLayer, HORIZONTAL )); |
| } |
| |
| |
| @Override |
| public boolean doCommand(final ILayerCommand command) { |
| //if this layer should handle a ClientAreaResizeCommand we have to ensure that |
| //it is only called on the ViewportLayer, as otherwise an undefined behaviour |
| //could occur because the ViewportLayer isn't informed about potential refreshes |
| if (command instanceof ClientAreaResizeCommand) { |
| this.viewportLayer.doCommand(command); |
| } |
| return super.doCommand(command); |
| } |
| |
| |
| // Persistence |
| |
| @Override |
| public void saveState(final String prefix, final Properties properties) { |
| PositionCoordinate coord= this.freezeLayer.getTopLeftPosition(); |
| properties.setProperty(prefix + FreezeLayer.PERSISTENCE_TOP_LEFT_POSITION, |
| coord.columnPosition + IPersistable.VALUE_SEPARATOR + coord.rowPosition); |
| |
| coord= this.freezeLayer.getBottomRightPosition(); |
| properties.setProperty(prefix + FreezeLayer.PERSISTENCE_BOTTOM_RIGHT_POSITION, |
| coord.columnPosition + IPersistable.VALUE_SEPARATOR + coord.rowPosition); |
| |
| super.saveState(prefix, properties); |
| } |
| |
| @Override |
| public void loadState(final String prefix, final Properties properties) { |
| String property= properties.getProperty(prefix + FreezeLayer.PERSISTENCE_TOP_LEFT_POSITION); |
| PositionCoordinate topLeftPosition= null; |
| if (property != null) { |
| final StringTokenizer tok= new StringTokenizer(property, IPersistable.VALUE_SEPARATOR); |
| final String columnPosition= tok.nextToken(); |
| final String rowPosition= tok.nextToken(); |
| topLeftPosition= new PositionCoordinate(this.freezeLayer, |
| Long.valueOf(columnPosition), Long.valueOf(rowPosition)); |
| } |
| |
| property= properties.getProperty(prefix + FreezeLayer.PERSISTENCE_BOTTOM_RIGHT_POSITION); |
| PositionCoordinate bottomRightPosition= null; |
| if (property != null) { |
| final StringTokenizer tok= new StringTokenizer(property, IPersistable.VALUE_SEPARATOR); |
| final String columnPosition= tok.nextToken(); |
| final String rowPosition= tok.nextToken(); |
| bottomRightPosition= new PositionCoordinate(this.freezeLayer, |
| Long.valueOf(columnPosition), Long.valueOf(rowPosition)); |
| } |
| |
| //only restore a freeze state if there is one persisted |
| if (topLeftPosition != null && bottomRightPosition != null) { |
| if (topLeftPosition.columnPosition == -1 && topLeftPosition.rowPosition == -1 |
| && bottomRightPosition.columnPosition == -1 && bottomRightPosition.rowPosition == -1) { |
| FreezeHelper.unfreeze(this.freezeLayer, this.viewportLayer); |
| } else { |
| FreezeHelper.freeze(this.freezeLayer, this.viewportLayer, topLeftPosition, bottomRightPosition); |
| } |
| } |
| |
| super.loadState(prefix, properties); |
| } |
| |
| |
| class FreezableLayerPainter extends CompositeLayerPainter { |
| |
| public FreezableLayerPainter() { |
| } |
| |
| @Override |
| public void paintLayer(final ILayer natLayer, final GC gc, final int xOffset, final int yOffset, final org.eclipse.swt.graphics.Rectangle rectangle, final IConfigRegistry configRegistry) { |
| super.paintLayer(natLayer, gc, xOffset, yOffset, rectangle, configRegistry); |
| |
| Color separatorColor= configRegistry.getConfigAttribute(IFreezeConfigAttributes.SEPARATOR_COLOR, DisplayMode.NORMAL); |
| if (separatorColor == null) { |
| separatorColor= GUIHelper.COLOR_BLUE; |
| } |
| |
| gc.setClipping(rectangle); |
| final Color oldFg= gc.getForeground(); |
| gc.setForeground(separatorColor); |
| final long freezeWidth= CompositeFreezeLayer.this.freezeLayer.getWidth() - 1; |
| if (freezeWidth > 0) { |
| gc.drawLine(safe(xOffset + freezeWidth), yOffset, safe(xOffset + freezeWidth), safe(yOffset + getHeight() - 1)); |
| } |
| final long freezeHeight= CompositeFreezeLayer.this.freezeLayer.getHeight() - 1; |
| if (freezeHeight > 0) { |
| gc.drawLine(xOffset, safe(yOffset + freezeHeight), safe(xOffset + getWidth() - 1), safe(yOffset + freezeHeight)); |
| } |
| gc.setForeground(oldFg); |
| } |
| |
| } |
| |
| } |