/*
* org.openmicroscopy.shoola.util.ui.tpane.BorderListener
*
*------------------------------------------------------------------------------
* Copyright (C) 2006 University of Dundee. 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 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.util.ui.tpane;
//Java imports
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import javax.swing.DefaultDesktopManager;
import javax.swing.DesktopManager;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
//Third-party libraries
//Application-internal dependencies
/**
* Listens to mouse motions and inputs events to move and resize the
* {@link TinyPane}. The {@link TinyPane} will behave like a
* {@link javax.swing.JInternalFrame}.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @version 2.2
* <small>
* (<b>Internal version:</b> $Revision: 4811 $ $Date: 2007-05-08 14:48:34 +0000 (Tue, 08 May 2007) $)
* </small>
* @since OME2.2
*/
class BorderListener
extends MouseInputAdapter
implements SwingConstants
{
/** Identifies the resizing zone. */
private static final int RESIZE_NONE = 0;
/** Flag to discard the release action. */
private boolean discardRelease;
/** Value added to resize the corner of the frame. */
private int resizeCornerSize = 16;
/** Reference to the desktopManager. */
private static DesktopManager sharedDesktopManager;
/** Flag to control the dragging events. */
private boolean dragging;
/** The mousePressed x-coordinate in absolute coordinate system. */
private int xAbs;
/** The mousePressed y-coordinate in absolute coordinate system. */
private int yAbs;
/** The mousePressed x-coordinate in source view's coordinate system. */
private int xView;
/** The mousePressed y-coordinate in source view's coordinate system. */
private int yView;
/** The starting rectangle. */
private Rectangle startingBounds;
/** The bounds of the parent of the {@link TinyPane} frame. */
private Rectangle parentBounds;
/** The direction of a move. */
private int resizeDir;
/** The Model this listener is for. */
private TinyPane frame;
/**
* Creates a {@link DesktopManager}.
*
* @return See above.
*/
protected DesktopManager getDesktopManager()
{
if (sharedDesktopManager == null)
sharedDesktopManager = new DefaultDesktopManager();
return sharedDesktopManager;
}
/**
* Creates a new instance.
*
* @param frame Reference to the {@link TinyPane model}. Mustn't be
* <code>null</code>.
*/
BorderListener(TinyPane frame)
{
if (frame == null) throw new NullPointerException("No frame.");
this.frame = frame;
Container parent = frame.getParent();
if (parent != null) parentBounds = parent.getBounds();
}
/**
* Handles <code>mouseReleased</code> event.
* @see MouseInputAdapter#mouseReleased(MouseEvent)
*/
public void mouseReleased(MouseEvent e)
{
if (discardRelease) {
discardRelease = false;
return;
}
frame.notifyEndMoving();
if (resizeDir == RESIZE_NONE) {
getDesktopManager().endDraggingFrame(frame);
dragging = false;
} else {
frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
getDesktopManager().endResizingFrame(frame);
//Rectangle r = frame.getBounds();
//Dimension d = r.getSize();
//frame.getInternalDesktop().setPreferredSize(d);
//frame.getInternalDesktop().setSize(d);
}
xAbs = 0;
yAbs = 0;
xView = 0;
yView = 0;
startingBounds = null;
resizeDir = RESIZE_NONE;
}
/**
* Handles <code>mousePressed</code> event.
* @see MouseInputAdapter#mousePressed(MouseEvent)
*/
public void mousePressed(MouseEvent e)
{
Point p = SwingUtilities.convertPoint((Component) e.getSource(),
e.getX(), e.getY(), null);
xView = e.getX();
yView = e.getY();
xAbs = p.x;
yAbs = p.y;
startingBounds = frame.getBounds();
resizeDir = RESIZE_NONE;
Insets i = frame.getInsets();
Point ep = new Point(xView, yView);
JComponent titleBar = frame.getTitleBar();
if (e.getSource() == titleBar) {
Point np = titleBar.getLocation();
ep.x += np.x;
ep.y += np.y;
}
frame.onFrameIconPressed(ep);
if (e.getSource() == titleBar) {
if (ep.x > i.left && ep.y > i.top && ep.x <
frame.getWidth()-i.right) {
getDesktopManager().beginDraggingFrame(frame);
dragging = true;
return;
}
}
if (!frame.isResizable()) return;
if (e.getSource() == frame || e.getSource() == titleBar) {
if (ep.x <= i.left) {
if (ep.y < resizeCornerSize + i.top) resizeDir = NORTH_WEST;
else if (ep.y > frame.getHeight()-resizeCornerSize-i.bottom)
resizeDir = SOUTH_WEST;
else resizeDir = WEST;
} else if (ep.x >= frame.getWidth()-i.right) {
if (ep.y < resizeCornerSize+i.top) resizeDir = NORTH_EAST;
else if (ep.y > frame.getHeight()-resizeCornerSize-i.bottom)
resizeDir = SOUTH_EAST;
else resizeDir = EAST;
} else if (ep.y <= i.top) {
if (ep.x < resizeCornerSize+i.left) resizeDir = NORTH_WEST;
else if (ep.x > frame.getWidth()-resizeCornerSize-i.right)
resizeDir = NORTH_EAST;
else resizeDir = NORTH;
} else if (ep.y >= frame.getHeight()-i.bottom) {
if (ep.x < resizeCornerSize+i.left) resizeDir = SOUTH_WEST;
else if (ep.x > frame.getWidth()-resizeCornerSize-i.right)
resizeDir = SOUTH_EAST;
else resizeDir = SOUTH;
} else {
/* the mouse press happened inside the frame, not in the
* border */
discardRelease = true;
return;
}
getDesktopManager().beginResizingFrame(frame, resizeDir);
Cursor s = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
switch (resizeDir) {
case SOUTH:
s = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
break;
case NORTH:
s = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
break;
case WEST:
s = Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
break;
case EAST:
s = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
break;
case SOUTH_EAST:
s = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
break;
case SOUTH_WEST:
s = Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR);
break;
case NORTH_WEST:
s = Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR);
break;
case NORTH_EAST:
s = Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR);
break;
}
frame.setCursor(s);
return;
}
}
/**
* Handles <code>mouseDragged</code> event.
* @see MouseInputAdapter#mouseDragged(MouseEvent)
*/
public void mouseDragged(MouseEvent e)
{
if (startingBounds == null) return;
Point p = SwingUtilities.convertPoint((Component) e.getSource(),
e.getX(), e.getY(), null);
int deltaX = xAbs-p.x;
int deltaY = yAbs-p.y;
Dimension min = frame.getMinimumSize();
Dimension max = frame.getMaximumSize();
int newX, newY, newW, newH;
Insets i = frame.getInsets();
// Handle a MOVE
if (dragging) {
//Don't allow moving of frames if left mouse button was not used.
if ((e.getModifiers() &
InputEvent.BUTTON1_MASK) != InputEvent.BUTTON1_MASK)
return;
int pWidth, pHeight;
Dimension s = frame.getParent().getSize();
pWidth = s.width;
pHeight = s.height;
newX = startingBounds.x-deltaX;
newY = startingBounds.y-deltaY;
// Make sure we stay in-bounds
if (newX+i.left <= -xView) newX = -xView-i.left+1;
if (newY+i.top <= -yView) newY = -yView-i.top+1;
if (newX+xView+i.right >= pWidth) newX = pWidth-xView-i.right-1;
if (newY+yView+i.bottom >= pHeight) newY = pHeight-yView-i.bottom-1;
getDesktopManager().dragFrame(frame, newX, newY);
return;
}
if (!frame.isResizable()) return;
newX = frame.getX();
newY = frame.getY();
newW = frame.getWidth();
newH = frame.getHeight();
parentBounds = frame.getParent().getBounds();
switch (resizeDir) {
case RESIZE_NONE:
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.DEFAULT_CURSOR));
return;
case NORTH:
if (startingBounds.height+deltaY < min.height)
deltaY = min.height-startingBounds.height;
else if (startingBounds.height+deltaY > max.height)
deltaY = max.height-startingBounds.height;
if (startingBounds.y-deltaY < 0) deltaY = startingBounds.y;
newX = startingBounds.x;
newY = startingBounds.y-deltaY;
newW = startingBounds.width;
newH = startingBounds.height+deltaY;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.N_RESIZE_CURSOR));
break;
case NORTH_EAST:
if (startingBounds.height+deltaY < min.height)
deltaY = min.height-startingBounds.height;
else if (startingBounds.height+deltaY > max.height)
deltaY = max.height-startingBounds.height;
if (startingBounds.y-deltaY < 0) deltaY = startingBounds.y;
if (startingBounds.width-deltaX < min.width)
deltaX = startingBounds.width-min.width;
else if (startingBounds.width-deltaX > max.width)
deltaX = -(max.width-startingBounds.width);
if (startingBounds.x+startingBounds.width-deltaX >
parentBounds.width)
deltaX = startingBounds.x+startingBounds.width-
parentBounds.width;
newX = startingBounds.x;
newY = startingBounds.y-deltaY;
newW = startingBounds.width-deltaX;
newH = startingBounds.height+deltaY;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.NE_RESIZE_CURSOR));
break;
case EAST:
if (startingBounds.width-deltaX < min.width)
deltaX = startingBounds.width-min.width;
else if (startingBounds.width-deltaX > max.width)
deltaX = startingBounds.width-max.width;
if (startingBounds.x+startingBounds.width-deltaX >
parentBounds.width)
deltaX = startingBounds.x+startingBounds.width -
parentBounds.width;
newW = startingBounds.width-deltaX;
newH = startingBounds.height;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.E_RESIZE_CURSOR));
break;
case SOUTH_EAST:
if (startingBounds.width-deltaX < min.width)
deltaX = startingBounds.width-min.width;
else if (startingBounds.width-deltaX > max.width)
deltaX = startingBounds.width-max.width;
if (startingBounds.x+startingBounds.width-deltaX >
parentBounds.width)
deltaX = startingBounds.x+startingBounds.width-
parentBounds.width;
if (startingBounds.height-deltaY < min.height)
deltaY = startingBounds.height-min.height;
else if (startingBounds.height-deltaY > max.height)
deltaY = -(max.height-startingBounds.height);
if (startingBounds.y+startingBounds.height-deltaY >
parentBounds.height)
deltaY = startingBounds.y+startingBounds.height-
parentBounds.height ;
newW = startingBounds.width-deltaX;
newH = startingBounds.height-deltaY;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.SE_RESIZE_CURSOR));
break;
case SOUTH:
if (startingBounds.height-deltaY < min.height)
deltaY = startingBounds.height-min.height;
else if (startingBounds.height-deltaY > max.height)
deltaY = -(max.height-startingBounds.height);
if (startingBounds.y+startingBounds.height-deltaY >
parentBounds.height)
deltaY = startingBounds.y+startingBounds.height-
parentBounds.height ;
newW = startingBounds.width;
newH = startingBounds.height-deltaY;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.S_RESIZE_CURSOR));
break;
case SOUTH_WEST:
if (startingBounds.height-deltaY < min.height)
deltaY = startingBounds.height - min.height;
else if (startingBounds.height-deltaY > max.height)
deltaY = -(max.height-startingBounds.height);
if (startingBounds.y+startingBounds.height-deltaY >
parentBounds.height)
deltaY = startingBounds.y+startingBounds.height-
parentBounds.height ;
if (startingBounds.width+deltaX < min.width)
deltaX = -(startingBounds.width-min.width);
else if (startingBounds.width+deltaX > max.width)
deltaX = max.width-startingBounds.width;
if (startingBounds.x-deltaX < 0) deltaX = startingBounds.x;
newX = startingBounds.x-deltaX;
newY = startingBounds.y;
newW = startingBounds.width+deltaX;
newH = startingBounds.height-deltaY;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.SW_RESIZE_CURSOR));
break;
case WEST:
if (startingBounds.width+deltaX < min.width)
deltaX = -(startingBounds.width-min.width);
else if (startingBounds.width+deltaX > max.width)
deltaX = max.width-startingBounds.width;
if (startingBounds.x-deltaX < 0) deltaX = startingBounds.x;
newX = startingBounds.x-deltaX;
newY = startingBounds.y;
newW = startingBounds.width+deltaX;
newH = startingBounds.height;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.W_RESIZE_CURSOR));
break;
case NORTH_WEST:
if (startingBounds.width+deltaX < min.width)
deltaX = -(startingBounds.width-min.width);
else if (startingBounds.width+deltaX > max.width)
deltaX = max.width-startingBounds.width;
if (startingBounds.x-deltaX < 0) deltaX = startingBounds.x;
if (startingBounds.height+deltaY < min.height)
deltaY = -(startingBounds.height-min.height);
else if (startingBounds.height+deltaY > max.height)
deltaY = max.height-startingBounds.height;
if (startingBounds.y-deltaY < 0) deltaY = startingBounds.y;
newX = startingBounds.x-deltaX;
newY = startingBounds.y-deltaY;
newW = startingBounds.width+deltaX;
newH = startingBounds.height+deltaY;
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.NW_RESIZE_CURSOR));
break;
default: return;
}
//frame.setBounds(newX, newY, newW, newH);
getDesktopManager().resizeFrame(frame, newX, newY, newW, newH);
}
/**
* Handles <code>mouseMoved</code> event.
* @see MouseInputAdapter#mouseMoved(MouseEvent)
*/
public void mouseMoved(MouseEvent e)
{
if (!frame.isResizable()) return;
JComponent titleBar = frame.getTitleBar();
if (e.getSource() == frame || e.getSource() == titleBar) {
Point ep = new Point(e.getX(), e.getY());
if (e.getSource() == titleBar) {
Point np = titleBar.getLocation();
ep.x += np.x;
ep.y += np.y;
frame.setCursor(new Cursor(Cursor.SE_RESIZE_CURSOR));
}
Insets i = frame.getInsets();
if (ep.x <= i.left) {
if (ep.y < resizeCornerSize+i.top)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.NW_RESIZE_CURSOR));
else if (ep.y > frame.getHeight()-resizeCornerSize-i.bottom)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.SW_RESIZE_CURSOR));
else frame.setCursor(Cursor.getPredefinedCursor(
Cursor.W_RESIZE_CURSOR));
} else if (ep.x >= frame.getWidth()-i.right) {
if (e.getY() < resizeCornerSize+i.top)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.NE_RESIZE_CURSOR));
else if (ep.y > frame.getHeight()-resizeCornerSize-i.bottom)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.SE_RESIZE_CURSOR));
else
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.E_RESIZE_CURSOR));
} else if (ep.y <= i.top) {
if (ep.x < resizeCornerSize+i.left)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.NW_RESIZE_CURSOR));
else if (ep.x > frame.getWidth()-resizeCornerSize-i.right)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.NE_RESIZE_CURSOR));
else
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.N_RESIZE_CURSOR));
} else if(ep.y >= frame.getHeight()-i.bottom) {
if (ep.x < resizeCornerSize+i.left)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.SW_RESIZE_CURSOR));
else if (ep.x > frame.getWidth()-resizeCornerSize-i.right)
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.SE_RESIZE_CURSOR));
else
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.S_RESIZE_CURSOR));
} else {
frame.setCursor(Cursor.getPredefinedCursor(
Cursor.DEFAULT_CURSOR));
return;
}
}
}
/**
* Sets the default cursor.
* @see MouseInputAdapter#mouseExited(MouseEvent)
*/
public void mouseExited(MouseEvent e)
{
frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
/**
* Required by the interface but no-op implementation in our case.
* @see MouseInputAdapter#mouseClicked(MouseEvent)
*/
public void mouseClicked(MouseEvent e) {}
}