1 package org.simantics.district.route.ui;
4 import java.util.concurrent.CompletableFuture;
6 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
7 import org.eclipse.jface.layout.GridDataFactory;
8 import org.eclipse.jface.layout.GridLayoutFactory;
9 import org.eclipse.jface.resource.JFaceResources;
10 import org.eclipse.jface.resource.LocalResourceManager;
11 import org.eclipse.jface.viewers.ColumnLabelProvider;
12 import org.eclipse.jface.viewers.DoubleClickEvent;
13 import org.eclipse.jface.viewers.IDoubleClickListener;
14 import org.eclipse.jface.viewers.IStructuredSelection;
15 import org.eclipse.jface.viewers.ITreeContentProvider;
16 import org.eclipse.jface.viewers.SelectionChangedEvent;
17 import org.eclipse.jface.viewers.StructuredSelection;
18 import org.eclipse.jface.viewers.TreePath;
19 import org.eclipse.jface.viewers.TreeViewer;
20 import org.eclipse.jface.viewers.Viewer;
21 import org.eclipse.jface.viewers.ViewerCell;
22 import org.eclipse.osgi.util.NLS;
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.widgets.Composite;
25 import org.simantics.db.Resource;
26 import org.simantics.district.route.Route;
27 import org.simantics.district.route.RouteEvent;
28 import org.simantics.district.route.RouteJob;
29 import org.simantics.district.route.RouteService;
30 import org.simantics.district.route.RouteServiceListener;
31 import org.simantics.district.route.Waypoint;
32 import org.simantics.district.route.ui.internal.Activator;
33 import org.simantics.utils.ui.SWTUtils;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * @author Tuukka Lehtonen
41 public class RouteTree extends Composite {
43 private static final Logger LOGGER = LoggerFactory.getLogger(RouteTree.class);
45 ESelectionService selectionService;
47 private final LocalResourceManager resourceManager;
49 private TreeViewer tree;
51 public RouteTree(Composite parent, int style, ESelectionService selectionService) {
53 this.selectionService = selectionService;
54 this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
55 defaultInitializeUI();
59 private RouteServiceListener routeServiceListener = e -> {
60 System.out.println("Route event: " + e);
62 case RouteEvent.TYPE_ROUTE_DISCARDED:
63 runUi(() -> tree.refresh());
66 case RouteEvent.TYPE_ROUTE_REGISTERED:
69 tree.setExpandedState(e.obj, true);
73 case RouteEvent.TYPE_ROUTE_MODIFIED:
76 tree.setExpandedState(e.obj, true);
80 case RouteEvent.TYPE_ROUTE_RENAMED:
81 runUi(() -> tree.refresh(e.obj));
84 case RouteEvent.TYPE_ROUTE_SOURCE_CHANGED:
85 runUi(() -> tree.setInput(e.service.listRoutes()));
90 private void trackRouteInput() {
91 RouteService rs = Activator.getDefault().getRouteService();
93 rs.addListener(routeServiceListener);
94 addDisposeListener(e -> rs.removeListener(routeServiceListener));
95 setInput(rs.listRoutes());
99 private void defaultInitializeUI() {
100 GridDataFactory.fillDefaults().grab(true, true).applyTo(this);
101 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this);
106 private void createTree(Composite parent) {
107 tree = new TreeViewer(parent, SWT.SINGLE);
108 tree.setUseHashlookup(true);
109 GridDataFactory.fillDefaults().grab(true, true).applyTo(tree.getControl());
110 tree.setContentProvider(new ContentProvider());
111 tree.setLabelProvider(new LabelProvider());
112 tree.addSelectionChangedListener(this::treeSelectionChanged);
113 //tree.addPostSelectionChangedListener(this::treeSelectionChanged);
114 tree.addDoubleClickListener(this::itemDoubleClicked);
115 // TODO: add route renaming (F2), DnD reordering support
118 private void itemDoubleClicked(DoubleClickEvent e) {
119 // TODO: default action, i.e. highlight route?
120 LOGGER.info("double click {}", e);
123 private void treeSelectionChanged(SelectionChangedEvent e) {
124 selectionService.setSelection(e.getSelection());
126 IStructuredSelection ss = (IStructuredSelection) e.getSelection();
127 Object[] arr = ss.toArray();
128 if (arr.length == 1) {
130 if (o instanceof Route) {
131 CompletableFuture<List<Resource>> callback = new CompletableFuture<>();
132 callback.thenAccept(dnElements -> {
133 runUi(() -> selectionService.setSelection(new StructuredSelection(dnElements)));
135 new RouteJob((Route) o, callback).schedule();
136 } else if (o instanceof Waypoint) {
137 selectionService.setSelection(new StructuredSelection(((Waypoint) o).<Object>getObject()));
143 protected void setInput(List<Route> result) {
145 TreePath[] paths = tree.getExpandedTreePaths();
146 tree.setInput(result);
147 tree.setExpandedTreePaths(paths);
151 protected void runUi(Runnable r) {
152 SWTUtils.asyncExec(getDisplay(), () -> {
153 if (!tree.getControl().isDisposed())
158 private static class ContentProvider implements ITreeContentProvider {
160 private static final Object[] NONE = {};
161 @SuppressWarnings("unused")
162 private List<?> input;
165 public void dispose() {
170 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
171 input = newInput instanceof List ? (List<?>) newInput : null;
175 public Object[] getElements(Object inputElement) {
176 if (inputElement instanceof List)
177 return ((List<?>) inputElement).toArray();
182 public Object[] getChildren(Object parentElement) {
183 if (parentElement instanceof Route) {
184 return ((Route) parentElement).waypoints().toArray();
190 public Object getParent(Object element) {
195 public boolean hasChildren(Object element) {
196 if (element instanceof Route) {
197 return !((Route) element).waypoints().isEmpty();
204 private static class LabelProvider extends ColumnLabelProvider {
206 public String getText(Object element) {
207 if (element instanceof Route) {
208 Route r = (Route) element;
209 return NLS.bind("{0} ({1} waypoints)", r.getName(), r.count());
210 } else if (element instanceof Waypoint) {
212 return element.toString();
215 public void update(ViewerCell cell) {
216 Object element = cell.getElement();
217 cell.setText(getText(element));