| /******************************************************************************* |
| * Copyright (c) 2012, 2020 Original authors and others. |
| * |
| * 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: |
| * Original authors and others - initial API and implementation |
| * Dirk Fauth <dirk.fauth@googlemail.com> - extended width of tree |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.examples.runner; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.lang.reflect.Modifier; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| 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.util.GUIHelper; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.browser.Browser; |
| import org.eclipse.swt.custom.CTabFolder; |
| import org.eclipse.swt.custom.CTabItem; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Link; |
| import org.eclipse.swt.widgets.Shell; |
| |
| public class TabbedNatExampleRunner { |
| |
| private static CTabFolder tabFolder; |
| private static Map<INatExample, Control> exampleControlMap = new HashMap<>(); |
| private static Map<String, INatExample> examplePathMap = new HashMap<>(); |
| private static Link link;; |
| |
| public static void run(String... examplePaths) |
| throws InstantiationException, IllegalAccessException, ClassNotFoundException { |
| run(1000, 600, examplePaths); |
| } |
| |
| public static void run(int shellWidth, int shellHeight, final String... examplePaths) |
| throws InstantiationException, IllegalAccessException, ClassNotFoundException { |
| // Setup |
| final Display display = Display.getDefault(); |
| final Shell shell = new Shell(display, SWT.SHELL_TRIM); |
| shell.setLayout(new GridLayout(2, false)); |
| shell.setSize(shellWidth, shellHeight); |
| shell.setText("NatTable Examples Application"); |
| |
| Image nebula16 = new Image(display, TabbedNatExampleRunner.class.getResourceAsStream("nebula_logo_16.png")); |
| Image nebula32 = new Image(display, TabbedNatExampleRunner.class.getResourceAsStream("nebula_logo_32.png")); |
| Image nebula64 = new Image(display, TabbedNatExampleRunner.class.getResourceAsStream("nebula_logo_64.png")); |
| |
| shell.setImages(new Image[] { nebula16, nebula32, nebula64 }); |
| |
| // Nav tree |
| final TreeViewer navTreeViewer = new TreeViewer(shell); |
| GridData gridData = new GridData(GridData.FILL_VERTICAL); |
| gridData.widthHint = 300; |
| navTreeViewer.getControl().setLayoutData(gridData); |
| final NavContentProvider contentProvider = new NavContentProvider(); |
| navTreeViewer.setContentProvider(contentProvider); |
| navTreeViewer.setLabelProvider(new NavLabelProvider(contentProvider)); |
| navTreeViewer.setInput(examplePaths); |
| 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()); |
| } |
| } |
| } |
| |
| }); |
| |
| tabFolder = new CTabFolder(shell, SWT.BORDER); |
| tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| |
| shell.open(); |
| |
| while (!shell.isDisposed()) { |
| if (!display.readAndDispatch()) { |
| display.sleep(); |
| } |
| } |
| |
| for (INatExample example : exampleControlMap.keySet()) { |
| // Stop |
| example.onStop(); |
| |
| Control exampleControl = exampleControlMap.get(example); |
| exampleControl.dispose(); |
| } |
| |
| tabFolder.dispose(); |
| |
| shell.dispose(); |
| display.dispose(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static Class<? extends INatExample> getExampleClass(String examplePath) { |
| String className = examplePath.replace('/', '.'); |
| try { |
| Class<?> clazz = Class.forName(className); |
| if (INatExample.class.isAssignableFrom(clazz) |
| && !Modifier.isAbstract(clazz.getModifiers())) { |
| return (Class<? extends INatExample>) clazz; |
| } |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| |
| return null; |
| } |
| |
| public static INatExample getExample(String examplePath) { |
| INatExample example = examplePathMap.get(examplePath); |
| if (example == null) { |
| String path = examplePath; |
| 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 + "/"); |
| } |
| |
| if (path.startsWith("/")) |
| path = path.substring(1); |
| |
| Class<? extends INatExample> exampleClass = getExampleClass(path); |
| if (exampleClass != null) { |
| try { |
| example = exampleClass.newInstance(); |
| examplePathMap.put(examplePath, example); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
| return example; |
| } |
| |
| private static void openExampleInTab(final String examplePath) { |
| final INatExample example = getExample(examplePath); |
| if (example == null) { |
| return; |
| } |
| |
| final String exampleName = example.getName(); |
| final CTabItem tabItem = new CTabItem(tabFolder, SWT.CLOSE); |
| tabItem.setText(exampleName); |
| tabItem.addDisposeListener(new DisposeListener() { |
| |
| @Override |
| public void widgetDisposed(DisposeEvent e) { |
| // Stop |
| example.onStop(); |
| |
| Control exampleControl = exampleControlMap.get(example); |
| if (exampleControl != null && !exampleControl.isDisposed()) { |
| exampleControl.dispose(); |
| } |
| |
| exampleControlMap.remove(example); |
| examplePathMap.remove(examplePath); |
| link.dispose(); |
| } |
| }); |
| |
| final Composite tabComposite = new Composite(tabFolder, SWT.NONE); |
| tabComposite.setLayout(new GridLayout(1, false)); |
| |
| // Create example control |
| final Control exampleControl = example.createExampleControl(tabComposite); |
| exampleControl.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| exampleControlMap.put(example, exampleControl); |
| |
| // Description |
| final String description = example.getDescription(); |
| if (description != null && description.length() > 0) { |
| final Group descriptionGroup = new Group(tabComposite, SWT.NONE); |
| descriptionGroup.setText("Description"); |
| descriptionGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| descriptionGroup.setLayout(new FillLayout()); |
| |
| final Label descriptionLabel = new Label(descriptionGroup, SWT.WRAP); |
| descriptionLabel.setText(description); |
| } |
| |
| link = new Link(tabComposite, SWT.NONE); |
| link.setText("<a href=\"" + examplePath + "\">View source</a>"); |
| |
| final SelectionAdapter linkSelectionListener = new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| String path = event.text; |
| if (path.startsWith("/" + INatExample.TUTORIAL_EXAMPLES_PREFIX)) { |
| path = path.replace("/" + INatExample.TUTORIAL_EXAMPLES_PREFIX, INatExample.BASE_PATH + "/"); |
| } else if (path.startsWith("/" + INatExample.CLASSIC_EXAMPLES_PREFIX)) { |
| path = path.replace("/" + INatExample.CLASSIC_EXAMPLES_PREFIX, INatExample.CLASSIC_BASE_PATH + "/"); |
| } |
| String source = getResourceAsString(path + ".java"); |
| if (source != null) { |
| viewSource(exampleName, source); |
| } |
| } |
| }; |
| link.addSelectionListener(linkSelectionListener); |
| |
| tabItem.setControl(tabComposite); |
| |
| // Start |
| example.onStart(); |
| |
| tabFolder.setSelection(tabItem); |
| } |
| |
| private static String getResourceAsString(String resource) { |
| try (InputStream inStream = TabbedNatExampleRunner.class.getResourceAsStream(resource)) { |
| if (inStream != null) { |
| StringBuilder strBuf = new StringBuilder(); |
| int i = -1; |
| while ((i = inStream.read()) != -1) { |
| strBuf.append((char) i); |
| } |
| |
| return strBuf.toString(); |
| } else { |
| System.out.println("null stream for resource " + resource); |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| |
| return null; |
| } |
| |
| private static void viewSource(String title, String source) { |
| Shell shell = new Shell(Display.getDefault()); |
| shell.setText(title); |
| shell.setLayout(new FillLayout()); |
| |
| Browser text = new Browser(shell, SWT.MULTI); |
| text.setBackground(GUIHelper.COLOR_WHITE); |
| text.setText("<pre>" + source + "</pre>"); |
| |
| shell.open(); |
| } |
| |
| } |