/*******************************************************************************
* Copyright (c) 2012, 2014 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
* Roman Flueckiger <roman.flueckiger@mac.com> - Bug 451486
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.columnChooser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.nebula.widgets.nattable.Messages;
import org.eclipse.nebula.widgets.nattable.columnChooser.gui.ColumnChooserDialog;
import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupHeaderLayer;
import org.eclipse.nebula.widgets.nattable.group.ColumnGroupModel;
import org.eclipse.nebula.widgets.nattable.group.command.ColumnGroupExpandCollapseCommand;
import org.eclipse.nebula.widgets.nattable.group.command.ReorderColumnGroupCommand;
import org.eclipse.nebula.widgets.nattable.group.command.ReorderColumnsAndGroupsCommand;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.reorder.command.ColumnReorderCommand;
import org.eclipse.nebula.widgets.nattable.reorder.command.MultiColumnReorderCommand;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
import org.eclipse.swt.widgets.Shell;
public class ColumnChooser {
private static final Comparator<ColumnEntry> COLUMN_ENTRY_LABEL_COMPARATOR = new Comparator<ColumnEntry>() {
@Override
public int compare(ColumnEntry o1, ColumnEntry o2) {
return o1.getLabel().compareToIgnoreCase(o2.getLabel());
}
};
protected final ColumnChooserDialog columnChooserDialog;
protected final ColumnHideShowLayer columnHideShowLayer;
protected final DataLayer columnHeaderDataLayer;
protected final ColumnHeaderLayer columnHeaderLayer;
protected List<ColumnEntry> hiddenColumnEntries;
protected List<ColumnEntry> visibleColumnsEntries;
protected final ColumnGroupModel columnGroupModel;
protected final SelectionLayer selectionLayer;
protected final boolean sortAvailableColumns;
protected final boolean preventHidingAllColumns;
List<Integer> nonModifiableColumns = new ArrayList<Integer>();
public ColumnChooser(Shell shell, SelectionLayer selectionLayer,
ColumnHideShowLayer columnHideShowLayer,
ColumnHeaderLayer columnHeaderLayer,
DataLayer columnHeaderDataLayer,
ColumnGroupHeaderLayer columnGroupHeaderLayer,
ColumnGroupModel columnGroupModel,
boolean sortAvailableColumns) {
this(shell, selectionLayer, columnHideShowLayer, columnHeaderLayer, columnHeaderDataLayer, columnGroupHeaderLayer, columnGroupModel, sortAvailableColumns, false);
}
public ColumnChooser(Shell shell, SelectionLayer selectionLayer,
ColumnHideShowLayer columnHideShowLayer,
ColumnHeaderLayer columnHeaderLayer,
DataLayer columnHeaderDataLayer,
ColumnGroupHeaderLayer columnGroupHeaderLayer,
ColumnGroupModel columnGroupModel,
boolean sortAvailableColumns,
boolean preventHidingAllColumns) {
this.selectionLayer = selectionLayer;
this.columnHideShowLayer = columnHideShowLayer;
this.columnHeaderLayer = columnHeaderLayer;
this.columnHeaderDataLayer = columnHeaderDataLayer;
this.columnGroupModel = columnGroupModel;
this.sortAvailableColumns = sortAvailableColumns;
this.preventHidingAllColumns = preventHidingAllColumns;
this.columnChooserDialog = new ColumnChooserDialog(shell, Messages.getString("ColumnChooser.availableColumns"), Messages.getString("ColumnChooser.selectedColumns")); //$NON-NLS-1$ //$NON-NLS-2$
this.columnChooserDialog.setPreventHidingAllColumns(preventHidingAllColumns);
}
public void setDialogSettings(IDialogSettings dialogSettings) {
this.columnChooserDialog.setDialogSettings(dialogSettings);
}
public void openDialog() {
this.columnChooserDialog.create();
this.hiddenColumnEntries = getHiddenColumnEntries();
this.columnChooserDialog.populateAvailableTree(this.hiddenColumnEntries, this.columnGroupModel);
this.visibleColumnsEntries = getVisibleColumnEntries();
this.columnChooserDialog.populateSelectedTree(this.visibleColumnsEntries, this.columnGroupModel);
this.columnChooserDialog.expandAllLeaves();
addListenersOnColumnChooserDialog();
this.columnChooserDialog.open();
}
private void addListenersOnColumnChooserDialog() {
this.columnChooserDialog.addListener(new ISelectionTreeListener() {
@Override
public void itemsRemoved(List<ColumnEntry> removedItems) {
ColumnChooserUtils.hideColumnEntries(removedItems, ColumnChooser.this.columnHideShowLayer);
refreshColumnChooserDialog();
}
@Override
public void itemsSelected(List<ColumnEntry> addedItems) {
ColumnChooserUtils.showColumnEntries(addedItems, ColumnChooser.this.columnHideShowLayer);
refreshColumnChooserDialog();
ColumnChooser.this.columnChooserDialog
.setSelectionIncludingNested(ColumnChooserUtils.getColumnEntryIndexes(addedItems));
}
@Override
public void itemsMoved(MoveDirectionEnum direction,
List<ColumnGroupEntry> movedColumnGroupEntries,
List<ColumnEntry> movedColumnEntries,
List<List<Integer>> fromPositions,
List<Integer> toPositions) {
moveItems(direction, movedColumnGroupEntries, movedColumnEntries, fromPositions, toPositions);
}
/**
* Fire appropriate commands depending on the events received from
* the column chooser dialog
*
* @param direction
* @param movedColumnGroupEntries
* @param movedColumnEntries
* @param fromPositions
* @param toPositions
*/
private void moveItems(MoveDirectionEnum direction,
List<ColumnGroupEntry> movedColumnGroupEntries,
List<ColumnEntry> movedColumnEntries,
List<List<Integer>> fromPositions,
List<Integer> toPositions) {
for (int i = 0; i < fromPositions.size(); i++) {
boolean columnGroupMoved = columnGroupMoved(fromPositions.get(i), movedColumnGroupEntries);
boolean multipleColumnsMoved = fromPositions.get(i).size() > 1;
ILayerCommand command = null;
if (!columnGroupMoved && !multipleColumnsMoved) {
int fromPosition = fromPositions.get(i).get(0).intValue();
int toPosition = adjustToPosition(direction, toPositions.get(i).intValue());
command = new ColumnReorderCommand(ColumnChooser.this.columnHideShowLayer, fromPosition, toPosition);
} else if (columnGroupMoved && multipleColumnsMoved) {
command = new ReorderColumnsAndGroupsCommand(ColumnChooser.this.columnHideShowLayer, fromPositions.get(i),
adjustToPosition(direction, toPositions.get(i)));
} else if (!columnGroupMoved && multipleColumnsMoved) {
command = new MultiColumnReorderCommand(ColumnChooser.this.columnHideShowLayer, fromPositions.get(i),
adjustToPosition(direction, toPositions.get(i)));
} else if (columnGroupMoved && !multipleColumnsMoved) {
command = new ReorderColumnGroupCommand(ColumnChooser.this.columnHideShowLayer, fromPositions.get(i)
.get(0), adjustToPosition(direction, toPositions.get(i)));
}
ColumnChooser.this.columnHideShowLayer.doCommand(command);
}
refreshColumnChooserDialog();
ColumnChooser.this.columnChooserDialog.setSelectionIncludingNested(ColumnChooserUtils.getColumnEntryIndexes(movedColumnEntries));
}
private int adjustToPosition(MoveDirectionEnum direction, Integer toColumnPosition) {
if (MoveDirectionEnum.DOWN == direction) {
return toColumnPosition + 1;
} else {
return toColumnPosition;
}
}
private boolean columnGroupMoved(List<Integer> fromPositions, List<ColumnGroupEntry> movedColumnGroupEntries) {
for (ColumnGroupEntry columnGroupEntry : movedColumnGroupEntries) {
if (fromPositions.contains(columnGroupEntry.getFirstElementPosition())) {
return true;
}
}
return false;
}
@Override
public void itemsCollapsed(ColumnGroupEntry columnGroupEntry) {
int index = columnGroupEntry.getFirstElementIndex().intValue();
int position = ColumnChooser.this.selectionLayer.getColumnPositionByIndex(index);
ColumnChooser.this.selectionLayer.doCommand(new ColumnGroupExpandCollapseCommand(ColumnChooser.this.selectionLayer, position));
}
@Override
public void itemsExpanded(ColumnGroupEntry columnGroupEntry) {
int index = columnGroupEntry.getFirstElementIndex().intValue();
int position = ColumnChooser.this.selectionLayer.getColumnPositionByIndex(index);
ColumnChooser.this.selectionLayer.doCommand(new ColumnGroupExpandCollapseCommand(ColumnChooser.this.selectionLayer, position));
}
});
}
private void refreshColumnChooserDialog() {
this.hiddenColumnEntries = getHiddenColumnEntries();
this.visibleColumnsEntries = getVisibleColumnEntries();
this.columnChooserDialog.removeAllLeaves();
this.columnChooserDialog.populateSelectedTree(this.visibleColumnsEntries, this.columnGroupModel);
this.columnChooserDialog.populateAvailableTree(this.hiddenColumnEntries, this.columnGroupModel);
this.columnChooserDialog.expandAllLeaves();
}
protected List<ColumnEntry> getHiddenColumnEntries() {
List<ColumnEntry> columnEntries = ColumnChooserUtils.getHiddenColumnEntries(this.columnHideShowLayer, this.columnHeaderLayer, this.columnHeaderDataLayer);
if (!this.nonModifiableColumns.isEmpty()) {
for (Iterator<ColumnEntry> it = columnEntries.iterator(); it.hasNext();) {
ColumnEntry entry = it.next();
if (this.nonModifiableColumns.contains(entry.getIndex())) {
it.remove();
}
}
}
if (this.sortAvailableColumns) {
Collections.sort(columnEntries, COLUMN_ENTRY_LABEL_COMPARATOR);
}
return columnEntries;
}
private List<ColumnEntry> getVisibleColumnEntries() {
List<ColumnEntry> columnEntries = ColumnChooserUtils.getVisibleColumnsEntries(this.columnHideShowLayer, this.columnHeaderLayer, this.columnHeaderDataLayer);
if (!this.nonModifiableColumns.isEmpty()) {
for (Iterator<ColumnEntry> it = columnEntries.iterator(); it.hasNext();) {
ColumnEntry entry = it.next();
if (this.nonModifiableColumns.contains(entry.getIndex())) {
it.remove();
}
}
}
return columnEntries;
}
public void addNonModifiableColumn(Integer... columnIndexes) {
for (Integer column : columnIndexes) {
this.nonModifiableColumns.add(column);
}
}
public void removeNonModifiableColumn(Integer... columnIndexes) {
for (Integer column : columnIndexes) {
this.nonModifiableColumns.remove(column);
}
}
}