]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.route.ui/src/org/simantics/district/route/ui/RouteTree.java
e58d6a68ec9d4d833c35f929e7405ab1f6c47242
[simantics/district.git] / org.simantics.district.route.ui / src / org / simantics / district / route / ui / RouteTree.java
1 package org.simantics.district.route.ui;
2
3 import java.util.List;
4
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;
31
32 /**
33  * @author Tuukka Lehtonen
34  * @since 6.09
35  */
36 public class RouteTree extends Composite {
37
38     private static final Logger LOGGER = LoggerFactory.getLogger(RouteTree.class);
39
40     ESelectionService selectionService;
41
42     private final LocalResourceManager resourceManager;
43
44     private TreeViewer tree;
45
46     public RouteTree(Composite parent, int style, ESelectionService selectionService) {
47         super(parent, style);
48         this.selectionService = selectionService;
49         this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
50         defaultInitializeUI();
51         trackRouteInput();
52     }
53
54     private RouteServiceListener routeServiceListener = e -> {
55         System.out.println("Route event: " + e);
56         switch (e.type) {
57             case RouteEvent.TYPE_ROUTE_DISCARDED:
58                 runUi(() -> tree.refresh());
59                 break;
60
61             case RouteEvent.TYPE_ROUTE_REGISTERED:
62                 runUi(() -> {
63                     tree.refresh();
64                     tree.setExpandedState(e.obj, true);
65                 });
66                 break;
67
68             case RouteEvent.TYPE_ROUTE_MODIFIED:
69                 runUi(() -> {
70                     tree.refresh(e.obj);
71                     tree.setExpandedState(e.obj, true);
72                 });
73                 break;
74
75             case RouteEvent.TYPE_ROUTE_RENAMED:
76                 runUi(() -> tree.refresh(e.obj));
77                 break;
78
79             case RouteEvent.TYPE_ROUTE_SOURCE_CHANGED:
80                 runUi(() -> tree.setInput(e.service.listRoutes()));
81                 break;
82         }
83     };
84
85     private void trackRouteInput() {
86         RouteService rs = Activator.getDefault().getRouteService();
87         if (rs != null) {
88             rs.addListener(routeServiceListener);
89             addDisposeListener(e -> rs.removeListener(routeServiceListener));
90             setInput(rs.listRoutes());
91         }
92     }
93
94     private void defaultInitializeUI() {
95         GridDataFactory.fillDefaults().grab(true, true).applyTo(this);
96         GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this);
97
98         createTree(this);
99     }
100
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
111     }
112
113     private void itemDoubleClicked(DoubleClickEvent e) {
114         // TODO: default action, i.e. highlight route?
115         LOGGER.info("double click {}", e);
116     }
117
118     private void treeSelectionChanged(SelectionChangedEvent e) {
119         selectionService.setSelection(e.getSelection());
120         /*
121         IStructuredSelection ss = (IStructuredSelection) e.getSelection();
122         Object[] arr = ss.toArray();
123         if (arr.length == 1) {
124             Object o = arr[0];
125             if (o instanceof Route) {
126                 CompletableFuture<List<Resource>> callback = new CompletableFuture<>();
127                 callback.thenAccept(dnElements -> {
128                     runUi(() -> selectionService.setSelection(new StructuredSelection(dnElements)));
129                 });
130                 new RouteJob((Route) o, callback).schedule();
131             } else if (o instanceof Waypoint) {
132                 selectionService.setSelection(new StructuredSelection(((Waypoint) o).<Object>getObject()));
133             }
134         }
135         */
136     }
137
138     protected void setInput(List<Route> result) {
139         runUi(() -> {
140             TreePath[] paths = tree.getExpandedTreePaths();
141             tree.setInput(result);
142             tree.setExpandedTreePaths(paths);
143         });
144     }
145
146     protected void runUi(Runnable r) {
147         SWTUtils.asyncExec(getDisplay(), () -> {
148             if (!tree.getControl().isDisposed())
149                 r.run();
150         });
151     }
152
153     private static class ContentProvider implements ITreeContentProvider {
154
155         private static final Object[] NONE = {};
156         @SuppressWarnings("unused")
157         private List<?> input;
158
159         @Override
160         public void dispose() {
161             input = null;
162         }
163
164         @Override
165         public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
166             input = newInput instanceof List ? (List<?>) newInput : null;
167         }
168
169         @Override
170         public Object[] getElements(Object inputElement) {
171             if (inputElement instanceof List)
172                 return ((List<?>) inputElement).toArray();
173             return NONE;
174         }
175
176         @Override
177         public Object[] getChildren(Object parentElement) {
178             if (parentElement instanceof Route) {
179                 return ((Route) parentElement).waypoints().toArray();
180             }
181             return NONE;
182         }
183
184         @Override
185         public Object getParent(Object element) {
186             return null;
187         }
188
189         @Override
190         public boolean hasChildren(Object element) {
191             if (element instanceof Route) {
192                 return !((Route) element).waypoints().isEmpty();
193             }
194             return false;
195         }
196
197     }
198
199     private static class LabelProvider extends ColumnLabelProvider {
200         @Override
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) {
206             }
207             return element.toString();
208         }
209         @Override
210         public void update(ViewerCell cell) {
211             Object element = cell.getElement();
212             cell.setText(getText(element));
213         }
214     }
215
216     public Tree getTree() {
217         return tree.getTree();
218     }
219
220 }