]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/SelectionAdapter.java
f3f9df914585e1a7f63be1a2cd93083bf4e84747
[simantics/3d.git] / org.simantics.proconf.g3d / src / org / simantics / proconf / g3d / base / SelectionAdapter.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
3  * All rights reserved. This program and the accompanying materials\r
4  * are made available under the terms of the Eclipse Public License v1.0\r
5  * which accompanies this distribution, and is available at\r
6  * http://www.eclipse.org/legal/epl-v10.html\r
7  *\r
8  * Contributors:\r
9  *     VTT Technical Research Centre of Finland - initial API and implementation\r
10  *******************************************************************************/\r
11 package org.simantics.proconf.g3d.base;\r
12 \r
13 import java.util.ArrayList;\r
14 import java.util.Iterator;\r
15 import java.util.List;\r
16 \r
17 import org.eclipse.jface.viewers.ISelection;\r
18 import org.eclipse.jface.viewers.ISelectionChangedListener;\r
19 import org.eclipse.jface.viewers.ISelectionProvider;\r
20 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
21 import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
22 import org.simantics.proconf.g3d.gizmo.Gizmo;\r
23 import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
24 import org.simantics.proconf.ui.utils.ResourceAdaptionUtils;\r
25 \r
26 import com.jme.intersection.PickData;\r
27 import com.jme.intersection.PickResults;\r
28 import com.jme.intersection.TrianglePickResults;\r
29 import com.jme.math.Ray;\r
30 \r
31 import org.simantics.db.Resource;\r
32 \r
33 /**\r
34  * Manages highlighting and selecting of objects.\r
35  * \r
36  * @author Marko Luukkainen\r
37  *\r
38  */\r
39 public abstract class SelectionAdapter implements ISelectionProvider{\r
40         \r
41         protected ScenegraphAdapter adapter;\r
42         \r
43         private Gizmo currentGizmo = null;\r
44         \r
45         public SelectionAdapter(ScenegraphAdapter adapter) {\r
46                 if (adapter == null)\r
47                         throw new NullPointerException("Scenegraph adapter must no be null");\r
48                 this.adapter = adapter;\r
49         }\r
50         \r
51     public enum SelectionType {\r
52         SET, MODIFY\r
53     };\r
54 \r
55     protected SelectionType mouseClickType = SelectionType.SET;\r
56     \r
57     public SelectionType getSelectionType() {\r
58         return mouseClickType;\r
59     }\r
60     \r
61     public void setSelectionType(SelectionType type) {\r
62         mouseClickType = type;\r
63     }\r
64     \r
65     public void setCurrentGizmo(Gizmo gizmo) {\r
66         currentGizmo = gizmo;\r
67     }\r
68     \r
69     /**\r
70      * Lists all selected objects\r
71      * <p>\r
72      * Selection may contain objects that are not in this view: those are NOT\r
73      * returned\r
74      * </p>\r
75      * \r
76      * @return\r
77      */\r
78     public List<IGraphicsNode> getSelectedObjects() {\r
79         return getSelectedObjects(selection);\r
80     }\r
81     \r
82     /**\r
83      * Lists all highlighted objects.\r
84      * <p>\r
85      * Typically there may be only one highlighted object.\r
86      * </p>\r
87      * @return\r
88      */\r
89     public List<IGraphicsNode> getHighlightedObjects() {\r
90         return getSelectedObjects(interactiveSelection);\r
91     }\r
92 \r
93     /**\r
94      * Lists all selected objects\r
95      * <p>\r
96      * Selection may contain objects that are not in this view: those are NOT\r
97      * returned\r
98      * </p>\r
99      * \r
100      * @return\r
101      */\r
102     public List<IGraphicsNode> getInteractiveSelectedObjects() {\r
103         return getSelectedObjects(interactiveSelection);\r
104     }\r
105 \r
106     /**\r
107      * Lists all selected objects\r
108      * <p>\r
109      * Selection may contain objects that are not in this view: those are NOT\r
110      * returned\r
111      * </p>\r
112      * \r
113      * @return\r
114      */\r
115     protected List<IGraphicsNode> getSelectedObjects(StructuredResourceSelection selection) {\r
116         List<IGraphicsNode> l = new ArrayList<IGraphicsNode>();\r
117         Iterator<Resource> i = selection.iterator();\r
118         while (i.hasNext()) {\r
119             Resource s = i.next();\r
120             IGraphicsNode shape = adapter.getNode(s);\r
121             if (shape != null)\r
122                 l.add(shape);\r
123 \r
124         }\r
125         return l;\r
126     }\r
127 \r
128     /**\r
129      * Return selected objects\r
130      * <p>\r
131      * May contain objects that are NOT in this view\r
132      * </p>\r
133      * \r
134      * @return\r
135      */\r
136     public List<Resource> getSelectedResources() {\r
137         List<Resource> l = new ArrayList<Resource>();\r
138         Iterator<Resource> i = selection.iterator();\r
139         while (i.hasNext()) {\r
140             Resource s = (Resource) i.next();\r
141             l.add(s);\r
142 \r
143         }\r
144         return l;\r
145     }\r
146     \r
147     private ArrayList<PickData> processed = new ArrayList<PickData>();\r
148     \r
149     private class ExtTrianglePickResults extends TrianglePickResults {\r
150         public ExtTrianglePickResults() {\r
151                 this.setCheckDistance(true);\r
152         }\r
153         \r
154         public void processPick() {\r
155                         processed.clear();\r
156                         if (getNumber() > 0) {\r
157                                 for (int j = 0; j < getNumber(); j++) {\r
158                                         PickData pData = getPickData(j);\r
159                                         ArrayList<Integer> tris = pData.getTargetTris();\r
160                                         if (tris != null && tris.size() > 0) {\r
161                                                 processed.add(pData);\r
162                                         }\r
163                                 }\r
164                                 \r
165                         }\r
166                         \r
167                 }\r
168     }\r
169     \r
170     private PickResults result = new ExtTrianglePickResults();\r
171 \r
172         \r
173         private void pickPrefix(String prefix) {\r
174 \r
175                 ArrayList<PickData> r= new ArrayList<PickData>();\r
176                 for (int i = 0; i < processed.size(); i++) {\r
177                         PickData pData = processed.get(i);\r
178                         if (pData.getTargetMesh().getParentGeom().getName().startsWith(prefix))\r
179                                 r.add(pData);\r
180                 }\r
181                 processed = r;\r
182         }\r
183         \r
184         /**\r
185          * Updates highlighted objects according to mouse position.\r
186          * \r
187          * @param mouseRay\r
188          */\r
189         public void updateHighlights(Ray mouseRay) {\r
190                 result.clear();\r
191                 adapter.getRenderingComponent().getRoot().calculatePick(mouseRay, result);\r
192                 if (currentGizmo != null) {\r
193                         pickPrefix(currentGizmo.getPickPrefix());\r
194                 }\r
195                 doHighlightPick(processed);\r
196         }\r
197         \r
198         /**\r
199          * Picks highlighted objects\r
200          */\r
201         public void pickHighlighted() {\r
202                 doPick(processed);\r
203         }\r
204         \r
205     /**\r
206      * Processes pick.\r
207      * @param result\r
208      */\r
209     protected void doPick(ArrayList<PickData> result) {\r
210         if (result != null) {\r
211 \r
212                 if (result.size() == 0) {\r
213                         if (mouseClickType != SelectionType.MODIFY)\r
214                     updateSelection(new StructuredResourceSelection());\r
215                         return;\r
216                 }\r
217                 \r
218                 String nodeName = result.get(0).getTargetMesh().getParentGeom().getName();\r
219 \r
220             StructuredResourceSelection s = new StructuredResourceSelection();\r
221             \r
222             Resource selectedResource = adapter.getNodeResource(nodeName);\r
223             if (adapter.getNode(selectedResource) == null) {\r
224                 updateSelection(new StructuredResourceSelection());\r
225                 return;\r
226                 //throw new RuntimeException("Picked resource that has no node ?!");\r
227             }\r
228             if (mouseClickType == SelectionType.MODIFY) {\r
229                 ArrayList<Resource> selected = new ArrayList<Resource>(getSelectedResources());\r
230                 if (selected.contains(selectedResource))\r
231                     selected.remove(selectedResource);\r
232                 else\r
233                     selected.add(selectedResource);\r
234                 for (Resource r : selected)\r
235                     s.add(r);\r
236 \r
237             } else {\r
238                 s.add(selectedResource);\r
239             }\r
240 \r
241             updateSelection(s);\r
242         } else {\r
243             // System.out.println("Picked nothing");\r
244             if (mouseClickType != SelectionType.MODIFY)\r
245                 updateSelection(new StructuredResourceSelection());\r
246         }\r
247     }\r
248 \r
249     /**\r
250      * Processes highlight pick\r
251      * @param result\r
252      */\r
253     protected void doHighlightPick(ArrayList<PickData> result) {\r
254         if (result != null) {\r
255 \r
256                 if (result.size() == 0) {\r
257                         updateGizmo(null);\r
258                 //System.out.println("IPicked nothing");\r
259                 updateHighlightSelection(new StructuredResourceSelection());\r
260                         return;\r
261                 }\r
262                 \r
263                 String nodeName = result.get(0).getTargetMesh().getParentGeom().getName();\r
264         \r
265             updateGizmo(null);\r
266             \r
267             // System.out.println("hits: " + result);\r
268             StructuredResourceSelection s = new StructuredResourceSelection();\r
269                       \r
270             Resource selectedResource = adapter.getNodeResource(nodeName);\r
271             \r
272             if (selectedResource == null) {\r
273                 if (currentGizmo != null && nodeName.startsWith(currentGizmo.getPickPrefix())) {\r
274                     updateGizmo(nodeName);\r
275                 } \r
276                 return;\r
277             }\r
278             \r
279             if (adapter.getNode(selectedResource) != null)\r
280                 s.add(selectedResource);\r
281 \r
282             updateHighlightSelection(s);\r
283         } else {\r
284             updateGizmo(null);\r
285             // System.out.println("IPicked nothing");\r
286             updateHighlightSelection(new StructuredResourceSelection());\r
287         }\r
288     }\r
289     \r
290     /**\r
291      * Updates gizmo according to picked object\r
292      * @param pickName\r
293      */\r
294     private void updateGizmo(String pickName) {\r
295         if (currentGizmo != null) {\r
296             currentGizmo.setSelected(pickName);\r
297             if (currentGizmo.isChanged()) {\r
298                 adapter.setChanged(true);\r
299                 currentGizmo.setChanged(false);\r
300             }\r
301         }\r
302     }\r
303     \r
304     \r
305     /**\r
306      * Contains selection\r
307      */\r
308     protected StructuredResourceSelection selection = new StructuredResourceSelection();\r
309 \r
310     protected StructuredResourceSelection interactiveSelection = new StructuredResourceSelection();\r
311     \r
312     public StructuredResourceSelection getCurrentSelection() {\r
313         return selection;\r
314     }\r
315 \r
316     public void setCurrentSelection(StructuredResourceSelection s) {\r
317         selection = s;\r
318     }\r
319 \r
320     public StructuredResourceSelection getHighlightSelection() {\r
321         return interactiveSelection;\r
322     }\r
323 \r
324     protected void setHighlightSelection(StructuredResourceSelection s) {\r
325         interactiveSelection = s;\r
326     }\r
327     \r
328     private ArrayList<ISelectionChangedListener> selectionChangedListeners = new ArrayList<ISelectionChangedListener>();\r
329 \r
330 \r
331     /*\r
332      * (non-Javadoc)\r
333      * \r
334      * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)\r
335      */\r
336     public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
337         selectionChangedListeners.add(listener);\r
338 \r
339     }\r
340 \r
341     /*\r
342      * (non-Javadoc)\r
343      * \r
344      * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()\r
345      */\r
346     public ISelection getSelection() {\r
347         return selection;\r
348     }\r
349 \r
350     \r
351     \r
352     public static StructuredResourceSelection transformSelection(ISelection sel) {\r
353         if (sel instanceof StructuredResourceSelection)\r
354                 return (StructuredResourceSelection)sel;\r
355         StructuredResourceSelection res = new StructuredResourceSelection();\r
356         Resource resources[] = ResourceAdaptionUtils.toResources(sel);\r
357         for (Resource r : resources)\r
358                 res.add(r);\r
359         return res;\r
360     }\r
361     \r
362 \r
363 \r
364     /*\r
365      * (non-Javadoc)\r
366      * \r
367      * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)\r
368      */\r
369     public void removeSelectionChangedListener(ISelectionChangedListener listener) {\r
370         selectionChangedListeners.remove(listener);\r
371 \r
372     }\r
373 \r
374     /*\r
375      * (non-Javadoc)\r
376      * \r
377      * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)\r
378      */\r
379     public void setSelection(ISelection selection) {\r
380         // System.out.println();\r
381         StructuredResourceSelection s = filterSelection(selection);\r
382         if (this.selection.equals(s))\r
383             return;\r
384         this.selection = s;\r
385         adapter.setChanged(true);\r
386         setEditorSelection();\r
387 \r
388     }\r
389 \r
390     /**\r
391      * Filters selection given with setSelection(ISelection selection) This\r
392      * allows impemented editors to modify selection before it's applied into\r
393      * this editor\r
394      * \r
395      * @param s\r
396      * @return the filtered selection\r
397      */\r
398     protected StructuredResourceSelection filterSelection(ISelection s) {\r
399         if (!(selection instanceof StructuredResourceSelection))\r
400                         return new StructuredResourceSelection();\r
401                 return (StructuredResourceSelection) selection;\r
402     }\r
403 \r
404     /**\r
405      * Updates visual part of selection event. Use getCurrentSelection() to get\r
406      * the selection\r
407      */\r
408     public abstract void setEditorSelection();\r
409 \r
410     /**\r
411      * Updates visual part of selection event. Use getInteractiveSelection() to\r
412      * get the selection\r
413      */\r
414     protected abstract void setEditorHighlightSelection();\r
415 \r
416     /**\r
417      * Editor's internal selection update<br>\r
418      * Sends events to other editors and views about changed selection\r
419      * \r
420      * @param selection\r
421      * @return\r
422      */\r
423     public boolean updateSelection(StructuredResourceSelection s) {\r
424         if (this.selection.equals(s))\r
425             return false;\r
426 \r
427         this.selection = s;\r
428         adapter.setChanged(true);\r
429         fireSelectionChangedEvent();\r
430         setEditorSelection();\r
431         return true;\r
432     }\r
433 \r
434     protected boolean updateHighlightSelection(StructuredResourceSelection s) {\r
435         if (interactiveSelection.equals(s))\r
436             return false;\r
437         this.interactiveSelection = s;\r
438         adapter.setChanged(true);\r
439         setEditorHighlightSelection();\r
440         return true;\r
441     }\r
442 \r
443     /**\r
444      * Fires selection changed events.\r
445      */\r
446     protected void fireSelectionChangedEvent() {\r
447         SelectionChangedEvent e = new SelectionChangedEvent(this, this.selection);\r
448         for (ISelectionChangedListener l : selectionChangedListeners)\r
449             l.selectionChanged(e);\r
450     }\r
451 }\r