]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.route.ui/src/org/simantics/district/route/ui/RouteTree.java
Merge "Initial version of the district network Routes view."
[simantics/district.git] / org.simantics.district.route.ui / src / org / simantics / district / route / ui / RouteTree.java
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 (file)
index 0000000..c275b5b
--- /dev/null
@@ -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<List<Resource>> 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).<Object>getObject()));
+            }
+        }
+        */
+    }
+
+    protected void setInput(List<Route> 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));
+        }
+    }
+
+}