blob: de4d0a6b04a661d9139f6a90657a846037882b92 [file] [log] [blame]
/*=============================================================================#
# 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 );
}
}