diff options
author | Sven Gothel <[email protected]> | 2010-12-19 14:54:08 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-12-19 14:54:08 +0100 |
commit | 2cbab63bd6c230d31b8ae6f1d794ad49bf23bb53 (patch) | |
tree | 9da105f466b81424ae089e59e4bd67fce7c32d54 /src/nativewindow | |
parent | 2323c30c23b6f9eb7d7ccf94e6cdcbcb3d2f34a6 (diff) |
JOGL/NEWT: Introduce WindowClosingProtocol (solves Bug/Request 444)
Similar to JFrame's closing behavior,
the following components window closing follow the new WindowClosingProtocol:
- GLCanvas
- GLJPanel
- NEWT Window, GLWindow
- NEWT NewtCanvasAWT
The implementation obeys either
1) the user value set by this interface,
2) an underlying toolkit set user value (JFrame, ..)
3) or it's default, eg. {@link #DO_NOTHING_ON_CLOSE DO_NOTHING_ON_CLOSE} within an AWT environment.
If none of the above determines the operation,
this protocol default behavior {@link #DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.
Diffstat (limited to 'src/nativewindow')
4 files changed, 301 insertions, 1 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/awt/AWTMisc.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/awt/AWTMisc.java new file mode 100644 index 000000000..c61ae5531 --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/awt/AWTMisc.java @@ -0,0 +1,96 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.nativewindow.impl.awt; + +import java.awt.Window; +import java.awt.Component; +import java.awt.Container; +import java.awt.Frame; +import javax.swing.JFrame; +import javax.swing.WindowConstants; + +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.WindowClosingProtocol; +import javax.swing.MenuSelectionManager; + +public class AWTMisc { + + public static final JFrame getJFrame(Component c) { + while (c != null && !(c instanceof JFrame)) { + c = c.getParent(); + } + return (JFrame) c; + } + + public static final Frame getFrame(Component c) { + while (c != null && !(c instanceof Frame)) { + c = c.getParent(); + } + return (Frame) c; + } + + public static final Window getWindow(Component c) { + while (c != null && !(c instanceof Window)) { + c = c.getParent(); + } + return (Window) c; + } + + public static final Container getContainer(Component c) { + while (c != null && !(c instanceof Container)) { + c = c.getParent(); + } + return (Container) c; + } + + /** + * Issue this when your non AWT toolkit gains focus to clear AWT menu path + */ + public static final void clearAWTMenus() { + MenuSelectionManager.defaultManager().clearSelectedPath(); + } + + public final static int AWT2NWClosingOperation(int awtClosingOperation) { + switch (awtClosingOperation) { + case WindowConstants.DISPOSE_ON_CLOSE: + case WindowConstants.EXIT_ON_CLOSE: + return WindowClosingProtocol.DISPOSE_ON_CLOSE; + case WindowConstants.DO_NOTHING_ON_CLOSE: + case WindowConstants.HIDE_ON_CLOSE: + return WindowClosingProtocol.DO_NOTHING_ON_CLOSE; + default: + throw new NativeWindowException("Unhandled AWT Closing Operation: " + awtClosingOperation); + } + } + + public final static int getNWClosingOperation(Component c) { + JFrame jf = getJFrame(c); + int op = (null != jf) ? jf.getDefaultCloseOperation() : WindowConstants.DO_NOTHING_ON_CLOSE ; + return AWT2NWClosingOperation(op); + } +} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java index 68d6dc2a8..39816ff6a 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -38,7 +39,6 @@ package com.jogamp.nativewindow.impl.jawt; import com.jogamp.nativewindow.impl.*; import java.awt.EventQueue; -import java.awt.Frame; import javax.media.nativewindow.*; diff --git a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java new file mode 100644 index 000000000..949aee79c --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java @@ -0,0 +1,66 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.nativewindow; + +/** + * Protocol for handling window closing events. + * <p> + * The implementation shall obey either the user value set by this interface,<br> + * an underlying toolkit set user value or it's default, eg. {@link #DO_NOTHING_ON_CLOSE DO_NOTHING_ON_CLOSE} within an AWT environment.<br> + * If none of the above determines the operation, + * this protocol default behavior {@link #DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.</p> + */ +public interface WindowClosingProtocol { + /** + * Dispose resources on native window close operation.<br> + * This is the default behavior in case no underlying toolkit defines otherwise. + */ + int DISPOSE_ON_CLOSE = 1; + + /** + * Do nothing on native window close operation.<br> + * This is the default behavior within an AWT environment. + */ + int DO_NOTHING_ON_CLOSE = 0; + + /** + * @return the current close operation value + * @see #DISPOSE_ON_CLOSE + * @see #DO_NOTHING_ON_CLOSE + */ + int getDefaultCloseOperation(); + + /** + * @param op the new close operation value + * @return the previous close operation value + * @see #DISPOSE_ON_CLOSE + * @see #DO_NOTHING_ON_CLOSE + */ + int setDefaultCloseOperation(int op); +} diff --git a/src/nativewindow/classes/javax/media/nativewindow/awt/AWTWindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTWindowClosingProtocol.java new file mode 100644 index 000000000..a0e9efa49 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTWindowClosingProtocol.java @@ -0,0 +1,138 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.nativewindow.awt; + +import java.awt.Component; +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import javax.media.nativewindow.WindowClosingProtocol; +import com.jogamp.nativewindow.impl.awt.AWTMisc; + +public class AWTWindowClosingProtocol implements WindowClosingProtocol { + + private Component comp; + private Runnable closingOperation; + private volatile boolean closingListenerSet = false; + private Object closingListenerLock = new Object(); + private int defaultCloseOperation = DISPOSE_ON_CLOSE; + private boolean defaultCloseOperationSetByUser = false; + + public AWTWindowClosingProtocol(Component comp, Runnable closingOperation) { + this.comp = comp; + this.closingOperation = closingOperation; + } + + class WindowClosingAdapter extends WindowAdapter { + public void windowClosing(WindowEvent e) { + int op = AWTWindowClosingProtocol.this.getDefaultCloseOperation(); + + if( DISPOSE_ON_CLOSE == op ) { + // we have to issue this call right away, + // otherwise the window gets destroyed + closingOperation.run(); + } + } + } + WindowListener windowClosingAdapter = new WindowClosingAdapter(); + + final boolean addClosingListenerImpl() { + Window w = AWTMisc.getWindow(comp); + if(null!=w) { + w.addWindowListener(windowClosingAdapter); + return true; + } + return false; + } + + /** + * Adds this closing listener to the components Window if exist and only one time.<br> + * Hence you may call this method every time to ensure it has been set, + * ie in case the Window parent is not available yet. + * + * @return + */ + public final boolean addClosingListenerOneShot() { + if(!closingListenerSet) { + synchronized(closingListenerLock) { + if(!closingListenerSet) { + closingListenerSet=addClosingListenerImpl(); + return closingListenerSet; + } + } + } + return false; + } + + public final boolean removeClosingListener() { + if(closingListenerSet) { + synchronized(closingListenerLock) { + if(closingListenerSet) { + Window w = AWTMisc.getWindow(comp); + if(null!=w) { + w.removeWindowListener(windowClosingAdapter); + closingListenerSet = false; + return true; + } + } + } + } + return false; + } + + /** + * + * @return the user set close operation if set by {@link #setDefaultCloseOperation(int) setDefaultCloseOperation(int)}, + * otherwise return the AWT/Swing close operation value translated to + * a {@link WindowClosingProtocol} value . + */ + public final int getDefaultCloseOperation() { + int op = -1; + synchronized(closingListenerLock) { + if(defaultCloseOperationSetByUser) { + op = defaultCloseOperation; + } + } + if(0 <= op) { + return op; + } + // User didn't determine the behavior, use underlying AWT behavior + return AWTMisc.getNWClosingOperation(comp); + } + + public final int setDefaultCloseOperation(int op) { + synchronized(closingListenerLock) { + int _op = defaultCloseOperation; + defaultCloseOperation = op; + defaultCloseOperationSetByUser = true; + return _op; + } + } +} |