Jump to content

Window Snapping


liverare

Recommended Posts

The client prevents my GUI's from being auto-positioned when snapped to the side. I like snapping windows to the side.

import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

/**
 * Windows that have auto-snap disabled, this is my 'hackery' alternative
 * that will provide the same result as Window's 7/8's auto-snap.
 */
public class WindowSnap implements ComponentListener {
	
	/**
	 * Trigger size is the offset distance that'll be used to provide
	 * an area for the mouse detection.
	 */
	public static final int TRIGGER_SIZE = 6;
	
	/**
	 * The window isn't set to snap anywhere.
	 */
	public static final byte NO_LOCK = 0x0;
	
	/**
	 * The window is set to snap against the left side.
	 */
	public static final byte LEFT_LOCK = 0x1;
	
	/**
	 * The window is set to snap against the right side.
	 */
	public static final byte RIGHT_LOCK = 0x2;
	
	/**
	 * The window is set to snap full screen (against the top).
	 */
	public static final byte FULL_LOCK = 0x3;

	/**
	 * Size of the user's screen. Used to calculate different areas.
	 */
	public static final Dimension SCREEN_SIZE;
	
	/**
	 * Entire screen snap bounds.
	 */
	public static final Rectangle SCREEN_BOUNDS;
	
	/**
	 * Left side snap bounds.
	 */
	public static final Rectangle LEFT_SIDE;
	
	/**
	 * Right side snap bounds.
	 */
	public static final Rectangle RIGHT_SIDE;
	
	/**
	 * Screen trigger set to the top.
	 */
	public static final Rectangle TOP_TRIGGER;
	
	/**
	 * Screen trigger set to the left.
	 */
	public static final Rectangle LEFT_TRIGGER;
	
	/**
	 * Screen trigger set to the right.
	 */
	public static final Rectangle RIGHT_TRIGGER;
	
	/**
	 * Size of the screen's width, retaining the screen's height.
	 */
	public static final Dimension HALF_SIZE;
	
	/**
	 * Prevent multiple window-moved events overwriting each other.
	 */
	private boolean lock;
	
	/**
	 * Retain some form of 'old bounds' to manipulate the new bounds to--when required.
	 */
	private Rectangle oldBounds;
	
	/**
	 * Current window snap position
	 */
	private byte snapSide;
	
	/**
	 * Initialise static variables upon class access
	 */
	static {
		SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
		SCREEN_BOUNDS = new Rectangle(0, 0, SCREEN_SIZE.width,
				SCREEN_SIZE.height - (SCREEN_SIZE.height / 20));

		HALF_SIZE = new Dimension((int) (SCREEN_BOUNDS.getWidth() / 2),
				SCREEN_BOUNDS.height);

		LEFT_SIDE = new Rectangle(0, 0, HALF_SIZE.width, HALF_SIZE.height);
		RIGHT_SIDE = new Rectangle(HALF_SIZE.width, 0, HALF_SIZE.width,
				HALF_SIZE.height);

		TOP_TRIGGER = new Rectangle(0, 0, SCREEN_SIZE.width, TRIGGER_SIZE);
		LEFT_TRIGGER = new Rectangle(0, 0, TRIGGER_SIZE, SCREEN_SIZE.height);
		RIGHT_TRIGGER = new Rectangle(SCREEN_SIZE.width - TRIGGER_SIZE, 0,
				TRIGGER_SIZE, SCREEN_SIZE.height);
	}
	
	/**
	 * 
	 * @param bounds
	 * 		Old bounds to revert the window to--when required.
	 */
	public WindowSnap(Rectangle bounds) {
		oldBounds = bounds;
	}
	
	@Override
	public void componentMoved(ComponentEvent e) {
		if (lock)
			return;
		lock = true;
		snapSide = getSnap();
		if (snapSide != NO_LOCK)
			e.getComponent().setBounds(getSnapBounds(snapSide));
		else if (snapSide == NO_LOCK) {
			e.getComponent().setSize(oldBounds.getSize());
		}
		lock = false;
	}
	
	@Override
	public void componentResized(ComponentEvent e) {
		if (!isSnapped())
			oldBounds.setBounds(e.getComponent().getBounds());
	}
	
	@Override
	public void componentShown(ComponentEvent e) {
	}
	
	@Override
	public void componentHidden(ComponentEvent e) {
	}
	
	/**
	 * 
	 * @param snap
	 * 		Snap position.
	 * @return
	 * 		Actual snap bounds.
	 */
	public Rectangle getSnapBounds(byte snap) {
		switch (snap) {
		case LEFT_LOCK:
			return LEFT_SIDE;
		case RIGHT_LOCK:
			return RIGHT_SIDE;
		case FULL_LOCK:
			return SCREEN_BOUNDS;
		default:
			return oldBounds;
		}
	}
	
	/**
	 * 
	 * @return
	 * 		Get current snap position based on user's mouse location
	 * 
	 * @see {@link MouseInfo#getPointerInfo()#getLocation()}
	 */
	public byte getSnap() {
		Point p = MouseInfo.getPointerInfo().getLocation();
		if (TOP_TRIGGER.contains(p))
			return FULL_LOCK;
		else if (LEFT_TRIGGER.contains(p))
			return LEFT_LOCK;
		else if (RIGHT_TRIGGER.contains(p))
			return RIGHT_LOCK;
		else
			return NO_LOCK;
	}
	
	/**
	 * 
	 * @return
	 * 		<tt>All-but the 'not locked' event will be ignored</tt>
	 */
	public boolean isLocked() {
		return lock;
	}
	
	/**
	 * 
	 * @return
	 * 		Window's snapped position.s
	 */
	public boolean isSnapped() {
		return snapSide != NO_LOCK;
	}
	
}

Use like:

Component#addComponentListener(new WindowSnap(Component#getBounds()));
Edited by liverare
  • Like 1
Link to comment
Share on other sites

If only we could apply this to the actual client

You could apply it once your script is loaded if you want.
Component c = JFrame.getWindows()[0];
		c.addComponentListener(new WindowSnap(c.getBounds()));

So where would I have to put that code at? Since you said "once your script is loaded" I'm guessing onStart().

Link to comment
Share on other sites

 

 

If only we could apply this to the actual client

You could apply it once your script is loaded if you want.
Component c = JFrame.getWindows()[0];
		c.addComponentListener(new WindowSnap(c.getBounds()));

So where would I have to put that code at? Since you said "once your script is loaded" I'm guessing onStart().

 

 

Bingo!

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...