/* * Copyright 2010-2013 Institut Pasteur. * * This file is part of Icy. * * Icy 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. * * Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>. */ package icy.gui.util; import icy.common.listener.weak.WeakComponentListener; import icy.common.listener.weak.WeakIcyFrameListener; import icy.common.listener.weak.WeakWindowListener; import icy.gui.component.ExternalizablePanel; import icy.gui.component.ExternalizablePanel.StateListener; import icy.gui.component.ExternalizablePanel.WeakStateListener; import icy.gui.frame.IcyFrame; import icy.gui.frame.IcyFrameAdapter; import icy.gui.frame.IcyFrameEvent; import icy.gui.main.MainFrame; import icy.preferences.IcyPreferences; import icy.preferences.XMLPreferences; import icy.system.SystemUtil; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JComponent; import javax.swing.JFrame; /** * Load and Save you window position in the registry * * @author fab & stephane */ public class WindowPositionSaver { final private static int DESKTOP_MARGIN = 100; final private static String ID_EXTERNALIZED = "Externalized"; final private static String ID_PANELIZED = "Panelized"; final private static String ID_XC = "XC"; final private static String ID_YC = "YC"; final private static String ID_WC = "WidthC"; final private static String ID_HC = "HeightC"; final private static String ID_XI = "XI"; final private static String ID_YI = "YI"; final private static String ID_WI = "WidthI"; final private static String ID_HI = "HeightI"; final private static String ID_MAXIMIZEDI = "MaximizedI"; final private static String ID_XE = "XE"; final private static String ID_YE = "YE"; final private static String ID_WE = "WidthE"; final private static String ID_HE = "HeightE"; final private static String ID_MAXIMIZEDE = "MaximizedE"; final XMLPreferences preferences; final private MainFrame mainFrame; final private IcyFrame icyFrame; final private ExternalizablePanel extPanel; final private JFrame jFrame; final private JComponent component; final WindowAdapter windowAdapter; final IcyFrameAdapter icyFrameAdapter; final ComponentAdapter componentAdapter; final StateListener stateListener; private WindowPositionSaver(final MainFrame mainFrame, final IcyFrame icyFrame, final ExternalizablePanel extPanel, final JFrame jFrame, final JComponent component, final String key, final Point defLoc, final Dimension defDim) { preferences = IcyPreferences.root().node(key); this.mainFrame = mainFrame; this.icyFrame = icyFrame; this.extPanel = extPanel; this.jFrame = jFrame; this.component = component; // directly load location and dimension if (defLoc != null) loadLocation(defLoc); if (defDim != null) loadDimension(defDim); loadState(); checkPosition(); // code for save frame informations final Runnable saver = new Runnable() { @Override public void run() { if (defLoc != null) saveLocation(); if (defDim != null) saveDimension(); saveState(); } }; // keep hard reference on it componentAdapter = new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { if (extPanel != null) { // event comes from panel itself if (e.getSource() == extPanel) saver.run(); else checkPosition(); } else { checkPosition(); saver.run(); } } @Override public void componentMoved(ComponentEvent e) { if (extPanel != null) { // event comes from panel itself if (e.getSource() == extPanel) saver.run(); // REMOVED: multiple workspace (linux) don't like that //else // checkPosition(); } else { // REMOVED: multiple workspace (linux) don't like that //checkPosition(); saver.run(); } } @Override public void componentShown(ComponentEvent e) { // correctly save internalized / externalized state saver.run(); } @Override public void componentHidden(ComponentEvent e) { // correctly save internalized / externalized state saver.run(); } }; // keep hard reference on it windowAdapter = new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { saver.run(); } }; // keep hard reference on it icyFrameAdapter = new IcyFrameAdapter() { @Override public void icyFrameClosing(IcyFrameEvent e) { saver.run(); } }; // keep hard reference on it stateListener = new StateListener() { @Override public void stateChanged(ExternalizablePanel source, boolean externalized) { saver.run(); } }; if (mainFrame != null) { mainFrame.addWindowListener(new WeakWindowListener(windowAdapter)); mainFrame.addComponentListener(new WeakComponentListener(componentAdapter)); } else if (icyFrame != null) { icyFrame.addFrameListener(new WeakIcyFrameListener(icyFrameAdapter)); icyFrame.addComponentListener(new WeakComponentListener(componentAdapter)); } else if (extPanel != null) { extPanel.addComponentListener(new WeakComponentListener(componentAdapter)); extPanel.addStateListener(new WeakStateListener(stateListener)); extPanel.getFrame().addFrameListener(new WeakIcyFrameListener(icyFrameAdapter)); extPanel.getFrame().addComponentListener(new WeakComponentListener(componentAdapter)); } else if (jFrame != null) { jFrame.addWindowListener(new WeakWindowListener(windowAdapter)); jFrame.addComponentListener(new WeakComponentListener(componentAdapter)); } else if (component != null) { component.addComponentListener(new WeakComponentListener(componentAdapter)); } } public WindowPositionSaver(MainFrame frame, String key, Point defLoc, Dimension defDim) { this(frame, null, null, null, null, key, defLoc, defDim); } public WindowPositionSaver(MainFrame frame, String key, Point defLoc) { this(frame, null, null, null, null, key, defLoc, null); } public WindowPositionSaver(MainFrame frame, String key, Dimension defDim) { this(frame, null, null, null, null, key, null, defDim); } public WindowPositionSaver(IcyFrame frame, String key, Point defLoc, Dimension defDim) { this(null, frame, null, null, null, key, defLoc, defDim); } public WindowPositionSaver(IcyFrame frame, String key, Point defLoc) { this(null, frame, null, null, null, key, defLoc, null); } public WindowPositionSaver(IcyFrame frame, String key, Dimension defDim) { this(null, frame, null, null, null, key, null, defDim); } public WindowPositionSaver(ExternalizablePanel extPanel, String key, Point defLoc, Dimension defDim) { this(null, null, extPanel, null, null, key, defLoc, defDim); } public WindowPositionSaver(ExternalizablePanel extPanel, String key, Point defLoc) { this(null, null, extPanel, null, null, key, defLoc, null); } public WindowPositionSaver(ExternalizablePanel extPanel, String key, Dimension defDim) { this(null, null, extPanel, null, null, key, null, defDim); } public WindowPositionSaver(JFrame frame, String key, Point defLoc, Dimension defDim) { this(null, null, null, frame, null, key, defLoc, defDim); } public WindowPositionSaver(JFrame frame, String key, Point defLoc) { this(null, null, null, frame, null, key, defLoc, null); } public WindowPositionSaver(JFrame frame, String key, Dimension defDim) { this(null, null, null, frame, null, key, null, defDim); } public WindowPositionSaver(JComponent component, String key, Point defLoc, Dimension defDim) { this(null, null, null, null, component, key, defLoc, defDim); } public WindowPositionSaver(JComponent component, String key, Point defLoc) { this(null, null, null, null, component, key, defLoc, null); } public WindowPositionSaver(JComponent component, String key, Dimension defDim) { this(null, null, null, null, component, key, null, defDim); } void checkPosition() { final Rectangle rect; // only for frame if (mainFrame != null) rect = mainFrame.getBounds(); else if (icyFrame != null) rect = icyFrame.getBounds(); // check position only for frame else if ((extPanel != null) && extPanel.isExternalized()) rect = extPanel.getFrame().getBounds(); else if (jFrame != null) rect = jFrame.getBounds(); else return; if (fixPosition(rect)) { if (mainFrame != null) mainFrame.setBounds(rect); else if (icyFrame != null) icyFrame.setBounds(rect); // check position only for frame else if ((extPanel != null) && extPanel.isExternalized()) extPanel.getFrame().setBounds(rect); else if (jFrame != null) jFrame.setBounds(rect); } } boolean fixPosition(Rectangle rect) { Rectangle desktopRect = SystemUtil.getDesktopBounds(); boolean result = false; int limit; limit = (int) (desktopRect.getMaxX() - DESKTOP_MARGIN); if (rect.x >= limit) { rect.x = limit; result = true; } else { limit = (int) desktopRect.getMinX(); if (((rect.x + rect.width) - DESKTOP_MARGIN) < limit) { rect.x = DESKTOP_MARGIN - rect.width; result = true; } } limit = (int) (desktopRect.getMaxY() - DESKTOP_MARGIN); if (rect.y >= limit) { rect.y = limit; result = true; } else { limit = (int) desktopRect.getMinY(); if (rect.y < limit) { rect.y = limit; result = true; } } return result; } public void loadLocation(Point defLoc) { final int defX, defY; if (defLoc == null) { defX = 0; defY = 0; } else { defX = defLoc.x; defY = defLoc.y; } final Point positionC = new Point(preferences.getInt(ID_XC, defX), preferences.getInt(ID_YC, defY)); final Point positionI = new Point(preferences.getInt(ID_XI, defX), preferences.getInt(ID_YI, defY)); final Point positionE = new Point(preferences.getInt(ID_XE, defX), preferences.getInt(ID_YE, defY)); if (mainFrame != null) { mainFrame.setLocation(positionE); } else if (icyFrame != null) { icyFrame.setLocationInternal(positionI); icyFrame.setLocationExternal(positionE); } else if (extPanel != null) { extPanel.setLocation(positionC); // get the panel frame final IcyFrame f = extPanel.getFrame(); f.setLocationInternal(positionI); f.setLocationExternal(positionE); } else if (jFrame != null) { jFrame.setLocation(positionE); } else if (component != null) { component.setLocation(positionC); } } public XMLPreferences getPreferences() { return preferences; } public void loadDimension(Dimension defDim) { final int defW, defH; if (defDim == null) { defW = 300; defH = 300; } else { defW = defDim.width; defH = defDim.height; } // minimum size is 10 pixels int widthC = Math.max(preferences.getInt(ID_WC, defW), 10); int heightC = Math.max(preferences.getInt(ID_HC, defH), 10); int widthI = Math.max(preferences.getInt(ID_WI, defW), 10); int heightI = Math.max(preferences.getInt(ID_HI, defH), 10); int widthE = Math.max(preferences.getInt(ID_WE, defW), 10); int heightE = Math.max(preferences.getInt(ID_HE, defH), 10); final Dimension dimC = new Dimension(widthC, heightC); final Dimension dimI = new Dimension(widthI, heightI); final Dimension dimE = new Dimension(widthE, heightE); if (mainFrame != null) { // set size only else we cannot pack anymore the frame for detached mode mainFrame.setSize(dimE); } else if (icyFrame != null) { icyFrame.setPreferredSizeExternal(dimE); icyFrame.setSizeExternal(dimE); icyFrame.setPreferredSizeInternal(dimI); icyFrame.setSizeInternal(dimI); } else if (extPanel != null) { extPanel.setPreferredSize(dimC); // get the panel frame final IcyFrame f = extPanel.getFrame(); f.setPreferredSizeExternal(dimE); f.setSizeExternal(dimE); f.setPreferredSizeInternal(dimI); f.setSizeInternal(dimI); } else if (jFrame != null) { jFrame.setPreferredSize(dimE); jFrame.setSize(dimE); } else if (component != null) { component.setPreferredSize(dimC); } } public void loadState() { // default is internalized and panelized final boolean externalized = preferences.getBoolean(ID_EXTERNALIZED, false); final boolean panelized = preferences.getBoolean(ID_PANELIZED, true); final boolean maximizedE = preferences.getBoolean(ID_MAXIMIZEDE, false); final boolean maximizedI = preferences.getBoolean(ID_MAXIMIZEDI, false); if (mainFrame != null) { ComponentUtil.setMaximized(mainFrame, maximizedE); } else if (icyFrame != null) { if (externalized) icyFrame.externalize(); else icyFrame.internalize(); icyFrame.setMaximizedExternal(maximizedE); icyFrame.setMaximizedInternal(maximizedI); } else if (extPanel != null) { // get the panel frame final IcyFrame f = extPanel.getFrame(); if (externalized) f.externalize(); else f.internalize(); f.setMaximizedExternal(maximizedE); f.setMaximizedInternal(maximizedI); if (panelized) extPanel.internalize(); else extPanel.externalize(); } else if (jFrame != null) { ComponentUtil.setMaximized(jFrame, maximizedE); } } public void saveLocation() { if (mainFrame != null) { if (!(ComponentUtil.isMaximized(mainFrame) || ComponentUtil.isMinimized(mainFrame))) { preferences.putInt(ID_XE, mainFrame.getX()); preferences.putInt(ID_YE, mainFrame.getY()); } } else if (icyFrame != null) { if (!(icyFrame.isMaximizedExternal() || icyFrame.isMinimizedExternal())) { preferences.putInt(ID_XE, icyFrame.getXExternal()); preferences.putInt(ID_YE, icyFrame.getYExternal()); } if (!(icyFrame.isMaximizedInternal() || icyFrame.isMinimizedInternal())) { preferences.putInt(ID_XI, icyFrame.getXInternal()); preferences.putInt(ID_YI, icyFrame.getYInternal()); } } else if (extPanel != null) { preferences.putInt(ID_XC, extPanel.getX()); preferences.putInt(ID_YC, extPanel.getY()); // get the panel frame final IcyFrame f = extPanel.getFrame(); if (!(f.isMaximizedExternal() || f.isMinimizedExternal())) { preferences.putInt(ID_XE, f.getXExternal()); preferences.putInt(ID_YE, f.getYExternal()); } if (!(f.isMaximizedInternal() || f.isMinimizedInternal())) { preferences.putInt(ID_XI, f.getXInternal()); preferences.putInt(ID_YI, f.getYInternal()); } } else if (jFrame != null) { if (!(ComponentUtil.isMaximized(jFrame) || ComponentUtil.isMinimized(jFrame))) { preferences.putInt(ID_XE, jFrame.getX()); preferences.putInt(ID_YE, jFrame.getY()); } } else if (component != null) { preferences.putInt(ID_XC, component.getX()); preferences.putInt(ID_YC, component.getY()); } } public void saveDimension() { if (mainFrame != null) { if (!(ComponentUtil.isMaximized(mainFrame) || ComponentUtil.isMinimized(mainFrame))) { final Dimension dim; if (mainFrame.isDetachedMode()) dim = new Dimension(mainFrame.getWidth(), mainFrame.getPreviousHeight()); else dim = mainFrame.getSize(); preferences.putInt(ID_WE, dim.width); preferences.putInt(ID_HE, dim.height); } } else if (icyFrame != null) { if (!(icyFrame.isMaximizedExternal() || icyFrame.isMinimizedExternal())) { preferences.putInt(ID_WE, icyFrame.getWidthExternal()); preferences.putInt(ID_HE, icyFrame.getHeightExternal()); } if (!(icyFrame.isMaximizedInternal() || icyFrame.isMinimizedInternal())) { preferences.putInt(ID_WI, icyFrame.getWidthInternal()); preferences.putInt(ID_HI, icyFrame.getHeightInternal()); } } else if (extPanel != null) { preferences.putInt(ID_WC, extPanel.getWidth()); preferences.putInt(ID_HC, extPanel.getHeight()); // get the panel frame final IcyFrame f = extPanel.getFrame(); if (!(f.isMaximizedExternal() || f.isMinimizedExternal())) { preferences.putInt(ID_WE, f.getWidthExternal()); preferences.putInt(ID_HE, f.getHeightExternal()); } if (!(f.isMaximizedInternal() || f.isMinimizedInternal())) { preferences.putInt(ID_WI, f.getWidthInternal()); preferences.putInt(ID_HI, f.getHeightInternal()); } } else if (jFrame != null) { if (!(ComponentUtil.isMaximized(jFrame) || ComponentUtil.isMinimized(jFrame))) { preferences.putInt(ID_WE, jFrame.getWidth()); preferences.putInt(ID_HE, jFrame.getHeight()); } } else if (component != null) { preferences.putInt(ID_WC, component.getWidth()); preferences.putInt(ID_HC, component.getHeight()); } } public void saveState() { if (mainFrame != null) { final boolean b; if (mainFrame.isDetachedMode()) b = mainFrame.getPreviousMaximized(); else b = ComponentUtil.isMaximized(mainFrame); preferences.putBoolean(ID_MAXIMIZEDE, b); } if (icyFrame != null) { preferences.putBoolean(ID_EXTERNALIZED, icyFrame.isExternalized()); preferences.putBoolean(ID_MAXIMIZEDI, icyFrame.isMaximizedInternal()); preferences.putBoolean(ID_MAXIMIZEDE, icyFrame.isMaximizedExternal()); } else if (extPanel != null) { preferences.putBoolean(ID_PANELIZED, extPanel.isInternalized()); // get the panel frame final IcyFrame f = extPanel.getFrame(); preferences.putBoolean(ID_EXTERNALIZED, f.isExternalized()); preferences.putBoolean(ID_MAXIMIZEDI, f.isMaximizedInternal()); preferences.putBoolean(ID_MAXIMIZEDE, f.isMaximizedExternal()); } else if (jFrame != null) { preferences.putBoolean(ID_MAXIMIZEDE, ComponentUtil.isMaximized(jFrame)); } } }