/******************************************************************************* * Copyright (c) 2000, 2006 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.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.ViewerComparator; public class TableComparator extends ViewerComparator 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 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 TableComparator(TableComparator other) { this(other.getFields(), other.getDefaultPriorities(), other .getDefaultDirections()); priorities = other.getPriorities(); directions = other.getDirections(); } public TableComparator(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 TableComparator 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 TableComparator(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 TableComparator.this.compare(viewer, a, b); } }); } }