xref: /AOO41X/main/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/ViewContainer.java (revision 27b2fc91b67b282ef25e5c8fc07f05afd8a62640)
1 /*************************************************************************
2  *
3  *  The Contents of this file are made available subject to the terms of
4  *  the BSD license.
5  *
6  *  Copyright 2000, 2010 Oracle and/or its affiliates.
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
18  *     contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *************************************************************************/
34 
35 // __________ Imports __________
36 
37 import com.sun.star.uno.UnoRuntime;
38 
39 import java.lang.*;
40 import java.util.*;
41 
42 // __________ Implementation __________
43 
44 /**
45  * It's implement a static container which hold
46  * all opened documents and her views alive.
47  * It's possible to register/deregister such views,
48  * to get information about these and it provides
49  * some global functionality - like termination of
50  * this demo application.
51  *
52  * @author     Andreas Schlüns
53  * @created    01.03.2002 08:42
54  */
55 public class ViewContainer extends Thread
56 {
57     // ____________________
58 
59     /**
60      * provides a singleton view container
61      * Neccessary for terminate(9 functionality to be able
62      * to call Runtime.runFinilization().
63      *
64      * @return a reference to the singleton ViewContainer instance
65      */
66     public static synchronized ViewContainer getGlobalContainer()
67     {
68         if (maSingleton==null)
69             maSingleton=new ViewContainer();
70         return maSingleton;
71     }
72 
73     // ____________________
74 
75     /**
76      * ctor
77      * It's private - because nobody should create any instance
78      * expect the only global one, which wil be created by ourself!
79      */
80     private ViewContainer()
81     {
82         mlViews          = new Vector();
83         mlListener       = new Vector();
84         mbShutdownActive = false       ;
85         Runtime.getRuntime().addShutdownHook(this);
86     }
87 
88     // ____________________
89 
90     /**
91      * This register a new view inside this global container
92      * (if it doesnt already exist).
93      *
94      * @param   aView       view which whish to be registered inside this container
95      */
96     public void addView(Object aView)
97     {
98         synchronized(mlViews)
99         {
100             if(mlViews.contains(aView)==false)
101                 mlViews.add(aView);
102         }
103     }
104 
105     // ____________________
106 
107     /**
108      * This deregister a view from this global container.
109      * Normaly it should be the last reference to the view
110      * and her finalize() method should be called.
111      * If last view will be closed here - we terminate these
112      * java application too. Because there is no further
113      * visible frame anymore.
114      *
115      * @param aView
116      *          view object which wish to be deregistered
117      */
118     public void removeView(Object aView)
119     {
120         int nViewCount = 0;
121         synchronized(mlViews)
122         {
123             if(mlViews.contains(aView)==true)
124                 mlViews.remove(aView);
125 
126             nViewCount = mlViews.size();
127 
128             if (nViewCount<1)
129                 mlViews = null;
130         }
131         // If this view is a registered shutdown listener on this view container
132         // too, we must call his interface and forget him as possible listener.
133         // It's neccessary to guarantee his dead ...
134         boolean bShutdownView = false;
135         synchronized(mlListener)
136         {
137             bShutdownView = mlListener.contains(aView);
138             if (bShutdownView==true)
139                 mlListener.remove(aView);
140         }
141         if (bShutdownView==true)
142             ((IShutdownListener)aView).shutdown();
143 
144         // We use a system.exit() to finish the whole application.
145         // And further we have registered THIS instance as a possible shutdown
146         // hook at the runtime class. So our run() method will be called.
147         // Teh our view container should be empty - but
148         // our listener container can include some references.
149         // These objects wich to be informed then and release e.g. some
150         // remote references.
151         if (nViewCount<1)
152         {
153             boolean bNeccessary = false;
154             synchronized(this)
155             {
156                 bNeccessary = ! mbShutdownActive;
157             }
158             if (bNeccessary==true)
159             {
160                 System.out.println("call exit(0)!");
161                 System.exit(0);
162             }
163         }
164     }
165 
166     // ____________________
167 
168     /**
169      * add/remove listener for possibe shutdown events
170      */
171     public void addListener( IShutdownListener rListener )
172     {
173         synchronized(mlListener)
174         {
175             if ( ! mlListener.contains(rListener) )
176                 mlListener.add(rListener);
177         }
178     }
179 
180     // ____________________
181 
182     public void removeListener( IShutdownListener rListener )
183     {
184         synchronized(mlListener)
185         {
186             if ( mlListener.contains(rListener) )
187                 mlListener.remove(rListener);
188         }
189     }
190 
191     // ____________________
192 
193     /**
194      * Is called from current runtime system of the java machine
195      * on shutdown. We inform all current registered listener and
196      * views. They should deinitialize her internal things then.
197      */
198     public void run()
199     {
200         synchronized(this)
201         {
202             if (mbShutdownActive)
203                 return;
204             mbShutdownActive=true;
205         }
206 
207         while( true )
208         {
209             IShutdownListener aListener = null;
210             synchronized(mlListener)
211             {
212                 try{
213                     aListener = (IShutdownListener)mlListener.firstElement();
214                 } catch(java.util.NoSuchElementException exEmpty) {}
215             }
216             if (aListener==null)
217                 break;
218 
219             aListener.shutdown();
220             // May this listener has dergeistered himself.
221             // But if not we must do it for him. Our own
222             // method "removeListener()" ignore requests for
223             // already gone listener objects.
224             removeListener(aListener);
225         }
226 
227         if (mlViews!=null)
228         {
229             synchronized(mlViews)
230             {
231                 mlViews.clear();
232                 mlViews = null;
233             }
234         }
235 
236         if (mlListener!=null)
237         {
238             synchronized(mlListener)
239             {
240                 mlListener.clear();
241                 mlListener = null;
242             }
243         }
244     }
245 
246     // ____________________
247 
248     /**
249      * @const   BASICNAME   it's used to create uinque names for all regieterd views
250      */
251     private static final String BASICNAME = "Document View ";
252 
253     // ____________________
254 
255     /**
256      * @member  mbInplace           indicates using of inplace office frames instead of outplace ones
257      * @member  maSingleton         singleton instance of this view container
258      * @member  mlViews             list of all currently registered document views
259      * @member  mlListener          list of all currently registered shutdown listener
260      * @member  mbShutdownActive    if this shutdown hook already was started it's not a good idea to
261      *                              call System.exit() again for other conditions.
262      *                              We supress it by using this variable!
263      */
264     public  static boolean       mbInplace   = false ;
265     private static ViewContainer maSingleton = null  ;
266     private        Vector        mlViews             ;
267     private        Vector        mlListener          ;
268     private        boolean       mbShutdownActive    ;
269 }
270