/***********************************************************************
* mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.input.gestureAction;
import org.mt4j.components.MTCanvas;
import org.mt4j.components.MTComponent;
import org.mt4j.components.StateChange;
import org.mt4j.components.StateChangeEvent;
import org.mt4j.components.StateChangeListener;
import org.mt4j.components.clusters.Cluster;
import org.mt4j.components.clusters.ClusterManager;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.lassoProcessor.IdragClusterable;
import org.mt4j.input.inputProcessors.componentProcessors.lassoProcessor.LassoEvent;
import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
import org.mt4j.util.MTColor;
import processing.core.PApplet;
/**
* The Class DefaultLassoAction.
*
* @author Christopher Ruff
*/
public class DefaultLassoAction implements IGestureEventListener {
/** The cluster mgr. */
private ClusterManager clusterMgr;
/** The canvas. */
private MTCanvas canvas;
/** The pa. */
private PApplet pa;
/**
* Instantiates a new default clustering action.
*
* @param pa the pa
* @param clustermgr the clustermgr
* @param canvas the canvas
*/
public DefaultLassoAction(PApplet pa, ClusterManager clustermgr, MTCanvas canvas){
this.pa = pa;
this.clusterMgr = clustermgr;
this.canvas = canvas;
}
/* (non-Javadoc)
* @see com.jMT.input.gestureAction.IGestureAction#processGesture(com.jMT.input.inputAnalyzers.GestureEvent)
*/
public boolean processGestureEvent(MTGestureEvent g) {
if (g instanceof LassoEvent){
LassoEvent dse = (LassoEvent)g;
switch (dse.getId()) {
case MTGestureEvent.GESTURE_DETECTED:
//System.out.println("dse detected");
canvas.addChild(dse.getSelectionPoly());
break;
case MTGestureEvent.GESTURE_UPDATED:
//System.out.println("dse updated");
break;
case MTGestureEvent.GESTURE_ENDED:
//TODO make method addSelection and do the stuff here
//so it can be called from the outside too /addNewSelection(comps[])
//System.out.println("dse ended");
IdragClusterable[] selectedComps = dse.getClusteredComponents();
//Create new selection only if at least more than 1 is selected
if (selectedComps.length > 1){
//Create new Cluster
Cluster cluster = new Cluster(pa, dse.getSelectionPoly());
//Attach a cam to the cluster because it doesent have the canvas as a parent as it is now..
cluster.attachCamera(selectedComps[0].getViewingCamera());
//Add gestures //TODO what about the isRotatable/dragable settings of the childs?
//TODO What if we want to click a item of the cluster only? ->Maybe cluster should
//delegate other gestures to the components..
// cluster.assignGestureClassAndAction(DragGestureAnalyzer.class, new DefaultDragAction());
cluster.registerInputProcessor(new DragProcessor(pa));
cluster.addGestureListener(DragProcessor.class, new DefaultDragAction());
cluster.addGestureListener(DragProcessor.class, new InertiaDragAction());
cluster.registerInputProcessor(new RotateProcessor(pa));
cluster.addGestureListener(RotateProcessor.class, new DefaultRotateAction());
cluster.registerInputProcessor(new ScaleProcessor(pa));
cluster.addGestureListener(ScaleProcessor.class, new DefaultScaleAction());
dse.getSelectionPoly().setFillColor(new MTColor(100,150,250, 50));
dse.getSelectionPoly().setGestureAllowance(DragProcessor.class, true);
dse.getSelectionPoly().setGestureAllowance(RotateProcessor.class, true);
dse.getSelectionPoly().setGestureAllowance(ScaleProcessor.class, true);
System.out.println("\n" + selectedComps.length + " Selected:");
// int n = -1;
int n = Integer.MAX_VALUE;
//Set all cards selected
for (IdragClusterable currentComp : selectedComps){
System.out.print((currentComp).getName() + " "); //remove later
if (currentComp instanceof MTComponent){//Add selected comps to selection - RIGHT NOW ONLY SUPPORTS INSTANCES OF MTCOMPONENT!
MTComponent mtCurrentComp = (MTComponent)currentComp;
///////////////////////////////
// Listen to destroy events of the clustered components, to remove them from
// the cluster and pack the polygon.
mtCurrentComp.addStateChangeListener(StateChange.COMPONENT_DESTROYED, new StateChangeListener(){
public void stateChanged(StateChangeEvent evt) {
if (evt.getSource() instanceof MTComponent) {
MTComponent sourceComp = (MTComponent) evt.getSource();
//Remove component from cluster it is in
Cluster clusterOfComponent = clusterMgr.getCluster(sourceComp);
if (clusterOfComponent != null){
((IdragClusterable)sourceComp).setSelected(false);
//Remvove the component from its former selection
clusterOfComponent.removeChild(sourceComp);
//System.out.println("Comp destroyed and removed from cluster: " + sourceComp.getName());
//remove the former selection from the selectionmanager if it consists only of 1 less components
if (clusterOfComponent.getChildCount() <= 2){
clusterMgr.removeCluster(clusterOfComponent);
}else{
//Tighten convex hull of reduced cluster
clusterOfComponent.packClusterPolygon();
}
}
}
}
});
////////////////////////////////
//Remove comp from former selection if it is in a new selection
Cluster formerSelection = clusterMgr.getCluster(currentComp);
if (formerSelection != null){
formerSelection.removeChild(mtCurrentComp);
//Remove the former selection from the selectionmanager if it consists only of 1 less components
if (formerSelection.getChildCount() <= 2){ //2 because the selection polygon is also always in the selection
// SceneManager.getInstance().getCurrentScene().getMainCanvas().getSelectionManager().removeSelection(formerSelection);
clusterMgr.removeCluster(formerSelection);
}else{
//Tighten convex hull of reduced cluster
formerSelection.packClusterPolygon();
}
}
//Get the last index of the selected component in the parent list to know where to add the selectionpoly
if (mtCurrentComp.getParent() != null){
int indexInParentList = mtCurrentComp.getParent().getChildIndexOf(mtCurrentComp);
// if (indexInParentList > n){
// n = indexInParentList;
// }
if (indexInParentList < n){
n = indexInParentList;
}
}
//ADD components to the selection and set it to selected
cluster.addChild(mtCurrentComp);
currentComp.setSelected(true);
}//if instance mtbasecomp
}//for
//Draw a convex hull around all selected shapes
cluster.packClusterPolygon();
dse.getSelectionPoly().setLineStipple((short)0xDDDD);
dse.getSelectionPoly().setStrokeColor(new MTColor(0,0,0,255));
//Add the selection poly 1 index after the index of the highest index of the selected components
if (selectedComps[0] instanceof MTComponent
&& ((MTComponent)selectedComps[0]).getParent() != null){
MTComponent firstSelectedComp = (MTComponent)selectedComps[0];
// System.out.println("n:" + n);
// System.out.println("Parent childcount: " + firstSelectedComp.getParent().getChildCount());
firstSelectedComp.getParent().addChild(n, dse.getSelectionPoly());
// if (n < firstSelectedComp.getParent().getChildCount())
// firstSelectedComp.getParent().addChild(n+1, dse.getSelectionPoly());
// else //FIXME this has caused out of bounds
// firstSelectedComp.getParent().addChild(n, dse.getSelectionPoly());
}
//Add selection to selection manager
clusterMgr.addCluster(cluster);
//IF exactly 1 component is selected and its already part of an selection remove it from it without making a new selection with it
}else if (selectedComps.length == 1){
for (IdragClusterable currentComp : selectedComps){
if (currentComp instanceof MTComponent){//Add selected comps to selection - RIGHT NOW ONLY SUPPORTS INSTANCES OF MTCOMPONENT!
//Remove comp from former selection if it is in a new selection
Cluster formerSelection = clusterMgr.getCluster(currentComp);
if (formerSelection != null){
currentComp.setSelected(false);
//Remvove the component from its former selection
formerSelection.removeChild((MTComponent)currentComp);
//remove the former selection from the selectionmanager if it consists only of 1 less components
if (formerSelection.getChildCount() <= 2){
clusterMgr.removeCluster(formerSelection);
}else{
//Tighten convex hull of reduced cluster
formerSelection.packClusterPolygon();
}
}
}
}
//Remove the Selection Polygon from the canvas when only 1 component is selected
clusterMgr.removeClusterPolyFromCanvas(dse.getSelectionPoly());
}
//If no comp is selected, just remove the selection polygon from canvas
else if (selectedComps.length < 1){
//Remove the Selection Polygon from the canvas when no component is selected
clusterMgr.removeClusterPolyFromCanvas(dse.getSelectionPoly());
}
break;
}//switch
}//instanceof clusterevt
return false;
}//processgesture()
}