diff options
author | Dirk Fauth | 2014-10-28 19:57:31 +0000 |
---|---|---|
committer | Dirk Fauth | 2014-10-28 20:10:49 +0000 |
commit | 1a816f9dacb177f429b727cd29c3ea3a17914646 (patch) | |
tree | e67d847a5bf82b502c56fa4d3c27597d65d76047 | |
parent | 315bb7094b8ba10a4607319d32cb525b60e079bb (diff) | |
download | org.eclipse.nebula.widgets.nattable-1a816f9dacb177f429b727cd29c3ea3a17914646.tar.gz org.eclipse.nebula.widgets.nattable-1a816f9dacb177f429b727cd29c3ea3a17914646.tar.xz org.eclipse.nebula.widgets.nattable-1a816f9dacb177f429b727cd29c3ea3a17914646.zip |
Bug 447133 - extended MoveSelectionCommandHandler to be able to specify
different traversal strategies for horizontal and vertical movement
5 files changed, 215 insertions, 83 deletions
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTraversalTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTraversalTest.java index 8cced726..88c8cf38 100644 --- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTraversalTest.java +++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/selection/CellSelectionTraversalTest.java @@ -36,6 +36,58 @@ public class CellSelectionTraversalTest { this.selectionLayer.clear(); } + // non movement + + @Test + public void testMoveNone() { + // register axis traversal + this.viewportLayer.registerCommandHandler( + new MoveCellSelectionCommandHandler(this.selectionLayer, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY)); + // select a cell + this.selectionLayer.setSelectedCell(4, 4); + assertEquals(4, this.selectionLayer.getLastSelectedCell().getColumnPosition()); + assertEquals(4, this.selectionLayer.getLastSelectedCell().getRowPosition()); + + // move none + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.NONE, false, false)); + + assertEquals(4, this.selectionLayer.getLastSelectedCell().getColumnPosition()); + assertEquals(4, this.selectionLayer.getLastSelectedCell().getRowPosition()); + + // move none 4 steps + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.NONE, 4, false, false)); + + assertEquals(4, this.selectionLayer.getLastSelectedCell().getColumnPosition()); + assertEquals(4, this.selectionLayer.getLastSelectedCell().getRowPosition()); + } + + // override strategy by command + + @Test + public void testMoveRightAxisOverride() { + // register axis traversal + this.viewportLayer.registerCommandHandler( + new MoveCellSelectionCommandHandler(this.selectionLayer, ITraversalStrategy.AXIS_TRAVERSAL_STRATEGY)); + // select a cell + this.selectionLayer.setSelectedCell(9, 4); + assertEquals(9, this.selectionLayer.getLastSelectedCell().getColumnPosition()); + assertEquals(4, this.selectionLayer.getLastSelectedCell().getRowPosition()); + + // move on to right at end -> stay + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.RIGHT, false, false)); + + assertEquals(9, this.selectionLayer.getLastSelectedCell().getColumnPosition()); + assertEquals(4, this.selectionLayer.getLastSelectedCell().getRowPosition()); + + // move on to right at end with axis cycle strategy -> move to beginning + // same row + this.viewportLayer.doCommand(new MoveSelectionCommand(MoveDirectionEnum.RIGHT, + ITraversalStrategy.AXIS_CYCLE_TRAVERSAL_STRATEGY, false, false)); + + assertEquals(0, this.selectionLayer.getLastSelectedCell().getColumnPosition()); + assertEquals(4, this.selectionLayer.getLastSelectedCell().getRowPosition()); + } + // move right @Test diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java index 080f4299..7882a5d0 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveCellSelectionCommandHandler.java @@ -55,6 +55,25 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler super(selectionLayer, traversalStrategy); } + /** + * Create a MoveCellSelectionCommandHandler for the given + * {@link SelectionLayer} . + * + * @param selectionLayer + * The {@link SelectionLayer} on which the selection should be + * performed. + * @param horizontalTraversalStrategy + * The strategy that should be used for horizontal selection + * movements. Can not be <code>null</code>. + * @param verticalTraversalStrategy + * The strategy that should be used for vertical selection + * movements. Can not be <code>null</code>. + */ + public MoveCellSelectionCommandHandler(SelectionLayer selectionLayer, + ITraversalStrategy horizontalTraversalStrategy, ITraversalStrategy verticalTraversalStrategy) { + super(selectionLayer, horizontalTraversalStrategy, verticalTraversalStrategy); + } + @Override protected void moveLastSelectedLeft(ITraversalStrategy traversalStrategy, boolean withShiftMask, boolean withControlMask) { if (this.selectionLayer.hasColumnSelection()) { @@ -126,53 +145,53 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler int stepSize = traversalStrategy.getStepCount(); this.newSelectedColumnPosition = (stepSize >= 0) ? (lastSelectedCell.getOriginColumnPosition() + lastSelectedCell.getColumnSpan() - 1 + stepSize) - : (this.selectionLayer.getColumnCount() - 1); + : (this.selectionLayer.getColumnCount() - 1); - this.newSelectedRowPosition = this.lastSelectedCellPosition.rowPosition; + this.newSelectedRowPosition = this.lastSelectedCellPosition.rowPosition; - if (this.newSelectedColumnPosition >= this.selectionLayer.getColumnCount()) { - if (traversalStrategy.getTraversalScope().equals(TraversalScope.AXIS)) { - if (!traversalStrategy.isCycle()) { - // on axis scope with no cycle, stop moving - this.newSelectedColumnPosition = this.selectionLayer.getColumnCount() - 1; - } - else { - // on axis scope with cycle, move to 0 - // TODO check if 0 is valid using step count - this.newSelectedColumnPosition = 0; - } - } - else if (traversalStrategy.getTraversalScope().equals(TraversalScope.TABLE)) { - // on table scope, move to 0 - // TODO check if 0 is valid using step count - this.newSelectedColumnPosition = 0; - this.newSelectedRowPosition = this.newSelectedRowPosition + 1; - if (this.newSelectedRowPosition >= this.selectionLayer.getRowCount()) { - if (traversalStrategy.isCycle()) { - // at the bottom and cycle so go to top - this.newSelectedRowPosition = 0; + if (this.newSelectedColumnPosition >= this.selectionLayer.getColumnCount()) { + if (traversalStrategy.getTraversalScope().equals(TraversalScope.AXIS)) { + if (!traversalStrategy.isCycle()) { + // on axis scope with no cycle, stop moving + this.newSelectedColumnPosition = this.selectionLayer.getColumnCount() - 1; + } + else { + // on axis scope with cycle, move to 0 + // TODO check if 0 is valid using step count + this.newSelectedColumnPosition = 0; + } } - else { - // at the bottom and no cycle so stop moving - this.newSelectedColumnPosition = this.selectionLayer.getColumnCount() - 1; - this.newSelectedRowPosition = this.selectionLayer.getRowCount() - 1; + else if (traversalStrategy.getTraversalScope().equals(TraversalScope.TABLE)) { + // on table scope, move to 0 + // TODO check if 0 is valid using step count + this.newSelectedColumnPosition = 0; + this.newSelectedRowPosition = this.newSelectedRowPosition + 1; + if (this.newSelectedRowPosition >= this.selectionLayer.getRowCount()) { + if (traversalStrategy.isCycle()) { + // at the bottom and cycle so go to top + this.newSelectedRowPosition = 0; + } + else { + // at the bottom and no cycle so stop moving + this.newSelectedColumnPosition = this.selectionLayer.getColumnCount() - 1; + this.newSelectedRowPosition = this.selectionLayer.getRowCount() - 1; + } + } } } - } - } - if (this.newSelectedColumnPosition != this.lastSelectedCellPosition.columnPosition) { - if (stepSize == SelectionLayer.MOVE_ALL && !withShiftMask) { - this.selectionLayer.clear(false); - } - this.selectionLayer.selectCell( - this.newSelectedColumnPosition, this.newSelectedRowPosition, - withShiftMask, withControlMask); - this.selectionLayer.fireCellSelectionEvent( - this.lastSelectedCellPosition.columnPosition, - this.lastSelectedCellPosition.rowPosition, true, - withShiftMask, withControlMask); - } + if (this.newSelectedColumnPosition != this.lastSelectedCellPosition.columnPosition) { + if (stepSize == SelectionLayer.MOVE_ALL && !withShiftMask) { + this.selectionLayer.clear(false); + } + this.selectionLayer.selectCell( + this.newSelectedColumnPosition, this.newSelectedRowPosition, + withShiftMask, withControlMask); + this.selectionLayer.fireCellSelectionEvent( + this.lastSelectedCellPosition.columnPosition, + this.lastSelectedCellPosition.rowPosition, true, + withShiftMask, withControlMask); + } } } } @@ -248,7 +267,7 @@ public class MoveCellSelectionCommandHandler extends MoveSelectionCommandHandler this.newSelectedRowPosition = (stepSize >= 0) ? lastSelectedCell.getOriginRowPosition() + lastSelectedCell.getRowSpan() - 1 + stepSize - : this.selectionLayer.getRowCount() - 1; + : this.selectionLayer.getRowCount() - 1; if (this.newSelectedRowPosition >= this.selectionLayer.getRowCount()) { if (traversalStrategy.getTraversalScope().equals(TraversalScope.AXIS)) { diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java index 43727fbc..b56acfb2 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveRowSelectionCommandHandler.java @@ -46,6 +46,25 @@ public class MoveRowSelectionCommandHandler extends MoveCellSelectionCommandHand super(selectionLayer, traversalStrategy); } + /** + * Create a MoveRowSelectionCommandHandler for the given + * {@link SelectionLayer} . + * + * @param selectionLayer + * The {@link SelectionLayer} on which the selection should be + * performed. + * @param horizontalTraversalStrategy + * The strategy that should be used for horizontal selection + * movements. Can not be <code>null</code>. + * @param verticalTraversalStrategy + * The strategy that should be used for vertical selection + * movements. Can not be <code>null</code>. + */ + public MoveRowSelectionCommandHandler(SelectionLayer selectionLayer, + ITraversalStrategy horizontalTraversalStrategy, ITraversalStrategy verticalTraversalStrategy) { + super(selectionLayer, horizontalTraversalStrategy, verticalTraversalStrategy); + } + @Override protected void moveLastSelectedLeft(ITraversalStrategy traversalStrategy, boolean withShiftMask, boolean withControlMask) { super.moveLastSelectedLeft(traversalStrategy, withShiftMask, withControlMask); diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveSelectionCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveSelectionCommandHandler.java index 0e66c357..98638fd7 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveSelectionCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/selection/MoveSelectionCommandHandler.java @@ -39,10 +39,16 @@ public abstract class MoveSelectionCommandHandler<T extends MoveSelectionCommand protected final SelectionLayer selectionLayer; /** - * The strategy to use on traversal. Specifies the behavior when the - * movement reaches a border. + * The strategy to use on horizontal traversal. Specifies the behavior when + * the movement reaches a border. */ - protected final ITraversalStrategy traversalStrategy; + protected final ITraversalStrategy horizontalTraversalStrategy; + + /** + * The strategy to use on vertical traversal. Specifies the behavior when + * the movement reaches a border. + */ + protected final ITraversalStrategy verticalTraversalStrategy; /** * Create a MoveSelectionCommandHandler for the given {@link SelectionLayer} @@ -69,11 +75,31 @@ public abstract class MoveSelectionCommandHandler<T extends MoveSelectionCommand * not be <code>null</code>. */ public MoveSelectionCommandHandler(SelectionLayer selectionLayer, ITraversalStrategy traversalStrategy) { - if (traversalStrategy == null) { + this(selectionLayer, traversalStrategy, traversalStrategy); + } + + /** + * Create a MoveSelectionCommandHandler for the given {@link SelectionLayer} + * . + * + * @param selectionLayer + * The {@link SelectionLayer} on which the selection should be + * performed. + * @param horizontalTraversalStrategy + * The strategy that should be used for horizontal selection + * movements. Can not be <code>null</code>. + * @param verticalTraversalStrategy + * The strategy that should be used for vertical selection + * movements. Can not be <code>null</code>. + */ + public MoveSelectionCommandHandler(SelectionLayer selectionLayer, + ITraversalStrategy horizontalTraversalStrategy, ITraversalStrategy verticalTraversalStrategy) { + if (horizontalTraversalStrategy == null || verticalTraversalStrategy == null) { throw new IllegalArgumentException("You need to specify an ITraversalStrategy!"); //$NON-NLS-1$ } this.selectionLayer = selectionLayer; - this.traversalStrategy = traversalStrategy; + this.horizontalTraversalStrategy = horizontalTraversalStrategy; + this.verticalTraversalStrategy = verticalTraversalStrategy; } @Override @@ -104,27 +130,64 @@ public abstract class MoveSelectionCommandHandler<T extends MoveSelectionCommand * @param command * The current handled command. * @return The {@link ITraversalStrategy} that should be used to move the - * selection. + * selection. <code>null</code> for {@link MoveDirectionEnum#NONE}. */ protected ITraversalStrategy getTraversalStrategy(final T command) { + if (MoveDirectionEnum.DOWN.equals(command.getDirection()) + || MoveDirectionEnum.UP.equals(command.getDirection())) { + return getTraversalStrategy(command, this.verticalTraversalStrategy); + } + else if (MoveDirectionEnum.LEFT.equals(command.getDirection()) + || MoveDirectionEnum.RIGHT.equals(command.getDirection())) { + return getTraversalStrategy(command, this.horizontalTraversalStrategy); + } + // the MoveDirectionEnum that is not handled yet is NONE + // so since no movement is involved, we return null + return null; + } + + /** + * Determines the {@link ITraversalStrategy} that should be used to move the + * selection on handling the given command. The strategy is determined in + * the following way: + * <ol> + * <li>Return the {@link ITraversalStrategy} carried by the command</li> + * <li>If it doesn't contain a {@link ITraversalStrategy} but a carries a + * dedicated step count, create a temporary {@link ITraversalStrategy} that + * is configured with the locally configured {@link ITraversalStrategy} but + * returns the step count carried by the command.</li> + * <li>If the command doesn't carry a {@link ITraversalStrategy} and no + * dedicated step count, the {@link ITraversalStrategy} registered with this + * command handler is returned.</li> + * </ol> + * + * @param command + * The current handled command. + * @param baseTraversalStrategy + * The {@link ITraversalStrategy} that should be used in case the + * given command does not carry one. + * @return The {@link ITraversalStrategy} that should be used to move the + * selection. + */ + private ITraversalStrategy getTraversalStrategy(final T command, final ITraversalStrategy baseTraversalStrategy) { // if the command comes with a strategy we use it ITraversalStrategy result = command.getTraversalStrategy(); if (result == null) { if (command.getStepSize() != null) { - // command carries a step size, so we use the internal strategy + // command carries a step size, so we use the provided strategy // with the transported step size this is mainly for backwards // compatibility result = new ITraversalStrategy() { @Override public TraversalScope getTraversalScope() { - return MoveSelectionCommandHandler.this.traversalStrategy.getTraversalScope(); + return baseTraversalStrategy.getTraversalScope(); } @Override public boolean isCycle() { - return MoveSelectionCommandHandler.this.traversalStrategy.isCycle(); + return baseTraversalStrategy.isCycle(); } @Override @@ -134,7 +197,7 @@ public abstract class MoveSelectionCommandHandler<T extends MoveSelectionCommand }; } else { - result = this.traversalStrategy; + result = baseTraversalStrategy; } } diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_505_Selection/_5055_SelectionTraversalExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_505_Selection/_5055_SelectionTraversalExample.java index c9922bbe..8d472f20 100644 --- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_505_Selection/_5055_SelectionTraversalExample.java +++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_500_Layers/_505_Selection/_5055_SelectionTraversalExample.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Dirk Fauth and others. + * Copyright (c) 2014 Dirk Fauth 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 @@ -12,7 +12,6 @@ package org.eclipse.nebula.widgets.nattable.examples._500_Layers._505_Selection; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.nebula.widgets.nattable.NatTable; -import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration; import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor; import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider; import org.eclipse.nebula.widgets.nattable.data.ListDataProvider; @@ -26,11 +25,6 @@ import org.eclipse.nebula.widgets.nattable.layer.DataLayer; import org.eclipse.nebula.widgets.nattable.selection.ITraversalStrategy; import org.eclipse.nebula.widgets.nattable.selection.MoveCellSelectionCommandHandler; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; -import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum; -import org.eclipse.nebula.widgets.nattable.selection.action.MoveSelectionAction; -import org.eclipse.nebula.widgets.nattable.ui.action.IKeyAction; -import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry; -import org.eclipse.nebula.widgets.nattable.ui.matcher.KeyEventMatcher; import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridLayout; @@ -146,31 +140,16 @@ public class _5055_SelectionTraversalExample extends AbstractNatExample { viewportLayer.setRegionName(GridRegion.BODY); // register a MoveCellSelectionCommandHandler with - // TABLE_CYCLE_TRAVERSAL_STRATEGY + // TABLE_CYCLE_TRAVERSAL_STRATEGY for horizontal traversal + // and AXIS_CYCLE_TRAVERSAL_STRATEGY for vertical traversal + // NOTE: + // You could achieve the same by registering a command handler + // with TABLE_CYCLE_TRAVERSAL_STRATEGY and registering + // MoveSelectionActions with a customized ITraversalStrategy, e.g. + // AXIS_CYCLE_TRAVERSAL_STRATEGY viewportLayer.registerCommandHandler( - new MoveCellSelectionCommandHandler(selectionLayer, ITraversalStrategy.TABLE_CYCLE_TRAVERSAL_STRATEGY)); - - viewportLayer.addConfiguration(new AbstractUiBindingConfiguration() { - - @Override - public void configureUiBindings(UiBindingRegistry uiBindingRegistry) { - // register move action with AXIS_CYCLE_TRAVERSAL_STRATEGY - IKeyAction traversalAction = - new MoveSelectionAction(MoveDirectionEnum.UP, ITraversalStrategy.AXIS_CYCLE_TRAVERSAL_STRATEGY); - uiBindingRegistry.registerFirstKeyBinding(new KeyEventMatcher(SWT.NONE, - SWT.ARROW_UP), traversalAction); - uiBindingRegistry.registerFirstKeyBinding(new KeyEventMatcher(SWT.SHIFT, - SWT.ARROW_UP), traversalAction); - - // register move action with AXIS_CYCLE_TRAVERSAL_STRATEGY - traversalAction = - new MoveSelectionAction(MoveDirectionEnum.DOWN, ITraversalStrategy.AXIS_CYCLE_TRAVERSAL_STRATEGY); - uiBindingRegistry.registerFirstKeyBinding(new KeyEventMatcher(SWT.NONE, - SWT.ARROW_DOWN), traversalAction); - uiBindingRegistry.registerFirstKeyBinding(new KeyEventMatcher(SWT.SHIFT, - SWT.ARROW_DOWN), traversalAction); - } - }); + new MoveCellSelectionCommandHandler(selectionLayer, + ITraversalStrategy.TABLE_CYCLE_TRAVERSAL_STRATEGY, ITraversalStrategy.AXIS_CYCLE_TRAVERSAL_STRATEGY)); natTable = new NatTable(panel, viewportLayer); GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable); |