--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+import org.simantics.proconf.g3d.gizmo.Gizmo;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.ui.utils.ResourceAdaptionUtils;\r
+\r
+import com.jme.intersection.PickData;\r
+import com.jme.intersection.PickResults;\r
+import com.jme.intersection.TrianglePickResults;\r
+import com.jme.math.Ray;\r
+\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Manages highlighting and selecting of objects.\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class SelectionAdapter implements ISelectionProvider{\r
+ \r
+ protected ScenegraphAdapter adapter;\r
+ \r
+ private Gizmo currentGizmo = null;\r
+ \r
+ public SelectionAdapter(ScenegraphAdapter adapter) {\r
+ if (adapter == null)\r
+ throw new NullPointerException("Scenegraph adapter must no be null");\r
+ this.adapter = adapter;\r
+ }\r
+ \r
+ public enum SelectionType {\r
+ SET, MODIFY\r
+ };\r
+\r
+ protected SelectionType mouseClickType = SelectionType.SET;\r
+ \r
+ public SelectionType getSelectionType() {\r
+ return mouseClickType;\r
+ }\r
+ \r
+ public void setSelectionType(SelectionType type) {\r
+ mouseClickType = type;\r
+ }\r
+ \r
+ public void setCurrentGizmo(Gizmo gizmo) {\r
+ currentGizmo = gizmo;\r
+ }\r
+ \r
+ /**\r
+ * Lists all selected objects\r
+ * <p>\r
+ * Selection may contain objects that are not in this view: those are NOT\r
+ * returned\r
+ * </p>\r
+ * \r
+ * @return\r
+ */\r
+ public List<IGraphicsNode> getSelectedObjects() {\r
+ return getSelectedObjects(selection);\r
+ }\r
+ \r
+ /**\r
+ * Lists all highlighted objects.\r
+ * <p>\r
+ * Typically there may be only one highlighted object.\r
+ * </p>\r
+ * @return\r
+ */\r
+ public List<IGraphicsNode> getHighlightedObjects() {\r
+ return getSelectedObjects(interactiveSelection);\r
+ }\r
+\r
+ /**\r
+ * Lists all selected objects\r
+ * <p>\r
+ * Selection may contain objects that are not in this view: those are NOT\r
+ * returned\r
+ * </p>\r
+ * \r
+ * @return\r
+ */\r
+ public List<IGraphicsNode> getInteractiveSelectedObjects() {\r
+ return getSelectedObjects(interactiveSelection);\r
+ }\r
+\r
+ /**\r
+ * Lists all selected objects\r
+ * <p>\r
+ * Selection may contain objects that are not in this view: those are NOT\r
+ * returned\r
+ * </p>\r
+ * \r
+ * @return\r
+ */\r
+ protected List<IGraphicsNode> getSelectedObjects(StructuredResourceSelection selection) {\r
+ List<IGraphicsNode> l = new ArrayList<IGraphicsNode>();\r
+ Iterator<Resource> i = selection.iterator();\r
+ while (i.hasNext()) {\r
+ Resource s = i.next();\r
+ IGraphicsNode shape = adapter.getNode(s);\r
+ if (shape != null)\r
+ l.add(shape);\r
+\r
+ }\r
+ return l;\r
+ }\r
+\r
+ /**\r
+ * Return selected objects\r
+ * <p>\r
+ * May contain objects that are NOT in this view\r
+ * </p>\r
+ * \r
+ * @return\r
+ */\r
+ public List<Resource> getSelectedResources() {\r
+ List<Resource> l = new ArrayList<Resource>();\r
+ Iterator<Resource> i = selection.iterator();\r
+ while (i.hasNext()) {\r
+ Resource s = (Resource) i.next();\r
+ l.add(s);\r
+\r
+ }\r
+ return l;\r
+ }\r
+ \r
+ private ArrayList<PickData> processed = new ArrayList<PickData>();\r
+ \r
+ private class ExtTrianglePickResults extends TrianglePickResults {\r
+ public ExtTrianglePickResults() {\r
+ this.setCheckDistance(true);\r
+ }\r
+ \r
+ public void processPick() {\r
+ processed.clear();\r
+ if (getNumber() > 0) {\r
+ for (int j = 0; j < getNumber(); j++) {\r
+ PickData pData = getPickData(j);\r
+ ArrayList<Integer> tris = pData.getTargetTris();\r
+ if (tris != null && tris.size() > 0) {\r
+ processed.add(pData);\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ private PickResults result = new ExtTrianglePickResults();\r
+\r
+ \r
+ private void pickPrefix(String prefix) {\r
+\r
+ ArrayList<PickData> r= new ArrayList<PickData>();\r
+ for (int i = 0; i < processed.size(); i++) {\r
+ PickData pData = processed.get(i);\r
+ if (pData.getTargetMesh().getParentGeom().getName().startsWith(prefix))\r
+ r.add(pData);\r
+ }\r
+ processed = r;\r
+ }\r
+ \r
+ /**\r
+ * Updates highlighted objects according to mouse position.\r
+ * \r
+ * @param mouseRay\r
+ */\r
+ public void updateHighlights(Ray mouseRay) {\r
+ result.clear();\r
+ adapter.getRenderingComponent().getRoot().calculatePick(mouseRay, result);\r
+ if (currentGizmo != null) {\r
+ pickPrefix(currentGizmo.getPickPrefix());\r
+ }\r
+ doHighlightPick(processed);\r
+ }\r
+ \r
+ /**\r
+ * Picks highlighted objects\r
+ */\r
+ public void pickHighlighted() {\r
+ doPick(processed);\r
+ }\r
+ \r
+ /**\r
+ * Processes pick.\r
+ * @param result\r
+ */\r
+ protected void doPick(ArrayList<PickData> result) {\r
+ if (result != null) {\r
+\r
+ if (result.size() == 0) {\r
+ if (mouseClickType != SelectionType.MODIFY)\r
+ updateSelection(new StructuredResourceSelection());\r
+ return;\r
+ }\r
+ \r
+ String nodeName = result.get(0).getTargetMesh().getParentGeom().getName();\r
+\r
+ StructuredResourceSelection s = new StructuredResourceSelection();\r
+ \r
+ Resource selectedResource = adapter.getNodeResource(nodeName);\r
+ if (adapter.getNode(selectedResource) == null) {\r
+ updateSelection(new StructuredResourceSelection());\r
+ return;\r
+ //throw new RuntimeException("Picked resource that has no node ?!");\r
+ }\r
+ if (mouseClickType == SelectionType.MODIFY) {\r
+ ArrayList<Resource> selected = new ArrayList<Resource>(getSelectedResources());\r
+ if (selected.contains(selectedResource))\r
+ selected.remove(selectedResource);\r
+ else\r
+ selected.add(selectedResource);\r
+ for (Resource r : selected)\r
+ s.add(r);\r
+\r
+ } else {\r
+ s.add(selectedResource);\r
+ }\r
+\r
+ updateSelection(s);\r
+ } else {\r
+ // System.out.println("Picked nothing");\r
+ if (mouseClickType != SelectionType.MODIFY)\r
+ updateSelection(new StructuredResourceSelection());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Processes highlight pick\r
+ * @param result\r
+ */\r
+ protected void doHighlightPick(ArrayList<PickData> result) {\r
+ if (result != null) {\r
+\r
+ if (result.size() == 0) {\r
+ updateGizmo(null);\r
+ //System.out.println("IPicked nothing");\r
+ updateHighlightSelection(new StructuredResourceSelection());\r
+ return;\r
+ }\r
+ \r
+ String nodeName = result.get(0).getTargetMesh().getParentGeom().getName();\r
+ \r
+ updateGizmo(null);\r
+ \r
+ // System.out.println("hits: " + result);\r
+ StructuredResourceSelection s = new StructuredResourceSelection();\r
+ \r
+ Resource selectedResource = adapter.getNodeResource(nodeName);\r
+ \r
+ if (selectedResource == null) {\r
+ if (currentGizmo != null && nodeName.startsWith(currentGizmo.getPickPrefix())) {\r
+ updateGizmo(nodeName);\r
+ } \r
+ return;\r
+ }\r
+ \r
+ if (adapter.getNode(selectedResource) != null)\r
+ s.add(selectedResource);\r
+\r
+ updateHighlightSelection(s);\r
+ } else {\r
+ updateGizmo(null);\r
+ // System.out.println("IPicked nothing");\r
+ updateHighlightSelection(new StructuredResourceSelection());\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Updates gizmo according to picked object\r
+ * @param pickName\r
+ */\r
+ private void updateGizmo(String pickName) {\r
+ if (currentGizmo != null) {\r
+ currentGizmo.setSelected(pickName);\r
+ if (currentGizmo.isChanged()) {\r
+ adapter.setChanged(true);\r
+ currentGizmo.setChanged(false);\r
+ }\r
+ }\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Contains selection\r
+ */\r
+ protected StructuredResourceSelection selection = new StructuredResourceSelection();\r
+\r
+ protected StructuredResourceSelection interactiveSelection = new StructuredResourceSelection();\r
+ \r
+ public StructuredResourceSelection getCurrentSelection() {\r
+ return selection;\r
+ }\r
+\r
+ public void setCurrentSelection(StructuredResourceSelection s) {\r
+ selection = s;\r
+ }\r
+\r
+ public StructuredResourceSelection getHighlightSelection() {\r
+ return interactiveSelection;\r
+ }\r
+\r
+ protected void setHighlightSelection(StructuredResourceSelection s) {\r
+ interactiveSelection = s;\r
+ }\r
+ \r
+ private ArrayList<ISelectionChangedListener> selectionChangedListeners = new ArrayList<ISelectionChangedListener>();\r
+\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)\r
+ */\r
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
+ selectionChangedListeners.add(listener);\r
+\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()\r
+ */\r
+ public ISelection getSelection() {\r
+ return selection;\r
+ }\r
+\r
+ \r
+ \r
+ public static StructuredResourceSelection transformSelection(ISelection sel) {\r
+ if (sel instanceof StructuredResourceSelection)\r
+ return (StructuredResourceSelection)sel;\r
+ StructuredResourceSelection res = new StructuredResourceSelection();\r
+ Resource resources[] = ResourceAdaptionUtils.toResources(sel);\r
+ for (Resource r : resources)\r
+ res.add(r);\r
+ return res;\r
+ }\r
+ \r
+\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)\r
+ */\r
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {\r
+ selectionChangedListeners.remove(listener);\r
+\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)\r
+ */\r
+ public void setSelection(ISelection selection) {\r
+ // System.out.println();\r
+ StructuredResourceSelection s = filterSelection(selection);\r
+ if (this.selection.equals(s))\r
+ return;\r
+ this.selection = s;\r
+ adapter.setChanged(true);\r
+ setEditorSelection();\r
+\r
+ }\r
+\r
+ /**\r
+ * Filters selection given with setSelection(ISelection selection) This\r
+ * allows impemented editors to modify selection before it's applied into\r
+ * this editor\r
+ * \r
+ * @param s\r
+ * @return the filtered selection\r
+ */\r
+ protected StructuredResourceSelection filterSelection(ISelection s) {\r
+ if (!(selection instanceof StructuredResourceSelection))\r
+ return new StructuredResourceSelection();\r
+ return (StructuredResourceSelection) selection;\r
+ }\r
+\r
+ /**\r
+ * Updates visual part of selection event. Use getCurrentSelection() to get\r
+ * the selection\r
+ */\r
+ public abstract void setEditorSelection();\r
+\r
+ /**\r
+ * Updates visual part of selection event. Use getInteractiveSelection() to\r
+ * get the selection\r
+ */\r
+ protected abstract void setEditorHighlightSelection();\r
+\r
+ /**\r
+ * Editor's internal selection update<br>\r
+ * Sends events to other editors and views about changed selection\r
+ * \r
+ * @param selection\r
+ * @return\r
+ */\r
+ public boolean updateSelection(StructuredResourceSelection s) {\r
+ if (this.selection.equals(s))\r
+ return false;\r
+\r
+ this.selection = s;\r
+ adapter.setChanged(true);\r
+ fireSelectionChangedEvent();\r
+ setEditorSelection();\r
+ return true;\r
+ }\r
+\r
+ protected boolean updateHighlightSelection(StructuredResourceSelection s) {\r
+ if (interactiveSelection.equals(s))\r
+ return false;\r
+ this.interactiveSelection = s;\r
+ adapter.setChanged(true);\r
+ setEditorHighlightSelection();\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Fires selection changed events.\r
+ */\r
+ protected void fireSelectionChangedEvent() {\r
+ SelectionChangedEvent e = new SelectionChangedEvent(this, this.selection);\r
+ for (ISelectionChangedListener l : selectionChangedListeners)\r
+ l.selectionChanged(e);\r
+ }\r
+}\r