blob: 13e5de1d80210759cc4f22170a01a8d357e6d5fc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2012 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
* itemis - copied from org.eclipse.ui.navigator.CommonViewerSorter
* to create a non-final and thereby extensible equivalent of it;
* can be removed when bug
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=478731
* has been resolved
*******************************************************************************/
package org.eclipse.sphinx.emf.explorer.sorters;
import java.util.Set;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreePathViewerSorter;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.internal.navigator.CommonNavigatorMessages;
import org.eclipse.ui.internal.navigator.NavigatorContentService;
import org.eclipse.ui.internal.navigator.NavigatorContentServiceContentProvider;
import org.eclipse.ui.internal.navigator.NavigatorPlugin;
import org.eclipse.ui.navigator.INavigatorContentDescriptor;
import org.eclipse.ui.navigator.INavigatorContentService;
import org.eclipse.ui.navigator.INavigatorSorterService;
import org.eclipse.ui.navigator.Priority;
@SuppressWarnings("restriction")
public class NonFinalCommonViewerSorter extends TreePathViewerSorter {
private static final int LEFT_UNDERSTANDS = 1;
private static final int RIGHT_UNDERSTANDS = 2;
private static final int BOTH_UNDERSTAND = LEFT_UNDERSTANDS | RIGHT_UNDERSTANDS;
private INavigatorContentService contentService;
private INavigatorSorterService sorterService;
/**
* Create a sorter service attached to the given content service.
*
* @param aContentService
* The content service used by the viewer that will use this sorter service.
* @since 3.3
*/
public void setContentService(INavigatorContentService aContentService) {
contentService = aContentService;
sorterService = contentService.getSorterService();
}
@Override
public int category(Object element) {
if (contentService == null) {
return 0;
}
INavigatorContentDescriptor source = getSource(element);
return source != null ? source.getSequenceNumber() : Priority.NORMAL_PRIORITY_VALUE;
}
private void logMissingExtension(Object parent, Object object) {
NavigatorPlugin.logError(0, NLS.bind(CommonNavigatorMessages.CommonViewerSorter_NoContentExtensionForObject,
object != null ? object.toString() : "<null>", parent != null ? parent.toString() : "<null>"), null); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public int compare(Viewer viewer, TreePath parentPath, Object e1, Object e2) {
if (contentService == null) {
return -1;
}
INavigatorContentDescriptor sourceOfLvalue = getSource(e1);
INavigatorContentDescriptor sourceOfRvalue = getSource(e2);
Object parent;
if (parentPath == null) {
parent = viewer.getInput();
} else {
parent = parentPath.getLastSegment();
}
if (sourceOfLvalue == null) {
logMissingExtension(parent, e1);
return -1;
}
if (sourceOfRvalue == null) {
logMissingExtension(parent, e2);
return -1;
}
ViewerSorter sorter = null;
// shortcut if contributed by same source
if (sourceOfLvalue == sourceOfRvalue) {
sorter = sorterService.findSorter(sourceOfLvalue, parent, e1, e2);
} else {
boolean flags[] = new boolean[4];
flags[0] = sourceOfLvalue.isTriggerPoint(e1);
flags[1] = sourceOfLvalue.isTriggerPoint(e2);
flags[2] = sourceOfRvalue.isTriggerPoint(e1);
flags[3] = sourceOfRvalue.isTriggerPoint(e2);
int whoknows = 0;
whoknows = whoknows | (flags[0] & flags[1] ? LEFT_UNDERSTANDS : 0);
whoknows = whoknows | (flags[2] & flags[3] ? RIGHT_UNDERSTANDS : 0);
switch (whoknows) {
case BOTH_UNDERSTAND:
sorter = sourceOfLvalue.getSequenceNumber() < sourceOfRvalue.getSequenceNumber()
? sorterService.findSorter(sourceOfLvalue, parent, e1, e2) : sorterService.findSorter(sourceOfRvalue, parent, e1, e2);
break;
case LEFT_UNDERSTANDS:
sorter = sorterService.findSorter(sourceOfLvalue, parent, e1, e2);
break;
case RIGHT_UNDERSTANDS:
sorter = sorterService.findSorter(sourceOfRvalue, parent, e1, e2);
break;
}
}
if (sorter != null) {
return sorter.compare(viewer, e1, e2);
}
int categoryDelta = category(e1) - category(e2);
if (categoryDelta == 0) {
return super.compare(viewer, e1, e2);
}
return categoryDelta;
}
@Override
public boolean isSorterProperty(Object element, String property) {
// Have to get the parent path from the content provider
NavigatorContentServiceContentProvider cp = (NavigatorContentServiceContentProvider) contentService.createCommonContentProvider();
TreePath[] parentPaths = cp.getParents(element);
for (TreePath parentPath : parentPaths) {
if (isSorterProperty(parentPath, element, property)) {
return true;
}
}
return false;
}
@Override
public boolean isSorterProperty(TreePath parentPath, Object element, String property) {
INavigatorContentDescriptor contentDesc = getSource(element);
if (parentPath.getSegmentCount() == 0) {
return false;
}
ViewerSorter sorter = sorterService.findSorter(contentDesc, parentPath.getLastSegment(), element, null);
if (sorter != null) {
return sorter.isSorterProperty(element, property);
}
return false;
}
private INavigatorContentDescriptor getSource(Object o) {
// Fast path - just an optimization for the common case
INavigatorContentDescriptor ncd = ((NavigatorContentService) contentService).getSourceOfContribution(o);
if (ncd != null) {
return ncd;
}
Set<?> descriptors = ((NavigatorContentService) contentService).findDescriptorsByTriggerPoint(o, NavigatorContentService.CONSIDER_OVERRIDES);
if (descriptors != null && descriptors.size() > 0) {
ncd = (INavigatorContentDescriptor) descriptors.iterator().next();
return ncd;
}
return null;
}
}