package org.limewire.ui.swing.mainframe;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import javax.swing.JFrame;
import org.limewire.ui.swing.settings.SwingUiSettings;
class FramePositioner {
/**
* The last state of the X/Y location and the time it was set.
* This is necessary to preserve the maximize size & prior size,
* as on Windows a move event is occasionally triggered when
* maximizing, prior to the state actually becoming maximized.
*/
private WindowState lastState;
/** The frame this is listening to. */
private JFrame frame;
void initialize(JFrame frame) {
assert this.frame == null : "already initialized on a frame!";
this.frame = frame;
listenToWindowPosition();
}
void setWindowPosition() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
int appWidth = Math.min(screenSize.width-insets.left-insets.right, SwingUiSettings.APP_WIDTH.getValue());
int appHeight = Math.min(screenSize.height-insets.top-insets.bottom, SwingUiSettings.APP_HEIGHT.getValue());
// TODO: Get a real minimum size?
frame.setMinimumSize(new Dimension(500, 500));
frame.setSize(new Dimension(appWidth, appHeight));
// Set the location of our window based on whether or not
// the user has run the program before, and therefore may have
// modified the location of the main window.
if(SwingUiSettings.POSITIONS_SET.getValue()) {
int locX = Math.max(insets.left, SwingUiSettings.WINDOW_X.getValue());
int locY = Math.max(insets.top, SwingUiSettings.WINDOW_Y.getValue());
// Make sure the Window is visible and not for example
// somewhere in the very bottom right corner.
if (locX+appWidth > screenSize.width) {
locX = Math.max(insets.left, screenSize.width - insets.left - insets.right - appWidth);
}
if (locY+appHeight > screenSize.height) {
locY = Math.max(insets.top, screenSize.height - insets.top - insets.bottom - appHeight);
}
frame.setLocation(locX, locY);
} else {
frame.setLocationRelativeTo(null);
}
//re-maximize if we shutdown while maximized.
if(SwingUiSettings.MAXIMIZE_WINDOW.getValue()
&& Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
}
frame.validate();
}
private void listenToWindowPosition() {
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentMoved(ComponentEvent e) {
lastState = new WindowState();
saveWindowState();
}
@Override
public void componentResized(ComponentEvent e) {
saveWindowState();
}
});
frame.addWindowStateListener(new WindowStateListener() {
public void windowStateChanged(WindowEvent e) {
saveWindowState();
}
});
// TODO: Is this listener necessary? I don't think it is.
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
saveWindowState();
}
});
}
/** Saves the state of the Window to settings. */
private void saveWindowState() {
int state = frame.getExtendedState();
if(state == Frame.NORMAL) {
// save the screen size and location
Dimension dim = frame.getSize();
if((dim.height > 100) && (dim.width > 100)) {
Point loc = frame.getLocation();
SwingUiSettings.APP_WIDTH.setValue(dim.width);
SwingUiSettings.APP_HEIGHT.setValue(dim.height);
SwingUiSettings.WINDOW_X.setValue(loc.x);
SwingUiSettings.WINDOW_Y.setValue(loc.y);
SwingUiSettings.MAXIMIZE_WINDOW.setValue(false);
SwingUiSettings.POSITIONS_SET.setValue(true);
}
} else if( (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {
SwingUiSettings.MAXIMIZE_WINDOW.setValue(true);
if(lastState != null && lastState.time == System.currentTimeMillis()) {
SwingUiSettings.POSITIONS_SET.setValue(true);
SwingUiSettings.WINDOW_X.setValue(lastState.x);
SwingUiSettings.WINDOW_Y.setValue(lastState.y);
lastState = null;
}
}
}
/** simple state. */
private static class WindowState {
private final int x;
private final int y;
private final long time;
WindowState() {
x = SwingUiSettings.WINDOW_X.getValue();
y = SwingUiSettings.WINDOW_Y.getValue();
time = System.currentTimeMillis();
}
}
}