| /***************************************************************************** |
| * 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); |
| } |
| } |