| /*=============================================================================# |
| # 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.painter.layer; |
| |
| 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.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Rectangle; |
| |
| import org.eclipse.statet.ecommons.waltable.config.CellConfigAttributes; |
| import org.eclipse.statet.ecommons.waltable.config.IConfigRegistry; |
| import org.eclipse.statet.ecommons.waltable.coordinate.LRectangle; |
| import org.eclipse.statet.ecommons.waltable.layer.ILayer; |
| import org.eclipse.statet.ecommons.waltable.layer.ILayerDim; |
| import org.eclipse.statet.ecommons.waltable.layer.cell.ILayerCell; |
| import org.eclipse.statet.ecommons.waltable.painter.cell.ICellPainter; |
| |
| |
| public class CellLayerPainter implements ILayerPainter { |
| |
| |
| protected static final long getEndPosition(final ILayerDim dim, final int pixel) { |
| final long positionByPixel= dim.getPositionByPixel(pixel); |
| return ((positionByPixel > 0) ? |
| Math.min(dim.getPositionCount(), positionByPixel) : |
| dim.getPositionCount() ); |
| } |
| |
| private static Map<Long, Long> calculateDimensionInfo(final ILayerDim dim, |
| final long startPosition, final long endPosition) { |
| final Map<Long, Long> positionToPixelMap= new HashMap<>(); |
| long start2= (startPosition > 0) ? |
| dim.getPositionStart(startPosition - 1) |
| + dim.getPositionSize(startPosition - 1) : |
| Long.MIN_VALUE; |
| for (long position= startPosition; position < endPosition; position++) { |
| final long start1= dim.getPositionStart(position); |
| positionToPixelMap.put(position, Math.max(start1, start2)); |
| start2= start1 + dim.getPositionSize(position); |
| } |
| if (endPosition < dim.getPositionCount()) { |
| final long start1= dim.getPositionStart(endPosition); |
| positionToPixelMap.put(endPosition, Math.max(start1, start2)); |
| } |
| return positionToPixelMap; |
| } |
| |
| private static long getPositionStart(final ILayerDim dim, final long position, |
| final Map<Long, Long> positionToPixelMap) { |
| if (position < dim.getPositionCount()) { |
| Long start= positionToPixelMap.get(position); |
| if (start == null) { |
| start= Long.valueOf(dim.getPositionStart(position)); |
| if (position > 0) { |
| final long start2= dim.getPositionStart(position - 1) |
| + dim.getPositionStart(position - 1); |
| if (start2 > start.longValue()) { |
| start= Long.valueOf(start2); |
| } |
| } |
| positionToPixelMap.put(position, start); |
| } |
| return start.longValue(); |
| } |
| else { |
| return dim.getSize(); |
| } |
| } |
| |
| |
| private ILayer natLayer; |
| |
| private Map<Long, Long> horizontalPositionToPixelMap; |
| private Map<Long, Long> verticalPositionToPixelMap; |
| |
| |
| @Override |
| public void paintLayer(final ILayer natLayer, final GC gc, final int xOffset, final int yOffset, |
| final Rectangle pixelRectangle, final IConfigRegistry configRegistry) { |
| if (pixelRectangle.isEmpty()) { |
| return; |
| } |
| |
| this.natLayer= natLayer; |
| final LRectangle positionRectangle= getPositionRectangleFromPixelRectangle(natLayer, pixelRectangle); |
| |
| calculateDimensionInfo(positionRectangle); |
| |
| final Collection<ILayerCell> spannedCells= new HashSet<>(); |
| |
| for (long columnPosition= positionRectangle.x; columnPosition < positionRectangle.x + positionRectangle.width; columnPosition++) { |
| for (long rowPosition= positionRectangle.y; rowPosition < positionRectangle.y + positionRectangle.height; rowPosition++) { |
| final ILayerCell cell= natLayer.getCellByPosition(columnPosition, rowPosition); |
| if (cell != null) { |
| if (cell.isSpannedCell()) { |
| spannedCells.add(cell); |
| } |
| else { |
| paintCell(cell, gc, configRegistry); |
| } |
| } |
| } |
| } |
| |
| for (final ILayerCell cell : spannedCells) { |
| paintCell(cell, gc, configRegistry); |
| } |
| } |
| |
| private void calculateDimensionInfo(final LRectangle positionRectangle) { |
| this.horizontalPositionToPixelMap= calculateDimensionInfo( |
| this.natLayer.getDim(HORIZONTAL), |
| positionRectangle.x, positionRectangle.x + positionRectangle.width); |
| this.verticalPositionToPixelMap= calculateDimensionInfo( |
| this.natLayer.getDim(VERTICAL), |
| positionRectangle.y, positionRectangle.y + positionRectangle.height); |
| } |
| |
| @Override |
| public LRectangle adjustCellBounds(final long columnPosition, final long rowPosition, final LRectangle cellBounds) { |
| return cellBounds; |
| } |
| |
| protected LRectangle getPositionRectangleFromPixelRectangle(final ILayer natLayer, final Rectangle pixelRectangle) { |
| final long columnPositionOffset= natLayer.getColumnPositionByX(pixelRectangle.x); |
| final long rowPositionOffset= natLayer.getRowPositionByY(pixelRectangle.y); |
| final long numColumns= natLayer.getColumnPositionByX(Math.min(natLayer.getWidth(), pixelRectangle.x + pixelRectangle.width) - 1) - columnPositionOffset + 1; |
| final long numRows= natLayer.getRowPositionByY(Math.min(natLayer.getHeight(), pixelRectangle.y + pixelRectangle.height) - 1) - rowPositionOffset + 1; |
| |
| if (columnPositionOffset < 0 || rowPositionOffset < 0 || numColumns < 0 || numRows < 0) { |
| // getPositionRectangleFromPixelRectangle(natLayer, pixelRectangle); |
| throw new RuntimeException(); |
| } |
| |
| return new LRectangle(columnPositionOffset, rowPositionOffset, numColumns, numRows); |
| } |
| |
| protected void paintCell(final ILayerCell cell, final GC gc, final IConfigRegistry configRegistry) { |
| final ILayer layer= cell.getLayer(); |
| final long columnPosition= cell.getColumnPosition(); |
| final long rowPosition= cell.getRowPosition(); |
| |
| final ICellPainter cellPainter= configRegistry.getConfigAttribute(CellConfigAttributes.CELL_PAINTER, |
| cell.getDisplayMode(), cell.getConfigLabels().getLabels() ); |
| final LRectangle adjustedCellBounds= layer.getLayerPainter().adjustCellBounds(columnPosition, rowPosition, cell.getBounds()); |
| if (cellPainter != null) { |
| final Rectangle originalClipping= gc.getClipping(); |
| |
| final long startX= getColumnPositionStart(columnPosition); |
| final long startY= getRowPositionStart(rowPosition); |
| |
| final long endX= getColumnPositionStart(cell.getOriginColumnPosition() + cell.getColumnSpan()); |
| final long endY= getRowPositionStart(cell.getOriginRowPosition() + cell.getRowSpan()); |
| |
| final LRectangle clipBounds= new LRectangle(startX, startY, endX - startX, endY - startY); |
| final LRectangle adjustedClipBounds= clipBounds.intersection(adjustedCellBounds); |
| // LRectangle adjustedClipBounds= layer.getLayerPainter().adjustCellBounds(columnPosition, rowPosition, clipBounds); |
| gc.setClipping(safe(adjustedClipBounds)); |
| |
| cellPainter.paintCell(cell, gc, adjustedCellBounds, configRegistry); |
| |
| gc.setClipping(originalClipping); |
| } |
| } |
| |
| private long getColumnPositionStart(final long columnPosition) { |
| return getPositionStart(this.natLayer.getDim(HORIZONTAL), columnPosition, |
| this.horizontalPositionToPixelMap ); |
| } |
| |
| private long getRowPositionStart(final long rowPosition) { |
| return getPositionStart(this.natLayer.getDim(VERTICAL), rowPosition, |
| this.verticalPositionToPixelMap ); |
| } |
| |
| } |