blob: 3ec499a32594ae31c808fe66ce450e5f82f3bdf8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.views.markers.internal;
import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
public class TableSorter extends ViewerSorter implements Comparator {
public static final int MAX_DEPTH = 4;
public static final int ASCENDING = 1;
public static final int DESCENDING = -1;
protected IField[] fields;
protected Collator collator = Collator.getInstance();
protected int[] priorities;
protected int[] directions;
protected int[] defaultPriorities;
protected int[] defaultDirections;
public static final String TAG_DIALOG_SECTION = "sorter"; //$NON-NLS-1$
private static final String TAG_PRIORITY = "priority"; //$NON-NLS-1$
private static final String TAG_DIRECTION = "direction"; //$NON-NLS-1$
private static final String TAG_DEFAULT_PRIORITY = "defaultPriority"; //$NON-NLS-1$
private static final String TAG_DEFAULT_DIRECTION = "defaultDirection"; //$NON-NLS-1$
public TableSorter(TableSorter other) {
this(other.getFields(), other.getDefaultPriorities(), other
.getDefaultDirections());
priorities = other.getPriorities();
directions = other.getDirections();
}
public TableSorter(IField[] properties, final int[] defaultPriorities,
final int[] defaultDirections) {
super();
this.fields = properties;
if (properties == null
|| defaultPriorities == null
|| defaultDirections == null
|| !(properties.length == defaultPriorities.length && properties.length == defaultDirections.length)
|| !verifyPriorities(defaultPriorities)
|| !verifyDirections(defaultDirections)) {
this.priorities = new int[0];
this.directions = new int[0];
this.defaultPriorities = new int[0];
this.defaultDirections = new int[0];
} else {
this.priorities = new int[defaultPriorities.length];
System.arraycopy(defaultPriorities, 0, this.priorities, 0,
priorities.length);
this.directions = new int[defaultDirections.length];
System.arraycopy(defaultDirections, 0, this.directions, 0,
directions.length);
this.defaultPriorities = new int[defaultPriorities.length];
System.arraycopy(defaultPriorities, 0, this.defaultPriorities, 0,
defaultPriorities.length);
this.defaultDirections = new int[defaultDirections.length];
System.arraycopy(defaultDirections, 0, this.defaultDirections, 0,
defaultDirections.length);
}
}
/**
* Return a TableSorter based on the supplied fields.
*
* @param sortingFields
*/
static TableSorter createTableSorter(IField[] sortingFields) {
int[] defaultPriorities = new int[sortingFields.length];
for (int i = 0; i < defaultPriorities.length; i++) {
defaultPriorities[i] = i;
}
int[] directions = new int[sortingFields.length];
for (int i = 0; i < directions.length; i++) {
directions[i] = sortingFields[i].getDefaultDirection();
}
return new TableSorter(sortingFields, defaultPriorities, directions);
}
protected void resetState() {
System
.arraycopy(defaultPriorities, 0, priorities, 0,
priorities.length);
System
.arraycopy(defaultDirections, 0, directions, 0,
directions.length);
}
public void reverseTopPriority() {
directions[priorities[0]] *= -1;
}
public void setTopPriority(IField property) {
for (int i = 0; i < fields.length; i++) {
if (fields[i].equals(property)) {
setTopPriority(i);
return;
}
}
}
public void setTopPriority(int priority) {
if (priority < 0 || priority >= priorities.length)
return;
int index = -1;
for (int i = 0; i < priorities.length; i++) {
if (priorities[i] == priority)
index = i;
}
if (index == -1) {
resetState();
return;
}
// shift the array
for (int i = index; i > 0; i--) {
priorities[i] = priorities[i - 1];
}
priorities[0] = priority;
directions[priority] = defaultDirections[priority];
}
public void setTopPriorityDirection(int direction) {
if (direction == ASCENDING || direction == DESCENDING)
directions[priorities[0]] = direction;
}
public int getTopPriorityDirection() {
return directions[priorities[0]];
}
public int getTopPriority() {
return priorities[0];
}
/**
* Return the field at the top priority.
*
* @return IField
*/
public IField getTopField() {
return fields[getTopPriority()];
}
public int[] getPriorities() {
int[] copy = new int[priorities.length];
System.arraycopy(priorities, 0, copy, 0, copy.length);
return copy;
}
public int[] getDirections() {
int[] copy = new int[directions.length];
System.arraycopy(directions, 0, copy, 0, copy.length);
return copy;
}
public int[] getDefaultPriorities() {
int[] copy = new int[defaultPriorities.length];
System.arraycopy(defaultPriorities, 0, copy, 0, copy.length);
return copy;
}
public int[] getDefaultDirections() {
int[] copy = new int[defaultDirections.length];
System.arraycopy(defaultDirections, 0, copy, 0, copy.length);
return copy;
}
public int compare(Viewer viewer, Object e1, Object e2) {
return compare(e1, e2, 0, true);
}
/**
* Compare obj1 and obj2 at depth. If continueSearching continue searching
* below depth to continue the comparison.
*
* @param obj1
* @param obj2
* @param depth
* @param continueSearching
* @return int
*/
protected int compare(Object obj1, Object obj2, int depth,
boolean continueSearching) {
if (depth >= priorities.length) {
return 0;
}
int column = priorities[depth];
IField property = fields[column];
int result = property.compare(obj1, obj2);
if (result == 0 && continueSearching)
return compare(obj1, obj2, depth + 1, continueSearching);
return result * directions[column];
}
/**
* @return IField[] an array of fields
*/
public IField[] getFields() {
return fields;
}
private boolean verifyPriorities(int[] priorities) {
int length = priorities.length;
boolean[] included = new boolean[length];
Arrays.fill(included, false);
for (int i = 0; i < length; i++) {
int priority = priorities[i];
if (priority < 0 || priority >= length)
return false;
if (included[priority])
return false;
included[priority] = true;
}
return true;
}
private boolean verifyDirections(int[] directions) {
for (int i = 0; i < directions.length; i++) {
if (directions[i] != ASCENDING && directions[i] != DESCENDING)
return false;
}
return true;
}
/*
* (non-Javadoc)
*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object o1, Object o2) {
return compare(null, o1, o2);
}
public void saveState(IDialogSettings dialogSettings) {
if (dialogSettings == null) {
return;
}
IDialogSettings settings = dialogSettings
.getSection(TAG_DIALOG_SECTION);
if (settings == null) {
settings = dialogSettings.addNewSection(TAG_DIALOG_SECTION);
}
for (int i = 0; i < priorities.length; i++) {
settings.put(TAG_PRIORITY + i, priorities[i]);
settings.put(TAG_DIRECTION + i, directions[i]);
settings.put(TAG_DEFAULT_PRIORITY + i, defaultPriorities[i]);
settings.put(TAG_DEFAULT_DIRECTION + i, defaultDirections[i]);
}
}
public void restoreState(IDialogSettings dialogSettings) {
if (dialogSettings == null) {
resetState();
return;
}
IDialogSettings settings = dialogSettings
.getSection(TAG_DIALOG_SECTION);
if (settings == null) {
resetState();
return;
}
try {
for (int i = 0; i < priorities.length; i++) {
String priority = settings.get(TAG_PRIORITY + i);
if (priority == null) {
resetState();
return;
}
int fieldIndex = Integer.parseInt(priority);
//Make sure it is not old data from a different sized array
if(fieldIndex < fields.length)
priorities[i] = fieldIndex;
String direction = settings.get(TAG_DIRECTION + i);
if (direction == null) {
resetState();
return;
}
directions[i] = Integer.parseInt(direction);
String defaultPriority = settings.get(TAG_DEFAULT_PRIORITY + i);
if (defaultPriority == null) {
resetState();
return;
}
defaultPriorities[i] = Integer.parseInt(defaultPriority);
String defaultDirection = settings.get(TAG_DEFAULT_DIRECTION
+ i);
if (defaultDirection == null) {
resetState();
return;
}
defaultDirections[i] = Integer.parseInt(defaultDirection);
}
} catch (NumberFormatException e) {
resetState();
}
}
/**
* Sort the array of markers in lastMarkers in place.
*
* @param viewer
* @param lastMarkers
*/
public void sort(TreeViewer viewer, MarkerList lastMarkers) {
sort(viewer, lastMarkers.getArray());
}
/**
* Sorts the given elements in-place, modifying the given array from index
* start to index end. <
*
* @param viewer
* @param elements
* @param start
* @param end
*/
public void sort(final Viewer viewer, Object[] elements, int start, int end) {
Arrays.sort(elements, start, end, new Comparator() {
public int compare(Object a, Object b) {
return TableSorter.this.compare(viewer, a, b);
}
});
}
}