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