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.awt.*;
40 import java.awt.event.*;
41 import java.lang.*;
42 import java.net.*;
43 import javax.swing.*;
44 import javax.swing.border.*;
45 import java.awt.AWTEvent;
46 import java.awt.event.WindowEvent;
47 
48 // __________ Implementation __________
49 
50 /**
51  * This implement a java frame wich contains
52  * an office document, shows some status informations
53  * about that, provides simple functionality on it
54  * (e.g. toggle menubar, save document) and
55  * react for different situations independent
56  * (e.g. closing the document from outside).
57  * Every instance of this class will be a member
58  * inside the global "ViewContainer" of this java
59  * demo application which holds all opened views alive.
60  *
61  * @author     Andreas Schlüns
62  * @created    06.03.2002 09:38
63  */
64 public class DocumentView extends    JFrame
65                           implements com.sun.star.lang.XEventListener, // react for Frame::disposing()
66                                      IShutdownListener                 // react for System.exit()
67 {
68     // ____________________
69 
70     /**
71      * const
72      * These command strings are used to identify a received action
73      * of buttons on which we listen for action events.
74      */
75     public static final String COMMAND_OPEN   = "open"   ;
76     public static final String COMMAND_SAVE   = "save"   ;
77     public static final String COMMAND_EXPORT = "export" ;
78     public static final String COMMAND_EXIT   = "exit"   ;
79 
80     // ____________________
81 
82     /**
83      * @member  mxFrame             office frame which contains the document of this view
84      *
85      * @member  maStatusView        special panel wich show available status informations of currently loaded document
86      * @member  maDocumentView      use JNI mechanism to plug an office window into our own java UI container (used for inplace mode only!)
87      * @member  maCustomizeView     special panel makes it possible to toggle menubar/toolbar or objectbar of loaded document
88      * @member  maInterceptor       interceptor thread which intercept "new" menu of office frame to open new frames inside this java application
89      *
90      * @member  msName              unique name of this view (returned by the global ViewContainer during registration)
91      *
92      * @member  mbOpen              button to open documents
93      * @member  mbSave              button to save currently loaded document
94      * @member  mbExport            button to save currently loaded document in HTML format (if it is possible!)
95      * @member  mbExit              button to exit this demo
96      *
97      * @member  maInterception      we try to intercept the file->new menu to open new document inside this java application
98      */
99     private com.sun.star.frame.XFrame       mxFrame             ;
100 
101     private StatusView                      maStatusView        ;
102     private NativeView                      maDocumentView      ;
103     private CustomizeView                   maCustomizeView     ;
104     private Interceptor                     maInterceptor       ;
105 
106     private String                          msName              ;
107 
108     private JButton                         mbtOpen             ;
109     private JButton                         mbtSave             ;
110     private JButton                         mbtExport           ;
111     private JButton                         mbtExit             ;
112 
113     private boolean                         mbDead              ;
114 
115     // ____________________
116 
117     /**
118      * ctor
119      * Create view controls on startup and initialize it with default values.
120      */
121     DocumentView()
122     {
123         this.setSize( new Dimension(800,600) );
124 
125         JPanel paMainPanel = (JPanel)this.getContentPane();
126 
127         // create and add command buttons to a panel
128         // it will be a sub panel of later layouted UI
129         mbtOpen   = new JButton("Open ..."        );
130         mbtSave   = new JButton("Save"            );
131         mbtExport = new JButton("Save as HTML ...");
132         mbtExit   = new JButton("Exit"            );
133 
134         mbtOpen.setEnabled  (true );
135         mbtSave.setEnabled  (false);
136         mbtExport.setEnabled(false);
137         mbtExit.setEnabled  (true );
138 
139         mbtOpen.setActionCommand  (COMMAND_OPEN  );
140         mbtSave.setActionCommand  (COMMAND_SAVE  );
141         mbtExport.setActionCommand(COMMAND_EXPORT);
142         mbtExit.setActionCommand  (COMMAND_EXIT  );
143 
144         Reactor aListener = new Reactor();
145         mbtOpen.addActionListener  (aListener);
146         mbtSave.addActionListener  (aListener);
147         mbtExport.addActionListener(aListener);
148         mbtExit.addActionListener  (aListener);
149 
150         JPanel paCommands = new JPanel( new GridLayout(4,0) );
151         paCommands.add(mbtOpen);
152         paCommands.add(mbtSave);
153         paCommands.add(mbtExport);
154         paCommands.add(mbtExit);
155 
156         // create view to show status informations of opened file
157         maStatusView = new StatusView();
158 
159         // create view for toggle different bar's of document
160         maCustomizeView = new CustomizeView();
161 
162         paCommands.setBorder     ( new TitledBorder(BorderFactory.createEtchedBorder(),"Commands")                );
163         maStatusView.setBorder   ( new TitledBorder(BorderFactory.createEtchedBorder(),"Status Informations")     );
164         maCustomizeView.setBorder( new TitledBorder(BorderFactory.createEtchedBorder(),"Customize Document View") );
165 
166         // layout the whole UI
167         JPanel paTest = new JPanel(new GridLayout(3,0));
168         paTest.add(paCommands     );
169         paTest.add(maStatusView   );
170         paTest.add(maCustomizeView);
171         JScrollPane paScroll = new JScrollPane();
172         paScroll.getViewport().add(paTest,null);
173 
174         if(ViewContainer.mbInplace==true)
175         {
176             // create view to show opened documents
177             // This special view is neccessary for inplace mode only!
178             maDocumentView = new NativeView();
179 
180             JSplitPane paSplit = new JSplitPane();
181             paSplit.setOneTouchExpandable( true );
182 
183             paSplit.setLeftComponent (maDocumentView);
184             paSplit.setRightComponent(paScroll      );
185 
186             paMainPanel.add(paSplit);
187         }
188         else
189         {
190             paMainPanel.add(paScroll);
191         }
192 
193         // Register this new view on our global view container.
194         msName = FunctionHelper.getUniqueFrameName();
195         this.setTitle(msName);
196         ViewContainer.getGlobalContainer().addView(this);
197         ViewContainer.getGlobalContainer().addListener(this);
198         // be listener for closing the application
199         this.enableEvents(AWTEvent.WINDOW_EVENT_MASK);
200     }
201 
202     // ____________________
203 
204     /**
205      * Create the view frame for showing the office documents on demand.
206      * Dependend from given command line parameter we create
207      * an office XFrame and initialize it with a window. This
208      * window can be a pure toolkit window (means toolkit of office!)
209      * or a plugged java canvas - office window combination.
210      */
211     public void createFrame()
212     {
213         // create view frame (as a XFrame!) here
214         // Look for right view mode setted by user command line parameter.
215         // First try to get a new unambigous frame name from our global ViewContainer.
216         if(ViewContainer.mbInplace==true)
217         {
218             // inplace document view can't be initialized without a visible parent window hierarchy!
219             // So make shure that we are visible in every case!
220             this.setVisible(true);
221             mxFrame = FunctionHelper.createViewFrame(msName,maDocumentView);
222         }
223         else
224             mxFrame = FunctionHelper.createViewFrame(msName,null);
225 
226         if(mxFrame!=null)
227         {
228             // start interception
229             maInterceptor = new Interceptor(mxFrame);
230             maInterceptor.startListening();
231 
232             // start listening for status events and actualization
233             // of our status view
234             // (of course for our CustomizeView too)
235             maStatusView.setFrame   (mxFrame);
236             maCustomizeView.setFrame(mxFrame);
237 
238             // be listener for closing the remote target view frame
239             com.sun.star.lang.XComponent xBroadcaster = (com.sun.star.lang.XComponent)UnoRuntime.queryInterface(
240                 com.sun.star.lang.XComponent.class,
241                 mxFrame);
242 
243             if(xBroadcaster!=null)
244                 xBroadcaster.addEventListener(this);
245         }
246     }
247 
248     // ____________________
249 
250     /**
251      * Different ways to load any URL from outside (may be by the command line)
252      * into this document view or to save it.
253      */
254     public void load(String sURL)
255     {
256         load(sURL,new com.sun.star.beans.PropertyValue[0]);
257     }
258 
259     // ____________________
260 
261     public void load(String sURL, com.sun.star.beans.PropertyValue[] lArguments)
262     {
263         com.sun.star.lang.XComponent xDocument = FunctionHelper.loadDocument(mxFrame,sURL,lArguments);
264         if(xDocument!=null)
265         {
266             mbtSave.setEnabled  (true);
267             mbtExport.setEnabled(true);
268         }
269         else
270         {
271             mbtSave.setEnabled  (false);
272             mbtExport.setEnabled(false);
273         }
274     }
275 
276     // ____________________
277 
278     public void save()
279     {
280         com.sun.star.frame.XController xController = mxFrame.getController();
281         if (xController==null)
282             return;
283         com.sun.star.frame.XModel xDocument = xController.getModel();
284         if (xDocument==null)
285             return;
286         FunctionHelper.saveDocument(xDocument);
287     }
288 
289     // ____________________
290 
291     public void exportHTML(String sURL)
292     {
293         com.sun.star.frame.XController xController = mxFrame.getController();
294         if (xController==null)
295             return;
296         com.sun.star.frame.XModel xDocument = xController.getModel();
297         if (xDocument==null)
298             return;
299         FunctionHelper.saveAsHTML(xDocument,sURL);
300     }
301 
302     // ____________________
303 
304     /**
305      * Overridden so we can react for window closing of this view.
306      */
307     protected void processWindowEvent(WindowEvent aEvent)
308     {
309         if (aEvent.getID()!=WindowEvent.WINDOW_CLOSING)
310         {
311             super.processWindowEvent(aEvent);
312         }
313         else
314         if (FunctionHelper.closeFrame(mxFrame))
315         {
316             mxFrame = null;
317             shutdown();
318             super.processWindowEvent(aEvent);
319         }
320     }
321 
322     // ____________________
323 
324     /**
325      * Here we can react for System.exit() normaly.
326      * But we use it for disposing() or windowClosing() too.
327      */
328     public void shutdown()
329     {
330         if (mbDead)
331             return;
332         mbDead=true;
333 
334         // force these sub view to release her remote
335         // refrences too!
336         maStatusView.shutdown();
337         maCustomizeView.shutdown();
338 
339         maStatusView    = null;
340         maCustomizeView = null;
341 
342         // disable all interceptions
343         maInterceptor.shutdown();
344         maInterceptor = null;
345 
346         // close the frame and his document
347         // Relaesing of our listener connections for disposing()
348         // will be forced automaticly then. Because the frame
349         // will call us back ...
350         if (mxFrame!=null)
351             FunctionHelper.closeFrame(mxFrame);
352 
353         // deregister this view in the global container
354         // Normaly we should die afterwards by garbage collection ...
355         // In cease this was the last view - it force a system.exit().
356         // But then we are no longer a member of the global container
357         // of possible shutdown listener ... and this method should be
358         // called again.
359         ViewContainer.getGlobalContainer().removeView(this);
360     }
361 
362     // ____________________
363 
364     /**
365      * callback from our internal saved frame
366      * which wish to die. Its not neccessary to remove listener connections
367      * here. Because the broadcaster do it automaticly.
368      * We have to release all references to him only.
369      *
370      * @param aSource
371      *          describe the broadcaster of this event
372      *          Must be our internal saved frame.
373      */
374     public void disposing(com.sun.star.lang.EventObject aSource)
375     {
376         mxFrame = null;
377     }
378 
379     // ____________________
380 
381     /**
382      * This inner class is used to react for events of our own UI controls.
383      * So we can start different actions then.
384      */
385     private class Reactor implements ActionListener
386     {
387         // ____________________
388 
389         /**
390         * This method react for pressed buttons or selected check boxes.
391         */
392         public void actionPerformed(ActionEvent aEvent)
393         {
394             String sCommand = aEvent.getActionCommand();
395             //-----------------------------
396             // open any file from disk
397             if( sCommand.compareTo(COMMAND_OPEN) == 0 )
398             {
399                 String sURL = FunctionHelper.askUserForFileURL(DocumentView.this,true);
400                 if(sURL!=null)
401                     DocumentView.this.load(sURL);
402             }
403             else
404             //-----------------------------
405             // save current document
406             if( sCommand.compareTo(COMMAND_SAVE) == 0 )
407             {
408                 DocumentView.this.save();
409             }
410             else
411             //-----------------------------
412             // export current document to html
413             if( sCommand.compareTo(COMMAND_EXPORT) == 0 )
414             {
415                 String sURL = FunctionHelper.askUserForFileURL(DocumentView.this,false);
416                 if(sURL!=null)
417                     DocumentView.this.exportHTML(sURL);
418             }
419             else
420             //-----------------------------
421             // exit application
422             if( sCommand.compareTo(COMMAND_EXIT) == 0 )
423             {
424                 // This will force deleting of this and
425                 // all other currently opened views automaticly!
426                 System.exit(0);
427             }
428         }
429     }
430 }
431