/*FreeMind - A Program for creating and viewing Mindmaps
*Copyright (C) 2000-2001 Joerg Mueller <joergmueller@bigfoot.com>
*See COPYING for Details
*
*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 2
*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, write to the Free Software
*Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package freemind.modes.mindmapmode.listeners;
import java.awt.AWTException;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import freemind.controller.NodeMotionListener.NodeMotionAdapter;
import freemind.main.Tools;
import freemind.modes.MindMapNode;
import freemind.modes.NodeAdapter;
import freemind.modes.mindmapmode.MindMapController;
import freemind.view.mindmapview.MapView;
import freemind.view.mindmapview.NodeMotionListenerView;
import freemind.view.mindmapview.NodeView;
/**
* The MouseMotionListener which belongs to every NodeView
*/
public class MindMapNodeMotionListener extends NodeMotionAdapter {
private final MindMapController c;
// Logging:
private static java.util.logging.Logger logger;
public MindMapNodeMotionListener(MindMapController controller) {
c = controller;
if (logger == null)
logger = c.getFrame().getLogger(this.getClass().getName());
}
public void mouseMoved(MouseEvent e) {
}
private Point dragStartingPoint = null;
private int originalParentVGap;
private int originalHGap;
private int originalShiftY;
/** Invoked when a mouse button is pressed on a component and then dragged. */
public void mouseDragged(MouseEvent e) {
logger.fine("Event: mouseDragged");
if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == (InputEvent.BUTTON1_DOWN_MASK)) {
final NodeMotionListenerView motionListenerView = (NodeMotionListenerView) e
.getSource();
final NodeView nodeView = getNodeView(e);
final MapView mapView = nodeView.getMap();
MindMapNode node = nodeView.getModel();
Point point = e.getPoint();
Tools.convertPointToAncestor(motionListenerView, point,
JScrollPane.class);
if (!isActive()) {
setDragStartingPoint(point, node);
} else {
Point dragNextPoint = point;
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) == 0) {
int nodeShiftY = getNodeShiftY(dragNextPoint, node,
dragStartingPoint);
int hGap = getHGap(dragNextPoint, node, dragStartingPoint);
node.setShiftY(nodeShiftY);
node.setHGap(hGap);
} else {
MindMapNode parentNode = nodeView.getVisibleParentView()
.getModel();
parentNode
.setVGap(getVGap(dragNextPoint, dragStartingPoint));
c.getModeController().nodeRefresh(parentNode);
}
dragStartingPoint = dragNextPoint;
c.getModeController().nodeRefresh(node);
}
Point mapPoint = e.getPoint();
Tools.convertPointToAncestor(motionListenerView, mapPoint, mapView);
boolean isEventPointVisible = mapView.getVisibleRect().contains(
mapPoint);
if (!isEventPointVisible) {
Rectangle r = new Rectangle(mapPoint);
Rectangle bounds = mapView.getBounds();
mapView.scrollRectToVisible(r);
Rectangle bounds2 = mapView.getBounds();
int diffx = bounds2.x - bounds.x;
int diffy = bounds2.y - bounds.y;
try {
mapPoint.translate(diffx, diffy);
// here, there are strange cases, when the mouse moves away.
// Workaround.
if (mapView.getVisibleRect().contains(mapPoint)) {
(new Robot()).mouseMove(e.getXOnScreen() + diffx,
e.getYOnScreen() + diffy);
}
} catch (AWTException e1) {
freemind.main.Resources.getInstance().logException(e1);
}
dragStartingPoint.x += ((node.getHGap() < 0) ? 2 : 1) * diffx;
dragStartingPoint.y += ((node.getShiftY() < 0) ? 2 : 1) * diffy;
}
}
}
private int getVGap(Point dragNextPoint, Point dragStartingPoint) {
int oldVGap = originalParentVGap;
int vGapChange = (int) ((dragNextPoint.y - dragStartingPoint.y) / c
.getView().getZoom());
oldVGap = Math.max(0, oldVGap - vGapChange);
return oldVGap;
}
private int getHGap(Point dragNextPoint, MindMapNode node,
Point dragStartingPoint) {
int oldHGap = node.getHGap();
int hGapChange = (int) ((dragNextPoint.x - dragStartingPoint.x) / c
.getView().getZoom());
if (node.isLeft())
hGapChange = -hGapChange;
oldHGap += +hGapChange;
return oldHGap;
}
private int getNodeShiftY(Point dragNextPoint, MindMapNode pNode,
Point dragStartingPoint) {
int shiftY = pNode.getShiftY();
int shiftYChange = (int) ((dragNextPoint.y - dragStartingPoint.y) / c
.getView().getZoom());
shiftY += shiftYChange;
return shiftY;
}
public void mouseClicked(MouseEvent e) {
if (e.getButton() == 1 && e.getClickCount() == 2) {
if (e.getModifiersEx() == 0) {
NodeView nodeV = getNodeView(e);
MindMapNode node = nodeV.getModel();
c.moveNodePosition(node, node.getVGap(), NodeAdapter.HGAP, 0);
return;
}
if (e.getModifiersEx() == InputEvent.CTRL_DOWN_MASK) {
NodeView nodeV = getNodeView(e);
MindMapNode node = nodeV.getModel();
c.moveNodePosition(node, NodeAdapter.VGAP, node.getHGap(),
node.getShiftY());
return;
}
}
}
/**
*/
private NodeView getNodeView(MouseEvent e) {
return ((NodeMotionListenerView) e.getSource()).getMovedView();
}
public void mouseEntered(MouseEvent e) {
logger.fine("Event: mouseEntered");
if (!JOptionPane.getFrameForComponent(e.getComponent()).isFocused())
return;
if (!isActive()) {
NodeMotionListenerView v = (NodeMotionListenerView) e.getSource();
v.setMouseEntered();
}
}
public void mouseExited(MouseEvent e) {
logger.fine("Event: mouseExited");
if (!isActive()) {
NodeMotionListenerView v = (NodeMotionListenerView) e.getSource();
v.setMouseExited();
}
}
private void stopDrag() {
setDragStartingPoint(null, null);
}
public void mouseReleased(MouseEvent e) {
logger.fine("Event: mouseReleased");
NodeMotionListenerView v = (NodeMotionListenerView) e.getSource();
if (!v.contains(e.getX(), e.getY()))
v.setMouseExited();
if (!isActive())
return;
NodeView nodeV = getNodeView(e);
Point point = e.getPoint();
Tools.convertPointToAncestor(nodeV, point, JScrollPane.class);
// move node to end position.
MindMapNode node = nodeV.getModel();
MindMapNode parentNode = nodeV.getModel().getParentNode();
final int parentVGap = parentNode.getVGap();
final int hgap = node.getHGap();
final int shiftY = node.getShiftY();
resetPositions(node);
c.moveNodePosition(node, parentVGap, hgap, shiftY);
stopDrag();
}
/**
*/
private void resetPositions(MindMapNode node) {
node.getParentNode().setVGap(originalParentVGap);
node.setHGap(originalHGap);
node.setShiftY(originalShiftY);
}
public boolean isActive() {
return getDragStartingPoint() != null;
}
void setDragStartingPoint(Point point, MindMapNode node) {
dragStartingPoint = point;
if (point != null) {
originalParentVGap = node.getParentNode().getVGap();
originalHGap = node.getHGap();
originalShiftY = node.getShiftY();
} else {
originalParentVGap = originalHGap = originalShiftY = 0;
}
}
Point getDragStartingPoint() {
return dragStartingPoint;
}
}