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