/*******************************************************************************
* Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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:
* itemis AG - implementation
* Puppet Labs - adaption to Geppetto/PP
*******************************************************************************/
package com.puppetlabs.geppetto.pp.dsl.ui.editor.findrefs;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
/**
* Mostly copied from {@link org.eclipse.search2.internal.ui.basic.views.TreeViewerNavigator}.
*
* @author Jan Koehnlein - Initial contribution and API
*/
public class TreeViewerNavigator {
private TreeViewer viewer;
private PPReferenceSearchViewPage page;
/**
* Same as the class with the same name in the corresponding Xtext pacakge except the Geppetto specific SearchViewPage
* required (as the implementation is not free from implementation concerns, and package private things).
*
* @param page
*/
public TreeViewerNavigator(PPReferenceSearchViewPage page) {
this.page = page;
this.viewer = page.getViewer();
}
private TreeItem[] getChildren(TreeItem item) {
viewer.setExpandedState(item.getData(), true);
return item.getItems();
}
private TreeItem getCurrentItem(boolean forward) {
Tree tree = viewer.getTree();
TreeItem[] selection = tree.getSelection();
if(selection.length == 0) {
selection = tree.getItems();
}
TreeItem nextItem = null;
if(selection.length > 0) {
nextItem = forward
? selection[0]
: selection[selection.length - 1];
}
return nextItem;
}
private TreeItem getFirstChildWithMatches(TreeItem item) {
TreeItem[] children = getChildren(item);
if(children.length == 0)
return null;
TreeItem child = children[0];
if(hasMatches(child))
return child;
return getFirstChildWithMatches(child);
}
private TreeItem getFirstItem() {
TreeItem[] roots = viewer.getTree().getItems();
if(roots.length == 0)
return null;
for(int i = 0; i < roots.length; i++) {
if(hasMatches(roots[i]))
return roots[i];
TreeItem firstChild = getFirstChildWithMatches(roots[0]);
if(firstChild != null)
return firstChild;
}
return null;
}
private TreeItem getLastChildWithMatches(TreeItem currentItem) {
TreeItem[] children = getChildren(currentItem);
if(children.length == 0)
return null;
TreeItem recursiveChild = getLastChildWithMatches(children[children.length - 1]);
if(recursiveChild == null)
return children[children.length - 1];
return recursiveChild;
}
private TreeItem getLastItem() {
TreeItem[] roots = viewer.getTree().getItems();
if(roots.length == 0)
return null;
return getLastChildWithMatches(roots[roots.length - 1]);
}
private TreeItem getNextItemBackward(TreeItem currentItem) {
TreeItem previousSibling = getNextSibling(currentItem, false);
if(previousSibling != null) {
TreeItem lastChild = getLastChildWithMatches(previousSibling);
if(lastChild != null)
return lastChild;
if(hasMatches(previousSibling))
return previousSibling;
return null;
}
TreeItem parent = currentItem.getParentItem();
if(parent != null) {
if(hasMatches(parent))
return parent;
return getNextItemBackward(parent);
}
return null;
}
private TreeItem getNextItemForward(TreeItem currentItem) {
TreeItem child = getFirstChildWithMatches(currentItem);
if(child != null)
return child;
TreeItem nextSibling = getNextSibling(currentItem, true);
if(nextSibling != null) {
if(hasMatches(nextSibling))
return nextSibling;
return getFirstChildWithMatches(nextSibling);
}
TreeItem parent = currentItem.getParentItem();
while(parent != null) {
nextSibling = getNextSibling(parent, true);
if(nextSibling != null) {
if(hasMatches(nextSibling))
return nextSibling;
return getFirstChildWithMatches(nextSibling);
}
parent = parent.getParentItem();
}
return null;
}
private TreeItem getNextSibling(TreeItem currentItem, boolean forward) {
TreeItem[] siblings = getSiblings(currentItem);
if(siblings.length < 2)
return null;
int index = -1;
for(int i = 0; i < siblings.length; i++) {
if(siblings[i] == currentItem) {
index = i;
break;
}
}
if(forward && index == siblings.length - 1) {
return null;
}
else if(!forward && index == 0) {
return null;
}
return forward
? siblings[index + 1]
: siblings[index - 1];
}
private TreeItem[] getSiblings(TreeItem currentItem) {
Tree tree = viewer.getTree();
TreeItem parentItem = currentItem.getParentItem();
if(parentItem != null)
return parentItem.getItems();
return tree.getItems();
}
private boolean hasMatches(TreeItem item) {
Object element = item.getData();
if(element == null)
return false;
return true;// page.getDisplayedMatchCount(element) > 0;
}
private void internalSetSelection(TreeItem ti) {
if(ti != null) {
Object data = ti.getData();
if(data != null) {
ISelection selection = new StructuredSelection(data);
viewer.setSelection(selection, true);
page.handleOpen(new OpenEvent(viewer, selection));
}
}
}
public void navigateNext(boolean forward) {
TreeItem currentItem = getCurrentItem(forward);
if(currentItem == null)
return;
TreeItem nextItem = null;
if(forward) {
nextItem = getNextItemForward(currentItem);
if(nextItem == null)
nextItem = getFirstItem();
}
else {
nextItem = getNextItemBackward(currentItem);
if(nextItem == null)
nextItem = getLastItem();
}
if(nextItem != null) {
internalSetSelection(nextItem);
}
}
}