blob: f5904c448b88a16e66fa05e1e1b0f8d3dbe34ea1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2020 Original authors and others.
*
* 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:
* Original authors and others - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.group.command;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.nebula.widgets.nattable.Messages;
import org.eclipse.nebula.widgets.nattable.columnRename.ColumnRenameDialog;
import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel.ColumnGroup;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupUtils;
import org.eclipse.nebula.widgets.nattable.group.event.GroupColumnsEvent;
import org.eclipse.nebula.widgets.nattable.group.event.UngroupColumnsEvent;
import org.eclipse.nebula.widgets.nattable.reorder.command.MultiColumnReorderCommand;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
public class ColumnGroupsCommandHandler extends
AbstractLayerCommandHandler<IColumnGroupCommand> {
private final ColumnGroupModel model;
private final SelectionLayer selectionLayer;
private final ColumnGroupHeaderLayer contextLayer;
private Map<Integer, Integer> columnIndexesToPositionsMap;
public ColumnGroupsCommandHandler(ColumnGroupModel model, SelectionLayer selectionLayer, ColumnGroupHeaderLayer contextLayer) {
this.model = model;
this.selectionLayer = selectionLayer;
this.contextLayer = contextLayer;
}
@Override
public boolean doCommand(IColumnGroupCommand command) {
if (command instanceof CreateColumnGroupCommand) {
if (this.columnIndexesToPositionsMap.size() > 0) {
handleGroupColumnsCommand(((CreateColumnGroupCommand) command).getColumnGroupName());
this.columnIndexesToPositionsMap.clear();
return true;
}
} else if (command instanceof OpenCreateColumnGroupDialog) {
OpenCreateColumnGroupDialog openDialogCommand = (OpenCreateColumnGroupDialog) command;
loadSelectedColumnsIndexesWithPositions();
if (this.selectionLayer.getFullySelectedColumnPositions().length > 0
&& this.columnIndexesToPositionsMap.size() > 0) {
openDialogCommand.openDialog(this.contextLayer);
} else {
openDialogCommand.openErrorBox(Messages.getString("ColumnGroups.selectNonGroupedColumns")); //$NON-NLS-1$
}
return true;
} else if (command instanceof UngroupColumnCommand) {
handleUngroupCommand();
return true;
} else if (command instanceof RemoveColumnGroupCommand) {
RemoveColumnGroupCommand removeColumnGroupCommand = (RemoveColumnGroupCommand) command;
int columnIndex = removeColumnGroupCommand.getColumnIndex();
handleRemoveColumnGroupCommand(columnIndex);
return true;
} else if (command instanceof DisplayColumnGroupRenameDialogCommand) {
return displayColumnGroupRenameDialog((DisplayColumnGroupRenameDialogCommand) command);
}
return false;
}
private boolean displayColumnGroupRenameDialog(DisplayColumnGroupRenameDialogCommand command) {
int columnPosition = command.getColumnPosition();
ColumnRenameDialog dialog = new ColumnRenameDialog(Display.getDefault().getActiveShell(), null, null);
Rectangle colHeaderBounds = this.contextLayer.getBoundsByPosition(columnPosition, 0);
Point point = new Point(colHeaderBounds.x, colHeaderBounds.y + colHeaderBounds.height);
dialog.setLocation(command.toDisplayCoordinates(point));
dialog.open();
if (!dialog.isCancelPressed()) {
int columnIndex = this.contextLayer.getColumnIndexByPosition(columnPosition);
ColumnGroup columnGroup = this.model.getColumnGroupByIndex(columnIndex);
columnGroup.setName(dialog.getNewColumnLabel());
}
return true;
}
@Override
public Class<IColumnGroupCommand> getCommandClass() {
return IColumnGroupCommand.class;
}
protected void loadSelectedColumnsIndexesWithPositions() {
this.columnIndexesToPositionsMap = new LinkedHashMap<>();
int[] fullySelectedColumns = this.selectionLayer.getFullySelectedColumnPositions();
if (fullySelectedColumns.length > 0) {
for (int index = 0; index < fullySelectedColumns.length; index++) {
final int columnPosition = fullySelectedColumns[index];
int columnIndex = this.selectionLayer.getColumnIndexByPosition(columnPosition);
if (this.model.isPartOfAGroup(columnIndex)) {
this.columnIndexesToPositionsMap.clear();
break;
}
this.columnIndexesToPositionsMap.put(columnIndex, columnPosition);
}
}
}
public void handleGroupColumnsCommand(String columnGroupName) {
try {
Set<Integer> positions = new HashSet<>();
List<Integer> selectedPositions = null;
ColumnGroup group = this.model.getColumnGroupByName(columnGroupName);
if (group != null) {
// a group with the same name already exists so we update the
// existing group as this command handler does not support
// multiple groups with the same name
for (Integer pos : group.getMembers()) {
positions.add(this.selectionLayer.getColumnPositionByIndex(pos));
}
positions.addAll(this.columnIndexesToPositionsMap.values());
selectedPositions = new ArrayList<>(positions);
} else {
selectedPositions = new ArrayList<>(this.columnIndexesToPositionsMap.values());
}
Collections.sort(selectedPositions);
int[] fullySelectedColumns = new int[this.columnIndexesToPositionsMap.size()];
int count = 0;
for (Integer columnIndex : this.columnIndexesToPositionsMap.keySet()) {
fullySelectedColumns[count++] = columnIndex.intValue();
}
// we first need to reorder and then process the group creation,
// otherwise the group reordering will be processed before the
// column reordering which breaks the rendering
this.selectionLayer.doCommand(
new MultiColumnReorderCommand(this.selectionLayer, selectedPositions, selectedPositions.get(0)));
this.model.addColumnsIndexesToGroup(columnGroupName, fullySelectedColumns);
this.selectionLayer.clear();
} catch (Exception t) {
// do nothing
}
this.contextLayer.fireLayerEvent(new GroupColumnsEvent(this.contextLayer));
}
public void handleUngroupCommand() {
// Grab fully selected column positions
int[] fullySelectedColumns = this.selectionLayer.getFullySelectedColumnPositions();
Map<String, Integer> toColumnPositions = new HashMap<>();
if (fullySelectedColumns.length > 0) {
// Pick the ones which belong to a group and remove them from the
// group
for (int index = 0; index < fullySelectedColumns.length; index++) {
final int columnPosition = fullySelectedColumns[index];
int columnIndex = this.selectionLayer.getColumnIndexByPosition(columnPosition);
if (this.model.isPartOfAGroup(columnIndex)
&& !this.model.isPartOfAnUnbreakableGroup(columnIndex)) {
handleRemovalFromGroup(toColumnPositions, columnIndex);
}
}
// The groups which were affected should be reordered to the start
// position, this should group all columns together
Collection<Integer> values = toColumnPositions.values();
final Iterator<Integer> toColumnPositionsIterator = values.iterator();
while (toColumnPositionsIterator.hasNext()) {
Integer toColumnPosition = toColumnPositionsIterator.next();
this.selectionLayer.doCommand(
new ReorderColumnGroupCommand(this.selectionLayer, toColumnPosition, toColumnPosition));
}
this.selectionLayer.clear();
}
this.contextLayer.fireLayerEvent(new UngroupColumnsEvent(this.contextLayer));
}
private void handleRemovalFromGroup(Map<String, Integer> toColumnPositions, int columnIndex) {
ColumnGroup columnGroup = this.model.getColumnGroupByIndex(columnIndex);
final String columnGroupName = columnGroup.getName();
final List<Integer> columnIndexesInGroup = columnGroup.getMembers();
final int columnGroupSize = columnIndexesInGroup.size();
if (!toColumnPositions.containsKey(columnGroupName)) {
for (int colGroupIndex : columnIndexesInGroup) {
if (ColumnGroupUtils.isFirstVisibleColumnIndexInGroup(colGroupIndex, this.selectionLayer, this.model)) {
int toPosition = this.selectionLayer.getColumnPositionByIndex(colGroupIndex);
if (colGroupIndex == columnIndex) {
if (columnGroupSize == 1) {
break;
} else {
toPosition++;
}
}
toColumnPositions.put(columnGroupName, toPosition);
break;
}
}
} else {
if (columnGroupSize - 1 <= 0) {
toColumnPositions.remove(columnGroupName);
}
}
columnGroup.removeColumn(columnIndex);
}
private void handleRemoveColumnGroupCommand(int columnIndex) {
ColumnGroup columnGroup = this.model.getColumnGroupByIndex(columnIndex);
this.model.removeColumnGroup(columnGroup);
}
}