summaryrefslogtreecommitdiff
path: root/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/DocumentView.java
blob: 639dfe2042e64bfc6a80dbd1dfba29849506619e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  the BSD license.
 *
 *  Copyright 2000, 2010 Oracle and/or its affiliates.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *************************************************************************/

// __________ Imports __________

import com.sun.star.uno.UnoRuntime;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.AWTEvent;
import java.awt.event.WindowEvent;

// __________ Implementation __________

/**
 * This implement a java frame which contains
 * an office document, shows some status information
 * about that, provides simple functionality on it
 * (e.g. toggle menubar, save document) and
 * react for different situations independent
 * (e.g. closing the document from outside).
 * Every instance of this class will be a member
 * inside the global "ViewContainer" of this java
 * demo application which holds all opened views alive.
 *
 */
public class DocumentView extends    JFrame
                          implements com.sun.star.lang.XEventListener, // react for Frame::disposing()
                                     IShutdownListener                 // react for System.exit()
{


    /**
     * const
     * These command strings are used to identify a received action
     * of buttons on which we listen for action events.
     */
    private static final String COMMAND_OPEN   = "open"   ;
    private static final String COMMAND_SAVE   = "save"   ;
    private static final String COMMAND_EXPORT = "export" ;
    private static final String COMMAND_EXIT   = "exit"   ;



    /**
     * @member  mxFrame             office frame which contains the document of this view
     *
     * @member  maStatusView        special panel which shows available status information of currently loaded document
     * @member  maDocumentView      use JNI mechanism to plug an office window into our own java UI container (used for inplace mode only!)
     * @member  maCustomizeView     special panel makes it possible to toggle menubar/toolbar or objectbar of loaded document
     * @member  maInterceptor       interceptor thread which intercept "new" menu of office frame to open new frames inside this java application
     *
     * @member  msName              unique name of this view (returned by the global ViewContainer during registration)
     *
     * @member  mbOpen              button to open documents
     * @member  mbSave              button to save currently loaded document
     * @member  mbExport            button to save currently loaded document in HTML format (if it is possible!)
     * @member  mbExit              button to exit this demo
     *
     * @member  maInterception      we try to intercept the file->new menu to open new document inside this java application
     */
    private com.sun.star.frame.XFrame       mxFrame             ;

    private StatusView                      maStatusView        ;
    private NativeView                      maDocumentView      ;
    private CustomizeView                   maCustomizeView     ;
    private Interceptor                     maInterceptor       ;

    private final String                    msName;

    private final JButton                   mbtSave;
    private final JButton                   mbtExport;

    private boolean                         mbDead              ;



    /**
     * ctor
     * Create view controls on startup and initialize it with default values.
     */
    DocumentView()
    {
        this.setSize( new Dimension(800,600) );

        JPanel paMainPanel = (JPanel)this.getContentPane();

        // create and add command buttons to a panel
        // it will be a sub panel of later layouted UI
        JButton mbtOpen   = new JButton("Open ..."        );
        mbtSave   = new JButton("Save"            );
        mbtExport = new JButton("Save as HTML ...");
        JButton mbtExit   = new JButton("Exit"            );

        mbtOpen.setEnabled  (true );
        mbtSave.setEnabled  (false);
        mbtExport.setEnabled(false);
        mbtExit.setEnabled  (true );

        mbtOpen.setActionCommand  (COMMAND_OPEN  );
        mbtSave.setActionCommand  (COMMAND_SAVE  );
        mbtExport.setActionCommand(COMMAND_EXPORT);
        mbtExit.setActionCommand  (COMMAND_EXIT  );

        Reactor aListener = new Reactor();
        mbtOpen.addActionListener  (aListener);
        mbtSave.addActionListener  (aListener);
        mbtExport.addActionListener(aListener);
        mbtExit.addActionListener  (aListener);

        JPanel paCommands = new JPanel( new GridLayout(4,0) );
        paCommands.add(mbtOpen);
        paCommands.add(mbtSave);
        paCommands.add(mbtExport);
        paCommands.add(mbtExit);

        // create view to show status information of opened file
        maStatusView = new StatusView();

        // create view for toggle different bar's of document
        maCustomizeView = new CustomizeView();

        paCommands.setBorder     ( new TitledBorder(BorderFactory.createEtchedBorder(),"Commands")                );
        maStatusView.setBorder   ( new TitledBorder(BorderFactory.createEtchedBorder(),"Status Information")      );
        maCustomizeView.setBorder( new TitledBorder(BorderFactory.createEtchedBorder(),"Customize Document View") );

        // layout the whole UI
        JPanel paTest = new JPanel(new GridLayout(3,0));
        paTest.add(paCommands     );
        paTest.add(maStatusView   );
        paTest.add(maCustomizeView);
        JScrollPane paScroll = new JScrollPane();
        paScroll.getViewport().add(paTest,null);

        if(ViewContainer.mbInplace)
        {
            // create view to show opened documents
            // This special view is necessary for inplace mode only!
            maDocumentView = new NativeView();

            JSplitPane paSplit = new JSplitPane();
            paSplit.setOneTouchExpandable( true );

            paSplit.setLeftComponent (maDocumentView);
            paSplit.setRightComponent(paScroll      );

            paMainPanel.add(paSplit);
        }
        else
        {
            paMainPanel.add(paScroll);
        }

        // Register this new view on our global view container.
        msName = FunctionHelper.getUniqueFrameName();
        this.setTitle(msName);
        ViewContainer.getGlobalContainer().addView(this);
        ViewContainer.getGlobalContainer().addListener(this);
        // be listener for closing the application
        this.enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    }



    /**
     * Create the view frame for showing the office documents on demand.
     * Dependend from given command line parameter we create
     * an office XFrame and initialize it with a window. This
     * window can be a pure toolkit window (means toolkit of office!)
     * or a plugged java canvas - office window combination.
     */
    public void createFrame()
    {
        // create view frame (as a XFrame!) here
        // Look for right view mode setted by user command line parameter.
        // First try to get a new unambigous frame name from our global ViewContainer.
        if(ViewContainer.mbInplace)
        {
            // inplace document view can't be initialized without a visible parent window hierarchy!
            // So make sure that we are visible in every case!
            this.setVisible(true);
            mxFrame = FunctionHelper.createViewFrame(msName,maDocumentView);
        }
        else
            mxFrame = FunctionHelper.createViewFrame(msName,null);

        if(mxFrame!=null)
        {
            // start interception
            maInterceptor = new Interceptor(mxFrame);
            maInterceptor.startListening();

            // start listening for status events and actualization
            // of our status view
            // (of course for our CustomizeView too)
            maStatusView.setFrame   (mxFrame);
            maCustomizeView.setFrame(mxFrame);

            // be listener for closing the remote target view frame
            com.sun.star.lang.XComponent xBroadcaster = UnoRuntime.queryInterface(
                com.sun.star.lang.XComponent.class,
                mxFrame);

            if(xBroadcaster!=null)
                xBroadcaster.addEventListener(this);
        }
    }



    /**
     * Different ways to load any URL from outside (may be by the command line)
     * into this document view or to save it.
     */
    public void load(String sURL)
    {
        load(sURL,new com.sun.star.beans.PropertyValue[0]);
    }



    public void load(String sURL, com.sun.star.beans.PropertyValue[] lArguments)
    {
        com.sun.star.lang.XComponent xDocument = FunctionHelper.loadDocument(mxFrame,sURL,lArguments);
        if(xDocument!=null)
        {
            mbtSave.setEnabled  (true);
            mbtExport.setEnabled(true);
        }
        else
        {
            mbtSave.setEnabled  (false);
            mbtExport.setEnabled(false);
        }
    }



    private void save()
    {
        com.sun.star.frame.XController xController = mxFrame.getController();
        if (xController==null)
            return;
        com.sun.star.frame.XModel xDocument = xController.getModel();
        if (xDocument==null)
            return;
        FunctionHelper.saveDocument(xDocument);
    }



    private void exportHTML(String sURL)
    {
        com.sun.star.frame.XController xController = mxFrame.getController();
        if (xController==null)
            return;
        com.sun.star.frame.XModel xDocument = xController.getModel();
        if (xDocument==null)
            return;
        FunctionHelper.saveAsHTML(xDocument,sURL);
    }



    /**
     * Overridden so we can react for window closing of this view.
     */
    @Override
    protected void processWindowEvent(WindowEvent aEvent)
    {
        if (aEvent.getID()!=WindowEvent.WINDOW_CLOSING)
        {
            super.processWindowEvent(aEvent);
        }
        else
        if (FunctionHelper.closeFrame(mxFrame))
        {
            mxFrame = null;
            shutdown();
            super.processWindowEvent(aEvent);
        }
    }



    /**
     * Here we can react for System.exit() normally.
     * But we use it for disposing() or windowClosing() too.
     */
    public void shutdown()
    {
        if (mbDead)
            return;
        mbDead=true;

        // force these sub view to release her remote
        // references too!
        maStatusView.shutdown();
        maCustomizeView.shutdown();

        maStatusView    = null;
        maCustomizeView = null;

        // disable all interceptions
        maInterceptor.shutdown();
        maInterceptor = null;

        // close the frame and his document
        // Relaesing of our listener connections for disposing()
        // will be forced automatically then. Because the frame
        // will call us back ...
        if (mxFrame!=null)
            FunctionHelper.closeFrame(mxFrame);

        // deregister this view in the global container
        // Normally we should die afterwards by garbage collection ...
        // In cease this was the last view - it force a system.exit().
        // But then we are no longer a member of the global container
        // of possible shutdown listener ... and this method should be
        // called again.
        ViewContainer.getGlobalContainer().removeView(this);
    }



    /**
     * callback from our internal saved frame
     * which wish to die. Its not necessary to remove listener connections
     * here. Because the broadcaster do it automatically.
     * We have to release all references to him only.
     *
     * @param aSource
     *          describe the broadcaster of this event
     *          Must be our internal saved frame.
     */
    public void disposing(com.sun.star.lang.EventObject aSource)
    {
        mxFrame = null;
    }



    /**
     * This inner class is used to react for events of our own UI controls.
     * So we can start different actions then.
     */
    private class Reactor implements ActionListener
    {


        /**
        * This method react for pressed buttons or selected check boxes.
        */
        public void actionPerformed(ActionEvent aEvent)
        {
            String sCommand = aEvent.getActionCommand();

            // open any file from disk
            if( sCommand.equals(COMMAND_OPEN) )
            {
                String sURL = FunctionHelper.askUserForFileURL(DocumentView.this,true);
                if(sURL!=null)
                    DocumentView.this.load(sURL);
            }
            else

            // save current document
            if( sCommand.equals(COMMAND_SAVE) )
            {
                DocumentView.this.save();
            }
            else

            // export current document to html
            if( sCommand.equals(COMMAND_EXPORT))
            {
                String sURL = FunctionHelper.askUserForFileURL(DocumentView.this,false);
                if(sURL!=null)
                    DocumentView.this.exportHTML(sURL);
            }
            else

            // exit application
            if( sCommand.equals(COMMAND_EXIT) )
            {
                // This will force deleting of this and
                // all other currently opened views automatically!
                System.exit(0);
            }
        }
    }
}