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

org.nuiton.jaxx.runtime.swing.session.WindowState Maven / Gradle / Ivy

There is a newer version: 3.1.5
Show newest version
package org.nuiton.jaxx.runtime.swing.session;

/*
 * #%L
 * JAXX :: Runtime
 * %%
 * Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import javax.swing.JFrame;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Window;

/**
 * State for Window
 *
 * @author poussin
 * @author Kevin Morin - [email protected]
 * @since 2.5.16
 */
public class WindowState implements State {

    private static final String WINDOW_STATE_NORMAL_BOUNDS =
            "WindowState.normalBounds";

    protected Rectangle bounds;
    protected Rectangle gcBounds;
    protected int frameState = Frame.NORMAL;

    public WindowState() {
    }

    public WindowState(Rectangle bounds, Rectangle gcBounds, int frameState) {
        this.bounds = new Rectangle(bounds);
        this.gcBounds = new Rectangle(gcBounds);
        this.frameState = frameState;
    }

    public Rectangle getBounds() {
        return bounds;
    }

    public void setBounds(Rectangle bounds) {
        this.bounds = bounds;
    }

    public Rectangle getGcBounds() {
        return gcBounds;
    }

    public void setGcBounds(Rectangle gcBounds) {
        this.gcBounds = gcBounds;
    }

    public int getFrameState() {
        return frameState;
    }

    public void setFrameState(int frameState) {
        this.frameState = frameState;
    }

    protected Window checkComponent(Object o) {
        if (o == null) {
            throw new IllegalArgumentException("null component");
        }
        if (!(o instanceof Window)) {
            throw new IllegalArgumentException("invalid component");
        }
        return (Window) o;
    }

    /**
     * Checks whether the window supports resizing
     *
     * @param window the {@code Window} to be checked
     * @return true if the window supports resizing
     */
    protected static boolean isResizable(Window window) {
        boolean resizable = true;
        if (window instanceof Frame) {
            resizable = ((Frame) window).isResizable();
        } else if (window instanceof Dialog) {
            resizable = ((Dialog) window).isResizable();
        }
        return resizable;
    }

    /**
     * Gets {@code Window} bounds from the client property
     *
     * @param window the source {@code Window}
     * @return bounds from the client property
     */
    protected static Rectangle getWindowNormalBounds(Window window) {
        Rectangle result = null;
        if (window instanceof JFrame) {
            Object res = ((JFrame) window).getRootPane().getClientProperty(
                    WINDOW_STATE_NORMAL_BOUNDS);
            if (res instanceof Rectangle) {
                result = (Rectangle) res;
            }
        }
        return result;
    }

    /**
     * Calculates virtual graphic bounds.
     * On multiscreen systems all screens are united into one virtual screen.
     *
     * @return the graphic bounds
     */
    public static Rectangle computeVirtualGraphicsBounds() {
        Rectangle virtualBounds = new Rectangle();
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[] gs = ge.getScreenDevices();
        for (GraphicsDevice gd : gs) {
            GraphicsConfiguration gc = gd.getDefaultConfiguration();
            virtualBounds = virtualBounds.union(gc.getBounds());
        }
        return virtualBounds;
    }

    /**
     * Puts {@code Window} bounds to client property.
     *
     * @param window the target {@code Window}
     * @param bounds bounds
     */
    public static void putWindowNormalBounds(Window window, Rectangle bounds) {
        if (window instanceof JFrame) {
            ((JFrame) window).getRootPane().putClientProperty(
                    WINDOW_STATE_NORMAL_BOUNDS, bounds);
        }
    }

    @Override
    public State getState(Object o) {
        Window c = checkComponent(o);
        int frameState = Frame.NORMAL;
        if (c instanceof Frame) {
            frameState = ((Frame) c).getExtendedState();
        }
        GraphicsConfiguration gc = c.getGraphicsConfiguration();
        Rectangle gcBounds = (gc == null) ? null : gc.getBounds();
        Rectangle frameBounds = c.getBounds();

            /* If this is a JFrame created by FrameView and it's been maximized,
             * retrieve the frame's normal (not maximized) bounds.  More info:
             * see FrameStateListener#windowStateChanged in FrameView.
             */
        if ((c instanceof JFrame) && (0 != (frameState & Frame.MAXIMIZED_BOTH))) {
            frameBounds = getWindowNormalBounds(c);
        }

        WindowState result = null;
        if (frameBounds != null && !frameBounds.isEmpty()) {
            result = new WindowState();
            result.setBounds(frameBounds);
            result.setGcBounds(gcBounds);
            result.setFrameState(frameState);
        }

        return result;
    }

    @Override
    public void setState(Object o, State state) {
        Window w = checkComponent(o);
        if ((state != null) && !(state instanceof WindowState)) {
            throw new IllegalArgumentException("invalid state");
        }
        WindowState windowState = (WindowState) state;
        if (windowState.getBounds() != null) {
            putWindowNormalBounds(w, windowState.getBounds());
            if (!w.isLocationByPlatform() && (state != null)) {

                Rectangle gcBounds0 = windowState.getGcBounds();
                if (gcBounds0 != null && isResizable(w)) {
                    if (computeVirtualGraphicsBounds().contains(gcBounds0.getLocation())) {
                        w.setBounds(windowState.getBounds());
                    } else {
                        w.setSize(windowState.getBounds().getSize());
                    }
                }
            }
            if (w instanceof Frame) {
                ((Frame) w).setExtendedState(windowState.getFrameState());
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy