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