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