/*******************************************************************************
* Copyright (c) 2012 xored software, Inc. 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:
* xored software, Inc. - initial API and implementation (Yuri Strot)
******************************************************************************/
package com.xored.glance.ui.controls.tree;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public abstract class UnknownTreeVisitor {
public void visit(IProgressMonitor monitor) {
monitor.beginTask("Tree indexing", 100);
try {
Object[] roots = getRoots();
monitor.worked(1);
breadthVisit(roots, monitor, 1);
} finally {
monitor.done();
}
}
protected abstract Object[] getChildren(Object element);
protected abstract Object[] getRoots();
private void breadthVisit(Object[] elements, IProgressMonitor monitor, int level) {
List<Object> next = new ArrayList<Object>();
for (Object element : elements) {
if (monitor.isCanceled()) {
return;
}
next.addAll(Arrays.asList(getChildren(element)));
}
if (monitor.isCanceled()) {
return;
}
int work = (int) Math.pow(2, level);
monitor.worked(work);
int totalWork = 2 * work - 1;
int size = next.size();
if (size == 0) {
return;
}
int remains = 100 - totalWork;
if (remains > size) {
breadthVisit(next.toArray(), monitor, level + 1);
} else {
SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, remains);
try {
subMonitor.beginTask("", size);
for (Object element : next) {
depthVisit(element, monitor, level + 1);
subMonitor.worked(1);
}
} finally {
subMonitor.done();
}
}
}
private void depthVisit(Object element, IProgressMonitor monitor, int level) {
if (level > 4) {
return;
}
for (Object child : getChildren(element)) {
if (monitor.isCanceled()) {
return;
}
depthVisit(child, monitor, level + 1);
}
}
}