X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.district.route.ui%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Froute%2Fui%2FRouteTree.java;fp=org.simantics.district.route.ui%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Froute%2Fui%2FRouteTree.java;h=c275b5b5f6be008b207f25e8da1b43ad2b3efcc3;hb=716ce6c9abe27be04635922ad437f242c4bd7dfc;hp=0000000000000000000000000000000000000000;hpb=cb14c9e0dfd0b7179c11f0a54af87e2b7fe16113;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.route.ui/src/org/simantics/district/route/ui/RouteTree.java b/org.simantics.district.route.ui/src/org/simantics/district/route/ui/RouteTree.java new file mode 100644 index 00000000..c275b5b5 --- /dev/null +++ b/org.simantics.district.route.ui/src/org/simantics/district/route/ui/RouteTree.java @@ -0,0 +1,221 @@ +package org.simantics.district.route.ui; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.e4.ui.workbench.modeling.ESelectionService; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerCell; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; +import org.simantics.district.route.Route; +import org.simantics.district.route.RouteEvent; +import org.simantics.district.route.RouteJob; +import org.simantics.district.route.RouteService; +import org.simantics.district.route.RouteServiceListener; +import org.simantics.district.route.Waypoint; +import org.simantics.district.route.ui.internal.Activator; +import org.simantics.utils.ui.SWTUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Tuukka Lehtonen + * @since 6.09 + */ +public class RouteTree extends Composite { + + private static final Logger LOGGER = LoggerFactory.getLogger(RouteTree.class); + + ESelectionService selectionService; + + private final LocalResourceManager resourceManager; + + private TreeViewer tree; + + public RouteTree(Composite parent, int style, ESelectionService selectionService) { + super(parent, style); + this.selectionService = selectionService; + this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent); + defaultInitializeUI(); + trackRouteInput(); + } + + private RouteServiceListener routeServiceListener = e -> { + System.out.println("Route event: " + e); + switch (e.type) { + case RouteEvent.TYPE_ROUTE_DISCARDED: + runUi(() -> tree.refresh()); + break; + + case RouteEvent.TYPE_ROUTE_REGISTERED: + runUi(() -> { + tree.refresh(); + tree.setExpandedState(e.obj, true); + }); + break; + + case RouteEvent.TYPE_ROUTE_MODIFIED: + runUi(() -> { + tree.refresh(e.obj); + tree.setExpandedState(e.obj, true); + }); + break; + + case RouteEvent.TYPE_ROUTE_RENAMED: + runUi(() -> tree.refresh(e.obj)); + break; + + case RouteEvent.TYPE_ROUTE_SOURCE_CHANGED: + runUi(() -> tree.setInput(e.service.listRoutes())); + break; + } + }; + + private void trackRouteInput() { + RouteService rs = Activator.getDefault().getRouteService(); + if (rs != null) { + rs.addListener(routeServiceListener); + addDisposeListener(e -> rs.removeListener(routeServiceListener)); + setInput(rs.listRoutes()); + } + } + + private void defaultInitializeUI() { + GridDataFactory.fillDefaults().grab(true, true).applyTo(this); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this); + + createTree(this); + } + + private void createTree(Composite parent) { + tree = new TreeViewer(parent, SWT.SINGLE); + tree.setUseHashlookup(true); + GridDataFactory.fillDefaults().grab(true, true).applyTo(tree.getControl()); + tree.setContentProvider(new ContentProvider()); + tree.setLabelProvider(new LabelProvider()); + tree.addSelectionChangedListener(this::treeSelectionChanged); + //tree.addPostSelectionChangedListener(this::treeSelectionChanged); + tree.addDoubleClickListener(this::itemDoubleClicked); + // TODO: add route renaming (F2), DnD reordering support + } + + private void itemDoubleClicked(DoubleClickEvent e) { + // TODO: default action, i.e. highlight route? + LOGGER.info("double click {}", e); + } + + private void treeSelectionChanged(SelectionChangedEvent e) { + selectionService.setSelection(e.getSelection()); + /* + IStructuredSelection ss = (IStructuredSelection) e.getSelection(); + Object[] arr = ss.toArray(); + if (arr.length == 1) { + Object o = arr[0]; + if (o instanceof Route) { + CompletableFuture> callback = new CompletableFuture<>(); + callback.thenAccept(dnElements -> { + runUi(() -> selectionService.setSelection(new StructuredSelection(dnElements))); + }); + new RouteJob((Route) o, callback).schedule(); + } else if (o instanceof Waypoint) { + selectionService.setSelection(new StructuredSelection(((Waypoint) o).getObject())); + } + } + */ + } + + protected void setInput(List result) { + runUi(() -> { + TreePath[] paths = tree.getExpandedTreePaths(); + tree.setInput(result); + tree.setExpandedTreePaths(paths); + }); + } + + protected void runUi(Runnable r) { + SWTUtils.asyncExec(getDisplay(), () -> { + if (!tree.getControl().isDisposed()) + r.run(); + }); + } + + private static class ContentProvider implements ITreeContentProvider { + + private static final Object[] NONE = {}; + @SuppressWarnings("unused") + private List input; + + @Override + public void dispose() { + input = null; + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + input = newInput instanceof List ? (List) newInput : null; + } + + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof List) + return ((List) inputElement).toArray(); + return NONE; + } + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof Route) { + return ((Route) parentElement).waypoints().toArray(); + } + return NONE; + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof Route) { + return !((Route) element).waypoints().isEmpty(); + } + return false; + } + + } + + private static class LabelProvider extends ColumnLabelProvider { + @Override + public String getText(Object element) { + if (element instanceof Route) { + Route r = (Route) element; + return NLS.bind("{0} ({1} waypoints)", r.getName(), r.count()); + } else if (element instanceof Waypoint) { + } + return element.toString(); + } + @Override + public void update(ViewerCell cell) { + Object element = cell.getElement(); + cell.setText(getText(element)); + } + } + +}