package textbender.o.awt; // Copyright 2001-2005, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. import java.awt.*; import java.awt.event.*; import textbender.g.hold.*; import textbender.o.swing.UIManagerX; /** Window utilities. */ public class WindowX { private WindowX() {} /** Centers a window on the screen. */ public static void center( Window window ) { window.setLocation( getCenterLocation( window.getSize() )); } /** Returns the location that would center the specified area on the screen. * The location returned is that of the top, left of the area. */ public static Point getCenterLocation( Dimension area ) { return getCenterLocation( area, Toolkit.getDefaultToolkit().getScreenSize() ); } /** Returns the location that would center the specified area within the specified surrounding. * The location returned is that of the top, left of the area in the surrounding coordinates. */ public static Point getCenterLocation( Dimension area, Dimension surrounding ) { return new Point ( (surrounding.width - area.width) / 2, (surrounding.height - area.height) / 2 ); } // ==================================================================================== /** Ties the disposal of a window to the unwinding of a spool. * When either window or spool is disposed/unwound, the other is too. *

* Merely closing the window (e.g. making it invisible, without disposing of it) * will have no effect on the spool. * Not unless you also tie window disposal to window closure, * e.g. with JDialog/JFrame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE ). *

*

* Unlike a normal window, you cannot reuse a spool-tied window after disposal; * not if anything critical was unwound from the spool. *

*/ public static final class SpoolTie { /** Constructs a SpoolTie. /** You must call {@linkplain #addListeners() addListeners}() to activate it. */ public SpoolTie( Window window, Spool spool ) { this.window = window; this.spool = spool; } // --- /** Cross-registers listeners between window and spool, to activate the tie. * * @see #removeListeners() * * @return this agent */ public SpoolTie addListeners() { spool.add( listenerR ); window.addWindowListener( listenerW ); return SpoolTie.this; } /** Returns the spool of this window/spool tie. */ public Spool spool() { return spool; } private final Spool spool; /** Unregisters listeners. * * @see #addListeners() */ public void removeListeners() { spool.remove( listenerR ); window.removeWindowListener( listenerW ); } /** Returns the the window of this window/hold-stack tie. */ public Window window() { return window; } private final Window window; ////// private final Hold listenerR = new Hold() { public void release() { window.removeWindowListener( listenerW ); // prevent echo window.dispose(); } }; private final WindowListener listenerW = new WindowAdapter() { public void windowClosed( WindowEvent e ) // misnomer, only called when disposed { spool.remove( listenerR ); // prevent echo spool.unwind(); } }; } // ==================================================================================== /** Updates the UI of a window, whenever the look and feel changes. */ public static final class LookAndFeelUpdater extends UIManagerX.LookAndFeelUpdater { /** Constructs a LookAndFeelUpdaterW that does not pack the window. * * @param window to update, usually a top-level one */ public LookAndFeelUpdater( Window window, Spool spool ) { this( window, spool, false ); } /** Constructs a LookAndFeelUpdaterW. * * @param window to update, usually a top-level one * @param isPacked true iff the window ought to be packed after updating the UI */ public LookAndFeelUpdater( Window window, Spool spool, boolean isPacked ) { super( window, spool ); this.isPacked = isPacked; } ////// private final boolean isPacked; protected void update() { super.update(); if( isPacked ) ((Window)rootComponent).pack(); } } }