/******************************************************************************* * 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Original authors and others - initial API and implementation * Jonas Hugo <Jonas.Hugo@jeppesen.com>, * Markus Wahl <Markus.Wahl@jeppesen.com> - Use getters and setters for * the markers of SelectionLayer instead of the fields. * Vincent Lorenzo <vincent.lorenzo@cea.fr> - Bug 478622 ******************************************************************************/ package org.eclipse.nebula.widgets.nattable.selection; import static org.eclipse.nebula.widgets.nattable.selection.SelectionUtils.isControlOnly; import static org.eclipse.nebula.widgets.nattable.selection.SelectionUtils.isShiftOnly; import static org.eclipse.nebula.widgets.nattable.selection.SelectionUtils.noShiftOrControl; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler; import org.eclipse.nebula.widgets.nattable.coordinate.Range; import org.eclipse.nebula.widgets.nattable.group.RowGroupHeaderLayer; import org.eclipse.nebula.widgets.nattable.group.RowGroupUtils; import org.eclipse.nebula.widgets.nattable.group.model.IRowGroupModel; import org.eclipse.nebula.widgets.nattable.selection.command.SelectRowGroupsCommand; import org.eclipse.nebula.widgets.nattable.selection.event.RowSelectionEvent; import org.eclipse.nebula.widgets.nattable.util.ObjectUtils; import org.eclipse.swt.graphics.Rectangle; public class SelectRowGroupCommandHandler<T> extends AbstractLayerCommandHandler<SelectRowGroupsCommand> { private final IRowGroupModel<T> model; private final RowGroupHeaderLayer<T> rowGroupHeaderLayer; private final SelectionLayer selectionLayer; public SelectRowGroupCommandHandler(IRowGroupModel<T> model, SelectionLayer selectionLayer, RowGroupHeaderLayer<T> rowGroupHeaderLayer) { this.model = model; this.selectionLayer = selectionLayer; this.rowGroupHeaderLayer = rowGroupHeaderLayer; } @Override public Class<SelectRowGroupsCommand> getCommandClass() { return SelectRowGroupsCommand.class; } @Override protected boolean doCommand(SelectRowGroupsCommand command) { final List<Integer> rowIndexes = RowGroupUtils.getRowIndexesInGroup( this.model, this.rowGroupHeaderLayer.getRowIndexByPosition(command .getRowPosition())); final List<Integer> rowPositions = RowGroupUtils .getRowPositionsInGroup(this.selectionLayer, rowIndexes); selectRows(command.getColumnPosition(), rowPositions, command.isWithShiftMask(), command.isWithControlMask(), command.getRowPositionToMoveIntoViewport(), command.isMoveAnchorToTopOfGroup()); return true; } protected void selectRows(int columnPosition, List<Integer> rowPositions, boolean withShiftMask, boolean withControlMask, int rowPositionToMoveIntoViewport, boolean moveAnchorToTopOfGroup) { Set<Range> changedRowRanges = new HashSet<Range>(); if (rowPositions.size() > 0) { changedRowRanges.addAll(internalSelectRow(columnPosition, rowPositions.get(0), rowPositions.size(), withShiftMask, withControlMask, moveAnchorToTopOfGroup)); } Set<Integer> changedRows = new HashSet<Integer>(); for (Range range : changedRowRanges) { for (int i = range.start; i < range.end; i++) { changedRows.add(Integer.valueOf(i)); } } this.selectionLayer.fireLayerEvent(new RowSelectionEvent(this.selectionLayer, changedRows, rowPositionToMoveIntoViewport, withShiftMask, withControlMask)); } private Set<Range> internalSelectRow(int columnPosition, int rowPosition, int rowCount, boolean withShiftMask, boolean withControlMask, boolean moveAnchorToTopOfGroup) { Set<Range> changedRowRanges = new HashSet<Range>(); if (noShiftOrControl(withShiftMask, withControlMask)) { changedRowRanges.addAll(this.selectionLayer.getSelectedRowPositions()); this.selectionLayer.clear(false); this.selectionLayer.selectCell(0, rowPosition, withShiftMask, withControlMask); this.selectionLayer.selectRegion(0, rowPosition, this.selectionLayer.getColumnCount(), rowCount); changedRowRanges .add(new Range(rowPosition, rowPosition + rowCount)); } else if (isControlOnly(withShiftMask, withControlMask)) { changedRowRanges.add(selectRowWithCtrlKey(columnPosition, rowPosition, rowCount)); } else if (isShiftOnly(withShiftMask, withControlMask)) { changedRowRanges.add(selectRowWithShiftKey(columnPosition, rowPosition, rowCount)); } if (moveAnchorToTopOfGroup) { this.selectionLayer.moveSelectionAnchor(columnPosition, rowPosition); } this.selectionLayer.getLastSelectedCellPosition().columnPosition = this.selectionLayer .getColumnCount() - 1; this.selectionLayer.getLastSelectedCellPosition().rowPosition = rowPosition; return changedRowRanges; } private Range selectRowWithCtrlKey(int columnPosition, int rowPosition, int rowCount) { Rectangle selectedRowRectangle = new Rectangle(0, rowPosition, this.selectionLayer.getColumnCount(), rowCount); if (this.selectionLayer.isRowPositionFullySelected(rowPosition)) { this.selectionLayer.clearSelection(selectedRowRectangle); if (this.selectionLayer.getLastSelectedRegion() != null && this.selectionLayer.getLastSelectedRegion().equals( selectedRowRectangle)) { this.selectionLayer.setLastSelectedRegion(null); } } else { // Preserve last selected region if (this.selectionLayer.getLastSelectedRegion() != null) { this.selectionLayer.selectionModel.addSelection(new Rectangle( this.selectionLayer.getLastSelectedRegion().x, this.selectionLayer.getLastSelectedRegion().y, this.selectionLayer.getLastSelectedRegion().width, this.selectionLayer.getLastSelectedRegion().height)); } this.selectionLayer.selectRegion(0, rowPosition, this.selectionLayer.getColumnCount(), rowCount); } return new Range(rowPosition, rowPosition + 1); } private Range selectRowWithShiftKey(int columnPosition, int rowPosition, int rowCount) { if (this.selectionLayer.getLastSelectedRegion() != null) { int start = Math.min(this.selectionLayer.getLastSelectedRegion().y, rowPosition); int end = Math.max(this.selectionLayer.getLastSelectedRegion().y, rowPosition); for (int i = start; i <= end; i++) { int index = this.selectionLayer.getRowIndexByPosition(i); if (RowGroupUtils.isPartOfAGroup(this.model, index) && !this.selectionLayer.isRowPositionFullySelected(i)) { List<Integer> rowPositions = new ArrayList<Integer>( RowGroupUtils.getRowPositionsInGroup( this.selectionLayer, RowGroupUtils .getRowIndexesInGroup(this.model, index))); Collections.sort(rowPositions); this.selectionLayer.selectRegion(0, rowPositions.get(0), this.selectionLayer.getColumnCount(), rowPositions.size()); i = ObjectUtils.getLastElement(rowPositions); } } } return new Range(rowPosition, rowPosition + 1); } }