/* * Copyright (c) 2015 the original author or authors. * 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: * Etienne Studer & Donát Csikós (Gradle Inc.) - initial API and implementation and initial documentation */ package org.eclipse.buildship.ui.view.task; import com.google.common.collect.Ordering; import com.gradleware.tooling.toolingmodel.OmniEclipseProject; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.buildship.ui.view.task.TaskNode.TaskNodeType; /** * Sorts {@link TaskNode} instances based on their type and/or visibility. */ public final class TaskNodeViewerSorter extends ViewerComparator { private final Ordering<ProjectNode> projectNodeOrdering; private final Ordering<TaskNode> taskNodeOrdering; private final Ordering<FaultyProjectNode> faultyProjectOrdering; private TaskNodeViewerSorter(Ordering<ProjectNode> projectNodeOrdering, Ordering<TaskNode> taskNodeOrdering) { this.projectNodeOrdering = projectNodeOrdering; this.taskNodeOrdering = taskNodeOrdering; this.faultyProjectOrdering = createLexicographicalFaultyProjectOrdering(); } @Override public int compare(Viewer viewer, Object leftNode, Object rightNode) { if (leftNode instanceof ProjectNode && rightNode instanceof ProjectNode) { ProjectNode left = (ProjectNode) leftNode; ProjectNode right = (ProjectNode) rightNode; return this.projectNodeOrdering.compare(left, right); } else if (leftNode instanceof TaskNode && rightNode instanceof TaskNode) { TaskNode left = (TaskNode) leftNode; TaskNode right = (TaskNode) rightNode; return this.taskNodeOrdering.compare(left, right); } else if (leftNode instanceof FaultyProjectNode && rightNode instanceof ProjectNode) { return 1; } else if (leftNode instanceof ProjectNode && rightNode instanceof FaultyProjectNode) { return -1; } else if (leftNode instanceof FaultyProjectNode && rightNode instanceof FaultyProjectNode) { FaultyProjectNode left = (FaultyProjectNode) leftNode; FaultyProjectNode right = (FaultyProjectNode) rightNode; return this.faultyProjectOrdering.compare(left, right); } else { return super.compare(viewer, leftNode, rightNode); } } /** * Creates a new instance. * <p> * The arguments define the properties of the sorting. If both * {@code TaskViewState#isSortByType} and {@code TaskViewState#isSortByVisibility} are true, * then first we order the nodes by type, then by visibility. If exactly one argument is true, * than that will be the sorting strategy. * <p> * If there is a tie in the sorting or both criteria are false, then the alphabetical ordering * is applied. * * @param state the state from which to derive how to sort the nodes * @return the new sorter instance */ public static TaskNodeViewerSorter createFor(TaskViewState state) { Ordering<ProjectNode> projectOrdering = createProjectNodeOrdering(); Ordering<TaskNode> taskOrdering = createTaskNodeOrdering(state.isSortByType(), state.isSortByVisibility()); return new TaskNodeViewerSorter(projectOrdering, taskOrdering); } private static Ordering<ProjectNode> createProjectNodeOrdering() { return new Ordering<ProjectNode>() { @Override public int compare(ProjectNode left, ProjectNode right) { OmniEclipseProject leftRoot = left.getEclipseProject().getRoot(); OmniEclipseProject rightRoot = right.getEclipseProject().getRoot(); if (leftRoot == rightRoot) { // do not change sorting of projects that belong to the same root return 0; } else { // projects that do not belong to the same root should be grouped by the name of // their root projects return leftRoot.getName().compareTo(rightRoot.getName()); } } }; } private static Ordering<TaskNode> createTaskNodeOrdering(boolean byType, boolean byVisibility) { // sort (optionally) by type, then (optionally) by visibility and // at the end (always) lexicographically Ordering<TaskNode> ord = createLexicographicalTaskOrdering(); if (byVisibility) { ord = createByVisibilityOrdering().compound(ord); } if (byType) { ord = createByTypeOrdering().compound(ord); } return ord; } private static Ordering<TaskNode> createLexicographicalTaskOrdering() { return new Ordering<TaskNode>() { @Override public int compare(TaskNode left, TaskNode right) { return left.getName().compareTo(right.getName()); } }; } private static Ordering<FaultyProjectNode> createLexicographicalFaultyProjectOrdering() { return new Ordering<FaultyProjectNode>() { @Override public int compare(FaultyProjectNode left, FaultyProjectNode right) { return left.getWorkspaceProject().get().getName().compareTo(right.getWorkspaceProject().get().getName()); } }; } private static Ordering<TaskNode> createByVisibilityOrdering() { return new Ordering<TaskNode>() { @Override public int compare(TaskNode left, TaskNode right) { int leftOrdinal = toOrdinal(left); int rightOrdinal = toOrdinal(right); return (leftOrdinal < rightOrdinal ? -1 : (leftOrdinal == rightOrdinal ? 0 : 1)); } private int toOrdinal(TaskNode node) { // public tasks to be shown first return node.isPublic() ? 1 : 2; } }; } private static Ordering<TaskNode> createByTypeOrdering() { return new Ordering<TaskNode>() { @Override public int compare(TaskNode left, TaskNode right) { int leftOrdinal = toOrdinal(left.getType()); int rightOrdinal = toOrdinal(right.getType()); return (leftOrdinal < rightOrdinal ? -1 : (leftOrdinal == rightOrdinal ? 0 : 1)); } private int toOrdinal(TaskNodeType type) { // project tasks to be shown first return type == TaskNodeType.PROJECT_TASK_NODE ? 1 : 2; } }; } }