/******************************************************************************* * Copyright (c) 2000, 2015 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.tasklist; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; /** * This is the task list's sorter. */ class TaskSorter extends ViewerComparator { private int[] priorities; private int[] directions; final static int ASCENDING = 1; final static int DEFAULT_DIRECTION = 0; final static int DESCENDING = -1; final static int TYPE = 0; final static int COMPLETION = 1; final static int PRIORITY = 2; final static int DESCRIPTION = 3; final static int RESOURCE = 4; final static int FOLDER = 5; final static int LOCATION = 6; final static int CREATION_TIME = 7; final static int[] DEFAULT_PRIORITIES = { FOLDER, RESOURCE, LOCATION, DESCRIPTION, TYPE, PRIORITY, COMPLETION, CREATION_TIME }; final static int[] DEFAULT_DIRECTIONS = { DESCENDING, //type DESCENDING, //completed DESCENDING, //priority ASCENDING, //description ASCENDING, //resource ASCENDING, //folder ASCENDING, //location ASCENDING }; //creation time /** * Creates a new task sorter. */ public TaskSorter() { resetState(); } /** * Compares two markers, sorting first by the main column of this sorter, * then by subsequent columns, depending on the column sort order. */ @Override public int compare(Viewer viewer, Object e1, Object e2) { IMarker m1 = (IMarker) e1; IMarker m2 = (IMarker) e2; return compareColumnValue(m1, m2, 0); } 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; break; } } 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] = DEFAULT_DIRECTIONS[priority]; } public int getTopPriority() { return priorities[0]; } public int[] getPriorities() { return priorities; } public void setTopPriorityDirection(int direction) { if (direction == DEFAULT_DIRECTION) { directions[priorities[0]] = DEFAULT_DIRECTIONS[priorities[0]]; } else if (direction == ASCENDING || direction == DESCENDING) { directions[priorities[0]] = direction; } } public int getTopPriorityDirection() { return directions[priorities[0]]; } public void reverseTopPriority() { directions[priorities[0]] *= -1; } public void resetState() { priorities = new int[DEFAULT_PRIORITIES.length]; System.arraycopy(DEFAULT_PRIORITIES, 0, priorities, 0, priorities.length); directions = new int[DEFAULT_DIRECTIONS.length]; System.arraycopy(DEFAULT_DIRECTIONS, 0, directions, 0, directions.length); } /** * Compares two markers, based only on the value of the specified column. */ private int compareColumnValue(IMarker m1, IMarker m2, int depth) { if (depth >= priorities.length) { return 0; } int columnNumber = priorities[depth]; int direction = directions[columnNumber]; switch (columnNumber) { case TYPE: { /* category */ int result = getCategoryOrder(m1) - getCategoryOrder(m2); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } case COMPLETION: { /* completed */ int result = getCompletedOrder(m1) - getCompletedOrder(m2); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } case PRIORITY: { /* priority */ int result = getPriorityOrder(m1) - getPriorityOrder(m2); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } case DESCRIPTION: { /* description */ int result = getComparator().compare(MarkerUtil.getMessage(m1), MarkerUtil .getMessage(m2)); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } case RESOURCE: { /* resource name */ IResource r1 = m1.getResource(); IResource r2 = m2.getResource(); String n1 = r1.getName(); String n2 = r2.getName(); int result = getComparator().compare(n1, n2); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } case FOLDER: { /* container name */ String c1 = MarkerUtil.getContainerName(m1); String c2 = MarkerUtil.getContainerName(m2); int result = c1.equals(c2) ? 0 : getComparator().compare(c1, c2); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } case LOCATION: { /* line and location */ int result = compareLineAndLocation(m1, m2); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } case CREATION_TIME: { /* creation time */ int result = compareCreationTime(m1, m2); if (result == 0) { return compareColumnValue(m1, m2, depth + 1); } return result * direction; } default: return 0; } } /** * Compares the creation time of two markers. */ private int compareCreationTime(IMarker m1, IMarker m2) { long result; try { result = m1.getCreationTime() - m2.getCreationTime(); } catch (CoreException e) { result = 0; } if (result > 0) { return 1; } else if (result < 0) { return -1; } return 0; } /** * Compares the line number and location of the two markers. * If line number is specified for both, this sorts first by line number (numerically), * then by start offset (numerically), then by location (textually). * If line number is not specified for either, this sorts by location. * Otherwise, if only one has a line number, this sorts by the combined text for line number and location. */ private int compareLineAndLocation(IMarker m1, IMarker m2) { int line1 = MarkerUtil.getLineNumber(m1); int line2 = MarkerUtil.getLineNumber(m2); if (line1 != -1 && line2 != -1) { if (line1 != line2) { return line1 - line2; } int start1 = MarkerUtil.getCharStart(m1); int start2 = MarkerUtil.getCharStart(m2); if (start1 != -1 && start2 != -1) { if (start1 != start2) { return start1 - start2; } } String loc1 = MarkerUtil.getLocation(m1); String loc2 = MarkerUtil.getLocation(m2); return getComparator().compare(loc1, loc2); } if (line1 == -1 && line2 == -1) { String loc1 = MarkerUtil.getLocation(m1); String loc2 = MarkerUtil.getLocation(m2); return getComparator().compare(loc1, loc2); } String loc1 = MarkerUtil.getLineAndLocation(m1); String loc2 = MarkerUtil.getLineAndLocation(m2); return getComparator().compare(loc1, loc2); } /** * Returns the sort order for the given marker based on its category. * Lower numbers appear first. */ private int getCategoryOrder(IMarker marker) { if (MarkerUtil.isMarkerType(marker, IMarker.PROBLEM)) { switch (MarkerUtil.getSeverity(marker)) { case IMarker.SEVERITY_ERROR: return 4; case IMarker.SEVERITY_WARNING: return 3; case IMarker.SEVERITY_INFO: return 2; } } else if (MarkerUtil.isMarkerType(marker, IMarker.TASK)) { return 1; } return 1000; } /** * Returns the sort order for the given marker based on its completion status. * Lower numbers appear first. */ private int getCompletedOrder(IMarker marker) { if (MarkerUtil.isMarkerType(marker, IMarker.TASK)) { return MarkerUtil.isComplete(marker) ? 2 : 1; } return 0; } /** * Returns the sort order for the given marker based on its priority. */ private int getPriorityOrder(IMarker marker) { if (MarkerUtil.isMarkerType(marker, IMarker.TASK)) { return MarkerUtil.getPriority(marker); } return -1; } public void saveState(IDialogSettings settings) { if (settings == null) { return; } for (int i = 0; i < directions.length; i++) { settings.put("direction" + i, directions[i]);//$NON-NLS-1$ settings.put("priority" + i, priorities[i]);//$NON-NLS-1$ } } public void restoreState(IDialogSettings settings) { if (settings == null) { return; } try { for (int i = 0; i < priorities.length; i++) { directions[i] = settings.getInt("direction" + i);//$NON-NLS-1$ priorities[i] = settings.getInt("priority" + i);//$NON-NLS-1$ } } catch (NumberFormatException e) { resetState(); } } }