Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDirk Fauth2015-12-24 13:18:06 +0000
committerDirk Fauth2015-12-24 13:18:06 +0000
commit0d4c91b45b272f328ecbe075b2775b4b8eb92b39 (patch)
treed1ded6d10ef5b96f16261bb1fe83a6e6ee5fa547
parent8955d78dbe8aa4618e15fa376a0eb658b1b38cea (diff)
downloadorg.eclipse.nebula.widgets.nattable-0d4c91b45b272f328ecbe075b2775b4b8eb92b39.tar.gz
org.eclipse.nebula.widgets.nattable-0d4c91b45b272f328ecbe075b2775b4b8eb92b39.tar.xz
org.eclipse.nebula.widgets.nattable-0d4c91b45b272f328ecbe075b2775b4b8eb92b39.zip
Bug 484880 - Add fill drag handle to support autofill actions
Change-Id: I287df69733b9095d8927fb97f8f5c8a413c291a0 Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
-rw-r--r--org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandlePasteTest.java905
-rw-r--r--org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleSeriesTest.java1320
-rw-r--r--org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/formula/FormulaFillHandlePasteTest.java269
-rw-r--r--org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java180
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF5
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java17
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/action/PasteDataAction.java (renamed from org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/FormulaPasteDataAction.java)10
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/action/PasteOrMoveSelectionAction.java (renamed from org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/PasteOrMoveSelectionAction.java)15
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalCopyDataCommandHandler.java75
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalPasteDataCommandHandler.java125
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/PasteDataCommand.java (renamed from org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommand.java)14
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleLayerPainter.java669
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleCursorAction.java104
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleDragMode.java324
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommand.java86
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommandHandler.java577
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillDirection.java23
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfigAttributes.java61
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfiguration.java103
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleEventMatcher.java56
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleMarkupListener.java41
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/CopySelectionLayerPainter.java (renamed from org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/FormulaLayerPainter.java)43
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/FormulaFillHandleDragMode.java87
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaCopyDataCommandHandler.java68
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaFillHandlePasteCommandHandler.java134
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommandHandler.java98
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/DefaultFormulaConfiguration.java37
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/FormulaStyleLabels.java33
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages.properties3
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages_de.properties3
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionConfigAttributes.java35
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java86
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayerPainter.java165
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java162
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/SelectionStyleLabels.java68
-rw-r--r--org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_300_Data/_305_FormulaDataExample.java24
36 files changed, 5709 insertions, 316 deletions
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandlePasteTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandlePasteTest.java
new file mode 100644
index 00000000..2df1069f
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandlePasteTest.java
@@ -0,0 +1,905 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.EditableRule;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataToClipboardCommand;
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand.FillHandleOperation;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfiguration;
+import org.eclipse.nebula.widgets.nattable.formula.TwoDimensionalArrayDataProvider;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
+import org.eclipse.nebula.widgets.nattable.test.fixture.NatTableFixture;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FillHandlePasteTest {
+
+ IDataProvider dataProvider = new TwoDimensionalArrayDataProvider(new Object[10][10]);
+ SelectionLayer selectionLayer = new SelectionLayer(new DataLayer(this.dataProvider));
+ NatTable natTable = new NatTableFixture(this.selectionLayer, false);
+
+ @Before
+ public void setup() {
+ this.natTable.addConfiguration(new FillHandleConfiguration(this.selectionLayer));
+ this.natTable.addConfiguration(new AbstractRegistryConfiguration() {
+
+ @Override
+ public void configureRegistry(IConfigRegistry configRegistry) {
+ configRegistry.registerConfigAttribute(
+ EditConfigAttributes.CELL_EDITABLE_RULE,
+ EditableRule.ALWAYS_EDITABLE);
+ }
+ });
+ this.natTable.configure();
+ }
+
+ @After
+ public void tearDown() {
+ this.selectionLayer.clear();
+ this.selectionLayer.setFillHandleRegion(null);
+ }
+
+ @Test
+ public void testSingleCellDragOneDown() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+ }
+
+ @Test
+ public void testSingleCellDragOneUp() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 3, 1, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 3));
+
+ testCellStates(new Point(4, 4), new Point(4, 3));
+ }
+
+ @Test
+ public void testSingleCellDragOneRight() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 2, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(5, 4));
+
+ testCellStates(new Point(4, 4), new Point(5, 4));
+ }
+
+ @Test
+ public void testSingleCellDragOneLeft() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 2, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(3, 4));
+
+ testCellStates(new Point(4, 4), new Point(3, 4));
+ }
+
+ @Test
+ public void testSingleCellDragMultipleDown() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 7));
+
+ testCellStates(new Point(4, 4), new Point(4, 5), new Point(4, 6), new Point(4, 7));
+ }
+
+ @Test
+ public void testSingleCellDragMultiUp() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 0, 1, 5));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 0));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 1));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 2));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 3));
+
+ testCellStates(new Point(4, 4), new Point(4, 0), new Point(4, 1), new Point(4, 2), new Point(4, 3));
+ }
+
+ @Test
+ public void testSingleCellDragMultiRight() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 4, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(7, 4));
+
+ testCellStates(new Point(4, 4), new Point(5, 4), new Point(6, 4), new Point(7, 4));
+ }
+
+ @Test
+ public void testSingleCellDragMultiLeft() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(0, 4, 5, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(0, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(1, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(2, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(3, 4));
+
+ testCellStates(new Point(4, 4), new Point(0, 4), new Point(1, 4), new Point(2, 4), new Point(3, 4));
+ }
+
+ @Test
+ public void testSingleCellDragDownRight() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 2, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(5, 5));
+
+ testCellStates(new Point(4, 4), new Point(4, 5), new Point(5, 4), new Point(5, 5));
+ }
+
+ @Test
+ public void testSingleCellDragOneUpRight() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 3, 2, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(5, 3));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(5, 4));
+
+ testCellStates(new Point(4, 3), new Point(5, 3), new Point(4, 4), new Point(5, 4));
+ }
+
+ @Test
+ public void testSingleCellDragUpLeft() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 3, 2, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(3, 3));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+
+ testCellStates(new Point(3, 3), new Point(4, 3), new Point(3, 4), new Point(4, 4));
+ }
+
+ @Test
+ public void testSingleCellDragDownLeft() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 2, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+ }
+
+ @Test
+ public void testMultiVerticalCellDragRight() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 3, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(5, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(6, 5));
+
+ testCellStates(new Point(4, 4), new Point(4, 5), new Point(5, 4), new Point(5, 5), new Point(6, 4), new Point(6, 5));
+ }
+
+ @Test
+ public void testMultiVerticalCellDragLeft() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(2, 4, 3, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(2, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(2, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(new Point(2, 4), new Point(2, 5), new Point(3, 4), new Point(3, 5), new Point(4, 4), new Point(4, 5));
+ }
+
+ @Test
+ public void testMultiVerticalCellDragDown() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 5));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 8));
+
+ testCellStates(new Point(4, 4), new Point(4, 5), new Point(4, 6), new Point(4, 7), new Point(4, 8));
+ }
+
+ @Test
+ public void testMultiVerticalCellDragUp() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 1, 1, 5));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 1));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 2));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(new Point(4, 1), new Point(4, 2), new Point(4, 3), new Point(4, 4), new Point(4, 5));
+ }
+
+ @Test
+ public void testMultiHorizontalCellDragRight() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 5, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(7, 4));
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(5, 4), new Point(6, 4), new Point(7, 4));
+ }
+
+ @Test
+ public void testMultiHorizontalCellDragLeft() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(0, 4, 5, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(0, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(1, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(2, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+
+ testCellStates(new Point(0, 4), new Point(1, 4), new Point(2, 4), new Point(3, 4), new Point(4, 4));
+ }
+
+ @Test
+ public void testMultiHorizontalCellDragDown() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 2, 3));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 6));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 6));
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5), new Point(3, 6), new Point(4, 6));
+ }
+
+ @Test
+ public void testMultiHorizontalCellDragUp() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 2, 2, 3));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 2));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 2));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 3));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+
+ testCellStates(new Point(3, 2), new Point(4, 2), new Point(3, 3), new Point(4, 3), new Point(3, 4), new Point(4, 4));
+ }
+
+ @Test
+ public void testMultiCellDragOneDown() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 2, 3));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 6));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 6));
+
+ testCellStates(
+ new Point(3, 4), new Point(4, 4),
+ new Point(3, 5), new Point(4, 5),
+ new Point(3, 6), new Point(4, 6));
+ }
+
+ @Test
+ public void testMultiCellDragThreeDown() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 2, 5));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 6));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 6));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 6));
+
+ testCellStates(
+ new Point(3, 4), new Point(4, 4),
+ new Point(3, 5), new Point(4, 5),
+ new Point(3, 6), new Point(4, 6),
+ new Point(3, 7), new Point(4, 7),
+ new Point(3, 8), new Point(4, 8));
+ }
+
+ @Test
+ public void testMultiCellDragOneUp() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 3, 2, 3));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 3));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(
+ new Point(3, 3), new Point(4, 3),
+ new Point(3, 4), new Point(4, 4),
+ new Point(3, 5), new Point(4, 5));
+ }
+
+ @Test
+ public void testMultiCellDragThreeUp() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 1, 2, 5));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 1));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 1));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 2));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 2));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 3));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(
+ new Point(3, 1), new Point(4, 1),
+ new Point(3, 2), new Point(4, 2),
+ new Point(3, 3), new Point(4, 3),
+ new Point(3, 4), new Point(4, 4),
+ new Point(3, 5), new Point(4, 5));
+ }
+
+ @Test
+ public void testMultiCellDragOneRight() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 3, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(5, 5));
+
+ testCellStates(
+ new Point(3, 4), new Point(4, 4), new Point(5, 4),
+ new Point(3, 5), new Point(4, 5), new Point(5, 5));
+ }
+
+ @Test
+ public void testMultiCellDragThreeRight() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(3, 4, 5, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(5, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(6, 5));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(7, 5));
+
+ testCellStates(
+ new Point(3, 4), new Point(4, 4), new Point(5, 4), new Point(6, 4), new Point(7, 4),
+ new Point(3, 5), new Point(4, 5), new Point(5, 5), new Point(6, 5), new Point(7, 5));
+ }
+
+ @Test
+ public void testMultiCellDragOneLeft() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(2, 4, 3, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(2, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(2, 5));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(
+ new Point(2, 4), new Point(3, 4), new Point(4, 4),
+ new Point(2, 5), new Point(3, 5), new Point(4, 5));
+ }
+
+ @Test
+ public void testMultiCellDragThreeLeft() {
+ this.dataProvider.setDataValue(3, 4, "Homer");
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+ this.dataProvider.setDataValue(3, 5, "Ned");
+ this.dataProvider.setDataValue(4, 5, "Flanders");
+
+ this.selectionLayer.selectCell(3, 4, false, true);
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(3, 5, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(3, 4), new Point(4, 4), new Point(3, 5), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(0, 4, 5, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(0, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(1, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(2, 4));
+ assertEquals("Homer", this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(0, 5));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(1, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(2, 5));
+ assertEquals("Ned", this.selectionLayer.getDataValueByPosition(3, 5));
+ assertEquals("Flanders", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(
+ new Point(0, 4), new Point(1, 4), new Point(2, 4), new Point(3, 4), new Point(4, 4),
+ new Point(0, 5), new Point(1, 5), new Point(2, 5), new Point(3, 5), new Point(4, 5));
+ }
+
+ private void testCellStates(Point... nonNull) {
+ for (int i = 0; i < this.dataProvider.getColumnCount(); i++) {
+ for (int j = 0; j < this.dataProvider.getRowCount(); j++) {
+
+ boolean check = true;
+ for (Point p : nonNull) {
+ if ((i == p.x) && (j == p.y)) {
+ check = false;
+ break;
+ }
+ }
+ if (check) {
+ assertNull("Position " + i + "/" + j + " is not null", this.selectionLayer.getDataValueByPosition(i, j));
+ } else {
+ assertNotNull("Position " + i + "/" + j + " is null", this.selectionLayer.getDataValueByPosition(i, j));
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleSeriesTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleSeriesTest.java
new file mode 100644
index 00000000..3c90b4f9
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleSeriesTest.java
@@ -0,0 +1,1320 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.EditableRule;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataToClipboardCommand;
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand.FillHandleOperation;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfiguration;
+import org.eclipse.nebula.widgets.nattable.formula.TwoDimensionalArrayDataProvider;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
+import org.eclipse.nebula.widgets.nattable.test.fixture.NatTableFixture;
+import org.eclipse.swt.graphics.Rectangle;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FillHandleSeriesTest {
+
+ IDataProvider dataProvider = new TwoDimensionalArrayDataProvider(new Object[10][10]);
+ SelectionLayer selectionLayer = new SelectionLayer(new DataLayer(this.dataProvider));
+ NatTable natTable = new NatTableFixture(this.selectionLayer, false);
+
+ @Before
+ public void setup() {
+ this.natTable.addConfiguration(new FillHandleConfiguration(this.selectionLayer));
+ this.natTable.addConfiguration(new AbstractRegistryConfiguration() {
+
+ @Override
+ public void configureRegistry(IConfigRegistry configRegistry) {
+ configRegistry.registerConfigAttribute(
+ EditConfigAttributes.CELL_EDITABLE_RULE,
+ EditableRule.ALWAYS_EDITABLE);
+ }
+ });
+ this.natTable.configure();
+ }
+
+ @After
+ public void tearDown() {
+ this.selectionLayer.clear();
+ this.selectionLayer.setFillHandleRegion(null);
+ }
+
+ @Test
+ public void testSingleCellIntegerValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testSingleCellIntegerValueDragUp() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 1, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("-2"), this.selectionLayer.getDataValueByPosition(4, 1));
+ assertEquals(Integer.valueOf("-1"), this.selectionLayer.getDataValueByPosition(4, 2));
+ assertEquals(Integer.valueOf("0"), this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ }
+
+ @Test
+ public void testSingleCellIntegerValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 4, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(7, 4));
+ }
+
+ @Test
+ public void testSingleCellIntegerValueDragLeft() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(1, 4, 4, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("-2"), this.selectionLayer.getDataValueByPosition(1, 4));
+ assertEquals(Integer.valueOf("-1"), this.selectionLayer.getDataValueByPosition(2, 4));
+ assertEquals(Integer.valueOf("0"), this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ }
+
+ @Test
+ public void testSingleCellByteValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Byte.valueOf("1"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Byte.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Byte.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Byte.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Byte.valueOf("4"), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testSingleCellShortValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Short.valueOf("1"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Short.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Short.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Short.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Short.valueOf("4"), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testSingleCellLongValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Long.valueOf("1"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Long.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Long.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Long.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Long.valueOf("4"), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testSingleCellFloatValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Float.valueOf("1.4"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Float.valueOf("1.4"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Float.valueOf("2.4"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Float.valueOf("3.4"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Float.valueOf("4.4"), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testSingleCellDoubleValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Double.valueOf("1.6"));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Double.valueOf("1.6"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Double.valueOf("2.6"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Double.valueOf("3.6"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Double.valueOf("4.6"), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testSingleCellBigIntegerValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, BigInteger.valueOf(100));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigInteger.valueOf(100), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(BigInteger.valueOf(101), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(BigInteger.valueOf(102), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(BigInteger.valueOf(103), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testSingleCellBigDecimalValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, BigDecimal.valueOf(13.8d));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigDecimal.valueOf(13.8d), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(BigDecimal.valueOf(14.8d), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(BigDecimal.valueOf(15.8d), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(BigDecimal.valueOf(16.8d), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testSingleCellDateValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, new Date(2015, 9, 29));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(new Date(2015, 9, 29), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(new Date(2015, 9, 30), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(new Date(2015, 9, 31), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(new Date(2015, 10, 1), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testSingleCellDateValueDragUp() {
+ this.dataProvider.setDataValue(4, 4, new Date(2015, 9, 2));
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 1, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals(new Date(2015, 8, 29), this.selectionLayer.getDataValueByPosition(4, 1));
+ assertEquals(new Date(2015, 8, 30), this.selectionLayer.getDataValueByPosition(4, 2));
+ assertEquals(new Date(2015, 9, 1), this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals(new Date(2015, 9, 2), this.selectionLayer.getDataValueByPosition(4, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffIntegerValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(4, 5, Integer.valueOf("3"));
+ this.dataProvider.setDataValue(4, 6, Integer.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Integer.valueOf("5"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Integer.valueOf("7"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Integer.valueOf("9"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Integer.valueOf("11"), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffIntegerValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(5, 4, Integer.valueOf("3"));
+ this.dataProvider.setDataValue(6, 4, Integer.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Integer.valueOf("5"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Integer.valueOf("7"), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(Integer.valueOf("9"), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(Integer.valueOf("11"), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffIntegerValueDragUp() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(4, 5, Integer.valueOf("3"));
+ this.dataProvider.setDataValue(4, 6, Integer.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 1, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.UP, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("-5"), this.selectionLayer.getDataValueByPosition(4, 1));
+ assertEquals(Integer.valueOf("-3"), this.selectionLayer.getDataValueByPosition(4, 2));
+ assertEquals(Integer.valueOf("-1"), this.selectionLayer.getDataValueByPosition(4, 3));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Integer.valueOf("5"), this.selectionLayer.getDataValueByPosition(4, 6));
+ }
+
+ @Test
+ public void testMultiCellSameDiffIntegerValueDragLeft() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(5, 4, Integer.valueOf("3"));
+ this.dataProvider.setDataValue(6, 4, Integer.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(1, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.LEFT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("-5"), this.selectionLayer.getDataValueByPosition(1, 4));
+ assertEquals(Integer.valueOf("-3"), this.selectionLayer.getDataValueByPosition(2, 4));
+ assertEquals(Integer.valueOf("-1"), this.selectionLayer.getDataValueByPosition(3, 4));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Integer.valueOf("5"), this.selectionLayer.getDataValueByPosition(6, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffByteValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Byte.valueOf("1"));
+ this.dataProvider.setDataValue(4, 5, Byte.valueOf("3"));
+ this.dataProvider.setDataValue(4, 6, Byte.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Byte.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Byte.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Byte.valueOf("5"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Byte.valueOf("7"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Byte.valueOf("9"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Byte.valueOf("11"), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffShortValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Short.valueOf("1"));
+ this.dataProvider.setDataValue(4, 5, Short.valueOf("3"));
+ this.dataProvider.setDataValue(4, 6, Short.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Short.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Short.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Short.valueOf("5"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Short.valueOf("7"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Short.valueOf("9"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Short.valueOf("11"), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffLongValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Long.valueOf("1"));
+ this.dataProvider.setDataValue(4, 5, Long.valueOf("3"));
+ this.dataProvider.setDataValue(4, 6, Long.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Long.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Long.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Long.valueOf("5"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Long.valueOf("7"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Long.valueOf("9"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Long.valueOf("11"), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffFloatValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Float.valueOf("1.3"));
+ this.dataProvider.setDataValue(4, 5, Float.valueOf("2.6"));
+ this.dataProvider.setDataValue(4, 6, Float.valueOf("3.9"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Float.valueOf("1.3"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Float.valueOf("2.6"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Float.valueOf("3.9"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Float.valueOf("5.2"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Float.valueOf("6.5"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Float.valueOf("7.8"), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffDoubleValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Double.valueOf("1.3"));
+ this.dataProvider.setDataValue(4, 5, Double.valueOf("2.6"));
+ this.dataProvider.setDataValue(4, 6, Double.valueOf("3.9"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Double.valueOf("1.3"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Double.valueOf("2.6"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Double.valueOf("3.9"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Double.valueOf("5.2"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Double.valueOf("6.5"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Double.valueOf("7.8"), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffBigIntegerValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, BigInteger.valueOf(1));
+ this.dataProvider.setDataValue(4, 5, BigInteger.valueOf(3));
+ this.dataProvider.setDataValue(4, 6, BigInteger.valueOf(5));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigInteger.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(BigInteger.valueOf(3), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(BigInteger.valueOf(5), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(BigInteger.valueOf(7), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(BigInteger.valueOf(9), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(BigInteger.valueOf(11), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffBigDecimalValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, BigDecimal.valueOf(1.2d));
+ this.dataProvider.setDataValue(4, 5, BigDecimal.valueOf(2.4d));
+ this.dataProvider.setDataValue(4, 6, BigDecimal.valueOf(3.6d));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigDecimal.valueOf(1.2d), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(BigDecimal.valueOf(2.4d), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(BigDecimal.valueOf(3.6d), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(BigDecimal.valueOf(4.8d), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(BigDecimal.valueOf(6d), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(BigDecimal.valueOf(7.2d), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testMultiCellSameDiffDateValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, new Date(2015, 9, 2));
+ this.dataProvider.setDataValue(4, 5, new Date(2015, 9, 5));
+ this.dataProvider.setDataValue(4, 6, new Date(2015, 9, 8));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(new Date(2015, 9, 2), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(new Date(2015, 9, 5), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(new Date(2015, 9, 8), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(new Date(2015, 9, 11), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(new Date(2015, 9, 14), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(new Date(2015, 9, 17), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testMultiCellSameDiffDateYearValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, new Date(2002, 9, 2));
+ this.dataProvider.setDataValue(4, 5, new Date(2004, 9, 5));
+ this.dataProvider.setDataValue(4, 6, new Date(2006, 9, 8));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.getConfigRegistry().registerConfigAttribute(
+ FillHandleConfigAttributes.INCREMENT_DATE_FIELD,
+ Calendar.YEAR);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(new Date(2002, 9, 2), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(new Date(2004, 9, 5), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(new Date(2006, 9, 8), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(new Date(2008, 9, 2), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(new Date(2010, 9, 5), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(new Date(2012, 9, 8), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellSameDiffByteValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, Byte.valueOf("1"));
+ this.dataProvider.setDataValue(5, 4, Byte.valueOf("3"));
+ this.dataProvider.setDataValue(6, 4, Byte.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Byte.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Byte.valueOf("3"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Byte.valueOf("5"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Byte.valueOf("7"), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(Byte.valueOf("9"), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(Byte.valueOf("11"), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffShortValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, Short.valueOf("1"));
+ this.dataProvider.setDataValue(5, 4, Short.valueOf("3"));
+ this.dataProvider.setDataValue(6, 4, Short.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Short.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Short.valueOf("3"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Short.valueOf("5"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Short.valueOf("7"), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(Short.valueOf("9"), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(Short.valueOf("11"), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffLongValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, Long.valueOf("1"));
+ this.dataProvider.setDataValue(5, 4, Long.valueOf("3"));
+ this.dataProvider.setDataValue(6, 4, Long.valueOf("5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Long.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Long.valueOf("3"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Long.valueOf("5"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Long.valueOf("7"), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(Long.valueOf("9"), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(Long.valueOf("11"), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffFloatValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, Float.valueOf("1.3"));
+ this.dataProvider.setDataValue(5, 4, Float.valueOf("2.6"));
+ this.dataProvider.setDataValue(6, 4, Float.valueOf("3.9"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Float.valueOf("1.3"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Float.valueOf("2.6"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Float.valueOf("3.9"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Float.valueOf("5.2"), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(Float.valueOf("6.5"), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(Float.valueOf("7.8"), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffDoubleValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, Double.valueOf("1.3"));
+ this.dataProvider.setDataValue(5, 4, Double.valueOf("2.6"));
+ this.dataProvider.setDataValue(6, 4, Double.valueOf("3.9"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(Double.valueOf("1.3"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Double.valueOf("2.6"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Double.valueOf("3.9"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Double.valueOf("5.2"), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(Double.valueOf("6.5"), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(Double.valueOf("7.8"), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffBigIntegerValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, BigInteger.valueOf(1));
+ this.dataProvider.setDataValue(5, 4, BigInteger.valueOf(3));
+ this.dataProvider.setDataValue(6, 4, BigInteger.valueOf(5));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigInteger.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(BigInteger.valueOf(3), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(BigInteger.valueOf(5), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(BigInteger.valueOf(7), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(BigInteger.valueOf(9), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(BigInteger.valueOf(11), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellSameDiffBigDecimalValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, BigDecimal.valueOf(1.2d));
+ this.dataProvider.setDataValue(5, 4, BigDecimal.valueOf(2.4d));
+ this.dataProvider.setDataValue(6, 4, BigDecimal.valueOf(3.6d));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigDecimal.valueOf(1.2d), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(BigDecimal.valueOf(2.4d), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(BigDecimal.valueOf(3.6d), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(BigDecimal.valueOf(4.8d), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(BigDecimal.valueOf(6d), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(BigDecimal.valueOf(7.2d), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testMultiCellSameDiffDateValueDragRight() {
+ this.dataProvider.setDataValue(4, 4, new Date(2002, 9, 2));
+ this.dataProvider.setDataValue(5, 4, new Date(2002, 9, 5));
+ this.dataProvider.setDataValue(6, 4, new Date(2002, 9, 8));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ assertEquals(new Date(2002, 9, 2), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(new Date(2002, 9, 5), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(new Date(2002, 9, 8), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(new Date(2002, 9, 11), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(new Date(2002, 9, 14), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(new Date(2002, 9, 17), this.selectionLayer.getDataValueByPosition(9, 4));
+ }
+
+ @Test
+ public void testMultiCellDifferentIntegerValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(4, 5, Integer.valueOf("2"));
+ this.dataProvider.setDataValue(4, 6, Integer.valueOf("4"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+ this.selectionLayer.selectCell(4, 6, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ // as there is no common diff value in the cells we simply perform a
+ // copy operation
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellIntegerValueDragDown() {
+ // column 4 simple series
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(4, 5, Integer.valueOf("2"));
+ this.dataProvider.setDataValue(4, 6, Integer.valueOf("3"));
+ // column 5 calculated series
+ this.dataProvider.setDataValue(5, 4, Integer.valueOf("2"));
+ this.dataProvider.setDataValue(5, 5, Integer.valueOf("4"));
+ this.dataProvider.setDataValue(5, 6, Integer.valueOf("6"));
+ // column 6 incontiguous
+ this.dataProvider.setDataValue(6, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(6, 5, Integer.valueOf("2"));
+ this.dataProvider.setDataValue(6, 6, Integer.valueOf("4"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(6, 6, true, false);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 3, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ // simple series
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Integer.valueOf("5"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertEquals(Integer.valueOf("6"), this.selectionLayer.getDataValueByPosition(4, 9));
+
+ // series with 2 difference
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(5, 5));
+ assertEquals(Integer.valueOf("6"), this.selectionLayer.getDataValueByPosition(5, 6));
+ assertEquals(Integer.valueOf("8"), this.selectionLayer.getDataValueByPosition(5, 7));
+ assertEquals(Integer.valueOf("10"), this.selectionLayer.getDataValueByPosition(5, 8));
+ assertEquals(Integer.valueOf("12"), this.selectionLayer.getDataValueByPosition(5, 9));
+
+ // as there is no common diff value in the cells we simply perform a
+ // copy operation
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(6, 5));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(6, 6));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(6, 7));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(6, 8));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(6, 9));
+ }
+
+ @Test
+ public void testMultiCellIntegerValueDragRight() {
+ // column 4 simple series
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(5, 4, Integer.valueOf("2"));
+ this.dataProvider.setDataValue(6, 4, Integer.valueOf("3"));
+ // column 5 calculated series
+ this.dataProvider.setDataValue(4, 5, Integer.valueOf("2"));
+ this.dataProvider.setDataValue(5, 5, Integer.valueOf("4"));
+ this.dataProvider.setDataValue(6, 5, Integer.valueOf("6"));
+ // column 6 incontiguous
+ this.dataProvider.setDataValue(4, 6, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(5, 6, Integer.valueOf("2"));
+ this.dataProvider.setDataValue(6, 6, Integer.valueOf("4"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(6, 6, true, false);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 6, 3));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ // simple series
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Integer.valueOf("3"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(7, 4));
+ assertEquals(Integer.valueOf("5"), this.selectionLayer.getDataValueByPosition(8, 4));
+ assertEquals(Integer.valueOf("6"), this.selectionLayer.getDataValueByPosition(9, 4));
+
+ // series with 2 difference
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(5, 5));
+ assertEquals(Integer.valueOf("6"), this.selectionLayer.getDataValueByPosition(6, 5));
+ assertEquals(Integer.valueOf("8"), this.selectionLayer.getDataValueByPosition(7, 5));
+ assertEquals(Integer.valueOf("10"), this.selectionLayer.getDataValueByPosition(8, 5));
+ assertEquals(Integer.valueOf("12"), this.selectionLayer.getDataValueByPosition(9, 5));
+
+ // as there is no common diff value in the cells we simply perform a
+ // copy operation
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(5, 6));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(6, 6));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(7, 6));
+ assertEquals(Integer.valueOf("2"), this.selectionLayer.getDataValueByPosition(8, 6));
+ assertEquals(Integer.valueOf("4"), this.selectionLayer.getDataValueByPosition(9, 6));
+ }
+
+ @Test
+ public void testByteNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Byte.valueOf("1"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Byte.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Byte.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Byte.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testShortNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Short.valueOf("1"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Short.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Short.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Short.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testIntegerNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testLongNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Long.valueOf("1"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Long.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Long.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Long.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testFloatNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Float.valueOf("1"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Float.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Float.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Float.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testDoubleNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, Double.valueOf("1"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(Double.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Double.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(Double.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testBigIntegerNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, BigInteger.valueOf(1));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigInteger.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(BigInteger.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(BigInteger.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testBigDecimalNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, BigDecimal.valueOf(1));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(BigDecimal.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(BigDecimal.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(BigDecimal.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testDateNullCellValueDragDown() {
+ this.dataProvider.setDataValue(4, 4, new Date(2015, 9, 13));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 6));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals(new Date(2015, 9, 13), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(new Date(2015, 9, 13), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 7));
+ assertEquals(new Date(2015, 9, 13), this.selectionLayer.getDataValueByPosition(4, 8));
+ assertNull(this.selectionLayer.getDataValueByPosition(4, 9));
+ }
+
+ @Test
+ public void testMultiCellDifferentTypesDragDown() {
+ this.dataProvider.setDataValue(4, 4, Float.valueOf("3.5"));
+ this.dataProvider.setDataValue(4, 5, BigInteger.valueOf(1));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ // result should be a copy because of different data types
+ assertEquals(Float.valueOf("3.5"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(BigInteger.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals(Float.valueOf("3.5"), this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals(BigInteger.valueOf(1), this.selectionLayer.getDataValueByPosition(4, 7));
+ }
+
+ @Test
+ public void testMultiCellDifferentTypesDragRight() {
+ this.dataProvider.setDataValue(4, 4, Integer.valueOf("1"));
+ this.dataProvider.setDataValue(5, 4, Float.valueOf("3.5"));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 4, 1));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.RIGHT, this.natTable.getConfigRegistry()));
+
+ // result should be a copy because of different data types
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals(Float.valueOf("3.5"), this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(Integer.valueOf("1"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals(Float.valueOf("3.5"), this.selectionLayer.getDataValueByPosition(7, 4));
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/formula/FormulaFillHandlePasteTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/formula/FormulaFillHandlePasteTest.java
new file mode 100644
index 00000000..2fcb7544
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/formula/FormulaFillHandlePasteTest.java
@@ -0,0 +1,269 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.formula;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.math.BigDecimal;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.EditableRule;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataToClipboardCommand;
+import org.eclipse.nebula.widgets.nattable.copy.command.InternalCopyDataCommandHandler;
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand.FillHandleOperation;
+import org.eclipse.nebula.widgets.nattable.formula.command.FormulaFillHandlePasteCommandHandler;
+import org.eclipse.nebula.widgets.nattable.formula.config.DefaultFormulaConfiguration;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
+import org.eclipse.nebula.widgets.nattable.test.fixture.NatTableFixture;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FormulaFillHandlePasteTest {
+
+ IDataProvider dataProvider = new TwoDimensionalArrayDataProvider(new String[10][10]);
+ FormulaDataProvider formulaDataProvider = new FormulaDataProvider(this.dataProvider);
+ SelectionLayer selectionLayer = new SelectionLayer(new DataLayer(this.formulaDataProvider));
+ NatTable natTable = new NatTableFixture(this.selectionLayer, false);
+
+ @Before
+ public void setup() {
+ InternalCellClipboard clipboard = new InternalCellClipboard();
+ this.selectionLayer.registerCommandHandler(
+ new InternalCopyDataCommandHandler(this.selectionLayer, clipboard));
+ this.selectionLayer.registerCommandHandler(
+ new FormulaFillHandlePasteCommandHandler(this.selectionLayer, clipboard, this.formulaDataProvider));
+
+ this.natTable.addConfiguration(new DefaultFormulaConfiguration(
+ this.formulaDataProvider,
+ this.selectionLayer,
+ clipboard));
+
+ this.natTable.addConfiguration(new AbstractRegistryConfiguration() {
+
+ @Override
+ public void configureRegistry(IConfigRegistry configRegistry) {
+ configRegistry.registerConfigAttribute(
+ EditConfigAttributes.CELL_EDITABLE_RULE,
+ EditableRule.ALWAYS_EDITABLE);
+ }
+ });
+ this.natTable.configure();
+ }
+
+ @After
+ public void tearDown() {
+ this.selectionLayer.clear();
+ this.selectionLayer.setFillHandleRegion(null);
+ }
+
+ @Test
+ public void testSingleCellDragOneDown() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.COPY, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+ }
+
+ @Test
+ public void testSingleCellSeriesStringDragOneDown() {
+ this.dataProvider.setDataValue(4, 4, "Simpson");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("Simpson", this.selectionLayer.getDataValueByPosition(4, 5));
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+ }
+
+ @Test
+ public void testSingleNumberCellDragDown() {
+ this.dataProvider.setDataValue(4, 4, "1");
+
+ this.selectionLayer.setSelectedCell(4, 4);
+
+ testCellStates(new Point(4, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("1", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("2", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("3", this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals("4", this.selectionLayer.getDataValueByPosition(4, 7));
+
+ testCellStates(new Point(4, 4), new Point(4, 5), new Point(4, 6), new Point(4, 7));
+ }
+
+ @Test
+ public void testMultiNumberCellDragDown() {
+ this.dataProvider.setDataValue(4, 4, "2");
+ this.dataProvider.setDataValue(4, 5, "4");
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(4, 5, false, true);
+
+ testCellStates(new Point(4, 4), new Point(4, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 1, 4));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("2", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("4", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("6", this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals("8", this.selectionLayer.getDataValueByPosition(4, 7));
+
+ testCellStates(new Point(4, 4), new Point(4, 5), new Point(4, 6), new Point(4, 7));
+ }
+
+ @Test
+ public void testFunctionCellDragDown() {
+ this.dataProvider.setDataValue(4, 4, "2");
+ this.dataProvider.setDataValue(5, 4, "21");
+ this.dataProvider.setDataValue(6, 4, "=E5*F5");
+ this.dataProvider.setDataValue(4, 5, "3");
+ this.dataProvider.setDataValue(5, 5, "22");
+
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ testCellStates(new Point(4, 4), new Point(5, 4), new Point(6, 4),
+ new Point(4, 5), new Point(5, 5));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(6, 4, 1, 2));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("2", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("21", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(new BigDecimal("42"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals("3", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("22", this.selectionLayer.getDataValueByPosition(5, 5));
+ assertEquals(new BigDecimal("66"), this.selectionLayer.getDataValueByPosition(6, 5));
+
+ testCellStates(new Point(4, 4), new Point(5, 4), new Point(6, 4),
+ new Point(4, 5), new Point(5, 5), new Point(6, 5));
+ }
+
+ @Test
+ public void testFullFunctionCellDragDown() {
+ this.dataProvider.setDataValue(4, 4, "2");
+ this.dataProvider.setDataValue(5, 4, "21");
+ this.dataProvider.setDataValue(6, 4, "=E5*F5");
+
+ assertEquals(new BigDecimal("42"), this.formulaDataProvider.getDataValue(6, 4));
+
+ this.selectionLayer.selectCell(4, 4, false, true);
+ this.selectionLayer.selectCell(5, 4, false, true);
+ this.selectionLayer.selectCell(6, 4, false, true);
+
+ testCellStates(new Point(4, 4), new Point(5, 4), new Point(6, 4));
+
+ this.natTable.doCommand(new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ this.natTable.getConfigRegistry()));
+
+ this.selectionLayer.setFillHandleRegion(new Rectangle(4, 4, 3, 3));
+ this.natTable.doCommand(
+ new FillHandlePasteCommand(FillHandleOperation.SERIES, MoveDirectionEnum.DOWN, this.natTable.getConfigRegistry()));
+
+ assertEquals("2", this.selectionLayer.getDataValueByPosition(4, 4));
+ assertEquals("21", this.selectionLayer.getDataValueByPosition(5, 4));
+ assertEquals(new BigDecimal("42"), this.selectionLayer.getDataValueByPosition(6, 4));
+ assertEquals("3", this.selectionLayer.getDataValueByPosition(4, 5));
+ assertEquals("22", this.selectionLayer.getDataValueByPosition(5, 5));
+ assertEquals(new BigDecimal("66"), this.selectionLayer.getDataValueByPosition(6, 5));
+ assertEquals("4", this.selectionLayer.getDataValueByPosition(4, 6));
+ assertEquals("23", this.selectionLayer.getDataValueByPosition(5, 6));
+ assertEquals(new BigDecimal("92"), this.selectionLayer.getDataValueByPosition(6, 6));
+
+ testCellStates(new Point(4, 4), new Point(5, 4), new Point(6, 4),
+ new Point(4, 5), new Point(5, 5), new Point(6, 5),
+ new Point(4, 6), new Point(5, 6), new Point(6, 6));
+ }
+
+ private void testCellStates(Point... nonNull) {
+ for (int i = 0; i < this.dataProvider.getColumnCount(); i++) {
+ for (int j = 0; j < this.dataProvider.getRowCount(); j++) {
+
+ boolean check = true;
+ for (Point p : nonNull) {
+ if ((i == p.x) && (j == p.y)) {
+ check = false;
+ break;
+ }
+ }
+ if (check) {
+ assertNull("Position " + i + "/" + j + " is not null", this.selectionLayer.getDataValueByPosition(i, j));
+ } else {
+ assertNotNull("Position " + i + "/" + j + " is null", this.selectionLayer.getDataValueByPosition(i, j));
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java
new file mode 100644
index 00000000..e759d47e
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtilsTest.java
@@ -0,0 +1,180 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.selection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.test.fixture.data.DataProviderFixture;
+import org.junit.Test;
+
+public class SelectionUtilsTest {
+
+ @Test
+ public void testConsecutivePositions() {
+ int[] test = new int[] { 1, 2, 3, 4, 5 };
+ assertTrue(SelectionUtils.isConsecutive(test));
+ }
+
+ @Test
+ public void testDuplicateConsecutivePositions() {
+ int[] test = new int[] { 1, 1, 2, 3, 4, 5 };
+ assertFalse(SelectionUtils.isConsecutive(test));
+ }
+
+ @Test
+ public void testGapConsecutivePositions() {
+ int[] test = new int[] { 1, 3, 4, 5 };
+ assertFalse(SelectionUtils.isConsecutive(test));
+ }
+
+ @Test
+ public void testEmptyArray() {
+ int[] test = new int[] {};
+ assertTrue(SelectionUtils.isConsecutive(test));
+ }
+
+ @Test
+ public void testOneEntryArray() {
+ int[] test = new int[] { 42 };
+ assertTrue(SelectionUtils.isConsecutive(test));
+ }
+
+ @Test
+ public void testGetBottomRightSelectAll() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select all cells
+ selectionLayer.selectAll();
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertEquals(9, bottomRight.getColumnPosition());
+ assertEquals(9, bottomRight.getRowPosition());
+ }
+
+ @Test
+ public void testGetBottomRightSelectOne() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select one cell
+ selectionLayer.selectCell(5, 5, false, false);
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertEquals(5, bottomRight.getColumnPosition());
+ assertEquals(5, bottomRight.getRowPosition());
+ }
+
+ @Test
+ public void testGetBottomRightSelectNothing() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertNull(bottomRight);
+ }
+
+ @Test
+ public void testGetBottomRightSelectRegion() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select region
+ selectionLayer.selectRegion(2, 2, 3, 3);
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertEquals(4, bottomRight.getColumnPosition());
+ assertEquals(4, bottomRight.getRowPosition());
+ }
+
+ @Test
+ public void testGetBottomRightSelectRegionDeselectMiddle() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select region
+ selectionLayer.selectRegion(2, 2, 3, 3);
+
+ // deselect a cell
+ selectionLayer.clearSelection(3, 3);
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertNull(bottomRight);
+ }
+
+ @Test
+ public void testGetBottomRightSelectRegionDeselectTopEdge() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select region
+ selectionLayer.selectRegion(2, 2, 3, 3);
+
+ // deselect a cell
+ selectionLayer.clearSelection(2, 2);
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertNull(bottomRight);
+ }
+
+ @Test
+ public void testGetBottomRightSelectRegionDeselectMiddleBottomEdge() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select region
+ selectionLayer.selectRegion(2, 2, 3, 3);
+
+ // deselect a cell
+ selectionLayer.clearSelection(4, 4);
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertNull(bottomRight);
+ }
+
+ @Test
+ public void testGetBottomRightSelectDifferentRows() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select cells for same columns in non consecutive rows
+ selectionLayer.selectRegion(2, 2, 3, 1);
+ selectionLayer.selectRegion(4, 4, 3, 1);
+
+ assertEquals(6, selectionLayer.getSelectedCells().size());
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertNull(bottomRight);
+ }
+
+ @Test
+ public void testGetBottomRightSelectDifferentColumns() {
+ DataLayer dataLayer = new DataLayer(new DataProviderFixture(10, 10));
+ SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
+
+ // select cells for same columns in non consecutive rows
+ selectionLayer.selectRegion(2, 2, 1, 3);
+ selectionLayer.selectRegion(4, 4, 1, 3);
+
+ assertEquals(6, selectionLayer.getSelectedCells().size());
+
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(selectionLayer);
+ assertNull(bottomRight);
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF b/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF
index fb4cf376..9787b58e 100644
--- a/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF
@@ -39,6 +39,11 @@ Export-Package: org.eclipse.nebula.widgets.nattable;version="1.4.0",
org.eclipse.nebula.widgets.nattable.export.command;version="1.4.0",
org.eclipse.nebula.widgets.nattable.export.config;version="1.4.0",
org.eclipse.nebula.widgets.nattable.export.excel;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.fillhandle;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.fillhandle.action;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.fillhandle.command;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.fillhandle.config;version="1.4.0",
+ org.eclipse.nebula.widgets.nattable.fillhandle.event;version="1.4.0",
org.eclipse.nebula.widgets.nattable.filterrow;version="1.4.0",
org.eclipse.nebula.widgets.nattable.filterrow.action;version="1.4.0",
org.eclipse.nebula.widgets.nattable.filterrow.combobox;version="1.4.0",
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java
index eda241bf..ca7855c0 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java
@@ -32,6 +32,7 @@ import org.eclipse.nebula.widgets.nattable.conflation.EventConflaterChain;
import org.eclipse.nebula.widgets.nattable.conflation.IEventConflater;
import org.eclipse.nebula.widgets.nattable.conflation.VisualChangeEventConflater;
import org.eclipse.nebula.widgets.nattable.coordinate.Range;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
import org.eclipse.nebula.widgets.nattable.edit.ActiveCellEditorRegistry;
import org.eclipse.nebula.widgets.nattable.edit.CellEditorCreatedEvent;
import org.eclipse.nebula.widgets.nattable.edit.editor.ICellEditor;
@@ -168,6 +169,12 @@ public class NatTable extends Canvas implements ILayer, PaintListener, IClientAr
private ThemeManager themeManager;
/**
+ * The {@link InternalCellClipboard} that is used for internal copy &amp;
+ * paste functionality.
+ */
+ private InternalCellClipboard clipboard = new InternalCellClipboard();
+
+ /**
* The active cell editor or {@code null} if there is no one.
*/
private ICellEditor activeCellEditor;
@@ -1122,6 +1129,16 @@ public class NatTable extends Canvas implements ILayer, PaintListener, IClientAr
doCommand(new VisualRefreshCommand());
}
+ /**
+ *
+ * @return The {@link InternalCellClipboard} that is used for internal copy
+ * &amp; paste functionality.
+ * @since 1.4
+ */
+ public InternalCellClipboard getInternalCellClipboard() {
+ return this.clipboard;
+ }
+
// Editor
/**
* Returns the active cell editor that is currently open or {@code null} if
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/FormulaPasteDataAction.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/action/PasteDataAction.java
index 4f15bae5..c248306d 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/FormulaPasteDataAction.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/action/PasteDataAction.java
@@ -10,23 +10,23 @@
* Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
*
*****************************************************************************/
-package org.eclipse.nebula.widgets.nattable.formula.action;
+package org.eclipse.nebula.widgets.nattable.copy.action;
import org.eclipse.nebula.widgets.nattable.NatTable;
-import org.eclipse.nebula.widgets.nattable.formula.command.FormulaPasteDataCommand;
+import org.eclipse.nebula.widgets.nattable.copy.command.PasteDataCommand;
import org.eclipse.nebula.widgets.nattable.ui.action.IKeyAction;
import org.eclipse.swt.events.KeyEvent;
/**
- * {@link IKeyAction} that triggers the {@link FormulaPasteDataCommand}.
+ * {@link IKeyAction} that triggers the {@link PasteDataCommand}.
*
* @since 1.4
*/
-public class FormulaPasteDataAction implements IKeyAction {
+public class PasteDataAction implements IKeyAction {
@Override
public void run(NatTable natTable, KeyEvent event) {
- natTable.doCommand(new FormulaPasteDataCommand(natTable.getConfigRegistry()));
+ natTable.doCommand(new PasteDataCommand(natTable.getConfigRegistry()));
}
}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/PasteOrMoveSelectionAction.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/action/PasteOrMoveSelectionAction.java
index 4bd09b67..51522447 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/PasteOrMoveSelectionAction.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/action/PasteOrMoveSelectionAction.java
@@ -10,19 +10,19 @@
* Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
*
*****************************************************************************/
-package org.eclipse.nebula.widgets.nattable.formula.action;
+package org.eclipse.nebula.widgets.nattable.copy.action;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
-import org.eclipse.nebula.widgets.nattable.formula.command.FormulaPasteDataCommand;
+import org.eclipse.nebula.widgets.nattable.copy.command.PasteDataCommand;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
import org.eclipse.nebula.widgets.nattable.selection.action.MoveSelectionAction;
import org.eclipse.swt.events.KeyEvent;
/**
- * Action implementation that performs a {@link FormulaPasteDataCommand} if
- * there are values in the {@link InternalCellClipboard}, otherwise it performs
- * a selection movement.
+ * Action implementation that performs a {@link PasteDataCommand} if there are
+ * values in the {@link InternalCellClipboard}, otherwise it performs a
+ * selection movement.
*
* @since 1.4
*/
@@ -59,11 +59,10 @@ public class PasteOrMoveSelectionAction extends MoveSelectionAction {
public void run(NatTable natTable, KeyEvent event) {
if (this.clipboard.getCopiedCells() != null) {
- natTable.doCommand(new FormulaPasteDataCommand(natTable.getConfigRegistry()));
+ natTable.doCommand(new PasteDataCommand(natTable.getConfigRegistry()));
this.clipboard.clear();
- }
- else {
+ } else {
super.run(natTable, event);
}
}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalCopyDataCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalCopyDataCommandHandler.java
new file mode 100644
index 00000000..26873924
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalCopyDataCommandHandler.java
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.copy.command;
+
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionUtils;
+
+/**
+ * Specialized {@link CopyDataCommandHandler} that stores the copied cells in
+ * the {@link InternalCellClipboard} so it can be pasted within NatTable.
+ *
+ * @since 1.4
+ */
+public class InternalCopyDataCommandHandler extends CopyDataCommandHandler {
+
+ protected InternalCellClipboard clipboard;
+
+ /**
+ * Creates an instance that only checks the {@link SelectionLayer} for the
+ * data to add to the system clipboard and the given
+ * {@link InternalCellClipboard}.
+ *
+ * @param selectionLayer
+ * The {@link SelectionLayer} within the NatTable. Can not be
+ * <code>null</code>.
+ * @param clipboard
+ * The {@link InternalCellClipboard} that should be used for
+ * copy/paste operations within a NatTable instance.
+ */
+ public InternalCopyDataCommandHandler(SelectionLayer selectionLayer, InternalCellClipboard clipboard) {
+ super(selectionLayer);
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ public boolean doCommand(CopyDataToClipboardCommand command) {
+ // copy to clipboard
+ super.doCommand(command);
+
+ // only copy if contiguous cells
+ if (SelectionUtils.hasConsecutiveSelection(this.selectionLayer)) {
+ preInternalCopy();
+
+ // remember cells to copy to support paste
+ this.clipboard.setCopiedCells(assembleCopiedDataStructure());
+
+ postInternalCopy();
+ }
+
+ return true;
+ }
+
+ /**
+ * Perform actions prior copying values to the internal clipboard. E.g.
+ * disabling formula evaluation.
+ */
+ protected void preInternalCopy() {}
+
+ /**
+ * Perform actions after copying values to the internal clipboard. E.g.
+ * enabling formula evaluation.
+ */
+ protected void postInternalCopy() {}
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalPasteDataCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalPasteDataCommandHandler.java
new file mode 100644
index 00000000..e11d8dc5
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/InternalPasteDataCommandHandler.java
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.copy.command;
+
+import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.edit.command.EditUtils;
+import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+
+/**
+ * {@link ILayerCommandHandler} for handling {@link PasteDataCommand}s using the
+ * {@link InternalCellClipboard}.
+ *
+ * @since 1.4
+ */
+public class InternalPasteDataCommandHandler extends AbstractLayerCommandHandler<PasteDataCommand> {
+
+ protected SelectionLayer selectionLayer;
+ protected InternalCellClipboard clipboard;
+
+ /**
+ *
+ * @param selectionLayer
+ * {@link SelectionLayer} that is needed to determine the
+ * position to paste the values to.
+ * @param clipboard
+ * The {@link InternalCellClipboard} that contains the values
+ * that should be pasted.
+ */
+ public InternalPasteDataCommandHandler(
+ SelectionLayer selectionLayer,
+ InternalCellClipboard clipboard) {
+
+ this.selectionLayer = selectionLayer;
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ protected boolean doCommand(PasteDataCommand command) {
+ if (this.clipboard.getCopiedCells() != null) {
+
+ preInternalPaste();
+
+ PositionCoordinate coord = this.selectionLayer.getSelectionAnchor();
+ int pasteColumn = coord.getColumnPosition();
+ int pasteRow = coord.getRowPosition();
+
+ for (ILayerCell[] cells : this.clipboard.getCopiedCells()) {
+ for (ILayerCell cell : cells) {
+ if (EditUtils.isCellEditable(
+ this.selectionLayer,
+ command.configRegistry,
+ new PositionCoordinate(this.selectionLayer, pasteColumn, pasteRow))) {
+
+ this.selectionLayer.doCommand(
+ new UpdateDataCommand(
+ this.selectionLayer,
+ pasteColumn,
+ pasteRow,
+ getPasteValue(cell, pasteColumn, pasteRow)));
+ }
+
+ pasteColumn++;
+
+ if (pasteColumn >= this.selectionLayer.getColumnCount()) {
+ break;
+ }
+ }
+ pasteRow++;
+ pasteColumn = coord.getColumnPosition();
+ }
+
+ postInternalPaste();
+ }
+ return true;
+ }
+
+ /**
+ * Returns the value that should be pasted.
+ *
+ * @param cell
+ * The {@link ILayerCell} from which to retrieve the value to
+ * paste from.
+ * @param pasteColumn
+ * The column position of the cell to paste to.
+ * @param pasteRow
+ * The row position of the cell to paste to.
+ * @return The value that should be pasted.
+ */
+ protected Object getPasteValue(ILayerCell cell, int pasteColumn, int pasteRow) {
+ return cell.getDataValue();
+ }
+
+ /**
+ * Perform actions prior pasting values from the internal clipboard. E.g.
+ * disabling formula evaluation.
+ */
+ protected void preInternalPaste() {}
+
+ /**
+ * Perform actions after pasting values from the internal clipboard. E.g.
+ * enabling formula evaluation.
+ */
+ protected void postInternalPaste() {}
+
+ @Override
+ public Class<PasteDataCommand> getCommandClass() {
+ return PasteDataCommand.class;
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommand.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/PasteDataCommand.java
index 92ffc28f..444d800e 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommand.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/copy/command/PasteDataCommand.java
@@ -10,7 +10,7 @@
* Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
*
*****************************************************************************/
-package org.eclipse.nebula.widgets.nattable.formula.command;
+package org.eclipse.nebula.widgets.nattable.copy.command;
import org.eclipse.nebula.widgets.nattable.command.AbstractContextFreeCommand;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
@@ -20,17 +20,13 @@ import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
*
* @since 1.4
*
- * @see FormulaPasteDataCommandHandler
+ * @see InternalPasteDataCommandHandler
*/
-public class FormulaPasteDataCommand extends AbstractContextFreeCommand {
+public class PasteDataCommand extends AbstractContextFreeCommand {
- private final IConfigRegistry configRegistry;
+ public final IConfigRegistry configRegistry;
- public FormulaPasteDataCommand(IConfigRegistry configRegistry) {
+ public PasteDataCommand(IConfigRegistry configRegistry) {
this.configRegistry = configRegistry;
}
-
- public IConfigRegistry getConfigRegistry() {
- return this.configRegistry;
- }
}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleLayerPainter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleLayerPainter.java
new file mode 100644
index 00000000..4d731b85
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/FillHandleLayerPainter.java
@@ -0,0 +1,669 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.painter.layer.ILayerPainter;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayerPainter;
+import org.eclipse.nebula.widgets.nattable.style.BorderStyle;
+import org.eclipse.nebula.widgets.nattable.style.BorderStyle.LineStyleEnum;
+import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
+import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
+import org.eclipse.nebula.widgets.nattable.style.IStyle;
+import org.eclipse.nebula.widgets.nattable.style.SelectionStyleLabels;
+import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+
+/**
+ * Extended {@link SelectionLayerPainter} that renders an additional border
+ * around cells that are selected via fill handle. By default the additional
+ * fill handle border style is a green solid 2 pixel sized line. This
+ * {@link BorderStyle} can be configured via IConfigRegistry using the config
+ * label {@link FillHandleConfigAttributes#FILL_HANDLE_REGION_BORDER_STYLE}.
+ * <p>
+ * You can also register a different cell style for cells in the fill handle
+ * region by configuring a style for the label
+ * {@link SelectionStyleLabels#FILL_HANDLE_REGION}
+ * </p>
+ * <p>
+ * This {@link ILayerPainter} also renders a border around cells that are
+ * currently copied to the {@link InternalCellClipboard}. For this an
+ * {@link InternalCellClipboard} needs to be set to this painter. Note that a
+ * global instance of {@link InternalCellClipboard} can be retrieved via
+ * {@link NatTable#getInternalCellClipboard()}.
+ * </p>
+ *
+ * @see FillHandleConfigAttributes#FILL_HANDLE_REGION_BORDER_STYLE
+ * @see SelectionStyleLabels#FILL_HANDLE_REGION
+ *
+ * @since 1.4
+ */
+public class FillHandleLayerPainter extends SelectionLayerPainter {
+
+ /**
+ * The bounds of the current visible selection handle or <code>null</code>
+ * if no fill handle is currently rendered.
+ */
+ protected Rectangle handleBounds;
+
+ /**
+ * The {@link InternalCellClipboard} that is used to identify whether a cell
+ * is currently copied. Can be <code>null</code> to disable special
+ * rendering of copied cells.
+ */
+ protected InternalCellClipboard clipboard;
+
+ /**
+ * Create a SelectionLayerPainter that renders gray grid lines and uses the
+ * default clipping behavior.
+ */
+ public FillHandleLayerPainter() {
+ super();
+ }
+
+ /**
+ * Create an {@link FillHandleLayerPainter} that renders grid lines in the
+ * specified color and uses the default clipping behavior.
+ *
+ * @param gridColor
+ * The color that should be used to render the grid lines.
+ */
+ public FillHandleLayerPainter(final Color gridColor) {
+ super(gridColor);
+ }
+
+ /**
+ * Create an {@link FillHandleLayerPainter} that renders gray grid lines and
+ * uses the specified clipping behavior.
+ *
+ * @param clipLeft
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the left cell will be clipped, if set to
+ * <code>false</code> the right cell will be clipped. The default
+ * value is <code>false</code>.
+ * @param clipTop
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the top cell will be clipped, if set to
+ * <code>false</code> the bottom cell will be clipped. The
+ * default value is <code>false</code>.
+ */
+ public FillHandleLayerPainter(boolean clipLeft, boolean clipTop) {
+ this(GUIHelper.COLOR_GRAY, clipLeft, clipTop);
+ }
+
+ /**
+ * Create an {@link FillHandleLayerPainter} that renders grid lines in the
+ * specified color and uses the specified clipping behavior.
+ *
+ * @param gridColor
+ * The color that should be used to render the grid lines.
+ * @param clipLeft
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the left cell will be clipped, if set to
+ * <code>false</code> the right cell will be clipped. The default
+ * value is <code>false</code>.
+ * @param clipTop
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the top cell will be clipped, if set to
+ * <code>false</code> the bottom cell will be clipped. The
+ * default value is <code>false</code>.
+ */
+ public FillHandleLayerPainter(final Color gridColor, boolean clipLeft, boolean clipTop) {
+ super(gridColor, clipLeft, clipTop);
+ }
+
+ /**
+ * Create an {@link FillHandleLayerPainter} that renders gray grid lines and
+ * uses the default clipping behavior. It also renders a border around
+ * internally copied cells.
+ *
+ * @param clipboard
+ * The {@link InternalCellClipboard} that stores the cells that
+ * are currently copied.
+ */
+ public FillHandleLayerPainter(InternalCellClipboard clipboard) {
+ this.clipboard = clipboard;
+ }
+
+ /**
+ * Create an {@link FillHandleLayerPainter} that renders grid lines in the
+ * specified color and uses the default clipping behavior.
+ *
+ * @param clipboard
+ * The {@link InternalCellClipboard} that stores the cells that
+ * are currently copied.
+ * @param gridColor
+ * The color that should be used to render the grid lines.
+ */
+ public FillHandleLayerPainter(InternalCellClipboard clipboard, final Color gridColor) {
+ super(gridColor);
+ }
+
+ /**
+ * Create an {@link FillHandleLayerPainter} that renders gray grid lines and
+ * uses the specified clipping behavior.
+ *
+ * @param clipboard
+ * The {@link InternalCellClipboard} that stores the cells that
+ * are currently copied.
+ * @param clipLeft
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the left cell will be clipped, if set to
+ * <code>false</code> the right cell will be clipped. The default
+ * value is <code>false</code>.
+ * @param clipTop
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the top cell will be clipped, if set to
+ * <code>false</code> the bottom cell will be clipped. The
+ * default value is <code>false</code>.
+ */
+ public FillHandleLayerPainter(InternalCellClipboard clipboard,
+ boolean clipLeft, boolean clipTop) {
+ this(clipboard, GUIHelper.COLOR_GRAY, clipLeft, clipTop);
+ }
+
+ /**
+ * Create an {@link FillHandleLayerPainter} that renders grid lines in the
+ * specified color and uses the specified clipping behavior.
+ *
+ * @param clipboard
+ * The {@link InternalCellClipboard} that stores the cells that
+ * are currently copied.
+ * @param gridColor
+ * The color that should be used to render the grid lines.
+ * @param clipLeft
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the left cell will be clipped, if set to
+ * <code>false</code> the right cell will be clipped. The default
+ * value is <code>false</code>.
+ * @param clipTop
+ * Configure the rendering behavior when cells overlap. If set to
+ * <code>true</code> the top cell will be clipped, if set to
+ * <code>false</code> the bottom cell will be clipped. The
+ * default value is <code>false</code>.
+ */
+ public FillHandleLayerPainter(InternalCellClipboard clipboard, final Color gridColor,
+ boolean clipLeft, boolean clipTop) {
+ super(gridColor, clipLeft, clipTop);
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ public void paintLayer(
+ ILayer natLayer, GC gc,
+ int xOffset, int yOffset, Rectangle pixelRectangle,
+ IConfigRegistry configRegistry) {
+
+ Rectangle positionRectangle = getPositionRectangleFromPixelRectangle(natLayer, pixelRectangle);
+ int columnPositionOffset = positionRectangle.x;
+ int rowPositionOffset = positionRectangle.y;
+
+ super.paintLayer(natLayer, gc, xOffset, yOffset, pixelRectangle, configRegistry);
+
+ // Save gc settings
+ int originalLineStyle = gc.getLineStyle();
+ int originalLineWidth = gc.getLineWidth();
+ Color originalForeground = gc.getForeground();
+
+ // Apply border settings
+ applyHandleBorderStyle(gc, configRegistry);
+
+ int handleBorderWidth = gc.getLineWidth();
+ int startAdjustment = (handleBorderWidth == 1) ? 1 : 0;
+ int endAdjustment = (handleBorderWidth == 1) ? 1 : handleBorderWidth - 1;
+
+ ILayerCell fillHandleCell = null;
+
+ // Draw horizontal borders
+ for (int columnPosition = columnPositionOffset; columnPosition < columnPositionOffset + positionRectangle.width; columnPosition++) {
+
+ ILayerCell previousCell = null;
+ ILayerCell currentCell = null;
+ ILayerCell afterCell = null;
+ for (int rowPosition = rowPositionOffset; rowPosition < rowPositionOffset + positionRectangle.height; rowPosition++) {
+
+ currentCell = natLayer.getCellByPosition(columnPosition, rowPosition);
+ afterCell = natLayer.getCellByPosition(columnPosition, rowPosition + 1);
+
+ if (currentCell != null) {
+ Rectangle currentCellBounds = currentCell.getBounds();
+
+ if (isFillHandleRegion(currentCell)) {
+ int x0 = currentCellBounds.x;
+ int x1 = currentCellBounds.x + currentCellBounds.width;
+
+ int y = currentCellBounds.y - startAdjustment;
+
+ if (previousCell != null) {
+ Rectangle previousCellBounds = previousCell.getBounds();
+ x0 = Math.max(x0, previousCellBounds.x);
+ x1 = Math.min(x1, previousCellBounds.x + previousCellBounds.width);
+ }
+
+ if (previousCell == null || !isFillHandleRegion(previousCell)) {
+ gc.drawLine(
+ x0 - startAdjustment - (handleBorderWidth == 1 ? 0 : 1),
+ y,
+ x1 - startAdjustment,
+ y);
+ }
+
+ // check after
+ if (afterCell == null || (!isFillHandleRegion(afterCell))) {
+ Rectangle cellBounds = afterCell != null ? afterCell.getBounds() : currentCell.getBounds();
+
+ y = currentCellBounds.y + currentCellBounds.height - endAdjustment;
+
+ x0 = Math.max(x0, cellBounds.x);
+ x1 = Math.min(x1, cellBounds.x + cellBounds.width);
+
+ gc.drawLine(
+ x0 - startAdjustment,
+ y,
+ x1 - startAdjustment,
+ y);
+ }
+ } else {
+ // check if previous was selected to not override the
+ // border again
+ // this is necessary because of single cell updates
+ if (positionRectangle.width == 2 || positionRectangle.height == 2) {
+ if (afterCell != null && (isFillHandleRegion(afterCell))) {
+ Rectangle afterCellBounds = afterCell.getBounds();
+
+ int x0 = Math.max(
+ afterCellBounds.x,
+ currentCellBounds.x);
+ int x1 = Math.min(
+ afterCellBounds.x + afterCellBounds.width,
+ currentCellBounds.x + currentCellBounds.width);
+
+ int y = currentCellBounds.y + currentCellBounds.height - startAdjustment;
+
+ if (isFillHandleRegion(afterCell)) {
+ gc.drawLine(
+ x0 - startAdjustment,
+ y,
+ x1 - startAdjustment,
+ y);
+ }
+
+ }
+ }
+ }
+ }
+ previousCell = currentCell;
+
+ if (fillHandleCell == null && isFillHandleCell(currentCell)) {
+ fillHandleCell = currentCell;
+ }
+ }
+ }
+
+ // Draw vertical borders
+ for (int rowPosition = rowPositionOffset; rowPosition < rowPositionOffset + positionRectangle.height; rowPosition++) {
+
+ ILayerCell previousCell = null;
+ ILayerCell currentCell = null;
+ ILayerCell afterCell = null;
+ for (int columnPosition = columnPositionOffset; columnPosition < columnPositionOffset + positionRectangle.width; columnPosition++) {
+
+ currentCell = natLayer.getCellByPosition(columnPosition, rowPosition);
+ afterCell = natLayer.getCellByPosition(columnPosition + 1, rowPosition);
+
+ if (currentCell != null) {
+ Rectangle currentCellBounds = currentCell.getBounds();
+
+ if (isFillHandleRegion(currentCell)) {
+ int y0 = currentCellBounds.y;
+ int y1 = currentCellBounds.y + currentCellBounds.height;
+
+ int x = currentCellBounds.x - startAdjustment;
+
+ if (previousCell != null) {
+ Rectangle previousCellBounds = previousCell.getBounds();
+ y0 = Math.max(y0, previousCellBounds.y);
+ y1 = Math.min(y1, previousCellBounds.y + previousCellBounds.height);
+ }
+
+ if (previousCell == null || !isFillHandleRegion(previousCell)) {
+ gc.drawLine(
+ x,
+ y0 - startAdjustment,
+ x,
+ y1 - startAdjustment);
+ }
+
+ // check after
+ if (afterCell == null || !isFillHandleRegion(afterCell)) {
+ Rectangle cellBounds = afterCell != null ? afterCell.getBounds() : currentCell.getBounds();
+
+ x = currentCellBounds.x + currentCellBounds.width - endAdjustment;
+
+ y0 = Math.max(y0, cellBounds.y);
+ y1 = Math.min(y1, cellBounds.y + cellBounds.height);
+
+ gc.drawLine(
+ x,
+ y0 - startAdjustment,
+ x,
+ y1 - startAdjustment);
+ }
+ } else {
+ // check if previous was selected to not override the
+ // border again
+ // this is necessary because of single cell updates
+ if (positionRectangle.width == 2
+ || positionRectangle.height == 2) {
+ if (afterCell != null && isFillHandleRegion(afterCell)) {
+ Rectangle afterCellBounds = afterCell.getBounds();
+
+ int y0 = Math.max(afterCellBounds.y, currentCellBounds.y);
+ int y1 = Math.min(
+ afterCellBounds.y + afterCellBounds.height,
+ currentCellBounds.y + currentCellBounds.height);
+
+ int x = currentCellBounds.x + currentCellBounds.width - startAdjustment;
+
+ gc.drawLine(
+ x,
+ y0 - startAdjustment,
+ x,
+ y1 - startAdjustment);
+ }
+ }
+ }
+ }
+ previousCell = currentCell;
+ }
+ }
+
+ // Restore original gc settings
+ gc.setLineStyle(originalLineStyle);
+ gc.setLineWidth(originalLineWidth);
+ gc.setForeground(originalForeground);
+
+ // paint the border around the copied cells if a clipboard is set
+ if (this.clipboard != null && this.clipboard.getCopiedCells() != null) {
+ paintCopyBorder(natLayer, gc, xOffset, yOffset, pixelRectangle, configRegistry);
+ }
+
+ if (fillHandleCell != null) {
+ paintFillHandle(fillHandleCell, gc, xOffset, yOffset, configRegistry);
+ } else {
+ // set the local stored bounds to null as no handle is rendered and
+ // therefore event matchers shouldn't react anymore
+ this.handleBounds = null;
+ }
+ }
+
+ protected void paintFillHandle(
+ ILayerCell bottomRight, GC gc,
+ int xOffset, int yOffset,
+ IConfigRegistry configRegistry) {
+
+ // Save gc settings
+ int originalLineStyle = gc.getLineStyle();
+ int originalLineWidth = gc.getLineWidth();
+ Color originalForeground = gc.getForeground();
+ Color originalBackground = gc.getBackground();
+
+ Rectangle bounds = bottomRight.getBounds();
+
+ applyHandleStyle(gc, configRegistry);
+
+ this.handleBounds = new Rectangle(
+ bounds.x + bounds.width - GUIHelper.convertHorizontalPixelToDpi(4),
+ bounds.y + bounds.height - GUIHelper.convertHorizontalPixelToDpi(4),
+ GUIHelper.convertHorizontalPixelToDpi(6),
+ GUIHelper.convertVerticalPixelToDpi(6));
+
+ gc.fillRectangle(this.handleBounds);
+ gc.drawRectangle(this.handleBounds);
+
+ // Restore original gc settings
+ gc.setLineStyle(originalLineStyle);
+ gc.setLineWidth(originalLineWidth);
+ gc.setForeground(originalForeground);
+ gc.setBackground(originalBackground);
+ }
+
+ protected void paintCopyBorder(
+ ILayer natLayer, GC gc,
+ int xOffset, int yOffset, Rectangle pixelRectangle,
+ IConfigRegistry configRegistry) {
+
+ Rectangle positionRectangle = getPositionRectangleFromPixelRectangle(natLayer, pixelRectangle);
+ int columnPositionOffset = positionRectangle.x;
+ int rowPositionOffset = positionRectangle.y;
+
+ // Save gc settings
+ int originalLineStyle = gc.getLineStyle();
+ Color originalForeground = gc.getForeground();
+
+ applyCopyBorderStyle(gc, configRegistry);
+
+ int x0 = 0;
+ int x1 = 0;
+ int y0 = 0;
+ int y1 = 0;
+ boolean isFirst = true;
+ for (ILayerCell[] cells : this.clipboard.getCopiedCells()) {
+ for (ILayerCell cell : cells) {
+ if (isFirst) {
+ x0 = cell.getBounds().x;
+ x1 = cell.getBounds().x + cell.getBounds().width;
+ y0 = cell.getBounds().y;
+ y1 = cell.getBounds().y + cell.getBounds().height;
+ isFirst = false;
+ } else {
+ x0 = Math.min(x0, cell.getBounds().x);
+ x1 = Math.max(x1, cell.getBounds().x + cell.getBounds().width);
+ y0 = Math.min(y0, cell.getBounds().y);
+ y1 = Math.max(y1, cell.getBounds().y + cell.getBounds().height);
+ }
+ }
+ }
+
+ x0 += xOffset - columnPositionOffset;
+ x1 += xOffset - columnPositionOffset;
+ y0 += yOffset - rowPositionOffset;
+ y1 += yOffset - rowPositionOffset;
+
+ gc.drawLine(x0, y0, x0, y1);
+ gc.drawLine(x0, y0, x1, y0);
+ gc.drawLine(x0, y1, x1, y1);
+ gc.drawLine(x1, y0, x1, y1);
+
+ // Restore original gc settings
+ gc.setLineStyle(originalLineStyle);
+ gc.setForeground(originalForeground);
+ }
+
+ /**
+ *
+ * @param cell
+ * The {@link ILayerCell} to check.
+ * @return <code>true</code> if the cell is part of the fill handle region,
+ * <code>false</code> if not.
+ */
+ protected boolean isFillHandleRegion(ILayerCell cell) {
+ return cell.getConfigLabels().hasLabel(SelectionStyleLabels.FILL_HANDLE_REGION);
+ }
+
+ /**
+ *
+ * @param cell
+ * The {@link ILayerCell} to check.
+ * @return <code>true</code> if the cell is the bottom right cell in a fill
+ * region, <code>false</code> if not.
+ */
+ protected boolean isFillHandleCell(ILayerCell cell) {
+ return cell.getConfigLabels().hasLabel(SelectionStyleLabels.FILL_HANDLE_CELL);
+ }
+
+ /**
+ * Apply the border style that should be used to render the border for cells
+ * that are currently part of the fill handle region. Checks the
+ * {@link IConfigRegistry} for a registered {@link IStyle} for the
+ * {@link FillHandleConfigAttributes#FILL_HANDLE_REGION_BORDER_STYLE} label.
+ * If none is registered, a default line style will be used to render the
+ * border.
+ *
+ * @param gc
+ * The current {@link GC} that is used for rendering.
+ * @param configRegistry
+ * The {@link IConfigRegistry} to retrieve the style information
+ * from.
+ */
+ protected void applyHandleBorderStyle(GC gc, IConfigRegistry configRegistry) {
+ BorderStyle borderStyle = configRegistry.getConfigAttribute(
+ FillHandleConfigAttributes.FILL_HANDLE_REGION_BORDER_STYLE,
+ DisplayMode.NORMAL);
+
+ // if there is no border style configured, use the default
+ if (borderStyle == null) {
+ gc.setLineStyle(SWT.LINE_SOLID);
+ gc.setLineWidth(2);
+ gc.setForeground(GUIHelper.getColor(0, 125, 10));
+ } else {
+ gc.setLineStyle(LineStyleEnum.toSWT(borderStyle.getLineStyle()));
+ gc.setLineWidth(borderStyle.getThickness());
+ gc.setForeground(borderStyle.getColor());
+ }
+ }
+
+ /**
+ * Apply the style for rendering the fill handle. If the
+ * {@link IConfigRegistry} is <code>null</code> or does not contain
+ * configurations for styling the fill handle, the default style is used.
+ * The default is a dark green square with a white solid one pixel width
+ * line.
+ *
+ * @param gc
+ * The {@link GC} to set the styles to.
+ * @param configRegistry
+ * The {@link IConfigRegistry} needed to determine the configured
+ * fill handle style. Can be <code>null</code> which results in
+ * using the default style of a green square with white 1 pixel
+ * solid line border.
+ */
+ protected void applyHandleStyle(GC gc, IConfigRegistry configRegistry) {
+ if (configRegistry != null) {
+ BorderStyle borderStyle = configRegistry.getConfigAttribute(
+ FillHandleConfigAttributes.FILL_HANDLE_BORDER_STYLE,
+ DisplayMode.NORMAL);
+
+ Color color = configRegistry.getConfigAttribute(
+ FillHandleConfigAttributes.FILL_HANDLE_COLOR,
+ DisplayMode.NORMAL);
+
+ if (color != null) {
+ gc.setBackground(color);
+ } else {
+ // set default color
+ gc.setBackground(GUIHelper.getColor(0, 125, 10));
+ }
+
+ if (borderStyle != null) {
+ gc.setLineStyle(LineStyleEnum.toSWT(borderStyle.getLineStyle()));
+ gc.setLineWidth(borderStyle.getThickness());
+ gc.setForeground(borderStyle.getColor());
+ } else {
+ gc.setLineStyle(SWT.LINE_SOLID);
+ gc.setLineWidth(1);
+ gc.setForeground(GUIHelper.COLOR_WHITE);
+ }
+ } else {
+ // set default border style
+ gc.setLineStyle(SWT.LINE_SOLID);
+ gc.setLineWidth(1);
+ gc.setForeground(GUIHelper.COLOR_WHITE);
+ // set default color
+ gc.setBackground(GUIHelper.getColor(0, 125, 10));
+ }
+ }
+
+ /**
+ * Apply the border style that should be used to render the border for cells
+ * that are currently copied to the {@link InternalCellClipboard}. Checks
+ * the {@link IConfigRegistry} for a registered {@link IStyle} for the
+ * {@link SelectionStyleLabels#COPY_BORDER_STYLE} label. If none is
+ * registered, a default line style will be used to render the border.
+ *
+ * @param gc
+ * The current {@link GC} that is used for rendering.
+ * @param configRegistry
+ * The {@link IConfigRegistry} to retrieve the style information
+ * from.
+ */
+ protected void applyCopyBorderStyle(GC gc, IConfigRegistry configRegistry) {
+ IStyle cellStyle = configRegistry.getConfigAttribute(
+ CellConfigAttributes.CELL_STYLE,
+ DisplayMode.NORMAL,
+ SelectionStyleLabels.COPY_BORDER_STYLE);
+ BorderStyle borderStyle = cellStyle != null ? cellStyle.getAttributeValue(CellStyleAttributes.BORDER_STYLE) : null;
+
+ // if there is no border style configured, use the default
+ if (borderStyle == null) {
+ gc.setLineStyle(SWT.LINE_DASH);
+ gc.setLineDash(new int[] { 2, 2 });
+ gc.setForeground(GUIHelper.COLOR_BLACK);
+ } else {
+ gc.setLineStyle(LineStyleEnum.toSWT(borderStyle.getLineStyle()));
+ gc.setLineWidth(borderStyle.getThickness());
+ gc.setForeground(borderStyle.getColor());
+ }
+ }
+
+ /**
+ *
+ * @return The bounds of the current visible selection handle or
+ * <code>null</code> if no fill handle is currently rendered.
+ */
+ public Rectangle getSelectionHandleBounds() {
+ return this.handleBounds;
+ }
+
+ /**
+ *
+ * @return The {@link InternalCellClipboard} that is used to identify
+ * whether a cell is currently copied or <code>null</code> if
+ * special rendering of copied cells is disabled.
+ */
+ public InternalCellClipboard getClipboard() {
+ return this.clipboard;
+ }
+
+ /**
+ *
+ * @param clipboard
+ * The {@link InternalCellClipboard} that should be used to
+ * identify whether a cell is currently copied or
+ * <code>null</code> to disable special rendering of copied
+ * cells.
+ */
+ public void setClipboard(InternalCellClipboard clipboard) {
+ this.clipboard = clipboard;
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleCursorAction.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleCursorAction.java
new file mode 100644
index 00000000..c2ad0ef1
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleCursorAction.java
@@ -0,0 +1,104 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.action;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfiguration;
+import org.eclipse.nebula.widgets.nattable.ui.action.IMouseAction;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Action to enable a custom cursor (small cross) on NatTable. Used when moving
+ * over the fill handle of a current selection.
+ *
+ * @see FillHandleConfiguration
+ *
+ * @since 1.4
+ */
+public class FillHandleCursorAction implements IMouseAction {
+
+ private Cursor fillHandleCursor;
+
+ @Override
+ public void run(NatTable natTable, MouseEvent event) {
+ if (this.fillHandleCursor == null) {
+ PaletteData paletteData = new PaletteData(new RGB[] {
+ new RGB(0, 0, 0), new RGB(255, 255, 255)
+ });
+ ImageData sourceData = new ImageData(16, 16, 1, paletteData);
+ ImageData maskData = new ImageData(16, 16, 1, paletteData);
+
+ byte[] cursorSource = new byte[] {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ };
+
+ byte[] cursorMask = new byte[] {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ sourceData.setPixels(0, 0, 255, cursorSource, 0);
+ maskData.setPixels(0, 0, 255, cursorMask, 0);
+
+ this.fillHandleCursor = new Cursor(Display.getDefault(), sourceData, maskData, 7, 7);
+
+ natTable.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ FillHandleCursorAction.this.fillHandleCursor.dispose();
+ }
+
+ });
+ }
+
+ natTable.setCursor(this.fillHandleCursor);
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleDragMode.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleDragMode.java
new file mode 100644
index 00000000..d6d2b131
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/action/FillHandleDragMode.java
@@ -0,0 +1,324 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.action;
+
+import java.util.Date;
+
+import org.eclipse.nebula.widgets.nattable.Messages;
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataToClipboardCommand;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommand.FillHandleOperation;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillDirection;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
+import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
+import org.eclipse.nebula.widgets.nattable.ui.action.IDragMode;
+import org.eclipse.nebula.widgets.nattable.viewport.command.ViewportDragCommand;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * The {@link IDragMode} that is registered to get triggered for dragging the
+ * fill drag handle.
+ *
+ * @since 1.4
+ */
+public class FillHandleDragMode implements IDragMode {
+
+ protected MouseEvent startEvent;
+ protected Point startIndex;
+ protected MoveDirectionEnum direction;
+
+ protected SelectionLayer selectionLayer;
+
+ protected ILayerCell selectionCell;
+
+ protected InternalCellClipboard clipboard;
+
+ protected Menu menu;
+
+ /**
+ *
+ * @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.
+ */
+ public FillHandleDragMode(SelectionLayer selectionLayer, InternalCellClipboard clipboard) {
+ if (selectionLayer == null) {
+ throw new IllegalArgumentException("SelectionLayer can not be null"); //$NON-NLS-1$
+ }
+ this.selectionLayer = selectionLayer;
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ public void mouseDown(NatTable natTable, MouseEvent event) {
+ PositionCoordinate[] selectedCellPositions = this.selectionLayer.getSelectedCellPositions();
+ if (selectedCellPositions.length > 0) {
+ this.startEvent = event;
+
+ this.selectionCell = this.selectionLayer.getCellByPosition(
+ selectedCellPositions[0].columnPosition,
+ selectedCellPositions[0].rowPosition);
+
+ this.startIndex = new Point(
+ this.selectionCell.getColumnIndex(),
+ this.selectionCell.getRowIndex());
+ }
+ }
+
+ @Override
+ public void mouseMove(NatTable natTable, MouseEvent event) {
+ Rectangle clientArea = natTable.getClientAreaProvider().getClientArea();
+
+ int x = event.x;
+ int y = event.y;
+
+ MoveDirectionEnum horizontal = MoveDirectionEnum.NONE;
+ if (event.x < 0) {
+ horizontal = MoveDirectionEnum.LEFT;
+ x = 0;
+ } else if (event.x > clientArea.width) {
+ horizontal = MoveDirectionEnum.RIGHT;
+ x = clientArea.width;
+ }
+
+ MoveDirectionEnum vertical = MoveDirectionEnum.NONE;
+ if (event.y < 0) {
+ vertical = MoveDirectionEnum.UP;
+ y = 0;
+ } else if (event.y > clientArea.height) {
+ vertical = MoveDirectionEnum.DOWN;
+ y = clientArea.height;
+ }
+
+ if (natTable.doCommand(new ViewportDragCommand(horizontal, vertical))) {
+
+ int selectedColumnPosition = natTable.getColumnPositionByX(x);
+ int selectedRowPosition = natTable.getRowPositionByY(y);
+
+ int selectedColumnIndex = natTable.getColumnIndexByPosition(selectedColumnPosition);
+ int selectedRowIndex = natTable.getRowIndexByPosition(selectedRowPosition);
+
+ if (selectedColumnPosition > -1 && selectedRowPosition > -1) {
+ Rectangle actionBounds = null;
+
+ int xStart = this.startIndex.x;
+ int yStart = this.startIndex.y;
+
+ // only increase range in one direction
+ int xDiff = selectedColumnIndex - this.startIndex.x;
+ if (xDiff < 0) {
+ xDiff *= -1;
+ }
+ xDiff++;
+
+ int yDiff = selectedRowIndex - this.startIndex.y;
+ if (yDiff < 0) {
+ yDiff *= -1;
+ }
+ yDiff++;
+
+ int width = -1;
+ int height = -1;
+
+ // check if only drag operations in one direction are supported
+ FillDirection direction = natTable.getConfigRegistry().getConfigAttribute(
+ FillHandleConfigAttributes.ALLOWED_FILL_DIRECTION,
+ DisplayMode.NORMAL,
+ this.selectionCell.getConfigLabels().getLabels());
+
+ if (direction == null) {
+ direction = FillDirection.BOTH;
+ }
+
+ if (direction == FillDirection.VERTICAL
+ || (direction == FillDirection.BOTH && yDiff >= xDiff)) {
+ height = Math.max(yDiff, this.selectionLayer.getSelectedRowCount());
+ width = this.selectionLayer.getSelectedColumnPositions().length;
+ this.direction = MoveDirectionEnum.DOWN;
+ if ((selectedRowIndex - this.startIndex.y) < 0) {
+ yStart = selectedRowIndex;
+ height = yDiff + this.selectionLayer.getSelectedRowCount() - 1;
+ this.direction = MoveDirectionEnum.UP;
+ }
+ } else {
+ height = this.selectionLayer.getSelectedRowCount();
+ width = Math.max(xDiff, this.selectionLayer.getSelectedColumnPositions().length);
+ this.direction = MoveDirectionEnum.RIGHT;
+ if ((selectedColumnIndex - this.startIndex.x) < 0) {
+ xStart = selectedColumnIndex;
+ width = xDiff + this.selectionLayer.getSelectedColumnPositions().length - 1;
+ this.direction = MoveDirectionEnum.LEFT;
+ }
+ }
+
+ actionBounds = new Rectangle(
+ xStart,
+ yStart,
+ width,
+ height);
+
+ this.selectionLayer.setFillHandleRegion(actionBounds);
+ natTable.redraw();
+ }
+ }
+ }
+
+ @Override
+ public void mouseUp(final NatTable natTable, MouseEvent event) {
+ if (natTable.doCommand(
+ new CopyDataToClipboardCommand(
+ "\t", //$NON-NLS-1$
+ System.getProperty("line.separator"), //$NON-NLS-1$
+ natTable.getConfigRegistry()))) {
+
+ if (this.clipboard != null) {
+ if (showMenu(natTable)) {
+ openMenu(natTable);
+ } else {
+ natTable.doCommand(
+ new FillHandlePasteCommand(
+ FillHandleOperation.COPY,
+ this.direction,
+ natTable.getConfigRegistry()));
+ reset(natTable);
+ }
+ } else {
+ natTable.doCommand(
+ new FillHandlePasteCommand(
+ FillHandleOperation.COPY,
+ this.direction,
+ natTable.getConfigRegistry()));
+ reset(natTable);
+ }
+ } else {
+ reset(natTable);
+ }
+ }
+
+ /**
+ * Check if the menu should be shown for selecting copy or series fill
+ * operation.
+ *
+ * @param natTable
+ * The NatTable instance on which the operation is performed.
+ * @return <code>true</code> if the menu should be shown, <code>false</code>
+ * if not.
+ */
+ protected boolean showMenu(final NatTable natTable) {
+ Class<?> type = null;
+ for (ILayerCell[] cells : this.clipboard.getCopiedCells()) {
+ for (ILayerCell cell : cells) {
+ if (cell.getDataValue() == null) {
+ return false;
+ } else {
+ if (type == null) {
+ type = cell.getDataValue().getClass();
+ if (!type.isAssignableFrom(Number.class)
+ && !type.isAssignableFrom(Date.class)) {
+ return false;
+ }
+ } else if (type != cell.getDataValue().getClass()) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Opens a menu that enables a user to select whether values should simply
+ * be copied or if a series should be filled.
+ *
+ * @param natTable
+ * The NatTable instance on which the operation is performed.
+ */
+ protected void openMenu(final NatTable natTable) {
+ // lazily create the menu
+ if (this.menu == null || this.menu.isDisposed()) {
+ this.menu = new Menu(natTable);
+ MenuItem copyItem = new MenuItem(this.menu, SWT.PUSH);
+ copyItem.setText(Messages.getLocalizedMessage("%FillHandleDragMode.menu.item.copy")); //$NON-NLS-1$
+ copyItem.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ natTable.doCommand(
+ new FillHandlePasteCommand(
+ FillHandleOperation.COPY,
+ FillHandleDragMode.this.direction,
+ natTable.getConfigRegistry()));
+ reset(natTable);
+ }
+ });
+ MenuItem seriesItem = new MenuItem(this.menu, SWT.PUSH);
+ seriesItem.setText(Messages.getLocalizedMessage("%FillHandleDragMode.menu.item.series")); //$NON-NLS-1$
+ seriesItem.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ natTable.doCommand(
+ new FillHandlePasteCommand(
+ FillHandleOperation.SERIES,
+ FillHandleDragMode.this.direction,
+ natTable.getConfigRegistry()));
+ reset(natTable);
+ }
+ });
+
+ // add the dispose listener for disposing the menu
+ natTable.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ FillHandleDragMode.this.menu.dispose();
+ }
+ });
+ }
+
+ this.menu.setVisible(true);
+ }
+
+ /**
+ * Reset the {@link FillHandleDragMode} states, the fill handle region in
+ * the {@link SelectionLayer} and redraw the given NatTable.
+ *
+ * @param natTable
+ * The NatTable instance on which the operation is performed.
+ */
+ protected void reset(NatTable natTable) {
+ this.selectionCell = null;
+ this.startEvent = null;
+ this.startIndex = null;
+ this.direction = null;
+ this.selectionLayer.setFillHandleRegion(null);
+ this.clipboard.clear();
+ natTable.redraw();
+ }
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommand.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommand.java
new file mode 100644
index 00000000..6a4de56d
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommand.java
@@ -0,0 +1,86 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.command;
+
+import org.eclipse.nebula.widgets.nattable.command.AbstractContextFreeCommand;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
+
+/**
+ * Command to trigger pasting data via fill handle drag operation.
+ *
+ * @since 1.4
+ */
+public class FillHandlePasteCommand extends AbstractContextFreeCommand {
+
+ /**
+ * The operation that should be triggered to fill the cells.
+ */
+ public enum FillHandleOperation {
+ /**
+ * Copy the current selected values to the cells in the fill handle
+ * area.
+ */
+ COPY,
+ /**
+ * Fill the cells in the fill handle area by creating a series based on
+ * the current selected values.
+ */
+ SERIES
+ }
+
+ /**
+ * The {@link FillHandleOperation} that should be triggered.
+ */
+ public final FillHandleOperation operation;
+ /**
+ * The direction in which the fill handle was dragged. Necessary for the
+ * series operation to calculate the values.
+ */
+ public final MoveDirectionEnum direction;
+ /**
+ * The {@link IConfigRegistry} needed to dynamically read configurations on
+ * command handling, e.g. editable state.
+ */
+ public final IConfigRegistry configRegistry;
+
+ /**
+ * Create a FillHandlePasteCommand that triggers a copy operation.
+ *
+ * @param configRegistry
+ * The {@link IConfigRegistry} needed to dynamically read
+ * configurations on command handling, e.g. editable state.
+ */
+ public FillHandlePasteCommand(IConfigRegistry configRegistry) {
+ this(FillHandleOperation.COPY, null, configRegistry);
+ }
+
+ /**
+ * Create a FillHandlePasteCommand.
+ *
+ * @param operation
+ * The {@link FillHandleOperation} that should be triggered.
+ * @param direction
+ * The direction in which the fill handle was dragged. Necessary
+ * for the series operation to calculate the values.
+ * @param configRegistry
+ * The {@link IConfigRegistry} needed to dynamically read
+ * configurations on command handling, e.g. editable state.
+ */
+ public FillHandlePasteCommand(
+ FillHandleOperation operation, MoveDirectionEnum direction, IConfigRegistry configRegistry) {
+ this.operation = operation;
+ this.direction = direction;
+ this.configRegistry = configRegistry;
+ }
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommandHandler.java
new file mode 100644
index 00000000..a8b637e0
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/command/FillHandlePasteCommandHandler.java
@@ -0,0 +1,577 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.command;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.edit.command.EditUtils;
+import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
+import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
+import org.eclipse.swt.graphics.Rectangle;
+
+/**
+ * Command handler for the {@link FillHandlePasteCommand}.
+ *
+ * @see FillHandlePasteCommand
+ *
+ * @since 1.4
+ */
+public class FillHandlePasteCommandHandler implements ILayerCommandHandler<FillHandlePasteCommand> {
+
+ protected SelectionLayer selectionLayer;
+ protected InternalCellClipboard clipboard;
+
+ /**
+ * Creates a {@link FillHandlePasteCommandHandler}
+ *
+ * @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.
+ */
+ public FillHandlePasteCommandHandler(
+ SelectionLayer selectionLayer,
+ InternalCellClipboard clipboard) {
+
+ this.selectionLayer = selectionLayer;
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ public boolean doCommand(ILayer targetLayer, FillHandlePasteCommand command) {
+ if (this.clipboard.getCopiedCells() != null) {
+ int pasteColumn = -1;
+ int pasteRow = -1;
+ int pasteWidth = this.clipboard.getCopiedCells().length;
+ int pasteHeight = this.clipboard.getCopiedCells()[0].length;
+ Rectangle handleRegion = this.selectionLayer.getFillHandleRegion();
+ if (handleRegion != null) {
+ pasteColumn = handleRegion.x;
+ pasteRow = handleRegion.y;
+ pasteWidth = handleRegion.width;
+ pasteHeight = handleRegion.height;
+ } else {
+ PositionCoordinate coord = this.selectionLayer.getSelectionAnchor();
+ pasteColumn = coord.getColumnPosition();
+ pasteRow = coord.getRowPosition();
+ }
+
+ int pasteStartColumn = pasteColumn;
+
+ int rowStartAdjustment = 0;
+ if (command.direction == MoveDirectionEnum.UP) {
+ rowStartAdjustment = pasteHeight % this.clipboard.getCopiedCells().length;
+ }
+
+ int columnStartAdjustment = 0;
+ if (command.direction == MoveDirectionEnum.LEFT) {
+ columnStartAdjustment = pasteWidth % this.clipboard.getCopiedCells()[0].length;
+ }
+
+ for (int i = 0; i < pasteHeight; i++) {
+ ILayerCell[] cells = this.clipboard.getCopiedCells()[(i + rowStartAdjustment) % this.clipboard.getCopiedCells().length];
+ for (int j = 0; j < pasteWidth; j++) {
+ ILayerCell cell = cells[(j + columnStartAdjustment) % this.clipboard.getCopiedCells()[0].length];
+
+ Object cellValue = getPasteValue(cell, command, pasteColumn, pasteRow);
+
+ if (EditUtils.isCellEditable(
+ this.selectionLayer,
+ command.configRegistry,
+ new PositionCoordinate(this.selectionLayer,
+ pasteColumn,
+ pasteRow))) {
+ this.selectionLayer.doCommand(new UpdateDataCommand(this.selectionLayer, pasteColumn, pasteRow, cellValue));
+ }
+
+ pasteColumn++;
+
+ if (pasteColumn >= this.selectionLayer.getColumnCount()) {
+ break;
+ }
+ }
+
+ pasteRow++;
+ pasteColumn = pasteStartColumn;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the value from the given cell that should be pasted to the given
+ * position.
+ *
+ * @param cell
+ * The cell that is copied.
+ * @param command
+ * The command that contains the necessary information for the
+ * paste operation.
+ * @param toColumn
+ * The column position of the cell to which the value should be
+ * pasted.
+ * @param toRow
+ * The row position of the cell to which the value should be
+ * pasted.
+ * @return The value that should be set to the given position.
+ */
+ protected Object getPasteValue(ILayerCell cell, FillHandlePasteCommand command, int toColumn, int toRow) {
+ switch (command.operation) {
+ case COPY:
+ return cell.getDataValue();
+ case SERIES:
+ Object diff = 0;
+ if (command.direction == MoveDirectionEnum.LEFT || command.direction == MoveDirectionEnum.RIGHT) {
+ diff = calculateVerticalDiff(cell, toColumn, command.configRegistry);
+ } else if (command.direction == MoveDirectionEnum.UP || command.direction == MoveDirectionEnum.DOWN) {
+ diff = calculateHorizontalDiff(cell, toRow, command.configRegistry);
+ }
+ Object value = cell.getDataValue();
+ // if we can not determine a common diff value we perform a copy
+ if (diff != null) {
+ if (value instanceof Byte) {
+ byte result = (byte) (((Byte) value).byteValue() + (Byte) diff);
+ return result;
+ } else if (value instanceof Short) {
+ short result = (short) (((Short) value).shortValue() + (Short) diff);
+ return result;
+ } else if (value instanceof Integer) {
+ return (Integer) value + (Integer) diff;
+ } else if (value instanceof Long) {
+ return (Long) value + (Long) diff;
+ } else if (value instanceof Float) {
+ return (Float) value + (Float) diff;
+ } else if (value instanceof Double) {
+ return (Double) value + (Double) diff;
+ } else if (value instanceof BigInteger) {
+ return ((BigInteger) value).add((BigInteger) diff);
+ } else if (value instanceof BigDecimal) {
+ return ((BigDecimal) value).add((BigDecimal) diff);
+ } else if (value instanceof Date) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime((Date) value);
+ cal.add(getIncrementDateField(cell, command.configRegistry), (Integer) diff);
+ return cal.getTime();
+ }
+ }
+ // if the value is neither a number nor a date simply return the
+ // value as we can't calculate a series for other data types
+ return value;
+ default:
+ return cell.getDataValue();
+ }
+ }
+
+ protected Number calculateHorizontalDiff(ILayerCell cell, int toRow, IConfigRegistry configRegistry) {
+ Class<?> type = cell.getDataValue() != null ? cell.getDataValue().getClass() : null;
+
+ ILayerCell[][] cells = this.clipboard.getCopiedCells();
+ int rowDiff = toRow - cell.getRowIndex();
+ if (cells.length == 1) {
+ return getCastValue(rowDiff, type);
+ } else if (type != null) {
+ int columnArrayIndex = cell.getColumnIndex() - this.clipboard.getCopiedCells()[0][0].getColumnIndex();
+ if (type.isAssignableFrom(Byte.class)) {
+ Byte diff = calculateByteDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ Byte temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateByteDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ byte result = (byte) (diff * rowDiff);
+ return result;
+ } else if (type.isAssignableFrom(Short.class)) {
+ Short diff = calculateShortDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ Short temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateShortDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ short result = (short) (diff * rowDiff);
+ return result;
+ } else if (type.isAssignableFrom(Integer.class)) {
+ Integer diff = calculateIntDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ Integer temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateIntDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff * rowDiff;
+ } else if (type.isAssignableFrom(Long.class)) {
+ Long diff = calculateLongDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ Long temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateLongDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff * rowDiff;
+ } else if (type.isAssignableFrom(Float.class)) {
+ Float diff = calculateFloatDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ Float temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateFloatDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return BigDecimal.valueOf(diff).multiply(BigDecimal.valueOf(rowDiff)).floatValue();
+ } else if (type.isAssignableFrom(Double.class)) {
+ Double diff = calculateDoubleDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ Double temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateDoubleDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return BigDecimal.valueOf(diff).multiply(BigDecimal.valueOf(rowDiff)).doubleValue();
+ } else if (type.isAssignableFrom(BigInteger.class)) {
+ BigInteger diff = calculateBigIntegerDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ BigInteger temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateBigIntegerDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff.multiply(BigInteger.valueOf(rowDiff));
+ } else if (type.isAssignableFrom(BigDecimal.class)) {
+ BigDecimal diff = calculateBigDecimalDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex]);
+ if (diff == null) {
+ return null;
+ }
+ BigDecimal temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateBigDecimalDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff.multiply(BigDecimal.valueOf(rowDiff));
+ } else if (type.isAssignableFrom(Date.class)) {
+ Integer diff = calculateDateDiff(cells[1][columnArrayIndex], cells[0][columnArrayIndex], configRegistry);
+ if (diff == null) {
+ return null;
+ }
+ Integer temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateDateDiff(cells[i][columnArrayIndex], cells[i - 1][columnArrayIndex], configRegistry);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff * rowDiff;
+ }
+ }
+ return null;
+ }
+
+ protected Number calculateVerticalDiff(ILayerCell cell, int toColumn, IConfigRegistry configRegistry) {
+ Class<?> type = cell.getDataValue() != null ? cell.getDataValue().getClass() : null;
+
+ ILayerCell[][] cells = this.clipboard.getCopiedCells();
+ int columnDiff = toColumn - cell.getColumnIndex();
+ int rowArrayIndex = cell.getRowIndex() - this.clipboard.getCopiedCells()[0][0].getRowIndex();
+ if (cells[rowArrayIndex].length == 1) {
+ return getCastValue(columnDiff, type);
+ } else if (type != null) {
+ if (type.isAssignableFrom(Byte.class)) {
+ Byte diff = calculateByteDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ Byte temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateByteDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ byte result = (byte) (diff * columnDiff);
+ return result;
+ } else if (type.isAssignableFrom(Short.class)) {
+ Short diff = calculateShortDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ Short temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateShortDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ short result = (short) (diff * columnDiff);
+ return result;
+ } else if (type.isAssignableFrom(Integer.class)) {
+ Integer diff = calculateIntDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ Integer temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateIntDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff * columnDiff;
+ } else if (type.isAssignableFrom(Long.class)) {
+ Long diff = calculateLongDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ Long temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateLongDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff * columnDiff;
+ } else if (type.isAssignableFrom(Float.class)) {
+ Float diff = calculateFloatDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ Float temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateFloatDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return BigDecimal.valueOf(diff).multiply(BigDecimal.valueOf(columnDiff)).floatValue();
+ } else if (type.isAssignableFrom(Double.class)) {
+ Double diff = calculateDoubleDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ Double temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateDoubleDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return BigDecimal.valueOf(diff).multiply(BigDecimal.valueOf(columnDiff)).doubleValue();
+ } else if (type.isAssignableFrom(BigInteger.class)) {
+ BigInteger diff = calculateBigIntegerDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ BigInteger temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateBigIntegerDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff.multiply(BigInteger.valueOf(columnDiff));
+ } else if (type.isAssignableFrom(BigDecimal.class)) {
+ BigDecimal diff = calculateBigDecimalDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0]);
+ if (diff == null) {
+ return null;
+ }
+ BigDecimal temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateBigDecimalDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1]);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff.multiply(BigDecimal.valueOf(columnDiff));
+ } else if (type.isAssignableFrom(Date.class)) {
+ Integer diff = calculateDateDiff(cells[rowArrayIndex][1], cells[rowArrayIndex][0], configRegistry);
+ if (diff == null) {
+ return null;
+ }
+ Integer temp = diff;
+ for (int i = 1; i < cells.length; i++) {
+ temp = calculateDateDiff(cells[rowArrayIndex][i], cells[rowArrayIndex][i - 1], configRegistry);
+ if (temp == null || !temp.equals(diff)) {
+ return null;
+ }
+ }
+ return diff * columnDiff;
+ }
+ }
+ return null;
+ }
+
+ protected Number getCastValue(int diff, Class<?> type) {
+ if (type != null) {
+ if (type.isAssignableFrom(Byte.class)) {
+ return (byte) diff;
+ } else if (type.isAssignableFrom(Short.class)) {
+ return (short) diff;
+ } else if (type.isAssignableFrom(Long.class)) {
+ return (long) diff;
+ } else if (type.isAssignableFrom(Float.class)) {
+ return (float) diff;
+ } else if (type.isAssignableFrom(Double.class)) {
+ return (double) diff;
+ } else if (type.isAssignableFrom(BigInteger.class)) {
+ return BigInteger.valueOf(diff);
+ } else if (type.isAssignableFrom(BigDecimal.class)) {
+ return BigDecimal.valueOf(diff);
+ }
+ }
+ return diff;
+ }
+
+ protected Byte calculateByteDiff(ILayerCell c1, ILayerCell c2) {
+ return (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof Byte) || !(c2.getDataValue() instanceof Byte))
+ ? null : (byte) (((Byte) c1.getDataValue()) - ((Byte) c2.getDataValue()));
+ }
+
+ protected Short calculateShortDiff(ILayerCell c1, ILayerCell c2) {
+ return (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof Short) || !(c2.getDataValue() instanceof Short))
+ ? null : (short) (((Short) c1.getDataValue()) - ((Short) c2.getDataValue()));
+ }
+
+ protected Integer calculateIntDiff(ILayerCell c1, ILayerCell c2) {
+ return (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof Integer) || !(c2.getDataValue() instanceof Integer))
+ ? null : (Integer) (c1.getDataValue()) - (Integer) (c2.getDataValue());
+ }
+
+ protected Long calculateLongDiff(ILayerCell c1, ILayerCell c2) {
+ return (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof Long) || !(c2.getDataValue() instanceof Long))
+ ? null : ((Long) c1.getDataValue()) - ((Long) c2.getDataValue());
+ }
+
+ protected Float calculateFloatDiff(ILayerCell c1, ILayerCell c2) {
+ if (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof Float) || !(c2.getDataValue() instanceof Float)) {
+ return null;
+ }
+
+ // Use BigDecimal for exact calculations because of floating point
+ // arithmetic issues. Because of that we also use the String constructor
+ // of BigDecimal.
+ BigDecimal v1 = new BigDecimal(c1.getDataValue().toString());
+ BigDecimal v2 = new BigDecimal(c2.getDataValue().toString());
+ return v1.subtract(v2).floatValue();
+ }
+
+ protected Double calculateDoubleDiff(ILayerCell c1, ILayerCell c2) {
+ if (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof Double) || !(c2.getDataValue() instanceof Double)) {
+ return null;
+ }
+
+ // Use BigDecimal for exact calculations because of floating point
+ // arithmetic issues. Because of that we also use the String constructor
+ // of BigDecimal.
+ BigDecimal v1 = new BigDecimal(c1.getDataValue().toString());
+ BigDecimal v2 = new BigDecimal(c2.getDataValue().toString());
+ return v1.subtract(v2).doubleValue();
+ }
+
+ protected BigInteger calculateBigIntegerDiff(ILayerCell c1, ILayerCell c2) {
+ return (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof BigInteger) || !(c2.getDataValue() instanceof BigInteger))
+ ? null : ((BigInteger) c1.getDataValue()).subtract((BigInteger) c2.getDataValue());
+ }
+
+ protected BigDecimal calculateBigDecimalDiff(ILayerCell c1, ILayerCell c2) {
+ return (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof BigDecimal) || !(c2.getDataValue() instanceof BigDecimal))
+ ? null : ((BigDecimal) c1.getDataValue()).subtract((BigDecimal) c2.getDataValue());
+ }
+
+ protected Integer calculateDateDiff(ILayerCell c1, ILayerCell c2, IConfigRegistry configRegistry) {
+ if (c1.getDataValue() == null || c2.getDataValue() == null
+ || !(c1.getDataValue() instanceof Date) || !(c2.getDataValue() instanceof Date)) {
+ return null;
+ }
+
+ int dateField = getIncrementDateField(c1, configRegistry);
+
+ Calendar cal1 = Calendar.getInstance();
+ cal1.setTime((Date) c1.getDataValue());
+ int fieldValue1 = cal1.get(dateField);
+
+ Calendar cal2 = Calendar.getInstance();
+ cal2.setTime((Date) c2.getDataValue());
+ int fieldValue2 = cal2.get(dateField);
+
+ return fieldValue1 - fieldValue2;
+ }
+
+ protected int getIncrementDateField(ILayerCell cell, IConfigRegistry configRegistry) {
+ Integer dateField = configRegistry.getConfigAttribute(
+ FillHandleConfigAttributes.INCREMENT_DATE_FIELD,
+ DisplayMode.NORMAL,
+ cell.getConfigLabels().getLabels());
+
+ if (dateField == null) {
+ dateField = Calendar.DATE;
+ }
+
+ return dateField;
+ }
+
+ @Override
+ public Class<FillHandlePasteCommand> getCommandClass() {
+ return FillHandlePasteCommand.class;
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillDirection.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillDirection.java
new file mode 100644
index 00000000..0ac287bf
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillDirection.java
@@ -0,0 +1,23 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.config;
+
+/**
+ * Enumeration that is used to configure which directions are allowed for using
+ * the fill drag handle.
+ *
+ * @since 1.4
+ */
+public enum FillDirection {
+ HORIZONTAL, VERTICAL, BOTH
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfigAttributes.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfigAttributes.java
new file mode 100644
index 00000000..c623ac8b
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfigAttributes.java
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.config;
+
+import java.util.Calendar;
+
+import org.eclipse.nebula.widgets.nattable.style.BorderStyle;
+import org.eclipse.nebula.widgets.nattable.style.ConfigAttribute;
+import org.eclipse.swt.graphics.Color;
+
+/**
+ * This interface contains {@link ConfigAttribute}s that can be used to
+ * configure the fill handle behavior.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ *
+ * @since 1.4
+ */
+public interface FillHandleConfigAttributes {
+
+ /**
+ * ConfigAttribute to configure the line style used to render a special
+ * border on dragging the fill handle.
+ */
+ ConfigAttribute<BorderStyle> FILL_HANDLE_REGION_BORDER_STYLE = new ConfigAttribute<BorderStyle>();
+
+ /**
+ * ConfigAttribute to configure the border style of the fill handle itself.
+ */
+ ConfigAttribute<BorderStyle> FILL_HANDLE_BORDER_STYLE = new ConfigAttribute<BorderStyle>();
+
+ /**
+ * ConfigAttribute to configure the color of the fill handle.
+ */
+ ConfigAttribute<Color> FILL_HANDLE_COLOR = new ConfigAttribute<Color>();
+
+ /**
+ * ConfigAttribute to configure the date field that should be incremented
+ * when inserting a series via fill handle. Fields from the {@link Calendar}
+ * class should be used for configuration.
+ */
+ ConfigAttribute<Integer> INCREMENT_DATE_FIELD = new ConfigAttribute<Integer>();
+
+ /**
+ * ConfigAttribute to configure the directions that are allowed for the fill
+ * handle. If nothing is specified {@link FillDirection#BOTH} will be used
+ * implicitly.
+ */
+ ConfigAttribute<FillDirection> ALLOWED_FILL_DIRECTION = new ConfigAttribute<FillDirection>();
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfiguration.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfiguration.java
new file mode 100644
index 00000000..95707d4f
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/config/FillHandleConfiguration.java
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.config;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.config.AbstractLayerConfiguration;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.copy.command.InternalCopyDataCommandHandler;
+import org.eclipse.nebula.widgets.nattable.fillhandle.FillHandleLayerPainter;
+import org.eclipse.nebula.widgets.nattable.fillhandle.action.FillHandleCursorAction;
+import org.eclipse.nebula.widgets.nattable.fillhandle.action.FillHandleDragMode;
+import org.eclipse.nebula.widgets.nattable.fillhandle.command.FillHandlePasteCommandHandler;
+import org.eclipse.nebula.widgets.nattable.fillhandle.event.FillHandleEventMatcher;
+import org.eclipse.nebula.widgets.nattable.fillhandle.event.FillHandleMarkupListener;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.ui.action.ClearCursorAction;
+import org.eclipse.nebula.widgets.nattable.ui.action.NoOpMouseAction;
+import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
+import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
+
+/**
+ * Default configuration for fill handle functionality. Registers the
+ * corresponding painter, command handler and ui bindings.
+ *
+ * @since 1.4
+ */
+public class FillHandleConfiguration extends AbstractLayerConfiguration<NatTable> {
+
+ protected SelectionLayer selectionLayer;
+
+ protected FillHandleLayerPainter painter;
+
+ protected InternalCellClipboard clipboard;
+
+ /**
+ * Create the FillHandleConfiguration for a NatTable.
+ *
+ * @param selectionLayer
+ * The {@link SelectionLayer} needed to determine the current
+ * selection on which the fill handle will be rendered. Can not
+ * be <code>null</code>.
+ */
+ public FillHandleConfiguration(SelectionLayer selectionLayer) {
+ if (selectionLayer == null) {
+ throw new IllegalArgumentException("SelectionLayer can not be null"); //$NON-NLS-1$
+ }
+ this.selectionLayer = selectionLayer;
+ }
+
+ @Override
+ public void configureTypedLayer(NatTable natTable) {
+ // initialization works here because configureLayer() is executed before
+ // configureUiBindings()
+ this.clipboard = natTable.getInternalCellClipboard();
+
+ this.painter = new FillHandleLayerPainter();
+ this.selectionLayer.setLayerPainter(this.painter);
+
+ this.selectionLayer.addLayerListener(new FillHandleMarkupListener(this.selectionLayer));
+
+ this.selectionLayer.registerCommandHandler(
+ new InternalCopyDataCommandHandler(this.selectionLayer, this.clipboard));
+ this.selectionLayer.registerCommandHandler(
+ new FillHandlePasteCommandHandler(this.selectionLayer, this.clipboard));
+ }
+
+ @Override
+ public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
+ FillHandleEventMatcher matcher = new FillHandleEventMatcher(this.painter);
+
+ // Mouse move
+ // Show fill handle cursor
+ uiBindingRegistry.registerFirstMouseMoveBinding(
+ matcher,
+ new FillHandleCursorAction());
+ uiBindingRegistry.registerMouseMoveBinding(
+ new MouseEventMatcher(),
+ new ClearCursorAction());
+
+ // Mouse drag
+ // trigger the handle drag operations
+ uiBindingRegistry.registerFirstMouseDragMode(
+ matcher,
+ new FillHandleDragMode(this.selectionLayer, this.clipboard));
+
+ // Mouse click
+ // ensure no selection is triggered on mouse down on the handle
+ uiBindingRegistry.registerFirstMouseDownBinding(
+ matcher,
+ new NoOpMouseAction());
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleEventMatcher.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleEventMatcher.java
new file mode 100644
index 00000000..03ee943e
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleEventMatcher.java
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.event;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.fillhandle.FillHandleLayerPainter;
+import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
+import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
+import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * Matcher that returns <code>true</code> in case the mouse moves over the fill
+ * handle rendered by the {@link FillHandleLayerPainter}.
+ *
+ * @since 1.4
+ */
+public class FillHandleEventMatcher extends MouseEventMatcher {
+
+ protected FillHandleLayerPainter fillHandlePainter;
+
+ /**
+ * Create a {@link FillHandleEventMatcher} that reacts when the mouse is
+ * moved over the fill handle rendered by the given
+ * {@link FillHandleLayerPainter}.
+ *
+ * @param fillHandlePainter
+ * The {@link FillHandleLayerPainter} that should be used to
+ * determine the bounds of the fill handle. Can not be
+ * <code>null</code>.
+ */
+ public FillHandleEventMatcher(FillHandleLayerPainter fillHandlePainter) {
+ if (fillHandlePainter == null) {
+ throw new IllegalArgumentException("FillHandleLayerPainter can not be null"); //$NON-NLS-1$
+ }
+ this.fillHandlePainter = fillHandlePainter;
+ }
+
+ @Override
+ public boolean matches(NatTable natTable, MouseEvent event, LabelStack regionLabels) {
+ if (this.fillHandlePainter.getSelectionHandleBounds() != null) {
+ return this.fillHandlePainter.getSelectionHandleBounds().contains(event.x, event.y);
+ }
+ return false;
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleMarkupListener.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleMarkupListener.java
new file mode 100644
index 00000000..84e4d569
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/fillhandle/event/FillHandleMarkupListener.java
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.fillhandle.event;
+
+import org.eclipse.nebula.widgets.nattable.layer.ILayerListener;
+import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.event.ISelectionEvent;
+
+/**
+ * {@link ILayerListener} that will trigger the markup in the
+ * {@link SelectionLayer} of the cell that will hold the fill handle.
+ *
+ * @since 1.4
+ */
+public class FillHandleMarkupListener implements ILayerListener {
+
+ private final SelectionLayer selectionLayer;
+
+ public FillHandleMarkupListener(SelectionLayer selectionLayer) {
+ this.selectionLayer = selectionLayer;
+ }
+
+ @Override
+ public void handleLayerEvent(ILayerEvent event) {
+ if (event instanceof ISelectionEvent) {
+ FillHandleMarkupListener.this.selectionLayer.markFillHandleCell();
+ }
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/FormulaLayerPainter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/CopySelectionLayerPainter.java
index 1a09fe0c..88bc8a97 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/FormulaLayerPainter.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/CopySelectionLayerPainter.java
@@ -16,7 +16,6 @@ import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
-import org.eclipse.nebula.widgets.nattable.formula.config.FormulaStyleLabels;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
@@ -26,6 +25,7 @@ import org.eclipse.nebula.widgets.nattable.style.BorderStyle.LineStyleEnum;
import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.style.IStyle;
+import org.eclipse.nebula.widgets.nattable.style.SelectionStyleLabels;
import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
@@ -42,25 +42,39 @@ import org.eclipse.swt.graphics.Rectangle;
*
* @since 1.4
*/
-public class FormulaLayerPainter extends SelectionLayerPainter {
+public class CopySelectionLayerPainter extends SelectionLayerPainter {
protected InternalCellClipboard clipboard;
/**
- * Create a FormulaLayerPainter that renders gray grid lines and uses the
- * default clipping behavior.
+ * Create a {@link CopySelectionLayerPainter} that renders gray grid lines
+ * and uses the default clipping behavior.
*
* @param clipboard
* The {@link InternalCellClipboard} that stores the cells that
* are currently copied.
*/
- public FormulaLayerPainter(InternalCellClipboard clipboard) {
+ public CopySelectionLayerPainter(InternalCellClipboard clipboard) {
this.clipboard = clipboard;
}
/**
- * Create a FormulaLayerPainter that renders grid lines in the specified
- * color and uses the specified clipping behavior.
+ * Create a {@link CopySelectionLayerPainter} that renders gray grid lines
+ * and uses the default clipping behavior.
+ *
+ * @param clipboard
+ * The {@link InternalCellClipboard} that stores the cells that
+ * are currently copied.
+ * @param gridColor
+ * The color that should be used to render the grid lines.
+ */
+ public CopySelectionLayerPainter(InternalCellClipboard clipboard, final Color gridColor) {
+ this.clipboard = clipboard;
+ }
+
+ /**
+ * Create a {@link CopySelectionLayerPainter} that renders grid lines in the
+ * specified color and uses the specified clipping behavior.
*
* @param clipboard
* The {@link InternalCellClipboard} that stores the cells that
@@ -78,14 +92,14 @@ public class FormulaLayerPainter extends SelectionLayerPainter {
* <code>false</code> the bottom cell will be clipped. The
* default value is <code>false</code>.
*/
- public FormulaLayerPainter(InternalCellClipboard clipboard, final Color gridColor, boolean clipLeft, boolean clipTop) {
+ public CopySelectionLayerPainter(InternalCellClipboard clipboard, final Color gridColor, boolean clipLeft, boolean clipTop) {
super(gridColor, clipLeft, clipTop);
this.clipboard = clipboard;
}
/**
- * Create a FormulaLayerPainter that renders gray grid lines and uses the
- * specified clipping behavior.
+ * Create a {@link CopySelectionLayerPainter} that renders gray grid lines
+ * and uses the specified clipping behavior.
*
* @param clipboard
* The {@link InternalCellClipboard} that stores the cells that
@@ -101,7 +115,7 @@ public class FormulaLayerPainter extends SelectionLayerPainter {
* <code>false</code> the bottom cell will be clipped. The
* default value is <code>false</code>.
*/
- public FormulaLayerPainter(InternalCellClipboard clipboard, boolean clipLeft, boolean clipTop) {
+ public CopySelectionLayerPainter(InternalCellClipboard clipboard, boolean clipLeft, boolean clipTop) {
this(clipboard, GUIHelper.COLOR_GRAY, clipLeft, clipTop);
}
@@ -135,8 +149,7 @@ public class FormulaLayerPainter extends SelectionLayerPainter {
y0 = cell.getBounds().y;
y1 = cell.getBounds().y + cell.getBounds().height;
isFirst = false;
- }
- else {
+ } else {
x0 = Math.min(x0, cell.getBounds().x);
x1 = Math.max(x1, cell.getBounds().x + cell.getBounds().width);
y0 = Math.min(y0, cell.getBounds().y);
@@ -165,7 +178,7 @@ public class FormulaLayerPainter extends SelectionLayerPainter {
* Apply the border style that should be used to render the border for cells
* that are currently copied to the {@link InternalCellClipboard}. Checks
* the {@link ConfigRegistry} for a registered {@link IStyle} for the
- * {@link FormulaStyleLabels#COPY_BORDER_STYLE} label. If none is
+ * {@link SelectionStyleLabels#COPY_BORDER_STYLE} label. If none is
* registered, a default line style will be used to render the border.
*
* @param gc
@@ -178,7 +191,7 @@ public class FormulaLayerPainter extends SelectionLayerPainter {
IStyle cellStyle = configRegistry.getConfigAttribute(
CellConfigAttributes.CELL_STYLE,
DisplayMode.NORMAL,
- FormulaStyleLabels.COPY_BORDER_STYLE);
+ SelectionStyleLabels.COPY_BORDER_STYLE);
BorderStyle borderStyle = cellStyle != null ? cellStyle.getAttributeValue(CellStyleAttributes.BORDER_STYLE) : null;
// if there is no border style configured, use the default
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/FormulaFillHandleDragMode.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/FormulaFillHandleDragMode.java
new file mode 100644
index 00000000..fda7295d
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/action/FormulaFillHandleDragMode.java
@@ -0,0 +1,87 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.formula.action;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
+import org.eclipse.nebula.widgets.nattable.fillhandle.action.FillHandleDragMode;
+import org.eclipse.nebula.widgets.nattable.formula.FormulaDataProvider;
+import org.eclipse.nebula.widgets.nattable.formula.command.DisableFormulaEvaluationCommand;
+import org.eclipse.nebula.widgets.nattable.formula.command.EnableFormulaEvaluationCommand;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+
+/**
+ * Specialized {@link FillHandleDragMode} that also opens the dialog in case of
+ * String values that can be converted to {@link BigDecimal} values using the
+ * {@link FormulaDataProvider}.
+ *
+ * @since 1.4
+ */
+public class FormulaFillHandleDragMode extends FillHandleDragMode {
+
+ 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 determine
+ * whether a value is a number value.
+ */
+ public FormulaFillHandleDragMode(SelectionLayer selectionLayer, InternalCellClipboard clipboard,
+ FormulaDataProvider dataProvider) {
+ super(selectionLayer, clipboard);
+ this.dataProvider = dataProvider;
+ }
+
+ @Override
+ protected boolean showMenu(final NatTable natTable) {
+ natTable.doCommand(new DisableFormulaEvaluationCommand());
+
+ try {
+ Class<?> type = null;
+ for (ILayerCell[] cells : this.clipboard.getCopiedCells()) {
+ for (ILayerCell cell : cells) {
+ if (cell.getDataValue() == null) {
+ return false;
+ } else {
+ if (type == null) {
+ type = cell.getDataValue().getClass();
+ if (!type.isAssignableFrom(Number.class)
+ && !type.isAssignableFrom(Date.class)
+ && (type.isAssignableFrom(String.class)
+ && !this.dataProvider.getFormulaParser().isNumber((String) cell.getDataValue()))) {
+ return false;
+ }
+ } else if (type != cell.getDataValue().getClass()) {
+ return false;
+ }
+ }
+ }
+ }
+ } finally {
+ natTable.doCommand(new EnableFormulaEvaluationCommand());
+ }
+
+ return true;
+ }
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaCopyDataCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaCopyDataCommandHandler.java
index 2493aea8..d6a1503a 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaCopyDataCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaCopyDataCommandHandler.java
@@ -14,8 +14,7 @@ package org.eclipse.nebula.widgets.nattable.formula.command;
import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler;
-import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataToClipboardCommand;
-import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.copy.command.InternalCopyDataCommandHandler;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
/**
@@ -24,9 +23,7 @@ import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
*
* @since 1.4
*/
-public class FormulaCopyDataCommandHandler extends CopyDataCommandHandler {
-
- private InternalCellClipboard clipboard;
+public class FormulaCopyDataCommandHandler extends InternalCopyDataCommandHandler {
/**
* Creates an instance that only checks the {@link SelectionLayer} for the
@@ -41,65 +38,16 @@ public class FormulaCopyDataCommandHandler extends CopyDataCommandHandler {
* copy/paste operations within a NatTable instance.
*/
public FormulaCopyDataCommandHandler(SelectionLayer selectionLayer, InternalCellClipboard clipboard) {
- super(selectionLayer);
- this.clipboard = clipboard;
+ super(selectionLayer, clipboard);
}
@Override
- public boolean doCommand(CopyDataToClipboardCommand command) {
- // copy to clipboard
- super.doCommand(command);
-
- // only copy if contiguous cells
- ILayerCell[][] cells = assembleCopiedDataStructure();
- if (!isDiscontiguousSelection(cells)) {
- this.selectionLayer.doCommand(new DisableFormulaEvaluationCommand());
-
- // remember cells to copy to support paste of formulas
- this.clipboard.setCopiedCells(assembleCopiedDataStructure());
-
- this.selectionLayer.doCommand(new EnableFormulaEvaluationCommand());
- }
-
- return true;
+ protected void preInternalCopy() {
+ this.selectionLayer.doCommand(new DisableFormulaEvaluationCommand());
}
- /**
- * Performs a check whether the selection contains discontinuous cells. In
- * such a case copy/paste operations are not possible.
- *
- * @param selectedCells
- * The selection to check.
- * @return <code>true</code> if the selection contains discontinuous cells,
- * therefore copy/paste operations are not possible,
- * <code>false</code> if a valid selection with continuous cells is
- * checked
- */
- protected boolean isDiscontiguousSelection(ILayerCell[][] selectedCells) {
- int previousColumnIndex = -1;
- int previousRowIndex = -1;
- for (ILayerCell[] cells : selectedCells) {
- for (ILayerCell cell : cells) {
- if (cell != null) {
- if (previousColumnIndex >= 0) {
- int diff = cell.getColumnIndex() - previousColumnIndex;
- if (diff > 1) {
- return true;
- }
- }
- previousColumnIndex = cell.getColumnIndex();
- }
- }
-
- if (previousRowIndex >= 0) {
- int diff = cells[0].getRowIndex() - previousRowIndex;
- if (diff > 1) {
- return true;
- }
- }
- previousRowIndex = cells[0].getRowIndex();
- }
- return false;
+ @Override
+ protected void postInternalCopy() {
+ this.selectionLayer.doCommand(new EnableFormulaEvaluationCommand());
}
-
}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaFillHandlePasteCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaFillHandlePasteCommandHandler.java
new file mode 100644
index 00000000..2914e6f9
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaFillHandlePasteCommandHandler.java
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * 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.getDataValue();
+ 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.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;
+ }
+
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommandHandler.java
index 0c38e518..455bc1a2 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/command/FormulaPasteDataCommandHandler.java
@@ -12,92 +12,72 @@
*****************************************************************************/
package org.eclipse.nebula.widgets.nattable.formula.command;
-import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler;
-import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
-import org.eclipse.nebula.widgets.nattable.edit.command.EditUtils;
-import org.eclipse.nebula.widgets.nattable.edit.command.UpdateDataCommand;
+import org.eclipse.nebula.widgets.nattable.copy.command.InternalPasteDataCommandHandler;
+import org.eclipse.nebula.widgets.nattable.copy.command.PasteDataCommand;
import org.eclipse.nebula.widgets.nattable.formula.FormulaDataProvider;
import org.eclipse.nebula.widgets.nattable.formula.function.FunctionException;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
/**
- * {@link ILayerCommandHandler} for handling {@link FormulaPasteDataCommand}s.
- * Uses the {@link InternalCellClipboard} and transforms formulas to match the
- * new position.
+ * {@link ILayerCommandHandler} for handling {@link PasteDataCommand}s. Uses the
+ * {@link InternalCellClipboard} and transforms formulas to match the new
+ * position.
*
* @since 1.4
*/
-public class FormulaPasteDataCommandHandler extends AbstractLayerCommandHandler<FormulaPasteDataCommand> {
+public class FormulaPasteDataCommandHandler extends InternalPasteDataCommandHandler {
- protected SelectionLayer selectionLayer;
protected FormulaDataProvider dataProvider;
- protected InternalCellClipboard clipboard;
+ /**
+ *
+ * @param selectionLayer
+ * {@link SelectionLayer} that is needed to determine the
+ * position to paste the values to.
+ * @param dataProvider
+ * the {@link FormulaDataProvider} that is needed to perform
+ * formula related functions on pasting data.
+ * @param clipboard
+ * The {@link InternalCellClipboard} that contains the values
+ * that should be pasted.
+ */
public FormulaPasteDataCommandHandler(
SelectionLayer selectionLayer,
- FormulaDataProvider dataProvider,
- InternalCellClipboard clipboard) {
+ InternalCellClipboard clipboard,
+ FormulaDataProvider dataProvider) {
- this.selectionLayer = selectionLayer;
+ super(selectionLayer, clipboard);
this.dataProvider = dataProvider;
- this.clipboard = clipboard;
}
@Override
- protected boolean doCommand(FormulaPasteDataCommand 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());
-
- PositionCoordinate coord = this.selectionLayer.getSelectionAnchor();
- int pasteColumn = coord.getColumnPosition();
- int pasteRow = coord.getRowPosition();
-
- for (ILayerCell[] cells : this.clipboard.getCopiedCells()) {
- for (ILayerCell cell : cells) {
- Object cellValue = cell.getDataValue();
- if (cellValue != null && this.dataProvider.getFormulaParser().isFunction(cellValue.toString())) {
- try {
- cellValue = this.dataProvider.getFormulaParser().updateReferences(
- cellValue.toString(), cell.getColumnPosition(), cell.getRowPosition(), pasteColumn, pasteRow);
- } catch (FunctionException e) {
- if (this.dataProvider.getErrorReporter() != null) {
- this.dataProvider.getErrorReporter().addFormulaError(pasteColumn, pasteRow, e.getLocalizedMessage());
- }
- cellValue = e.getErrorMarkup();
- }
- }
-
- if (EditUtils.isCellEditable(
- this.selectionLayer,
- command.getConfigRegistry(),
- new PositionCoordinate(this.selectionLayer, pasteColumn, pasteRow))) {
-
- this.selectionLayer.doCommand(new UpdateDataCommand(this.selectionLayer, pasteColumn, pasteRow, cellValue));
- }
-
- pasteColumn++;
-
- if (pasteColumn >= this.selectionLayer.getColumnCount()) {
- break;
- }
+ protected Object getPasteValue(ILayerCell cell, int pasteColumn, int pasteRow) {
+ Object cellValue = cell.getDataValue();
+ if (cellValue != null && this.dataProvider.getFormulaParser().isFunction(cellValue.toString())) {
+ try {
+ cellValue = this.dataProvider.getFormulaParser().updateReferences(
+ cellValue.toString(), cell.getColumnPosition(), cell.getRowPosition(), pasteColumn, pasteRow);
+ } catch (FunctionException e) {
+ if (this.dataProvider.getErrorReporter() != null) {
+ this.dataProvider.getErrorReporter().addFormulaError(pasteColumn, pasteRow, e.getLocalizedMessage());
}
- pasteRow++;
- pasteColumn = coord.getColumnPosition();
+ cellValue = e.getErrorMarkup();
}
-
- this.selectionLayer.doCommand(new EnableFormulaEvaluationCommand());
}
- return true;
+ return cellValue;
+ }
+
+ @Override
+ protected void preInternalPaste() {
+ this.selectionLayer.doCommand(new DisableFormulaEvaluationCommand());
}
@Override
- public Class<FormulaPasteDataCommand> getCommandClass() {
- return FormulaPasteDataCommand.class;
+ protected void postInternalPaste() {
+ this.selectionLayer.doCommand(new EnableFormulaEvaluationCommand());
}
}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/DefaultFormulaConfiguration.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/DefaultFormulaConfiguration.java
index 183d1f65..7bda0015 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/DefaultFormulaConfiguration.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/DefaultFormulaConfiguration.java
@@ -19,19 +19,23 @@ import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
import org.eclipse.nebula.widgets.nattable.copy.InternalClipboardStructuralChangeListener;
import org.eclipse.nebula.widgets.nattable.copy.action.ClearClipboardAction;
+import org.eclipse.nebula.widgets.nattable.copy.action.PasteDataAction;
+import org.eclipse.nebula.widgets.nattable.copy.action.PasteOrMoveSelectionAction;
import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
import org.eclipse.nebula.widgets.nattable.edit.action.DeleteSelectionAction;
import org.eclipse.nebula.widgets.nattable.edit.command.DeleteSelectionCommandHandler;
import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor;
import org.eclipse.nebula.widgets.nattable.export.command.ExportCommandHandler;
+import org.eclipse.nebula.widgets.nattable.fillhandle.FillHandleLayerPainter;
+import org.eclipse.nebula.widgets.nattable.fillhandle.event.FillHandleEventMatcher;
import org.eclipse.nebula.widgets.nattable.formula.FormulaDataProvider;
import org.eclipse.nebula.widgets.nattable.formula.FormulaEditDisplayConverter;
import org.eclipse.nebula.widgets.nattable.formula.FormulaResultDisplayConverter;
-import org.eclipse.nebula.widgets.nattable.formula.action.FormulaPasteDataAction;
-import org.eclipse.nebula.widgets.nattable.formula.action.PasteOrMoveSelectionAction;
+import org.eclipse.nebula.widgets.nattable.formula.action.FormulaFillHandleDragMode;
import org.eclipse.nebula.widgets.nattable.formula.command.DisableFormulaEvaluationCommandHandler;
import org.eclipse.nebula.widgets.nattable.formula.command.EnableFormulaEvaluationCommandHandler;
import org.eclipse.nebula.widgets.nattable.formula.command.FormulaCopyDataCommandHandler;
+import org.eclipse.nebula.widgets.nattable.formula.command.FormulaFillHandlePasteCommandHandler;
import org.eclipse.nebula.widgets.nattable.formula.command.FormulaPasteDataCommandHandler;
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
@@ -41,6 +45,7 @@ import org.eclipse.nebula.widgets.nattable.style.BorderStyle.LineStyleEnum;
import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.style.IStyle;
+import org.eclipse.nebula.widgets.nattable.style.SelectionStyleLabels;
import org.eclipse.nebula.widgets.nattable.style.Style;
import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
import org.eclipse.nebula.widgets.nattable.ui.matcher.KeyEventMatcher;
@@ -98,7 +103,7 @@ public class DefaultFormulaConfiguration implements IConfiguration {
CellConfigAttributes.CELL_STYLE,
copyBorderStyle,
DisplayMode.NORMAL,
- FormulaStyleLabels.COPY_BORDER_STYLE);
+ SelectionStyleLabels.COPY_BORDER_STYLE);
}
@Override
@@ -111,7 +116,7 @@ public class DefaultFormulaConfiguration implements IConfiguration {
// ui binding to perform a paste action on pressing CTRL+V
uiBindingRegistry.registerFirstKeyBinding(
new KeyEventMatcher(SWT.MOD1, 'v'),
- new FormulaPasteDataAction());
+ new PasteDataAction());
// ui binding to perform paste or selection movement on ENTER
uiBindingRegistry.registerFirstKeyBinding(
@@ -122,6 +127,14 @@ public class DefaultFormulaConfiguration implements IConfiguration {
uiBindingRegistry.registerFirstKeyBinding(
new KeyEventMatcher(SWT.NONE, SWT.ESC),
new ClearClipboardAction(this.clipboard));
+
+ // Mouse drag
+ // trigger the handle drag operations
+ // Note: we ensure a FillHandleLayerPainter is set in configureLayer
+ uiBindingRegistry.registerFirstMouseDragMode(
+ new FillHandleEventMatcher((FillHandleLayerPainter) this.selectionLayer.getLayerPainter()),
+ new FormulaFillHandleDragMode(this.selectionLayer, this.clipboard, this.dataProvider));
+
}
@Override
@@ -145,8 +158,20 @@ public class DefaultFormulaConfiguration implements IConfiguration {
// changes
this.selectionLayer.addLayerListener(new InternalClipboardStructuralChangeListener(this.clipboard));
+ // add the layer painter that renders a border around copied cells
+ if (!(this.selectionLayer.getLayerPainter() instanceof FillHandleLayerPainter)) {
+ this.selectionLayer.setLayerPainter(new FillHandleLayerPainter(this.clipboard));
+ } else {
+ // ensure the clipboard is set
+ ((FillHandleLayerPainter) this.selectionLayer.getLayerPainter()).setClipboard(this.clipboard);
+ }
+
// register special copy+paste command handlers
- layer.registerCommandHandler(new FormulaCopyDataCommandHandler(this.selectionLayer, this.clipboard));
- layer.registerCommandHandler(new FormulaPasteDataCommandHandler(this.selectionLayer, this.dataProvider, this.clipboard));
+ layer.registerCommandHandler(
+ new FormulaCopyDataCommandHandler(this.selectionLayer, this.clipboard));
+ layer.registerCommandHandler(
+ new FormulaPasteDataCommandHandler(this.selectionLayer, this.clipboard, this.dataProvider));
+ layer.registerCommandHandler(
+ new FormulaFillHandlePasteCommandHandler(this.selectionLayer, this.clipboard, this.dataProvider));
}
} \ No newline at end of file
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/FormulaStyleLabels.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/FormulaStyleLabels.java
deleted file mode 100644
index a3bdbf44..00000000
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/formula/config/FormulaStyleLabels.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*****************************************************************************
- * Copyright (c) 2015 CEA LIST.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
- *
- *****************************************************************************/
-package org.eclipse.nebula.widgets.nattable.formula.config;
-
-import org.eclipse.nebula.widgets.nattable.formula.FormulaLayerPainter;
-import org.eclipse.nebula.widgets.nattable.formula.command.FormulaCopyDataCommandHandler;
-import org.eclipse.nebula.widgets.nattable.formula.command.FormulaPasteDataCommandHandler;
-
-/**
- * @since 1.4
- */
-public class FormulaStyleLabels {
-
- /**
- * Style label for configuring the copy border.
- *
- * @see FormulaLayerPainter
- * @see FormulaCopyDataCommandHandler
- * @see FormulaPasteDataCommandHandler
- */
- public static final String COPY_BORDER_STYLE = "copyBorderStyle"; //$NON-NLS-1$
-
-}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages.properties b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages.properties
index 41a7d8f7..0285d9a0 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages.properties
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages.properties
@@ -176,3 +176,6 @@ FormulaParser.error.parenthesisNotClosed=Parenthesis not closed
FormulaParser.error.functionParameterNotOpened=Parameter list not opened
FormulaParser.error.functionParameterNotClosed=Parameter list not closed
FormulaParser.error.instantiation=Could not instantiate FunctionValue: {0}
+
+FillHandleDragMode.menu.item.copy=Copy
+FillHandleDragMode.menu.item.series=Series \ No newline at end of file
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages_de.properties b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages_de.properties
index e2f7dbd2..cd6ce1fa 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages_de.properties
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/messages_de.properties
@@ -175,3 +175,6 @@ FormulaParser.error.parenthesisNotOpened=Klammer nicht ge\u00F6ffnet
FormulaParser.error.parenthesisNotClosed=Klammer nicht geschlossen
FormulaParser.error.functionParameterNotOpened=Parameterliste nicht ge\u00F6ffnet
FormulaParser.error.functionParameterNotClosed=Parameterliste nicht geschlossen
+
+FillHandleDragMode.menu.item.copy=Kopieren
+FillHandleDragMode.menu.item.series=Datenreihe auff\u00FCllen \ No newline at end of file
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionConfigAttributes.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionConfigAttributes.java
new file mode 100644
index 00000000..2f060075
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionConfigAttributes.java
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.nebula.widgets.nattable.selection;
+
+import org.eclipse.nebula.widgets.nattable.style.BorderStyle;
+import org.eclipse.nebula.widgets.nattable.style.ConfigAttribute;
+
+/**
+ * This interface contains {@link ConfigAttribute}s that can be used to
+ * configure selection rendering, like the border style of the active selection.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ *
+ * @since 1.4
+ */
+public interface SelectionConfigAttributes {
+
+ /**
+ * ConfigAttribute to configure the line style used to render the selection
+ * border around selected cells. This is the line that surrounds an active
+ * selection. By default this is the black dotted one pixel line.
+ */
+ ConfigAttribute<BorderStyle> SELECTION_GRID_LINE_STYLE = new ConfigAttribute<BorderStyle>();
+}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java
index d1bf62c3..2fb6b311 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2013, 2014 Original authors and others.
+ * Copyright (c) 2012, 2015 Original authors and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -27,6 +27,8 @@ import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
import org.eclipse.nebula.widgets.nattable.coordinate.Range;
import org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler;
import org.eclipse.nebula.widgets.nattable.edit.command.EditSelectionCommandHandler;
+import org.eclipse.nebula.widgets.nattable.fillhandle.FillHandleLayerPainter;
+import org.eclipse.nebula.widgets.nattable.fillhandle.action.FillHandleDragMode;
import org.eclipse.nebula.widgets.nattable.grid.command.InitializeAutoResizeColumnsCommandHandler;
import org.eclipse.nebula.widgets.nattable.grid.command.InitializeAutoResizeRowsCommandHandler;
import org.eclipse.nebula.widgets.nattable.hideshow.command.ColumnHideCommand;
@@ -75,6 +77,23 @@ public class SelectionLayer extends AbstractIndexLayerTransform {
protected final PositionCoordinate selectionAnchor;
protected Rectangle lastSelectedRegion;
+ /**
+ * The region <i>selected</i> via fill handle to extend the current
+ * selection for triggering a fill action. Can be <code>null</code>.
+ *
+ * @since 1.4
+ */
+ protected Rectangle fillHandleRegion;
+
+ /**
+ * The bottom right cell in a contiguous selection or <code>null</code> if
+ * there is no selection or the selection is not contiguous. Needed to
+ * identify the cell on which the fill handle should be rendered.
+ *
+ * @since 1.4
+ */
+ protected PositionCoordinate bottomRightInSelection;
+
protected SelectRowCommandHandler selectRowCommandHandler;
protected SelectCellCommandHandler selectCellCommandHandler;
protected SelectColumnCommandHandler selectColumnCommandHandler;
@@ -302,8 +321,7 @@ public class SelectionLayer extends AbstractIndexLayerTransform {
// null, simply set the reference
if (region == null || this.lastSelectedRegion == null) {
this.lastSelectedRegion = region;
- }
- else {
+ } else {
// we are modifying the values of the current lastSelectedRegion
// instead of setting a new reference because of reference
// issues in other places
@@ -496,8 +514,19 @@ public class SelectionLayer extends AbstractIndexLayerTransform {
if (cellRectangle.contains(getSelectionAnchor().columnPosition, getSelectionAnchor().rowPosition)) {
labelStack.addLabel(SelectionStyleLabels.SELECTION_ANCHOR_STYLE);
}
+
+ if (this.bottomRightInSelection != null
+ && cellRectangle.contains(
+ this.bottomRightInSelection.columnPosition,
+ this.bottomRightInSelection.rowPosition)) {
+ labelStack.addLabel(SelectionStyleLabels.FILL_HANDLE_CELL);
+ }
}
+ if (this.fillHandleRegion != null
+ && this.fillHandleRegion.contains(cell.getColumnIndex(), cell.getRowIndex())) {
+ labelStack.addLabel(SelectionStyleLabels.FILL_HANDLE_REGION);
+ }
return labelStack;
}
@@ -570,7 +599,8 @@ public class SelectionLayer extends AbstractIndexLayerTransform {
* least one fully selected column position, the {@link ColumnHideCommand}
* will be consumed and a {@link MultiColumnHideCommand} will be created and
* executed further down the layer stack, that contains all fully selected
- * column positions. Otherwise the given command will be executed further.<br>
+ * column positions. Otherwise the given command will be executed further.
+ * <br>
*
* This is necessary because neither the ColumnHideShowLayer nor the action
* that caused the execution of the {@link ColumnHideCommand} is aware of
@@ -725,4 +755,52 @@ public class SelectionLayer extends AbstractIndexLayerTransform {
return super.doCommand(command);
}
}
+
+ /**
+ * Set the region that is currently <i>selected</i> via fill handle to
+ * extend the current active selection for triggering a fill action.
+ *
+ * @param region
+ * The region <i>selected</i> via fill handle.
+ *
+ * @see FillHandleDragMode
+ * @see FillHandleLayerPainter
+ *
+ * @since 1.4
+ */
+ public void setFillHandleRegion(Rectangle region) {
+ this.fillHandleRegion = region;
+ }
+
+ /**
+ * Returns the region that is currently <i>selected</i> via fill handle to
+ * extend the current active selection. Used to perform actions on drag
+ * &amp; drop of the fill handle.
+ *
+ * @return The region <i>selected</i> via fill handle or <code>null</code>.
+ *
+ * @since 1.4
+ */
+ public Rectangle getFillHandleRegion() {
+ return this.fillHandleRegion;
+ }
+
+ /**
+ * Marks the bottom right cell in a contiguous selection within the
+ * {@link SelectionLayer}. Also removes the markup in case there is no
+ * selection or the selection is not contiguous.
+ *
+ * @since 1.4
+ */
+ public void markFillHandleCell() {
+ ILayerCell bottomRight = SelectionUtils.getBottomRightCellInSelection(this);
+ if (bottomRight != null) {
+ this.bottomRightInSelection = new PositionCoordinate(
+ this,
+ bottomRight.getColumnPosition(),
+ bottomRight.getRowPosition());
+ } else {
+ this.bottomRightInSelection = null;
+ }
+ }
}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayerPainter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayerPainter.java
index f40e0ddf..49915fa1 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayerPainter.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionLayerPainter.java
@@ -74,8 +74,7 @@ public class SelectionLayerPainter extends GridLineCellLayerPainter {
* <code>false</code> the bottom cell will be clipped. The
* default value is <code>false</code>.
*/
- public SelectionLayerPainter(final Color gridColor, boolean clipLeft,
- boolean clipTop) {
+ public SelectionLayerPainter(final Color gridColor, boolean clipLeft, boolean clipTop) {
super(gridColor, clipLeft, clipTop);
}
@@ -99,68 +98,63 @@ public class SelectionLayerPainter extends GridLineCellLayerPainter {
}
@Override
- public void paintLayer(ILayer natLayer, GC gc, int xOffset, int yOffset,
- Rectangle pixelRectangle, IConfigRegistry configRegistry) {
- Rectangle positionRectangle = getPositionRectangleFromPixelRectangle(
- natLayer, pixelRectangle);
+ public void paintLayer(
+ ILayer natLayer, GC gc,
+ int xOffset, int yOffset, Rectangle pixelRectangle,
+ IConfigRegistry configRegistry) {
+
+ Rectangle positionRectangle = getPositionRectangleFromPixelRectangle(natLayer, pixelRectangle);
int columnPositionOffset = positionRectangle.x;
int rowPositionOffset = positionRectangle.y;
- super.paintLayer(natLayer, gc, xOffset, yOffset, pixelRectangle,
- configRegistry);
+ super.paintLayer(natLayer, gc, xOffset, yOffset, pixelRectangle, configRegistry);
// Save gc settings
int originalLineStyle = gc.getLineStyle();
+ int originalLineWidth = gc.getLineWidth();
Color originalForeground = gc.getForeground();
// Apply border settings
applyBorderStyle(gc, configRegistry);
// Draw horizontal borders
- for (int columnPosition = columnPositionOffset; columnPosition < columnPositionOffset
- + positionRectangle.width; columnPosition++) {
+ for (int columnPosition = columnPositionOffset; columnPosition < columnPositionOffset + positionRectangle.width; columnPosition++) {
+
ILayerCell previousCell = null;
ILayerCell currentCell = null;
ILayerCell afterCell = null;
- for (int rowPosition = rowPositionOffset; rowPosition < rowPositionOffset
- + positionRectangle.height; rowPosition++) {
- currentCell = natLayer.getCellByPosition(columnPosition,
- rowPosition);
- afterCell = natLayer.getCellByPosition(columnPosition,
- rowPosition + 1);
+ for (int rowPosition = rowPositionOffset; rowPosition < rowPositionOffset + positionRectangle.height; rowPosition++) {
+
+ currentCell = natLayer.getCellByPosition(columnPosition, rowPosition);
+ afterCell = natLayer.getCellByPosition(columnPosition, rowPosition + 1);
if (currentCell != null) {
Rectangle currentCellBounds = currentCell.getBounds();
if (isSelected(currentCell)) {
int x0 = currentCellBounds.x - 1;
- int x1 = currentCellBounds.x + currentCellBounds.width
- - 1;
+ int x1 = currentCellBounds.x + currentCellBounds.width - 1;
int y = currentCellBounds.y - 1;
if (previousCell != null) {
- Rectangle previousCellBounds = previousCell
- .getBounds();
+ Rectangle previousCellBounds = previousCell.getBounds();
x0 = Math.max(x0, previousCellBounds.x - 1);
- x1 = Math.min(x1, previousCellBounds.x
- + previousCellBounds.width - 1);
+ x1 = Math.min(x1, previousCellBounds.x + previousCellBounds.width - 1);
}
- if (previousCell == null || !isSelected(previousCell))
+ if (previousCell == null || !isSelected(previousCell)) {
gc.drawLine(x0, y, x1, y);
+ }
// check after
if (afterCell == null || !isSelected(afterCell)) {
- Rectangle cellBounds = afterCell != null ? afterCell
- .getBounds() : currentCell.getBounds();
+ Rectangle cellBounds = afterCell != null ? afterCell.getBounds() : currentCell.getBounds();
- y = currentCellBounds.y + currentCellBounds.height
- - 1;
+ y = currentCellBounds.y + currentCellBounds.height - 1;
x0 = Math.max(x0, cellBounds.x - 1);
- x1 = Math.min(x1, cellBounds.x + cellBounds.width
- - 1);
+ x1 = Math.min(x1, cellBounds.x + cellBounds.width - 1);
gc.drawLine(x0, y, x1, y);
}
@@ -171,18 +165,16 @@ public class SelectionLayerPainter extends GridLineCellLayerPainter {
if (positionRectangle.width == 2
|| positionRectangle.height == 2) {
if (afterCell != null && isSelected(afterCell)) {
- Rectangle afterCellBounds = afterCell
- .getBounds();
+ Rectangle afterCellBounds = afterCell.getBounds();
- int x0 = Math.max(afterCellBounds.x - 1,
+ int x0 = Math.max(
+ afterCellBounds.x - 1,
currentCellBounds.x - 1);
- int x1 = Math.min(afterCellBounds.x
- + afterCellBounds.width - 1,
- currentCellBounds.x
- + currentCellBounds.width - 1);
+ int x1 = Math.min(
+ afterCellBounds.x + afterCellBounds.width - 1,
+ currentCellBounds.x + currentCellBounds.width - 1);
- int y = currentCellBounds.y
- + currentCellBounds.height - 1;
+ int y = currentCellBounds.y + currentCellBounds.height - 1;
gc.drawLine(x0, y, x1, y);
}
}
@@ -193,50 +185,43 @@ public class SelectionLayerPainter extends GridLineCellLayerPainter {
}
// Draw vertical borders
- for (int rowPosition = rowPositionOffset; rowPosition < rowPositionOffset
- + positionRectangle.height; rowPosition++) {
+ for (int rowPosition = rowPositionOffset; rowPosition < rowPositionOffset + positionRectangle.height; rowPosition++) {
+
ILayerCell previousCell = null;
ILayerCell currentCell = null;
ILayerCell afterCell = null;
- for (int columnPosition = columnPositionOffset; columnPosition < columnPositionOffset
- + positionRectangle.width; columnPosition++) {
- currentCell = natLayer.getCellByPosition(columnPosition,
- rowPosition);
- afterCell = natLayer.getCellByPosition(columnPosition + 1,
- rowPosition);
+ for (int columnPosition = columnPositionOffset; columnPosition < columnPositionOffset + positionRectangle.width; columnPosition++) {
+
+ currentCell = natLayer.getCellByPosition(columnPosition, rowPosition);
+ afterCell = natLayer.getCellByPosition(columnPosition + 1, rowPosition);
if (currentCell != null) {
Rectangle currentCellBounds = currentCell.getBounds();
if (isSelected(currentCell)) {
int y0 = currentCellBounds.y - 1;
- int y1 = currentCellBounds.y + currentCellBounds.height
- - 1;
+ int y1 = currentCellBounds.y + currentCellBounds.height - 1;
int x = currentCellBounds.x - 1;
if (previousCell != null) {
- Rectangle previousCellBounds = previousCell
- .getBounds();
+ Rectangle previousCellBounds = previousCell.getBounds();
y0 = Math.max(y0, previousCellBounds.y - 1);
- y1 = Math.min(y1, previousCellBounds.y
- + previousCellBounds.height - 1);
+ y1 = Math.min(y1, previousCellBounds.y + previousCellBounds.height - 1);
}
- if (previousCell == null || !isSelected(previousCell))
+ if (previousCell == null || !isSelected(previousCell)) {
gc.drawLine(x, y0, x, y1);
+ }
// check after
if (afterCell == null || !isSelected(afterCell)) {
- Rectangle cellBounds = afterCell != null ? afterCell
- .getBounds() : currentCell.getBounds();
+ Rectangle cellBounds = afterCell != null ? afterCell.getBounds() : currentCell.getBounds();
- x = currentCellBounds.x + currentCellBounds.width
- - 1;
+ x = currentCellBounds.x + currentCellBounds.width - 1;
y0 = Math.max(y0, cellBounds.y - 1);
- y1 = Math.min(y1, cellBounds.y + cellBounds.height
- - 1);
+ y1 = Math.min(y1, cellBounds.y + cellBounds.height - 1);
gc.drawLine(x, y0, x, y1);
}
@@ -244,24 +229,19 @@ public class SelectionLayerPainter extends GridLineCellLayerPainter {
// check if previous was selected to not override the
// border again
// this is necessary because of single cell updates
- // check if previous was selected to not override the
- // border again
- // this is necessary because of single cell updates
if (positionRectangle.width == 2
|| positionRectangle.height == 2) {
if (afterCell != null && isSelected(afterCell)) {
- Rectangle afterCellBounds = afterCell
- .getBounds();
+ Rectangle afterCellBounds = afterCell.getBounds();
- int y0 = Math.max(afterCellBounds.y - 1,
+ int y0 = Math.max(
+ afterCellBounds.y - 1,
currentCellBounds.y - 1);
- int y1 = Math.min(afterCellBounds.y
- + afterCellBounds.height - 1,
- currentCellBounds.y
- + currentCellBounds.height - 1);
+ int y1 = Math.min(
+ afterCellBounds.y + afterCellBounds.height - 1,
+ currentCellBounds.y + currentCellBounds.height - 1);
- int x = currentCellBounds.x
- + currentCellBounds.width - 1;
+ int x = currentCellBounds.x + currentCellBounds.width - 1;
gc.drawLine(x, y0, x, y1);
}
}
@@ -273,31 +253,38 @@ public class SelectionLayerPainter extends GridLineCellLayerPainter {
// Restore original gc settings
gc.setLineStyle(originalLineStyle);
+ gc.setLineWidth(originalLineWidth);
gc.setForeground(originalForeground);
}
private boolean isSelected(ILayerCell cell) {
- return (cell.getDisplayMode() == DisplayMode.SELECT || cell
- .getDisplayMode() == DisplayMode.SELECT_HOVER);
+ return (cell.getDisplayMode() == DisplayMode.SELECT
+ || cell.getDisplayMode() == DisplayMode.SELECT_HOVER);
}
protected void applyBorderStyle(GC gc, IConfigRegistry configRegistry) {
- // Note: If there is no style configured for the
- // SelectionStyleLabels.SELECTION_ANCHOR_GRID_LINE_STYLE
- // label, the style configured for DisplayMode.SELECT will be retrieved
- // by this call.
- // Ensure that the selection style configuration does not contain a
- // border style configuration
- // to avoid strange rendering behaviour. By default there is no border
- // configuration added,
- // so there shouldn't be issues with backwards compatibility. And if
- // there are some, they can
- // be solved easily by adding the necessary border style configuration.
- IStyle cellStyle = configRegistry.getConfigAttribute(
- CellConfigAttributes.CELL_STYLE, DisplayMode.SELECT,
- SelectionStyleLabels.SELECTION_ANCHOR_GRID_LINE_STYLE);
- BorderStyle borderStyle = cellStyle != null ? cellStyle
- .getAttributeValue(CellStyleAttributes.BORDER_STYLE) : null;
+ BorderStyle borderStyle = configRegistry.getConfigAttribute(
+ SelectionConfigAttributes.SELECTION_GRID_LINE_STYLE,
+ DisplayMode.SELECT);
+
+ // check for backwards compatibility style configuration
+ if (borderStyle == null) {
+ // Note: If there is no style configured for the
+ // SelectionStyleLabels.SELECTION_ANCHOR_GRID_LINE_STYLE
+ // label, the style configured for DisplayMode.SELECT will be
+ // retrieved by this call.
+ // Ensure that the selection style configuration does not contain a
+ // border style configuration to avoid strange rendering behavior.
+ // By default there is no border configuration added, so there
+ // shouldn't be issues with backwards compatibility. And if there
+ // are some, they can be solved easily by adding the necessary
+ // border style configuration.
+ IStyle cellStyle = configRegistry.getConfigAttribute(
+ CellConfigAttributes.CELL_STYLE,
+ DisplayMode.SELECT,
+ SelectionStyleLabels.SELECTION_ANCHOR_GRID_LINE_STYLE);
+ borderStyle = cellStyle != null ? cellStyle.getAttributeValue(CellStyleAttributes.BORDER_STYLE) : null;
+ }
// if there is no border style configured, use the default one for
// backwards compatibility
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java
index 5172cad0..f9b0527a 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/SelectionUtils.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2015 Original authors and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,25 +10,169 @@
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.selection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+
+/**
+ * Helper class to operate with selections.
+ */
public class SelectionUtils {
- public static boolean noShiftOrControl(boolean withShiftMask,
- boolean withControlMask) {
+ /**
+ *
+ * @param withShiftMask
+ * flag to indicate whether the shift masked is active
+ * @param withControlMask
+ * flag to indicate whether the control masked is active
+ * @return <code>true</code> if both, shift and control mask, are not active
+ */
+ public static boolean noShiftOrControl(boolean withShiftMask, boolean withControlMask) {
return !withShiftMask && !withControlMask;
}
- public static boolean bothShiftAndControl(boolean withShiftMask,
- boolean withControlMask) {
+ /**
+ *
+ * @param withShiftMask
+ * flag to indicate whether the shift masked is active
+ * @param withControlMask
+ * flag to indicate whether the control masked is active
+ * @return <code>true</code> if both, shift and control mask are active
+ */
+ public static boolean bothShiftAndControl(boolean withShiftMask, boolean withControlMask) {
return withShiftMask && withControlMask;
}
- public static boolean isControlOnly(boolean withShiftMask,
- boolean withControlMask) {
+ /**
+ *
+ * @param withShiftMask
+ * flag to indicate whether the shift masked is active
+ * @param withControlMask
+ * flag to indicate whether the control masked is active
+ * @return <code>true</code> if only the control mask is active
+ */
+ public static boolean isControlOnly(boolean withShiftMask, boolean withControlMask) {
return !withShiftMask && withControlMask;
}
- public static boolean isShiftOnly(boolean withShiftMask,
- boolean withControlMask) {
+ /**
+ *
+ * @param withShiftMask
+ * flag to indicate whether the shift masked is active
+ * @param withControlMask
+ * flag to indicate whether the control masked is active
+ * @return <code>true</code> if only the shift mask is active
+ */
+ public static boolean isShiftOnly(boolean withShiftMask, boolean withControlMask) {
return withShiftMask && !withControlMask;
}
+
+ /**
+ * Test if the numbers in the given array are consecutive. If there are
+ * duplicates or gaps in the array, <code>false</code> will be returned.
+ *
+ * @param pos
+ * the array of numbers to check
+ * @return <code>true</code> if the numbers are consecutive,
+ * <code>false</code> if there are duplicates or gaps.
+ *
+ * @since 1.4
+ */
+ public static boolean isConsecutive(int[] pos) {
+ for (int i = 1; i < pos.length; i++) {
+ if (pos[i - 1] + 1 != pos[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether the selected region tracked by the given
+ * {@link SelectionLayer} is consecutive or not.
+ *
+ * @param selectionLayer
+ * The {@link SelectionLayer} that tracks the selection.
+ * @return <code>true</code> if the current selection is consecutive,
+ * <code>false</code> if not.
+ *
+ * @since 1.4
+ */
+ public static boolean hasConsecutiveSelection(SelectionLayer selectionLayer) {
+ if (selectionLayer != null
+ && SelectionUtils.isConsecutive(selectionLayer.getSelectedColumnPositions())) {
+
+ Map<Integer, Set<Integer>> positions = new HashMap<Integer, Set<Integer>>();
+ int column = -1;
+ int row = -1;
+
+ // collect the selection information
+ for (PositionCoordinate coord : selectionLayer.getSelectedCellPositions()) {
+ Set<Integer> rows = positions.get(coord.columnPosition);
+ if (rows == null) {
+ rows = new LinkedHashSet<Integer>();
+ positions.put(coord.columnPosition, rows);
+ }
+ rows.add(coord.rowPosition);
+
+ column = Math.max(column, coord.columnPosition);
+ row = Math.max(row, coord.rowPosition);
+ }
+
+ // check if the selected region is a rectangle
+ // every row collection for each column needs to have the same size
+ // and the same content
+ Set<Integer> previous = null;
+ for (Set<Integer> rows : positions.values()) {
+ if (previous != null && !previous.equals(rows)) {
+ return false;
+ }
+ previous = rows;
+ }
+
+ // test if rows are consecutive
+ if (previous != null) {
+ int[] rowPositions = new int[previous.size()];
+ int i = 0;
+ for (Integer rowPos : previous) {
+ rowPositions[i++] = rowPos;
+ }
+ if (SelectionUtils.isConsecutive(rowPositions)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the bottom right cell of a selected region. Will only return an
+ * ILayerCell if the selected region is consecutive. Otherwise
+ * <code>null</code> will be returned.
+ *
+ * @param selectionLayer
+ * The {@link SelectionLayer} needed to determine the selection.
+ *
+ * @return The bottom right cell of a selected region or <code>null</code>
+ * if the selected region is not consecutive.
+ *
+ * @since 1.4
+ */
+ public static ILayerCell getBottomRightCellInSelection(SelectionLayer selectionLayer) {
+ if (hasConsecutiveSelection(selectionLayer)) {
+ int column = -1;
+ int row = -1;
+ for (PositionCoordinate coord : selectionLayer.getSelectedCellPositions()) {
+ column = Math.max(column, coord.columnPosition);
+ row = Math.max(row, coord.rowPosition);
+ }
+ return selectionLayer.getCellByPosition(column, row);
+ }
+ return null;
+ }
+
}
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/SelectionStyleLabels.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/SelectionStyleLabels.java
index 3146d9d0..cd6e8fac 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/SelectionStyleLabels.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/SelectionStyleLabels.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 Original authors and others.
+ * Copyright (c) 2012, 2015 Original authors and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,18 +10,72 @@
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.style;
+import org.eclipse.nebula.widgets.nattable.copy.command.InternalCopyDataCommandHandler;
+import org.eclipse.nebula.widgets.nattable.copy.command.InternalPasteDataCommandHandler;
+import org.eclipse.nebula.widgets.nattable.fillhandle.FillHandleLayerPainter;
+import org.eclipse.nebula.widgets.nattable.formula.CopySelectionLayerPainter;
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
+/**
+ * Interface that contains labels that are used to style selection related
+ * components.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
public interface SelectionStyleLabels {
- public static final String SELECTION_ANCHOR_STYLE = "selectionAnchor"; //$NON-NLS-1$
+ /**
+ * Label that is applied to the cell which is currently holding the
+ * selection anchor.
+ */
+ String SELECTION_ANCHOR_STYLE = "selectionAnchor"; //$NON-NLS-1$
+
+ /**
+ * Label that is used to configure the line style of the selection grid
+ * line. This is the line that surrounds an active selection. By default
+ * this is the black dotted one pixel line.
+ */
+ String SELECTION_ANCHOR_GRID_LINE_STYLE = "selectionAnchorGridLine"; //$NON-NLS-1$
+
+ /**
+ * Label that is applied to the column header cell of the column that is
+ * fully selected.
+ */
+ String COLUMN_FULLY_SELECTED_STYLE = GridRegion.COLUMN_HEADER + "_FULL"; //$NON-NLS-1$
- public static final String SELECTION_ANCHOR_GRID_LINE_STYLE = "selectionAnchorGridLine"; //$NON-NLS-1$
+ /**
+ * Label that is applied to the row header cell of the row that is fully
+ * selected.
+ */
+ String ROW_FULLY_SELECTED_STYLE = GridRegion.ROW_HEADER + "_FULL"; //$NON-NLS-1$
- public static final String COLUMN_FULLY_SELECTED_STYLE = GridRegion.COLUMN_HEADER
- + "_FULL"; //$NON-NLS-1$
+ /**
+ * Label that is used to mark cells as part of the fill handle region. This
+ * is the region that is <i>selected</i> via fill handle to trigger a fill
+ * action (copy/series) by dragging a current selection.
+ *
+ * @since 1.4
+ */
+ String FILL_HANDLE_REGION = "FILL_HANDLE_REGION"; //$NON-NLS-1$
- public static final String ROW_FULLY_SELECTED_STYLE = GridRegion.ROW_HEADER
- + "_FULL"; //$NON-NLS-1$
+ /**
+ * Label that is added to the bottom right cell of a contiguous selection.
+ * Used to mark the cell for rendering the fill handle.
+ *
+ * @since 1.4
+ */
+ String FILL_HANDLE_CELL = "selectionHandleCell"; //$NON-NLS-1$
+ /**
+ * Style label for configuring the copy border.
+ *
+ * @see CopySelectionLayerPainter
+ * @see FillHandleLayerPainter
+ * @see InternalCopyDataCommandHandler
+ * @see InternalPasteDataCommandHandler
+ *
+ * @since 1.4
+ */
+ String COPY_BORDER_STYLE = "copyBorderStyle"; //$NON-NLS-1$
}
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_300_Data/_305_FormulaDataExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_300_Data/_305_FormulaDataExample.java
index 78a6a1da..ecdfb323 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_300_Data/_305_FormulaDataExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_300_Data/_305_FormulaDataExample.java
@@ -18,15 +18,14 @@ import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
-import org.eclipse.nebula.widgets.nattable.copy.InternalCellClipboard;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
import org.eclipse.nebula.widgets.nattable.export.ExportConfigAttributes;
import org.eclipse.nebula.widgets.nattable.extension.poi.HSSFExcelExporter;
import org.eclipse.nebula.widgets.nattable.extension.poi.PoiExcelExporter;
+import org.eclipse.nebula.widgets.nattable.fillhandle.config.FillHandleConfiguration;
import org.eclipse.nebula.widgets.nattable.formula.FormulaDataProvider;
-import org.eclipse.nebula.widgets.nattable.formula.FormulaLayerPainter;
import org.eclipse.nebula.widgets.nattable.formula.FormulaTooltipErrorReporter;
import org.eclipse.nebula.widgets.nattable.formula.command.DisableFormulaEvaluationCommand;
import org.eclipse.nebula.widgets.nattable.formula.command.EnableFormulaEvaluationCommand;
@@ -100,15 +99,16 @@ public class _305_FormulaDataExample extends AbstractNatExample {
final FormulaBodyLayerStack bodyLayer = gridLayer.getBodyLayer();
- // This is the formula specific configuration
- InternalCellClipboard clipboard = new InternalCellClipboard();
+ natTable.addConfiguration(new FillHandleConfiguration(bodyLayer.getSelectionLayer()));
+ // This is the formula specific configuration
natTable.addConfiguration(
- new DefaultFormulaConfiguration(bodyLayer.getFormulaDataProvider(), bodyLayer.getSelectionLayer(), clipboard));
+ new DefaultFormulaConfiguration(
+ bodyLayer.getFormulaDataProvider(),
+ bodyLayer.getSelectionLayer(),
+ natTable.getInternalCellClipboard()));
bodyLayer.getFormulaDataProvider().setErrorReporter(new FormulaTooltipErrorReporter(natTable, bodyLayer.getDataLayer()));
- bodyLayer.getSelectionLayer().setLayerPainter(new FormulaLayerPainter(clipboard));
-
natTable.addConfiguration(new AbstractRegistryConfiguration() {
@Override
@@ -134,8 +134,7 @@ public class _305_FormulaDataExample extends AbstractNatExample {
if (_305_FormulaDataExample.this.evaluationEnabled) {
natTable.doCommand(new EnableFormulaEvaluationCommand());
toggleFormulaButton.setText("Disable Formula Evaluation");
- }
- else {
+ } else {
natTable.doCommand(new DisableFormulaEvaluationCommand());
toggleFormulaButton.setText("Enable Formula Evaluation");
}
@@ -226,9 +225,10 @@ public class _305_FormulaDataExample extends AbstractNatExample {
bodyLayer, selectionLayer);
// Corner
- ILayer cornerLayer = new CornerLayer(new DataLayer(
- new DefaultCornerDataProvider(columnHeaderDataProvider,
- rowHeaderDataProvider)), rowHeaderLayer,
+ ILayer cornerLayer = new CornerLayer(
+ new DataLayer(
+ new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider)),
+ rowHeaderLayer,
columnHeaderLayer);
setBodyLayer(bodyLayer);

Back to the top