blob: 127cb3dd8c11a1d30c05013ecedd5999ab01a325 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2020 Dirk Fauth.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.selection;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
/**
* This interface is used to configure the traversal behavior when moving the
* selection in a NatTable via key actions, e.g. tab or the arrow keys. You can
* specify the scope, if the traversal should cycle and specify logic to
* determine the step count if necessary. It is also possible to add logic that
* determines whether a target is a valid selection movement target. This allows
* traversal of editable cells while non-editable cells would be skipped.
*/
public interface ITraversalStrategy {
/**
* The scope of the traversal which is necessary to determine what should
* happen on cycling.
*/
enum TraversalScope {
/**
* The scope of the traversal is on the axis, row or column. Using this
* TraversalScope means that if cycling is enabled the selection stays
* on the same row/column.
*/
AXIS,
/**
* The scope of the traversal is on the table itself. Using this
* TraversalScope means that if cycling is enabled the selection will
* move to the next row/column too.
*/
TABLE
}
/**
*
* @return The {@link TraversalScope} this traversal strategy specifies.
*/
TraversalScope getTraversalScope();
/**
*
* @return <code>true</code> if on traversal the selection should cycle,
* <code>false</code> if the selection should stay at the last/first
* position without cycling.
*/
boolean isCycle();
/**
*
* @return The number of steps to jump on traversal.
*/
int getStepCount();
/**
* Checks whether the {@link ILayerCell} that would be selected after the
* selection movement is valid or not. In case the target is invalid, the
* responsible command handler is able to react accordingly, e.g. move the
* next valid cell.
* <p>
* This is for example useful for editing traversal. If the selection
* movement is triggered on committing a value in an editor, the next
* editable cell should be selected and the editor opened immediately.
* </p>
*
* @param from
* The {@link ILayerCell} from which the selection movement is
* started.
* @param to
* The {@link ILayerCell} to which the selection movement should
* be performed.
* @return <code>true</code> if the target is a valid target for selection
* movement, <code>false</code> if not
*/
boolean isValidTarget(ILayerCell from, ILayerCell to);
/**
* {@link ITraversalStrategy} that specifies the following:<br>
* <ul>
* <li>traversal scope = axis</li>
* <li>cycle = false</li>
* <li>step count = 1</li>
* <li>valid = true</li>
* </ul>
* This means for example, on moving a selection to the right, the selection
* will move one cell at a time and stop at the right border.
* <p>
* This is the default traversal strategy.
* </p>
*/
ITraversalStrategy AXIS_TRAVERSAL_STRATEGY = new ITraversalStrategy() {
@Override
public TraversalScope getTraversalScope() {
return TraversalScope.AXIS;
}
@Override
public boolean isCycle() {
return false;
}
@Override
public int getStepCount() {
return 1;
}
@Override
public boolean isValidTarget(ILayerCell from, ILayerCell to) {
return true;
};
};
/**
* {@link ITraversalStrategy} that specifies the following:<br>
* <ul>
* <li>traversal scope = axis</li>
* <li>cycle = true</li>
* <li>step count = 1</li>
* <li>valid = true</li>
* </ul>
* This means for example, on moving a selection to the right, the selection
* will move one cell at a time and jump to the first column when moving
* over the right border.
*/
ITraversalStrategy AXIS_CYCLE_TRAVERSAL_STRATEGY = new ITraversalStrategy() {
@Override
public TraversalScope getTraversalScope() {
return TraversalScope.AXIS;
}
@Override
public boolean isCycle() {
return true;
}
@Override
public int getStepCount() {
return 1;
}
@Override
public boolean isValidTarget(ILayerCell from, ILayerCell to) {
return true;
};
};
/**
* {@link ITraversalStrategy} that specifies the following:<br>
* <ul>
* <li>traversal scope = table</li>
* <li>cycle = false</li>
* <li>step count = 1</li>
* <li>valid = true</li>
* </ul>
* This means for example, on moving a selection to the right, the selection
* will move one cell at a time and jump to the first column and move one
* row down when moving over the right border. At the end of the table the
* selection will stop and doesn't move to the beginning.
*/
ITraversalStrategy TABLE_TRAVERSAL_STRATEGY = new ITraversalStrategy() {
@Override
public TraversalScope getTraversalScope() {
return TraversalScope.TABLE;
}
@Override
public boolean isCycle() {
return false;
}
@Override
public int getStepCount() {
return 1;
}
@Override
public boolean isValidTarget(ILayerCell from, ILayerCell to) {
return true;
};
};
/**
* {@link ITraversalStrategy} that specifies the following:<br>
* <ul>
* <li>traversal scope = table</li>
* <li>cycle = true</li>
* <li>step count = 1</li>
* <li>valid = true</li>
* </ul>
* This means for example, on moving a selection to the right, the selection
* will move one cell at a time and jump to the first column and move one
* row down when moving over the right border. At the end of the table the
* selection will cycle to the beginning of the table.
*/
ITraversalStrategy TABLE_CYCLE_TRAVERSAL_STRATEGY = new ITraversalStrategy() {
@Override
public TraversalScope getTraversalScope() {
return TraversalScope.TABLE;
}
@Override
public boolean isCycle() {
return true;
}
@Override
public int getStepCount() {
return 1;
}
@Override
public boolean isValidTarget(ILayerCell from, ILayerCell to) {
return true;
};
};
}