/*
* Copyright 2004-2010 Information & Software Engineering Group (188/1)
* Institute of Software Technology and Interactive Systems
* Vienna University of Technology, Austria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.tuwien.ifs.somtoolbox.apps.viewer.handlers;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.event.InputEvent;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import java.util.logging.Logger;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.event.PInputEventFilter;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolox.event.PNotificationCenter;
import edu.umd.cs.piccolox.nodes.PLine;
import at.tuwien.ifs.somtoolbox.apps.viewer.GeneralUnitPNode;
/**
* Implements the line selection model, everything below a drawn line is selected.
*
* @author Robert Neumayer
* @version $Id: LineSelectionEventHandler.java 3888 2010-11-02 17:42:53Z frank $
*/
public class LineSelectionEventHandler extends OrderedPSelectionEventHandler {
public static final String SELECTION_CHANGED_NOTIFICATION = "SELECTION_CHANGED_NOTIFICATION";
// width of units * blur factor = selection --> blur factor 1.0 means that every unit below the selection and +/-
// unit with is selected
public static final float BLUR_FACTOR = 0.2f;
private String selectionStatusString = "";
private Vector<PNode> lineParts = null; // stores parts of lines drawn for later removal
private List<PNode> selectableParents = null; // List of nodes whose children can be selected
private PNode marqueeParent = null; // Node that marquee is added to as a child
// private Point2D presspt = null;
// private Point2D canvasPressPt = null;
private HashMap<Object, Boolean> allItems = null; // Used within drag handler temporarily
// private ArrayList unselectList = null; // Used within drag handler temporarily
// private HashMap marqueeMap = null;
private PNode pressNode = null; // Node pressed on (or null if none)
// private boolean firsttime = true;
/**
* Creates a selection event handler.
*
* @param marqueeParent The node to which the event handler dynamically adds a marquee (temporarily) to represent
* the area being selected.
* @param selectableParent The node whose children will be selected by this event handler.
*/
public LineSelectionEventHandler(PNode marqueeParent, PNode selectableParent) {
super(marqueeParent, selectableParent);
this.marqueeParent = marqueeParent;
this.selectableParents = new ArrayList<PNode>();
this.selectableParents.add(selectableParent);
setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK));
init();
}
@Override
public void decorateSelectedNode(PNode node) {
// do nothing now
// super.decorateSelectedNode(arg0);
if (GeneralUnitPNode.class.isInstance(node)) {
((GeneralUnitPNode) node).setSelected(true);
}
}
@Override
public void undecorateSelectedNode(PNode node) {
// super.undecorateSelectedNode(node);
if (GeneralUnitPNode.class.isInstance(node)) {
((GeneralUnitPNode) node).setSelected(false);
}
}
@Override
public void init() {
super.init();
this.lineParts = new Vector<PNode>();
allItems = new HashMap<Object, Boolean>();
this.setIsDragging(false);
}
/**
* delete the old selection / line
*/
public void deleteOldLine() {
// System.out.println("delete old line " + lineParts.size());
if (!lineParts.isEmpty()) {
for (PNode linePart : lineParts) {
marqueeParent.removeChild(linePart);
}
lineParts.clear();
}
unselectAll();
marqueeParent.repaint();
}
// //////////////////////////////////////////////////////
// The overridden methods from PDragSequenceEventHandler
// //////////////////////////////////////////////////////
static Point2D startPoint;
static Point2D lastPoint;
static Point2D nextPoint;
static Point2D endPoint;
PLine currentLine = null;
@Override
protected void startDrag(PInputEvent e) {
super.startDrag(e);
startPoint = marqueeParent.globalToLocal(e.getPosition());
this.initializeSelection(e);
this.deleteOldLine();
this.selectionStatusString = "Selected Units:";
lastPoint = startPoint;
// currentLine = new PLine();
// currentLine.setStroke(new BasicStroke(14, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
// currentLine.setStrokePaint(Color.red);
// // currentLine.setTransparency(0.2f);
// marqueeParent.addChild(currentLine);
// lineParts.add(currentLine);
}
@Override
protected void drag(PInputEvent e) {
nextPoint = marqueeParent.globalToLocal(e.getPosition());
// float blur = 0.4f;
PPath pp = PPath.createLine((float) lastPoint.getX(), (float) lastPoint.getY(), (float) nextPoint.getX(),
(float) nextPoint.getY());
pp.setStroke(new BasicStroke(14));
pp.setStrokePaint(Color.red);
// pp.setTransparency(0.2f);
marqueeParent.addChild(pp);
lineParts.add(pp);
// PLine pl = new PLine();
// pl.addPoint(0, lastPoint.getX(), lastPoint.getY());
// pl.addPoint(1, nextPoint.getX(), nextPoint.getY());
// pl.setStroke(new BasicStroke(14, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
// pl.setStrokePaint(Color.red);
// marqueeParent.addChild(pl);
// lineParts.add(pl);
if (currentLine != null) {
currentLine.addPoint(currentLine.getPointCount(), nextPoint.getX(), nextPoint.getY());
}
updateWhatever(e);
lastPoint = nextPoint;
PNotificationCenter.defaultCenter().postNotification(SELECTION_CHANGED_NOTIFICATION, this);
}
// //////////////////////////
// Additional methods, partly restricted
// //////////////////////////
@Override
protected boolean isMarqueeSelection(PInputEvent pie) {
return true;
}
@Override
protected void initializeMarquee(PInputEvent e) {
}
@Override
protected void startMarqueeSelection(PInputEvent e) {
}
/** adds the node specified by the event e to the current selection (if it is not selected already) */
protected void updateWhatever(PInputEvent e) {
for (PNode parent : selectableParents) {
for (Object o : parent.getAllNodes()) {
if (o instanceof GeneralUnitPNode) {
GeneralUnitPNode upn = (GeneralUnitPNode) o;
if (this.onSelection(upn, nextPoint)) {
if (!this.alreadySelected(o)) {
super.select(upn);
this.selectionStatusString += " (" + upn.getUnit().getXPos() + "/"
+ upn.getUnit().getYPos() + ")";
Logger.getLogger("at.tuwien.ifs.somtoolbox").finer(selectionStatusString);
}
}
}
allItems.put(o, Boolean.TRUE);
}
}
}
/**
* check if the given Point lies on the given UnitPNode
*
* @return - true if coordinates match, false if not
*/
protected boolean onSelection(GeneralUnitPNode upn, Point2D selectedPoint) {
double nodex1 = upn.getX();
double nodex2 = upn.getX() + upn.getWidth();
double nodey1 = upn.getY();
double nodey2 = upn.getY() + upn.getHeight();
/*
* debug System.out.println("_______________"); System.out.println(nodex1); System.out.println(nodex2); System.out.println(nodey1);
* System.out.println(nodey2); System.out.println("_____"); System.out.println(selectedPoint.getX() + " " + selectedPoint.getY());
*/
if (selectedPoint.getX() >= nodex1 - upn.getWidth() * BLUR_FACTOR
&& selectedPoint.getX() <= nodex2 + upn.getWidth() * BLUR_FACTOR) {
if (selectedPoint.getY() >= nodey1 - upn.getWidth() * BLUR_FACTOR
&& selectedPoint.getY() <= nodey2 + upn.getHeight() * BLUR_FACTOR) {
return true;
}
}
return false;
}
@Override
protected void endMarqueeSelection(PInputEvent e) {
}
@Override
protected void endStandardSelection(PInputEvent e) {
pressNode = null;
}
}