All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.util.AbstractResizeHotSpot Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwind.util;

import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.event.SelectEvent;

import java.awt.*;
import java.awt.event.*;

/**
 * A HotSpot for resizing a frame or window. This class handles the resize input events, but does does not actually draw
 * the resize controls. The HotSpot is defined by a direction, for example, {@link AVKey#NORTH} indicates that the
 * HotSpot resizes the frame vertically from the north edge (the user clicks the top edge of the frame and drags
 * vertically).
 * 

* An instance of this class should be added to the picked object when the edge or corner of the frame is picked. *

* Subclasses must the implement {#getSize}, {#setSize}, {#getScreenPoint}, and {#setScreenPoint} to manipulate the * frame that they want to resize. * * @author pabercrombie * @version $Id: AbstractResizeHotSpot.java 1171 2013-02-11 21:45:02Z dcollins $ */ public abstract class AbstractResizeHotSpot extends AbstractHotSpot { protected static final int NORTH = 1; protected static final int SOUTH = 2; protected static final int EAST = 4; protected static final int WEST = 8; protected static final int NORTHWEST = NORTH + WEST; protected static final int NORTHEAST = NORTH + EAST; protected static final int SOUTHWEST = SOUTH + WEST; protected static final int SOUTHEAST = SOUTH + EAST; protected boolean dragging; protected Point dragRefPoint; protected Dimension refSize; protected Point refLocation; protected boolean allowVerticalResize = true; protected boolean allowHorizontalResize = true; /** * True if the window needs to be moved in the X direction as it is resized. For example, if the upper left corner * is being dragged, the window should move to keep that corner under the cursor. */ protected boolean adjustLocationX; /** True if the window needs to be moved in the Y direction as it is resized. */ protected boolean adjustLocationY; protected int xSign = 1; protected int ySign = 1; protected int cursor; protected void setDirection(String direction) { int dir = 0; if (AVKey.NORTH.equals(direction)) dir = NORTH; else if (AVKey.SOUTH.equals(direction)) dir = SOUTH; else if (AVKey.EAST.equals(direction)) dir = EAST; else if (AVKey.WEST.equals(direction)) dir = WEST; else if (AVKey.NORTHEAST.equals(direction)) dir = NORTHEAST; else if (AVKey.NORTHWEST.equals(direction)) dir = NORTHWEST; else if (AVKey.SOUTHEAST.equals(direction)) dir = SOUTHEAST; else if (AVKey.SOUTHWEST.equals(direction)) dir = SOUTHWEST; this.setDirection(dir); } protected void setDirection(int direction) { this.adjustLocationX = NORTH == direction || WEST == direction || SOUTHWEST == direction || NORTHWEST == direction; this.adjustLocationY = NORTH == direction || WEST == direction || NORTHWEST == direction || NORTHEAST == direction; if (NORTH == direction || SOUTH == direction) { this.allowVerticalResize = true; this.allowHorizontalResize = false; } else if (EAST == direction || WEST == direction) { this.allowVerticalResize = false; this.allowHorizontalResize = true; } else { this.allowVerticalResize = true; this.allowHorizontalResize = true; } if (WEST == direction || SOUTHWEST == direction || NORTHWEST == direction) this.xSign = -1; else this.xSign = 1; if (NORTH == direction || NORTHEAST == direction || NORTHWEST == direction) this.ySign = -1; else this.ySign = 1; if (NORTH == direction) this.cursor = Cursor.N_RESIZE_CURSOR; else if (SOUTH == direction) this.cursor = Cursor.S_RESIZE_CURSOR; else if (EAST == direction) this.cursor = Cursor.E_RESIZE_CURSOR; else if (WEST == direction) this.cursor = Cursor.W_RESIZE_CURSOR; else if (NORTHEAST == direction) this.cursor = Cursor.NE_RESIZE_CURSOR; else if (SOUTHEAST == direction) this.cursor = Cursor.SE_RESIZE_CURSOR; else if (SOUTHWEST == direction) this.cursor = Cursor.SW_RESIZE_CURSOR; else if (NORTHWEST == direction) this.cursor = Cursor.NW_RESIZE_CURSOR; } /** * Set the resize direction based on which point on the frame was picked (if a point on the left of the frame is * picked, the resize direction is west, if a point on the top edge is picked the resize direction is north, etc). * * @param pickPoint The point on the frame that was picked. */ protected void setDirectionFromPoint(Point pickPoint) { Point topLeft = this.getScreenPoint(); Dimension size = this.getSize(); if (topLeft == null || size == null) return; // Find the center of the frame Point center = new Point(topLeft.x + size.width / 2, topLeft.y + size.height / 2); // Find horizontal and vertical distance from pick point to center point int dy = center.y - pickPoint.y; int dx = pickPoint.x - center.x; // Use the sign of dx and dy to determine if we are resizing up or down, left or right int vdir = (dy > 0) ? NORTH : SOUTH; int hdir = (dx > 0) ? EAST : WEST; // Compare the aspect ratio of the frame to the aspect ratio of the rectangle formed by the pick point and the // center point. If the aspect ratios are close to equal, resize both horizontally and vertically. Otherwise, // resize only horizontally or only vertically. double frameAspectRatio = (double) size.width / size.height; double pickAspectRatio = Math.abs((double) dx / dy); int dir; double tolerance = frameAspectRatio * 0.1; if (Math.abs(pickAspectRatio - frameAspectRatio) < tolerance) dir = hdir + vdir; else if (pickAspectRatio < frameAspectRatio) dir = vdir; else dir = hdir; this.setDirection(dir); } /** * Is the control currently dragging? * * @return True if the control is dragging. */ public boolean isDragging() { return this.dragging; } /** * Handle a {@link gov.nasa.worldwind.event.SelectEvent} and call {@link #beginDrag}, {@link #drag}, {@link * #endDrag} as appropriate. Subclasses may override this method if they need to handle events other than drag * events. * * @param event Select event. */ @Override public void selected(SelectEvent event) { if (event == null || this.isConsumed(event)) return; Point pickPoint = event.getPickPoint(); if (pickPoint != null) { if (event.isDrag()) { if (!this.isDragging()) { this.dragging = true; this.beginDrag(pickPoint); } this.drag(pickPoint); event.consume(); } } if (event.isDragEnd()) { this.dragging = false; this.endDrag(); event.consume(); } } /** * Update the resize cursor when the mouse moves. * * @param e Mouse event. */ @Override public void mouseMoved(MouseEvent e) { if (e == null || e.isConsumed()) return; this.setDirectionFromPoint(e.getPoint()); } protected void beginDrag(Point point) { this.dragRefPoint = point; this.refSize = this.getSize(); this.refLocation = this.getScreenPoint(); } public void drag(Point point) { int deltaX = 0; int deltaY = 0; if (this.refLocation == null || this.refSize == null) return; if (this.allowHorizontalResize) deltaX = (point.x - this.dragRefPoint.x) * this.xSign; if (this.allowVerticalResize) deltaY = (point.y - this.dragRefPoint.y) * this.ySign; int width = this.refSize.width + deltaX; int height = this.refSize.height + deltaY; if (this.isValidSize(width, height)) { this.setSize(new Dimension(width, height)); if (this.adjustLocationX || this.adjustLocationY) { double x = this.refLocation.x - (this.adjustLocationX ? deltaX : 0); double y = this.refLocation.y - (this.adjustLocationY ? deltaY : 0); this.setScreenPoint(new Point((int) x, (int) y)); } } } /** Called when a drag action ends. This implementation sets {@link #dragRefPoint} to null. */ protected void endDrag() { this.dragRefPoint = null; } /** * Get a cursor for the type of resize that this hotspot handles. * * @return New cursor. */ @Override public Cursor getCursor() { return Cursor.getPredefinedCursor(this.cursor); } /** * {@inheritDoc} * * Overridden to reset state when the mouse leaves the resize area. * * @param active {@code true} if the HotSpot is being activated, {@code false} if it is being deactivated. */ @Override public void setActive(boolean active) { // If the resize area is being deactivated, reset the cursor so that the next time the HotSpot becomes active // we won't show the wrong cursor. if (!active) this.cursor = Cursor.DEFAULT_CURSOR; super.setActive(active); } /** * Is a frame size valid? This method is called before attempting to resize the frame. If this method returns false, * the resize operation is not attempted. This implementation ensures that the proposed frame size is greater than * or equal to the minimum frame size. * * @param width Frame width. * @param height Frame height. * * @return True if this frame size is valid. * * @see #getMinimumSize() */ protected boolean isValidSize(int width, int height) { Dimension minSize = this.getMinimumSize(); return width >= minSize.width && height >= minSize.height; } /** * Get the minimum size of the frame. The user is not allowed to resize the frame to be smaller than this size. This * implementation returns 0, 0. * * @return Minimum frame size. * * @see #isValidSize(int, int) */ protected Dimension getMinimumSize() { return new Dimension(0, 0); } /** * Get the size of the frame. * * @return Frame size in pixels. */ protected abstract Dimension getSize(); /** * Set the size of the frame. * * @param newSize New frame size in pixels. */ protected abstract void setSize(Dimension newSize); /** * Get the screen point of the upper left corner of the frame. * * @return Screen point measured from upper left corner of the screen (AWT coordinates). */ protected abstract Point getScreenPoint(); /** * Set the screen point of the upper left corner of the frame. * * @param newPoint New screen point measured from upper left corner of the screen (AWT coordinates). */ protected abstract void setScreenPoint(Point newPoint); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy