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