/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // __________ Imports __________ import com.sun.star.uno.UnoRuntime; import java.awt.*; import java.awt.event.*; import java.lang.*; import java.net.*; 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 informations * 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. * * @author Andreas Schlüns * @created 06.03.2002 09:38 */ 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. */ public static final String COMMAND_OPEN = "open" ; public static final String COMMAND_SAVE = "save" ; public static final String COMMAND_EXPORT = "export" ; public static final String COMMAND_EXIT = "exit" ; // ____________________ /** * @member mxFrame office frame which contains the document of this view * * @member maStatusView special panel which show available status informations 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 String msName ; private JButton mbtOpen ; private JButton mbtSave ; private JButton mbtExport ; private JButton mbtExit ; 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 mbtOpen = new JButton("Open ..." ); mbtSave = new JButton("Save" ); mbtExport = new JButton("Save as HTML ..."); 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 informations 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 Informations") ); 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==true) { // 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. * Dependent 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 set by user command line parameter. // First try to get a new unambiguous frame name from our global ViewContainer. if(ViewContainer.mbInplace==true) { // 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 = (com.sun.star.lang.XComponent)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); } } // ____________________ public 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); } // ____________________ public 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. */ 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 case this was the last view - it forces 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.compareTo(COMMAND_OPEN) == 0 ) { String sURL = FunctionHelper.askUserForFileURL(DocumentView.this,true); if(sURL!=null) DocumentView.this.load(sURL); } else //----------------------------- // save current document if( sCommand.compareTo(COMMAND_SAVE) == 0 ) { DocumentView.this.save(); } else //----------------------------- // export current document to html if( sCommand.compareTo(COMMAND_EXPORT) == 0 ) { String sURL = FunctionHelper.askUserForFileURL(DocumentView.this,false); if(sURL!=null) DocumentView.this.exportHTML(sURL); } else //----------------------------- // exit application if( sCommand.compareTo(COMMAND_EXIT) == 0 ) { // This will force deleting of this and // all other currently opened views automatically! System.exit(0); } } } }