428 lines
15 KiB
Java
428 lines
15 KiB
Java
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* 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.
|
|
* Depending on 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 set by user command line parameter.
|
|
// First try to get a new unambiguous 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
|
|
// Releasing 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 wishes to die. It's 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|