| /***************************************************************************** |
| * 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 |
| * & paste operation triggered by using the fill handle. |
| * @param dataProvider |
| * The {@link FormulaDataProvider} that is needed to copy & |
| * 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; |
| } |
| |
| } |