blob: b4b95290f95c1b14263dd59bc838e690b6139630 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Exyte
* 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:
* Yuri Strot - initial API and Implementation
******************************************************************************/
package org.eclipse.ui.glance.controls.tree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
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[] getRoots();
protected abstract Object[] getChildren(Object element);
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);
}
}
}