blob: 71e4033eb3b82e330d0ca4b5c389b2142f72c03b [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2016, 2020 Dirk Fauth.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.nebula.widgets.nattable.examples.e4;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.nebula.widgets.nattable.examples.INatExample;
import org.eclipse.nebula.widgets.nattable.examples.NatTableExamples;
import org.eclipse.nebula.widgets.nattable.examples.runner.NavContentProvider;
import org.eclipse.nebula.widgets.nattable.examples.runner.NavLabelProvider;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.wiring.BundleWiring;
public class NavigationPart {
public static final String E4_EXAMPLES_PREFIX = "E4 Examples/";
public static final String E4_BASE_PATH = "/org/eclipse/nebula/widgets/nattable/examples/e4/part";
private EPartService partService;
private ClassLoader exampleClassLoader;
@Inject
EModelService modelService;
@Inject
MApplication app;
@Inject
public NavigationPart(EPartService partService) {
this.partService = partService;
exampleClassLoader = FrameworkUtil.getBundle(NatTableExamples.class).adapt(BundleWiring.class).getClassLoader();
}
@PostConstruct
public void postConstruct(Composite parent) {
final TreeViewer navTreeViewer = new TreeViewer(parent);
final NavContentProvider contentProvider = new NavContentProvider() {
@Override
public Object[] getElements(Object inputElement) {
Set<String> topLevelElements = new LinkedHashSet<>();
String[] examplePaths = (String[]) inputElement;
for (final String examplePath : examplePaths) {
String parentPath = "";
String absolutePath = "";
// remove the package name for the tree structure
String path = examplePath;
if (examplePath.startsWith(INatExample.TUTORIAL_EXAMPLES_PREFIX)) {
path = examplePath.replace(INatExample.BASE_PATH, "");
} else if (examplePath.startsWith(INatExample.CLASSIC_EXAMPLES_PREFIX)) {
path = examplePath.replace(INatExample.CLASSIC_BASE_PATH, "");
} else if (examplePath.startsWith(E4_EXAMPLES_PREFIX)) {
path = examplePath.replace(E4_BASE_PATH, "");
}
final StringTokenizer tok = new StringTokenizer(path, "/");
while (tok.hasMoreTokens()) {
final String pathElement = tok.nextToken();
if (parentPath.length() == 0) {
topLevelElements.add("/" + pathElement);
}
absolutePath += "/" + pathElement;
final Collection<String> children = getChildren(parentPath);
children.add(absolutePath);
parentPath = absolutePath;
}
}
return topLevelElements.toArray();
}
};
navTreeViewer.setContentProvider(contentProvider);
navTreeViewer.setLabelProvider(new NavLabelProvider(contentProvider) {
@Override
public String getText(Object element) {
String str = (String) element;
if (!contentProvider.hasChildren(element)) {
INatExample example = getExample(str);
return example.getName();
}
int lastSlashIndex = str.lastIndexOf('/');
if (lastSlashIndex < 0) {
return format(str);
} else {
return format(str.substring(lastSlashIndex + 1));
}
}
});
navTreeViewer.setInput(getExamplePaths());
navTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
TreeSelection selection = (TreeSelection) event.getSelection();
for (TreePath path : selection.getPaths()) {
// check for item - if node expand/collapse, if child open
if (contentProvider.hasChildren(path.getLastSegment().toString())) {
boolean expanded = navTreeViewer.getExpandedState(path);
navTreeViewer.setExpandedState(path, !expanded);
} else {
openExampleInTab(path.getLastSegment().toString());
}
}
}
});
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
parent.setLayout(layout);
GridDataFactory.fillDefaults().grab(true, true).applyTo(navTreeViewer.getControl());
}
private String[] getExamplePaths() {
List<String> examples = null;
try {
InputStream inputStream = NatTableExamples.class.getResourceAsStream("/src/examples.index");
if (inputStream != null) {
examples = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line = reader.readLine();
while (line != null) {
examples.add(line);
line = reader.readLine();
}
}
} else {
System.out.println("examples.index not found, reconstructing");
Bundle bundle = FrameworkUtil.getBundle(NatTableExamples.class);
URL location = FileLocator.resolve(bundle.getEntry("/"));
examples = NatTableExamples.createExamplesIndex(location.getPath().trim());
}
// add e4 examples
examples.add(E4_EXAMPLES_PREFIX + "/org/eclipse/nebula/widgets/nattable/examples/e4/part/CSSExample");
examples.add(E4_EXAMPLES_PREFIX + "/org/eclipse/nebula/widgets/nattable/examples/e4/part/DarkExample");
examples.add(E4_EXAMPLES_PREFIX + "/org/eclipse/nebula/widgets/nattable/examples/e4/part/PercentageExample");
examples.add(E4_EXAMPLES_PREFIX + "/org/eclipse/nebula/widgets/nattable/examples/e4/part/TreeExample");
examples.add(E4_EXAMPLES_PREFIX + "/org/eclipse/nebula/widgets/nattable/examples/e4/part/SelectionListenerExample");
examples.add(E4_EXAMPLES_PREFIX + "/org/eclipse/nebula/widgets/nattable/examples/e4/part/MenuExample");
} catch (IOException e) {
e.printStackTrace();
}
return examples != null ? examples.toArray(new String[0]) : null;
}
@SuppressWarnings("unchecked")
public Class<? extends INatExample> getExampleClass(String examplePath, ClassLoader loader) {
String className = examplePath.replace('/', '.');
try {
Class<?> clazz = Class.forName(className, true, loader);
if (INatExample.class.isAssignableFrom(clazz)
&& !Modifier.isAbstract(clazz.getModifiers())) {
return (Class<? extends INatExample>) clazz;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
public INatExample getExample(String examplePath) {
INatExample example = null;
String path = examplePath;
ClassLoader loader = exampleClassLoader;
if (examplePath.startsWith("/" + INatExample.TUTORIAL_EXAMPLES_PREFIX)) {
path = examplePath.replace("/" + INatExample.TUTORIAL_EXAMPLES_PREFIX, INatExample.BASE_PATH + "/");
} else if (examplePath.startsWith("/" + INatExample.CLASSIC_EXAMPLES_PREFIX)) {
path = examplePath.replace("/" + INatExample.CLASSIC_EXAMPLES_PREFIX, INatExample.CLASSIC_BASE_PATH + "/");
} else if (examplePath.startsWith("/" + E4_EXAMPLES_PREFIX)) {
path = examplePath.replace("/" + E4_EXAMPLES_PREFIX, E4_BASE_PATH + "/");
loader = this.getClass().getClassLoader();
}
if (path.startsWith("/"))
path = path.substring(1);
Class<? extends INatExample> exampleClass = getExampleClass(path, loader);
if (exampleClass != null) {
try {
example = exampleClass.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return example;
}
private void openExampleInTab(final String examplePath) {
final INatExample example = getExample(examplePath);
if (example == null) {
return;
}
MPartStack stack = (MPartStack) modelService.find("org.eclipse.nebula.widgets.nattable.examples.e4.partstack.0", app);
MPart part = null;
if (examplePath.startsWith("/" + E4_EXAMPLES_PREFIX)) {
part = (MPart) modelService.find(example.getClass().getName(), app);
if (part == null) {
part = partService.createPart(example.getClass().getName());
part.getTags().add(LifecycleManager.CLOSE_ON_SHUTDOWN_TAG);
part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG);
stack.getChildren().add(part);
}
} else {
part = partService.createPart("org.eclipse.nebula.widgets.nattable.examples.e4.partdescriptor.natexample");
part.getTags().add(LifecycleManager.CLOSE_ON_SHUTDOWN_TAG);
part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG);
part.getTransientData().put("example", example);
part.getTransientData().put("examplePath", examplePath);
stack.getChildren().add(part);
}
part.setLabel(example.getName());
partService.showPart(part, PartState.ACTIVATE);
}
}