/* * $Id$ * * Copyright (c) 2000-2003 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.preferences; import java.awt.Dimension; import java.awt.Frame; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.util.StringTokenizer; import VASSAL.build.BadDataReport; import VASSAL.tools.ErrorDialog; public class PositionOption extends VASSAL.configure.Configurer implements ComponentListener { public static String key = "BoundsOf"; private static Point initialPos = new Point(0, 0); protected Window theFrame; protected Rectangle bounds; protected Rectangle defaultValue; protected Rectangle previousBounds; public PositionOption(String key, Window f, Rectangle defaultValue) { super(key, null, defaultValue); adjustInitialOffset(); theFrame = f; theFrame.pack(); setFrameBounds(); this.defaultValue = defaultValue; theFrame.addComponentListener(this); } private static void adjustInitialOffset() { Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); if (initialPos.x >= d.width-30 || initialPos.y >= d.height-30) { initialPos.move(0,0); } else { initialPos.translate(30, 30); } } public PositionOption(String key, Window f) { this(key,f,new Rectangle(initialPos,new Dimension(0,0))); } public Object getValue() { return bounds; } public void setValue(Object o) { if (o instanceof Rectangle) { bounds = new Rectangle((Rectangle)o); if (theFrame != null) { setFrameBounds(); } } super.setValue(o); } public java.awt.Component getControls() { return null; } public void setValue(String in) { final StringTokenizer st = new StringTokenizer(in, ","); try { setValue(new Rectangle(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()))); } catch (NumberFormatException e) { // This can happen if a VisibilityOption has the same name // as a PositionOption, either currently, or due to editing. // Don't throw a bug, just log it. if (in.indexOf('\t') > 0) { ErrorDialog.dataError(new BadDataReport("Map or Chart window with same name as piece Palette", getKey(), e)); } else { ErrorDialog.bug(e); } } } public String getValueString() { return bounds.x + "," + bounds.y + "," + bounds.width + "," + bounds.height; } private boolean isOnScreen(Point p) { return p.x < Toolkit.getDefaultToolkit().getScreenSize().width && p.y < Toolkit.getDefaultToolkit().getScreenSize().height; } public void componentMoved(ComponentEvent e) { if (theFrame.isShowing()) { Point p = theFrame.getLocationOnScreen(); if (isOnScreen(p)) { // Save the previous size in case this is the start of a Maximize previousBounds = new Rectangle(bounds); bounds.setLocation(p); } } } public void componentResized(ComponentEvent e) { if (theFrame.isShowing()) { // A resize when the window is already maximised only happens when // a window is first resized. Record the pre-maximised bounds. if (theFrame instanceof Frame && previousBounds != null && ((((Frame) theFrame).getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH)) { bounds.setBounds(previousBounds); } else { bounds.setSize(theFrame.getSize()); } } } public void componentShown(ComponentEvent e) { } public void componentHidden(ComponentEvent e) { } protected void setFrameBounds() { final Rectangle desktopBounds = GraphicsEnvironment.getLocalGraphicsEnvironment( ).getMaximumWindowBounds( ); // Respect any existing bounds if (bounds.width != 0 && bounds.height != 0) { theFrame.setSize(new Dimension(Math.abs(bounds.width),Math.abs(bounds.height))); } theFrame.setLocation(bounds.getLocation()); // Reduce size to fit on desktop int width = theFrame.getSize().width > desktopBounds.width ? desktopBounds.width : theFrame.getSize().width; int height = theFrame.getSize().height > desktopBounds.height ? desktopBounds.height : theFrame.getSize().height; if (width != theFrame.getSize().width || height != theFrame.getSize().height) { theFrame.setSize(width, height); } // Slide whole window onto desktop if any part off desktop int x = theFrame.getLocation().x; int y = theFrame.getLocation().y; if (x < desktopBounds.x) x = desktopBounds.x; if (y < desktopBounds.y) y = desktopBounds.y; if (x + theFrame.getSize().width > desktopBounds.x + desktopBounds.width) { x = (desktopBounds.x + desktopBounds.width) - theFrame.getSize().width; } if (y + theFrame.getSize().height > desktopBounds.y + desktopBounds.height) { y = (desktopBounds.y + desktopBounds.height) - theFrame.getSize().height; } if (x != theFrame.getLocation().x || y != theFrame.getLocation().y) { theFrame.setLocation(x, y); } } }