1 /** 2 * Copyright 2010 JogAmp Community. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, are 5 * permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, this list of 8 * conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 * of conditions and the following disclaimer in the documentation and/or other materials 12 * provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * The views and conclusions contained in the software and documentation are those of the 25 * authors and should not be interpreted as representing official policies, either expressed 26 * or implied, of JogAmp Community. 27 */ 28 29 package com.jogamp.nativewindow.awt; 30 31 import java.awt.Component; 32 import java.awt.Window; 33 import java.awt.event.WindowAdapter; 34 import java.awt.event.WindowEvent; 35 import java.awt.event.WindowListener; 36 37 import com.jogamp.nativewindow.WindowClosingProtocol; 38 39 import jogamp.nativewindow.awt.AWTMisc; 40 41 public class AWTWindowClosingProtocol implements WindowClosingProtocol { 42 43 private final Component comp; 44 private Window listenTo; 45 private final Runnable closingOperationClose; 46 private final Runnable closingOperationNOP; 47 private final Object closingListenerLock = new Object(); 48 private WindowClosingMode defaultCloseOperation = WindowClosingMode.DISPOSE_ON_CLOSE; 49 private boolean defaultCloseOperationSetByUser = false; 50 51 /** 52 * @param comp mandatory AWT component which AWT Window is being queried by parent traversal 53 * @param closingOperationClose mandatory closing operation, triggered if windowClosing and {@link WindowClosingMode#DISPOSE_ON_CLOSE} 54 * @param closingOperationNOP optional closing operation, triggered if windowClosing and {@link WindowClosingMode#DO_NOTHING_ON_CLOSE} 55 */ AWTWindowClosingProtocol(final Component comp, final Runnable closingOperationClose, final Runnable closingOperationNOP)56 public AWTWindowClosingProtocol(final Component comp, final Runnable closingOperationClose, final Runnable closingOperationNOP) { 57 this.comp = comp; 58 this.listenTo = null; 59 this.closingOperationClose = closingOperationClose; 60 this.closingOperationNOP = closingOperationNOP; 61 } 62 63 class WindowClosingAdapter extends WindowAdapter { 64 @Override windowClosing(final WindowEvent e)65 public void windowClosing(final WindowEvent e) { 66 final WindowClosingMode op = AWTWindowClosingProtocol.this.getDefaultCloseOperation(); 67 68 if( WindowClosingMode.DISPOSE_ON_CLOSE == op ) { 69 // we have to issue this call right away, 70 // otherwise the window gets destroyed 71 closingOperationClose.run(); 72 } else if( null != closingOperationNOP ){ 73 closingOperationNOP.run(); 74 } 75 } 76 } 77 WindowListener windowClosingAdapter = new WindowClosingAdapter(); 78 79 /** 80 * Adds this closing listener to the components Window if exist and only one time. 81 * <p> 82 * If the closing listener is already added, and {@link IllegalStateException} is thrown. 83 * </p> 84 * 85 * @return true if added, otherwise false. 86 * @throws IllegalStateException 87 */ addClosingListener()88 public final boolean addClosingListener() throws IllegalStateException { 89 synchronized(closingListenerLock) { 90 if(null != listenTo) { 91 throw new IllegalStateException("WindowClosingListener already set"); 92 } 93 listenTo = AWTMisc.getWindow(comp); 94 if(null!=listenTo) { 95 listenTo.addWindowListener(windowClosingAdapter); 96 return true; 97 } 98 } 99 return false; 100 } 101 removeClosingListener()102 public final boolean removeClosingListener() { 103 synchronized(closingListenerLock) { 104 if(null != listenTo) { 105 listenTo.removeWindowListener(windowClosingAdapter); 106 listenTo = null; 107 return true; 108 } 109 } 110 return false; 111 } 112 113 /** 114 * 115 * @return the user set close operation if set by {@link #setDefaultCloseOperation(WindowClosingMode) setDefaultCloseOperation(int)}, 116 * otherwise return the AWT/Swing close operation value translated to 117 * a {@link WindowClosingProtocol} value . 118 */ 119 @Override getDefaultCloseOperation()120 public final WindowClosingMode getDefaultCloseOperation() { 121 synchronized(closingListenerLock) { 122 if(defaultCloseOperationSetByUser) { 123 return defaultCloseOperation; 124 } 125 } 126 // User didn't determine the behavior, use underlying AWT behavior 127 return AWTMisc.getNWClosingOperation(comp); 128 } 129 130 @Override setDefaultCloseOperation(final WindowClosingMode op)131 public final WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) { 132 synchronized(closingListenerLock) { 133 final WindowClosingMode _op = defaultCloseOperation; 134 defaultCloseOperation = op; 135 defaultCloseOperationSetByUser = true; 136 return _op; 137 } 138 } 139 } 140