blob: 2e00f75be42693ae2987b8947ac28023c3d0efb0 [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.columnRename;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import org.eclipse.nebula.widgets.nattable.coordinate.Range;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.layer.event.StructuralDiff;
import org.eclipse.nebula.widgets.nattable.layer.event.StructuralDiff.DiffTypeEnum;
import org.eclipse.nebula.widgets.nattable.persistence.IPersistable;
import org.eclipse.nebula.widgets.nattable.util.PersistenceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Helper class for handling column renaming by user interactions on the column
* header.
*/
public class RenameColumnHelper implements IPersistable {
private static final Logger LOG = LoggerFactory.getLogger(RenameColumnHelper.class);
public static final String PERSISTENCE_KEY_RENAMED_COLUMN_HEADERS = ".renamedColumnHeaders"; //$NON-NLS-1$
private final ColumnHeaderLayer columnHeaderLayer;
/**
* Tracks the renamed labels provided by the user.
*/
protected Map<Integer, String> renamedColumnsLabelsByIndex = new TreeMap<>();
/**
*
* @param columnHeaderLayer
* The {@link ColumnHeaderLayer} this helper is connected to.
*/
public RenameColumnHelper(ColumnHeaderLayer columnHeaderLayer) {
this.columnHeaderLayer = columnHeaderLayer;
}
/**
* Rename the column at the given position. Note: This does not change the
* underlying column name.
*
* @param columnPosition
* The column position of the column that should be renamed.
* @param customColumnName
* The name that should used as the user defined column name.
*
* @return <code>true</code> if the column at the given position was
* successfully changed.
*/
public boolean renameColumnPosition(int columnPosition, String customColumnName) {
int index = this.columnHeaderLayer.getColumnIndexByPosition(columnPosition);
return renameColumnIndex(index, customColumnName);
}
/**
* Rename the column at the given index. Note: This does not change the
* underlying column name.
*
* @param index
* The column index of the column that should be renamed.
* @param customColumnName
* The name that should used as the user defined column name.
*
* @return <code>true</code> if the column at the given index was
* successfully changed.
*/
public boolean renameColumnIndex(int index, String customColumnName) {
if (index >= 0) {
if (customColumnName == null) {
this.renamedColumnsLabelsByIndex.remove(index);
} else {
this.renamedColumnsLabelsByIndex.put(index, customColumnName);
}
return true;
}
return false;
}
/**
* @param columnIndex
* the column index
* @return the custom label for this column as specified by the user Null if
* the columns is not renamed
*/
public String getRenamedColumnLabel(int columnIndex) {
return this.renamedColumnsLabelsByIndex.get(columnIndex);
}
/**
* @param columnIndex
* the column index
* @return <code>true</code> if the column at the specified index was
* renamed by a user.
*/
public boolean isColumnRenamed(int columnIndex) {
return this.renamedColumnsLabelsByIndex.get(columnIndex) != null;
}
/**
* @return <code>true</code> if a user renamed any column.
*/
public boolean isAnyColumnRenamed() {
return this.renamedColumnsLabelsByIndex.size() > 0;
}
/**
* Handle the given collection of {@link StructuralDiff} objects to update
* the indexes of the renamed column labels.
*
* @param columnDiffs
* The {@link StructuralDiff}s to handle
* @since 1.4
*/
public void handleStructuralChanges(Collection<StructuralDiff> columnDiffs) {
// the number of all deleted columns that don't have a corresponding
// index anymore (last column cases)
List<Integer> toRemove = new ArrayList<>();
for (StructuralDiff columnDiff : columnDiffs) {
if (columnDiff.getDiffType() != null
&& columnDiff.getDiffType().equals(DiffTypeEnum.DELETE)) {
Range beforePositionRange = columnDiff.getBeforePositionRange();
for (int i = beforePositionRange.start; i < beforePositionRange.end; i++) {
int index = i;
if (index >= 0)
toRemove.add(index);
}
}
}
// remove the column indexes that are deleted
for (Integer r : toRemove) {
this.renamedColumnsLabelsByIndex.remove(r);
}
// modify column indexes regarding the deleted columns
List<Integer> indices = new ArrayList<>(this.renamedColumnsLabelsByIndex.keySet());
Collections.sort(indices);
Map<Integer, String> modified = new TreeMap<>();
for (Integer column : indices) {
// check number of removed indexes that are lower than the current
// one
int deletedBefore = 0;
for (Integer removed : toRemove) {
if (removed < column) {
deletedBefore++;
}
}
int modColumn = column - deletedBefore;
if (modColumn >= 0)
modified.put(modColumn, this.renamedColumnsLabelsByIndex.get(column));
}
this.renamedColumnsLabelsByIndex.clear();
this.renamedColumnsLabelsByIndex.putAll(modified);
for (StructuralDiff columnDiff : columnDiffs) {
if (columnDiff.getDiffType() != null
&& columnDiff.getDiffType().equals(DiffTypeEnum.ADD)) {
indices = new ArrayList<>(this.renamedColumnsLabelsByIndex.keySet());
Collections.sort(indices);
Range beforePositionRange = columnDiff.getBeforePositionRange();
Range afterPositionRange = columnDiff.getAfterPositionRange();
Map<Integer, String> modifiedColumns = new TreeMap<>();
int beforeIndex = this.columnHeaderLayer.getColumnIndexByPosition(beforePositionRange.start);
for (Integer column : indices) {
if (column >= beforeIndex) {
modifiedColumns.put(column + (afterPositionRange.end - afterPositionRange.start), this.renamedColumnsLabelsByIndex.get(column));
} else {
modifiedColumns.put(column, this.renamedColumnsLabelsByIndex.get(column));
}
}
this.renamedColumnsLabelsByIndex.clear();
this.renamedColumnsLabelsByIndex.putAll(modifiedColumns);
}
}
}
@Override
public void loadState(String prefix, Properties properties) {
Object property = properties.get(prefix + PERSISTENCE_KEY_RENAMED_COLUMN_HEADERS);
try {
this.renamedColumnsLabelsByIndex = PersistenceUtils.parseString(property);
} catch (Exception e) {
LOG.error("Error while restoring renamed column headers: {}", e.getMessage()); //$NON-NLS-1$
LOG.error("Skipping restore."); //$NON-NLS-1$
this.renamedColumnsLabelsByIndex.clear();
}
}
@Override
public void saveState(String prefix, Properties properties) {
String string = PersistenceUtils.mapAsString(this.renamedColumnsLabelsByIndex);
if (string != null && string.length() > 0) {
properties.put(prefix + PERSISTENCE_KEY_RENAMED_COLUMN_HEADERS, string);
}
}
}