/*========================================================================= Program: FusionViewer Module: $RCSfile: SplitWindowMouseTool.java,v $ Language: Java Date: $Date: 2007/02/02 19:25:27 $ Version: $Revision: 1.3 $ Copyright (c) Insightful Corporation. All rights reserved. See Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ package org.fusionviewer.display; import java.awt.Cursor; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import org.fusionviewer.display.composite.SplitWindowCompositor; import org.fusionviewer.io.Env; import org.fusionviewer.model.FusionDisplayModel; import org.fusionviewer.ui.CursorControl; /**\class SplitWindowMouseTool *\brief Moves and resizes the split window display. Used in conjunction with SplitWindowCompositor. */ public class SplitWindowMouseTool implements MouseTool { private ImageSliceView m_parent; private SplitWindowCompositor m_compositor; private int m_anchor; private Point m_tempPoint = new Point(); private Point m_moveOffset = new Point(); // when moving the entire window, the position of // the mouse when it was clicked private static final int ANCHOR_NONE = 0; private static final int ANCHOR_TOPLEFT = 1; private static final int ANCHOR_TOPRIGHT = 2; private static final int ANCHOR_BOTTOMLEFT = 3; private static final int ANCHOR_BOTTOMRIGHT = 4; private static final int ANCHOR_TOP = 5; private static final int ANCHOR_LEFT = 6; private static final int ANCHOR_RIGHT = 7; private static final int ANCHOR_BOTTOM = 8; private static final int ANCHOR_CENTER = 9; // Size of the area around the boundaries that will register as a mouse grab. private static final int MARGIN = 10; // Minimum dimensions for the split window view rectangle private static final int MIN_SIZE = 50; public SplitWindowMouseTool(ImageSliceView parent, SplitWindowCompositor compositor) { m_parent = parent; m_compositor = compositor; } public boolean canHandle(MouseEvent e) { FusionDisplayModel viewModel = (FusionDisplayModel) m_parent.getViewModel(); if (viewModel.getFusionMode() != FusionDisplayModel.SPLITWINDOW_MODE) return false; m_tempPoint.setLocation(e.getX(), e.getY()); m_parent.transformPoint(m_tempPoint); Rectangle r = m_compositor.getBounds(); r.grow(MARGIN, MARGIN); return r.contains(m_tempPoint.x, m_tempPoint.y); } public void mousePressed(MouseEvent e) { m_tempPoint.setLocation(e.getX(), e.getY()); m_parent.transformPoint(m_tempPoint); m_anchor = findAnchor(m_tempPoint.x, m_tempPoint.y); if (m_anchor == ANCHOR_NONE) { m_parent.releaseMouseTool(); } else { setCursor(m_anchor); if (m_anchor == ANCHOR_CENTER) { Rectangle r = m_compositor.getBounds(); m_moveOffset.x = m_tempPoint.x - r.x; m_moveOffset.y = m_tempPoint.y - r.y; } } } public void mouseReleased(MouseEvent e) { m_tempPoint.setLocation(e.getX(), e.getY()); m_parent.transformPoint(m_tempPoint); if (!canHandle(e)) m_parent.releaseMouseTool(); else setCursor(findAnchor(m_tempPoint.x, m_tempPoint.y)); m_anchor = ANCHOR_NONE; m_parent.getParent().display(); } public void mouseDragged(MouseEvent e) { m_tempPoint.setLocation(e.getX(), e.getY()); m_parent.transformPoint(m_tempPoint); adjustBounds(m_tempPoint.x, m_tempPoint.y); } public void mouseMoved(MouseEvent e) { if (!canHandle(e)) { m_parent.releaseMouseTool(); } else { m_tempPoint.setLocation(e.getX(), e.getY()); m_parent.transformPoint(m_tempPoint); setCursor(findAnchor(m_tempPoint.x, m_tempPoint.y)); } } private int findAnchor(int x, int y) { int anchor = ANCHOR_NONE; Rectangle bounds = m_compositor.getBounds(); int leftBound = bounds.x; int topBound = bounds.y; int rightBound = bounds.x + bounds.width; int bottomBound = bounds.y + bounds.height; Rectangle topLeft, topRight, bottomLeft, bottomRight, left, right, top, bottom, center; int doubleMargin = MARGIN * 2; topLeft = new Rectangle(leftBound - MARGIN, topBound - MARGIN, doubleMargin, doubleMargin); topRight = new Rectangle(rightBound - MARGIN, topBound - MARGIN, doubleMargin, doubleMargin); bottomLeft = new Rectangle(leftBound - MARGIN, bottomBound - MARGIN, doubleMargin, doubleMargin); bottomRight = new Rectangle(rightBound - MARGIN, bottomBound - MARGIN, doubleMargin, doubleMargin); top = new Rectangle(leftBound + MARGIN, topBound - MARGIN, bounds.width - doubleMargin, doubleMargin); bottom = new Rectangle(leftBound + MARGIN, bottomBound - MARGIN, bounds.width - doubleMargin, doubleMargin); left = new Rectangle(leftBound - MARGIN, topBound + MARGIN, doubleMargin, bounds.height - doubleMargin); right = new Rectangle(rightBound - MARGIN, topBound + MARGIN, doubleMargin, bounds.height - doubleMargin); center = new Rectangle(leftBound + MARGIN, topBound + MARGIN, bounds.width - doubleMargin, bounds.height - doubleMargin); if (topLeft.contains(x, y)) anchor = ANCHOR_BOTTOMRIGHT; else if (top.contains(x, y)) anchor = ANCHOR_BOTTOM; else if (topRight.contains(x, y)) anchor = ANCHOR_BOTTOMLEFT; else if (right.contains(x, y)) anchor = ANCHOR_LEFT; else if (bottomRight.contains(x, y)) anchor = ANCHOR_TOPLEFT; else if (bottom.contains(x, y)) anchor = ANCHOR_TOP; else if (bottomLeft.contains(x ,y)) anchor = ANCHOR_TOPRIGHT; else if (left.contains(x, y)) anchor = ANCHOR_RIGHT; else if (center.contains(x, y)) anchor = ANCHOR_CENTER; return anchor; } private void adjustBounds(int x, int y) { Rectangle bounds = m_compositor.getBounds(); int left = bounds.x; int top = bounds.y; int right = bounds.x + bounds.width; int bottom = bounds.y + bounds.height; int surfaceWidth = m_parent.getViewWidth() - 1; int surfaceHeight = m_parent.getViewHeight() - 1; if (x < 0) x = 0; if (y < 0) y = 0; if (x > surfaceWidth) x = surfaceWidth; if (y > surfaceHeight) y = surfaceHeight; switch (m_anchor) { case ANCHOR_TOPLEFT: right = x; bottom = y; if (right - left < MIN_SIZE) right = left + MIN_SIZE; if (bottom - top < MIN_SIZE) bottom = top + MIN_SIZE; break; case ANCHOR_BOTTOMRIGHT: left = x; top = y; if (right - left < MIN_SIZE) left = right - MIN_SIZE; if (bottom - top < MIN_SIZE) top = bottom - MIN_SIZE; break; case ANCHOR_TOPRIGHT: left = x; bottom = y; if (right - left < MIN_SIZE) left = right - MIN_SIZE; if (bottom - top < MIN_SIZE) bottom = top + MIN_SIZE; break; case ANCHOR_BOTTOMLEFT: right = x; top = y; if (right - left < MIN_SIZE) right = left + MIN_SIZE; if (bottom - top < MIN_SIZE) top = bottom - MIN_SIZE; break; case ANCHOR_TOP: bottom = y; if (bottom - top < MIN_SIZE) bottom = top + MIN_SIZE; break; case ANCHOR_BOTTOM: top = y; if (bottom - top < MIN_SIZE) top = bottom - MIN_SIZE; break; case ANCHOR_LEFT: right = x; if (right - left < MIN_SIZE) right = left + MIN_SIZE; break; case ANCHOR_RIGHT: left = x; if (right - left < MIN_SIZE) left = right - MIN_SIZE; break; case ANCHOR_CENTER: int height = bottom - top; int width = right - left; if (x - m_moveOffset.x < 0) x = m_moveOffset.x; if (y - m_moveOffset.y < 0) y = m_moveOffset.y; if (x - m_moveOffset.x + width > surfaceWidth) x = surfaceWidth - width + m_moveOffset.x; if (y - m_moveOffset.y + height > surfaceHeight) y = surfaceHeight - height + m_moveOffset.y; left = x - m_moveOffset.x; right = left + width; top = y - m_moveOffset.y; bottom = top + height; break; } if (left < 0) left = 0; if (top < 0) top = 0; if (right > surfaceWidth) right = surfaceWidth; if (bottom > surfaceHeight) bottom = surfaceHeight; m_compositor.setBounds(left, top, right - left, bottom - top); m_parent.getParent().display(); } private void setCursor(int anchor) { if (Env.isMac) { // Cursors and GLCanvases don't work together on the Mac switch (anchor) { case ANCHOR_TOP: case ANCHOR_BOTTOM: CursorControl.setResizeUpDownCursor(m_parent.getParent()); break; case ANCHOR_LEFT: case ANCHOR_RIGHT: CursorControl.setResizeLeftRightCursor(m_parent.getParent()); break; case ANCHOR_CENTER: CursorControl.setHandCursor(m_parent.getParent()); break; default: CursorControl.setArrowCursor(m_parent.getParent()); break; } } else { switch (anchor) { case ANCHOR_TOPLEFT: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)); break; case ANCHOR_BOTTOMRIGHT: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)); break; case ANCHOR_TOPRIGHT: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)); break; case ANCHOR_BOTTOMLEFT: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR)); break; case ANCHOR_TOP: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); break; case ANCHOR_BOTTOM: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); break; case ANCHOR_LEFT: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); break; case ANCHOR_RIGHT: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); break; case ANCHOR_CENTER: m_parent.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); break; default: CursorControl.setArrowCursor(m_parent.getParent()); break; } } } }