Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Snapping JFrame to screen edge

I'm going to preface this with "this is more of an answer".

As in, I'm answering this myself.

I searched by tags, I searched with Google, I searched using a combination of tags and plaintext (on this site) and I still couldn't find the damn question that this originated from. Some guy pastes the source, or links the source, as an answer.

This is (one of the) original source(s), it's all over the web.

http://bit.ly/1eYKNXS (code.google.com domain, I can edit with full URL if necessary)

It's not perfect. The offset of 0 doesn't always seem to work (tested on my home machine and here, using a multi-monitor setup and without), while an offset of 5 does. It doesn't have multi-monitor support. The snap behaviour is a bit excitable (it keeps on firing).

Answer is the answer to this question. Feel free to lock, archive, etc. Just trying to help :)

like image 942
Gorbles Avatar asked Oct 20 '22 16:10

Gorbles


1 Answers

So, behold, the improved code. Hope it helps people, and that it isn't too verbose or a pain to read.

package widgets;

import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

public class WindowSnapper extends ComponentAdapter {

    private boolean locked = false;

    // feel free to modify; set based on my own preferences
    // incorporate as user option?
    private int sd = 30;
    private GraphicsDevice[] screenList  = GraphicsEnvironment
            .getLocalGraphicsEnvironment().getScreenDevices();  

    // clamping at 5 seems correct, 0 clamps at -5 beyond screen boundary
    public void componentMoved(ComponentEvent evt) {
        // gets current display device
        Window myWindow = new Window((Frame) evt.getComponent());
        GraphicsConfiguration config = myWindow.getGraphicsConfiguration();
        GraphicsDevice myScreen = config.getDevice();
        // matches against active display
        for(GraphicsDevice gd : getScreenList()) {
            // this will set the display to a new display if the window is moved to a new display
            if(gd.equals(myScreen)) {
                myScreen = gd;
                break;
            }
        }

        // minimising calls to stack
        int screenWidth = myScreen.getDefaultConfiguration().getBounds().width;
        int screenHeight = myScreen.getDefaultConfiguration().getBounds().height;
        int compWidth = evt.getComponent().getWidth();
        int compHeight = evt.getComponent().getHeight();
        int nx = evt.getComponent().getX();
        int ny = evt.getComponent().getY();
        // setting offsets in case of different screen
        int currentX = myScreen.getDefaultConfiguration().getBounds().x;
        int currentY = myScreen.getDefaultConfiguration().getBounds().y;

        // see end of method
        // OR conditions seem to stabilise movement when close to screen edge
        if(locked
                || nx == currentX + 5
                || ny == currentY + 5
                || nx == currentX + screenWidth - compWidth - 5
                || ny == currentY + screenHeight - compHeight - 5)
            return;

        // left
        if(nx < (currentX + sd) && nx > (currentX + 5)) {
            nx = currentX + 5;
        }

        // top
        if(ny < (currentY + sd) && ny > (currentY + 5)) {
            ny = currentY + 5;
        }

        // right
        if(nx > currentX + screenWidth - compWidth - sd
                && nx < currentX + screenWidth - compWidth - 5) {
            nx = currentX + screenWidth - compWidth - 5;
        }

        // bottom
        if(ny > currentY + screenHeight - compHeight - sd
                && ny < currentY + screenHeight - compHeight - 5) {
            ny = currentY + screenHeight - compHeight - 5;
        }

        // make sure we don't get into a recursive loop when the
        // set location generates more events
        locked = true;
        evt.getComponent().setLocation(nx, ny);
        locked = false;
    }

    public int returnSD() {
        return sd;
    }

    public void setSD(int sd) {
        this.sd = sd;
    }

    public GraphicsDevice[] getScreenList() {
        return screenList;
    }

    public void setScreenList(GraphicsDevice[] screenList) {
        this.screenList = screenList;
    }

}
like image 154
Gorbles Avatar answered Oct 23 '22 11:10

Gorbles