1 package org.simantics.district.route.ui;
5 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
6 import org.eclipse.jface.layout.GridDataFactory;
7 import org.eclipse.jface.layout.GridLayoutFactory;
8 import org.eclipse.jface.resource.JFaceResources;
9 import org.eclipse.jface.resource.LocalResourceManager;
10 import org.eclipse.jface.viewers.ColumnLabelProvider;
11 import org.eclipse.jface.viewers.DoubleClickEvent;
12 import org.eclipse.jface.viewers.ITreeContentProvider;
13 import org.eclipse.jface.viewers.SelectionChangedEvent;
14 import org.eclipse.jface.viewers.TreePath;
15 import org.eclipse.jface.viewers.TreeViewer;
16 import org.eclipse.jface.viewers.Viewer;
17 import org.eclipse.jface.viewers.ViewerCell;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.widgets.Composite;
21 import org.eclipse.swt.widgets.Tree;
22 import org.simantics.district.route.Route;
23 import org.simantics.district.route.RouteEvent;
24 import org.simantics.district.route.RouteService;
25 import org.simantics.district.route.RouteServiceListener;
26 import org.simantics.district.route.Waypoint;
27 import org.simantics.district.route.ui.internal.Activator;
28 import org.simantics.utils.ui.SWTUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * @author Tuukka Lehtonen
36 public class RouteTree extends Composite {
38 private static final Logger LOGGER = LoggerFactory.getLogger(RouteTree.class);
40 ESelectionService selectionService;
42 private final LocalResourceManager resourceManager;
44 private TreeViewer tree;
46 public RouteTree(Composite parent, int style, ESelectionService selectionService) {
48 this.selectionService = selectionService;
49 this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
50 defaultInitializeUI();
54 private RouteServiceListener routeServiceListener = e -> {
55 System.out.println("Route event: " + e);
57 case RouteEvent.TYPE_ROUTE_DISCARDED:
58 runUi(() -> tree.refresh());
61 case RouteEvent.TYPE_ROUTE_REGISTERED:
64 tree.setExpandedState(e.obj, true);
68 case RouteEvent.TYPE_ROUTE_MODIFIED:
71 tree.setExpandedState(e.obj, true);
75 case RouteEvent.TYPE_ROUTE_RENAMED:
76 runUi(() -> tree.refresh(e.obj));
79 case RouteEvent.TYPE_ROUTE_SOURCE_CHANGED:
80 runUi(() -> tree.setInput(e.service.listRoutes()));
85 private void trackRouteInput() {
86 RouteService rs = Activator.getDefault().getRouteService();
88 rs.addListener(routeServiceListener);
89 addDisposeListener(e -> rs.removeListener(routeServiceListener));
90 setInput(rs.listRoutes());
94 private void defaultInitializeUI() {
95 GridDataFactory.fillDefaults().grab(true, true).applyTo(this);
96 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this);
101 private void createTree(Composite parent) {
102 tree = new TreeViewer(parent, SWT.SINGLE);
103 tree.setUseHashlookup(true);
104 GridDataFactory.fillDefaults().grab(true, true).applyTo(tree.getControl());
105 tree.setContentProvider(new ContentProvider());
106 tree.setLabelProvider(new LabelProvider());
107 tree.addSelectionChangedListener(this::treeSelectionChanged);
108 //tree.addPostSelectionChangedListener(this::treeSelectionChanged);
109 tree.addDoubleClickListener(this::itemDoubleClicked);
110 // TODO: add route renaming (F2), DnD reordering support
113 private void itemDoubleClicked(DoubleClickEvent e) {
114 // TODO: default action, i.e. highlight route?
115 LOGGER.info("double click {}", e);
118 private void treeSelectionChanged(SelectionChangedEvent e) {
119 selectionService.setSelection(e.getSelection());
121 IStructuredSelection ss = (IStructuredSelection) e.getSelection();
122 Object[] arr = ss.toArray();
123 if (arr.length == 1) {
125 if (o instanceof Route) {
126 CompletableFuture<List<Resource>> callback = new CompletableFuture<>();
127 callback.thenAccept(dnElements -> {
128 runUi(() -> selectionService.setSelection(new StructuredSelection(dnElements)));
130 new RouteJob((Route) o, callback).schedule();
131 } else if (o instanceof Waypoint) {
132 selectionService.setSelection(new StructuredSelection(((Waypoint) o).<Object>getObject()));
138 protected void setInput(List<Route> result) {
140 TreePath[] paths = tree.getExpandedTreePaths();
141 tree.setInput(result);
142 tree.setExpandedTreePaths(paths);
146 protected void runUi(Runnable r) {
147 SWTUtils.asyncExec(getDisplay(), () -> {
148 if (!tree.getControl().isDisposed())
153 private static class ContentProvider implements ITreeContentProvider {
155 private static final Object[] NONE = {};
156 @SuppressWarnings("unused")
157 private List<?> input;
160 public void dispose() {
165 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
166 input = newInput instanceof List ? (List<?>) newInput : null;
170 public Object[] getElements(Object inputElement) {
171 if (inputElement instanceof List)
172 return ((List<?>) inputElement).toArray();
177 public Object[] getChildren(Object parentElement) {
178 if (parentElement instanceof Route) {
179 return ((Route) parentElement).waypoints().toArray();
185 public Object getParent(Object element) {
190 public boolean hasChildren(Object element) {
191 if (element instanceof Route) {
192 return !((Route) element).waypoints().isEmpty();
199 private static class LabelProvider extends ColumnLabelProvider {
201 public String getText(Object element) {
202 if (element instanceof Route) {
203 Route r = (Route) element;
204 return NLS.bind("{0} ({1} waypoints)", r.getName(), r.count());
205 } else if (element instanceof Waypoint) {
207 return element.toString();
210 public void update(ViewerCell cell) {
211 Object element = cell.getElement();
212 cell.setText(getText(element));
216 public Tree getTree() {
217 return tree.getTree();