package org.openlca.app.navigation;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.CommonViewer;
import org.openlca.app.App;
import org.openlca.app.db.Database;
import org.openlca.app.db.IDatabaseConfiguration;
import org.openlca.app.navigation.actions.DatabaseActivateAction;
import org.openlca.app.util.Colors;
import org.openlca.app.util.viewers.Viewers;
import com.google.common.base.Objects;
public class Navigator extends CommonNavigator {
public static String ID = "views.navigation";
private NavigationRoot root;
@Override
protected Object getInitialInput() {
root = new NavigationRoot();
return root;
}
@Override
protected CommonViewer createCommonViewer(Composite aParent) {
CommonViewer viewer = super.createCommonViewer(aParent);
viewer.getTree().setBackground(Colors.systemColor(SWT.COLOR_WIDGET_BACKGROUND));
return viewer;
}
@Override
protected void initListeners(TreeViewer viewer) {
super.initListeners(viewer);
viewer.setUseHashlookup(true);
ColumnViewerToolTipSupport.enableFor(viewer);
viewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
onDoubleClick(event.getSelection());
}
});
}
private void onDoubleClick(ISelection selection) {
Object element = Viewers.getFirst(selection);
if (element instanceof ModelElement) {
ModelElement e = (ModelElement) element;
App.openEditor(e.getContent());
} else if (element instanceof DatabaseElement) {
DatabaseElement e = (DatabaseElement) element;
IDatabaseConfiguration config = e.getContent();
if (config != null && !Database.isActive(config)) {
new DatabaseActivateAction(config).run();
}
}
}
/**
* Get the root of the navigation tree.
*/
public NavigationRoot getRoot() {
return root;
}
/**
* Refresh the navigation view if it is available.
*/
public static void refresh() {
CommonViewer viewer = getNavigationViewer();
NavigationRoot root = getNavigationRoot();
if (viewer == null || root == null)
return;
Object[] oldExpansion = viewer.getExpandedElements();
root.update();
viewer.refresh();
setRefreshedExpansion(viewer, oldExpansion);
}
/**
* Refreshes the content *under* the given element.
*/
public static void refresh(INavigationElement<?> element) {
CommonViewer viewer = getNavigationViewer();
if (viewer == null || element == null)
return;
element.update();
Object[] oldExpansion = viewer.getExpandedElements();
viewer.refresh(element);
updateLabels(viewer, element);
if (oldExpansion == null)
return;
setRefreshedExpansion(viewer, oldExpansion);
}
private static void updateLabels(CommonViewer viewer,
INavigationElement<?> element) {
TreeItem item = findItem(viewer, element);
if (item == null)
return;
do {
viewer.doUpdateItem(item);
item = item.getParentItem();
} while (item != null);
}
private static TreeItem findItem(CommonViewer viewer,
INavigationElement<?> element) {
Stack<TreeItem> items = new Stack<>();
for (TreeItem item : viewer.getTree().getItems())
items.add(item);
while (!items.empty()) {
TreeItem next = items.pop();
if (itemEqualsElement(next, element))
return next;
for (TreeItem item : next.getItems())
items.add(item);
}
return null;
}
private static boolean itemEqualsElement(TreeItem item,
INavigationElement<?> element) {
INavigationElement<?> data = (INavigationElement<?>) item.getData();
if (data == null)
return false;
return Objects.equal(data.getContent(), element.getContent());
}
/**
* Expands the elements in the viewer that have the same content as in the
* elements of the <code>oldExpansion</code> array.
*/
private static void setRefreshedExpansion(CommonViewer viewer,
Object[] oldExpansion) {
List<INavigationElement<?>> newExpanded = new ArrayList<>();
for (Object expandedElem : oldExpansion) {
if (!(expandedElem instanceof INavigationElement))
continue;
INavigationElement<?> oldElem = (INavigationElement<?>) expandedElem;
INavigationElement<?> newElem = findElement(oldElem.getContent());
if (newElem != null)
newExpanded.add(newElem);
}
viewer.setExpandedElements(newExpanded.toArray());
}
/**
* Selects the navigation element with the given *content* in the tree.
*/
public static void select(Object element) {
if (element == null)
return;
Navigator instance = getInstance();
if (instance == null)
return;
INavigationElement<?> navElement = findElement(element);
if (navElement == null)
return;
instance.selectReveal(new StructuredSelection(navElement));
}
private static CommonViewer getNavigationViewer() {
CommonViewer viewer = null;
Navigator instance = getInstance();
if (instance != null) {
viewer = instance.getCommonViewer();
}
return viewer;
}
/**
* Returns the instance of the navigation view or NULL if there is# no such
* instance available.
*/
public static Navigator getInstance() {
IWorkbench workbench = PlatformUI.getWorkbench();
if (workbench == null)
return null;
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
if (window == null)
return null;
IWorkbenchPage page = window.getActivePage();
if (page == null)
return null;
IViewPart part = page.findView(ID);
if (part instanceof Navigator)
return (Navigator) part;
return null;
}
/**
* Returns the root of the navigation tree or NULL if there is no such root
* available.
*/
public static NavigationRoot getNavigationRoot() {
NavigationRoot root = null;
Navigator navigator = getInstance();
if (navigator != null)
root = navigator.getRoot();
return root;
}
/**
* Returns the navigation element with the given content if it exists.
*/
public static INavigationElement<?> findElement(Object content) {
NavigationRoot root = getNavigationRoot();
if (content == null || root == null)
return null;
Queue<INavigationElement<?>> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
INavigationElement<?> next = queue.poll();
if (Objects.equal(next.getContent(), content))
return next;
queue.addAll(next.getChildren());
}
return null;
}
public INavigationElement<?> getFirstSelected() {
INavigationElement<?>[] all = getAllSelected();
return all.length > 0 ? all[0] : null;
}
public INavigationElement<?>[] getAllSelected() {
List<INavigationElement<?>> selection = Viewers
.getAllSelected(getNavigationViewer());
return selection.toArray(new INavigationElement[selection.size()]);
}
}