/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp 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 Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp;
import java.awt.AWTEvent;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.WindowEvent;
import jpcsp.settings.Settings;
/**
* This class implements the automatic storing and loading of window positions
* for Frames and Dialogs.
*
* @note Loading the window position only on the WINDOW_OPENED event might lead
* to flicker. See the comment on loadWindowProperties() for details.
*
* @author tempura
*/
public class WindowPropSaver implements AWTEventListener {
@Override
public void eventDispatched(AWTEvent awte) {
Window window = (Window) ((WindowEvent) awte).getComponent();
switch (awte.getID()) {
case WindowEvent.WINDOW_DEACTIVATED:
onSavePosition(window);
break;
case WindowEvent.WINDOW_OPENED:
// this is only a fall-back for windows which do not call
// loadWindowProperties() on GUI construction time
// failing to do so will lead to a short flicker, as the window
// is placed at the default position and moved afterwards after
// signaling the OPENED event
onLoadPosition(window);
break;
}
}
/**
* Put a call to this function into the Frame's contructor in order to
* ensure a flicker-free placing of the Frame.
*
* @note Call this function as last line of the constructor.
*
* @param window The window to place and resize.
*/
public static void loadWindowProperties(Window window) {
onLoadPosition(window);
}
/**
* Only use this for MainGUI - as this is the only window which can be
* closed without being deactivated first.
*
* @param window The MainGUI window.
*/
public static void saveWindowProperties(MainGUI mainGUI) {
onSavePosition(mainGUI);
}
/**
* This will set the window position to either the stored position or to the
* screen center if not position was found.
*
* @note It uses the class name as identifier in the settings.
*
* @param frame The frame to initialise.
* @param identifierForConfig The identifier used in the settings file.
*/
private static void onLoadPosition(Window window) {
if (!isWindowFrameOrDialog(window)) {
return;
}
String identifierForConfig = window.getClass().getSimpleName();
// do not load positions for standard dialogs (like file open)
if (identifierForConfig.equals("JDialog")) {
return;
}
// MainGUI needs special handling due to being able to go fullscreen
if (identifierForConfig.equals("MainGUI") && Emulator.getMainGUI().isFullScreen()) {
return;
}
if (Settings.getInstance().readBool("gui.saveWindowPos")
&& Settings.getInstance().readWindowPos(identifierForConfig) != null) {
Emulator.log.debug("loading window position of '" + identifierForConfig + "'");
// LogWindow needs special handling if it shall be attached to the MainGUI
if (!(identifierForConfig.equals("LogWindow") && Settings.getInstance().readBool("gui.snapLogwindow"))) {
window.setLocation(Settings.getInstance().readWindowPos(identifierForConfig));
}
// read the size only if the frame is resizeable
if (isWindowResizeable(window)
&& Settings.getInstance().readWindowSize(identifierForConfig) != null) {
window.setSize(Settings.getInstance().readWindowSize(identifierForConfig));
}
} else {
// show the frame simply centered
window.setLocationRelativeTo(null);
}
}
/**
* Store the current position of the window.
*
* @note It uses the class name as identifier in the settings.
*
* @param frame The frame to initialise.
* @param identifierForConfig The identifier used in the settings file.
*/
private static void onSavePosition(Window window) {
if (!isWindowFrameOrDialog(window)) {
return;
}
if (Settings.getInstance().readBool("gui.saveWindowPos")) {
String identifierForConfig = window.getClass().getSimpleName();
// do not save positions for standard dialogs (like file open)
if (identifierForConfig.equals("JDialog")) {
return;
}
// MainGUI needs special handling due to being able to go fullscreen
if (identifierForConfig.equals("MainGUI") && Emulator.getMainGUI().isFullScreen()) {
return;
}
Emulator.log.debug("saving window position of '" + identifierForConfig + "'");
Settings.getInstance().writeWindowPos(identifierForConfig, window.getLocation());
// write the window size only if the window is resizeable
if (isWindowResizeable(window)) {
Settings.getInstance().writeWindowSize(identifierForConfig, window.getSize());
}
}
}
/**
* Check if the given window object is resizeable.
*
* @note Only done for Frames and Dialogs.
*
* @param window The window instance to check.
* @return true if the window is resizable, false otherwise.
*/
private static boolean isWindowResizeable(Window window) {
return (window instanceof Frame && ((Frame) window).isResizable())
|| (window instanceof Dialog && ((Dialog) window).isResizable());
}
/**
* Check if the given window is an instance of Frame or Dialog.
*
* @param window The window instance to check.
* @return true if the window is an instance of Frame or Dialog, else false.
*/
private static boolean isWindowFrameOrDialog(Window window) {
return (window instanceof Frame) || (window instanceof Dialog);
}
}