blob: defc77aca6f8ffb5f5f0859917d1fe5c32357ca5 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2015, 2020 CEA LIST.
*
* 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:
* Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
*****************************************************************************/
package org.eclipse.nebula.widgets.nattable.formula.command;
import java.math.BigDecimal;
import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand;
import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommandHandler;
import org.eclipse.nebula.widgets.nattable.formula.FormulaDataProvider;
import org.eclipse.nebula.widgets.nattable.formula.function.FunctionException;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
import org.eclipse.nebula.widgets.nattable.layer.cell.LayerCell;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
/**
* Specialized command handler for {@link FillHandlePasteCommand}s that is able
* to deal with formulas.
*
* @since 1.4
*/
public class FormulaFillHandlePasteCommandHandler extends FillHandlePasteCommandHandler {
protected FormulaDataProvider dataProvider;
/**
*
* @param selectionLayer
* The {@link SelectionLayer} needed to determine the fill handle
* region and perform the update command.
* @param clipboard
* The internal clipboard that carries the cells for the copy
* &amp; paste operation triggered by using the fill handle.
* @param dataProvider
* The {@link FormulaDataProvider} that is needed to copy &amp;
* paste formulas.
*/
public FormulaFillHandlePasteCommandHandler(
SelectionLayer selectionLayer,
InternalCellClipboard clipboard,
FormulaDataProvider dataProvider) {
super(selectionLayer, clipboard);
this.dataProvider = dataProvider;
}
@Override
public boolean doCommand(ILayer targetLayer, FillHandlePasteCommand command) {
if (this.clipboard.getCopiedCells() != null) {
// in case there are no cached data information held in the copied
// cells, ensure that formulas are not evaluated on paste
this.selectionLayer.doCommand(new DisableFormulaEvaluationCommand());
super.doCommand(targetLayer, command);
this.selectionLayer.doCommand(new EnableFormulaEvaluationCommand());
}
return true;
}
@Override
protected Object getPasteValue(ILayerCell cell, FillHandlePasteCommand command, int toColumn, int toRow) {
Object cellValue = (cell != null) ? cell.getDataValue() : null;
if (cellValue != null && this.dataProvider.getFormulaParser().isFunction(cellValue.toString())) {
try {
cellValue = this.dataProvider.getFormulaParser().updateReferences(
cellValue.toString(), cell.getColumnPosition(), cell.getRowPosition(), toColumn, toRow);
} catch (FunctionException e) {
if (this.dataProvider.getErrorReporter() != null) {
this.dataProvider.getErrorReporter().addFormulaError(toColumn, toRow, e.getLocalizedMessage());
}
cellValue = e.getErrorMarkup();
}
} else if (cellValue != null
&& cellValue instanceof String
&& this.dataProvider.getFormulaParser().isNumber((String) cellValue)) {
final BigDecimal converted = this.dataProvider.getFormulaParser().convertToBigDecimal((String) cellValue);
ILayerCell temp = new LayerCell(cell.getLayer(),
cell.getOriginColumnPosition(), cell.getOriginRowPosition(),
cell.getColumnPosition(), cell.getRowPosition(),
cell.getColumnSpan(), cell.getRowSpan()) {
@Override
public Object getDataValue() {
return converted;
}
};
Object calculated = super.getPasteValue(temp, command, toColumn, toRow);
cellValue = (calculated != null) ? calculated.toString() : calculated;
} else {
cellValue = super.getPasteValue(cell, command, toColumn, toRow);
}
return cellValue;
}
@Override
protected BigDecimal calculateBigDecimalDiff(ILayerCell c1, ILayerCell c2) {
BigDecimal result = null;
if (c1 != null && c2 != null && c1.getDataValue() != null && c2.getDataValue() != null) {
BigDecimal v1 = null;
if (c1.getDataValue() instanceof BigDecimal) {
v1 = (BigDecimal) c1.getDataValue();
} else if (c1.getDataValue() instanceof String
&& this.dataProvider.getFormulaParser().isNumber((String) c1.getDataValue())) {
v1 = this.dataProvider.getFormulaParser().convertToBigDecimal((String) c1.getDataValue());
}
BigDecimal v2 = null;
if (c2.getDataValue() instanceof BigDecimal) {
v2 = (BigDecimal) c2.getDataValue();
} else if (c2.getDataValue() instanceof String
&& this.dataProvider.getFormulaParser().isNumber((String) c2.getDataValue())) {
v2 = this.dataProvider.getFormulaParser().convertToBigDecimal((String) c2.getDataValue());
}
if (v1 != null && v2 != null) {
result = v1.subtract(v2);
}
}
return result;
}
}