summaryrefslogtreecommitdiffstats
path: root/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment')
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java285
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Desk.java93
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/DocumentView.java428
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java939
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IOnewayLink.java71
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IShutdownListener.java48
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Install.txt10
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java655
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/JavaWindowPeerFake.java109
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Makefile131
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/NativeView.java186
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OfficeConnect.java127
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OnewayExecutor.java189
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java469
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusView.java264
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/ViewContainer.java260
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/Makefile72
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.c112
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.h64
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/Makefile77
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.c181
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.def3
-rw-r--r--odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.h64
23 files changed, 4837 insertions, 0 deletions
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java
new file mode 100644
index 0000000000..f194295854
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/CustomizeView.java
@@ -0,0 +1,285 @@
+/* -*- 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.
+ *
+ *************************************************************************/
+
+import java.awt.*;
+import javax.swing.*;
+import java.awt.event.*;
+
+/**
+ * Makes it possible to change some states of currently loaded
+ * document (e.g. enable/disable menubar, toolbar, objectbar)
+ *
+ */
+public class CustomizeView extends JPanel
+ implements IShutdownListener
+{
+ /**
+ * These const URL's describe feature for toggling some properties of loaded document.
+ * Dispatch it with the corresponding parameter to the frame.
+ */
+ private static final String FEATUREURL_MENUBAR = "slot:6661" ;
+ private static final String FEATUREURL_TOOLBAR = "slot:5909" ;
+ private static final String FEATUREURL_OBJECTBAR = "slot:5905" ;
+
+ private static final String FEATUREPROP_MENUBAR = "MenuBarVisible" ;
+ private static final String FEATUREPROP_TOOLBAR = "ToolBarVisible" ;
+ private static final String FEATUREPROP_OBJECTBAR = "ObjectBarVisible" ;
+
+ private static final String ACTION_MENUBAR = "toggle_menu" ;
+ private static final String ACTION_TOOLBAR = "toggle_toolbar" ;
+ private static final String ACTION_OBJECTBAR = "toggle_objectbar" ;
+
+ private static final String MENUBAR_ON = "menubar on" ;
+ private static final String TOOLBAR_ON = "toolbar on" ;
+ private static final String OBJECTBAR_ON = "objectbar on" ;
+
+ private static final String MENUBAR_OFF = "menubar off" ;
+ private static final String TOOLBAR_OFF = "toolbar off" ;
+ private static final String OBJECTBAR_OFF = "objectbar off" ;
+
+
+ // member
+
+ /**
+ * @member m_cbMenuBar reference to checkbox for toggling menubar
+ * @member m_cbToolBar reference to checkbox for toggling toolbar
+ * @member m_cbObjectBar reference to checkbox for toggling objectbar
+ *
+ * @member m_aMenuBarListener listener for status events of the menu bar
+ * @member m_aToolBarListener listener for status events of the tool bar
+ * @member m_aObjectBarListener listener for status events of the object bar
+ */
+ private final JCheckBox m_cbMenuBar ;
+ private final JCheckBox m_cbToolBar ;
+ private final JCheckBox m_cbObjectBar ;
+
+ private StatusListener m_aMenuBarListener ;
+ private StatusListener m_aToolBarListener ;
+ private StatusListener m_aObjectBarListener;
+
+
+
+ /**
+ * ctor
+ * Create view controls on startup and initialize it.
+ * We don't start listening here. see setFrame()!
+ */
+ CustomizeView()
+ {
+ this.setLayout(new GridLayout(3,0));
+
+ m_cbMenuBar = new JCheckBox(MENUBAR_OFF , false);
+ m_cbToolBar = new JCheckBox(TOOLBAR_OFF , false);
+ m_cbObjectBar = new JCheckBox(OBJECTBAR_OFF, false);
+
+ m_cbMenuBar.setEnabled (false);
+ m_cbToolBar.setEnabled (false);
+ m_cbObjectBar.setEnabled(false);
+
+ m_cbMenuBar.setActionCommand (ACTION_MENUBAR );
+ m_cbToolBar.setActionCommand (ACTION_TOOLBAR );
+ m_cbObjectBar.setActionCommand(ACTION_OBJECTBAR);
+
+ this.add(m_cbMenuBar );
+ this.add(m_cbToolBar );
+ this.add(m_cbObjectBar);
+ }
+
+
+
+ /**
+ * set new frame for this view
+ * We start listening for frame action/status and click events instandly.
+ * If an event occurs, we use it to synchronize our controls
+ * with states of a (maybe) new document view of this frame.
+ *
+ * @param xFrame
+ * the reference to the frame, which provides the
+ * possibility to get the required status information
+ *
+ * Attention: We don't accept new frames here.
+ * We get one after startup and work with it.
+ * That's it!
+ */
+ public void setFrame(com.sun.star.frame.XFrame xFrame)
+ {
+ if (xFrame==null)
+ return;
+
+ // be listener for click events
+ // They will toggle the UI controls.
+ ClickListener aMenuBarHandler = new ClickListener(FEATUREURL_MENUBAR ,FEATUREPROP_MENUBAR ,xFrame);
+ ClickListener aToolBarHandler = new ClickListener(FEATUREURL_TOOLBAR ,FEATUREPROP_TOOLBAR ,xFrame);
+ ClickListener aObjectBarHandler = new ClickListener(FEATUREURL_OBJECTBAR,FEATUREPROP_OBJECTBAR,xFrame);
+
+ m_cbMenuBar.addActionListener (aMenuBarHandler );
+ m_cbToolBar.addActionListener (aToolBarHandler );
+ m_cbObjectBar.addActionListener(aObjectBarHandler);
+
+ // be frame action listener
+ // The callback will update listener connections
+ // for status updates automatically!
+ m_aMenuBarListener = new StatusListener(m_cbMenuBar ,MENUBAR_ON ,MENUBAR_OFF ,xFrame, FEATUREURL_MENUBAR );
+ m_aToolBarListener = new StatusListener(m_cbToolBar ,TOOLBAR_ON ,TOOLBAR_OFF ,xFrame, FEATUREURL_TOOLBAR );
+ m_aObjectBarListener = new StatusListener(m_cbObjectBar,OBJECTBAR_ON,OBJECTBAR_OFF,xFrame, FEATUREURL_OBJECTBAR);
+
+ m_aMenuBarListener.startListening();
+ m_aToolBarListener.startListening();
+ m_aObjectBarListener.startListening();
+ }
+
+
+
+ /*
+ * react for click events of the used check boxes
+ * We use our internal set dispatch objects to
+ * call it. This calls toggle the menu/object- or toolbar.
+ * Note: Because we are listener status events too - hopefully
+ * we get a notification, if toggling was successfully or not.
+ * We use this information to update our check boxes again.
+ * But such update doesn't force (hopefully) an action event. Otherwise
+ * we can produce a never ending recursion!
+ */
+ private class ClickListener implements ActionListener,
+ com.sun.star.lang.XEventListener
+ {
+ /// URL, to toggle the requested UI item
+ private final String m_sURL;
+ /// name of the property which must be used in combination with the URL
+ private final String m_sProp;
+ /// we must use this frame to dispatch a request
+ private com.sun.star.frame.XFrame m_xFrame;
+
+
+
+ /**
+ * ctor
+ * It initialize an instance of this class only.
+ */
+ private ClickListener( String sURL ,
+ String sProp ,
+ com.sun.star.frame.XFrame xFrame )
+ {
+ m_sURL = sURL ;
+ m_sProp = sProp ;
+ m_xFrame = xFrame;
+ }
+
+
+
+ /**
+ * callback for action events
+ * Such events occur, if someone clicked the
+ * JCheckBox control, on which we are registered.
+ * Such events do not occur, if we set it programmatically
+ * (e.g. if we get status events to -> see class StatusListener too)
+ *
+ * @param aEvent
+ * describes the check box and its state
+ * we can use to toggle the requested office
+ * resource.
+ */
+ public void actionPerformed(ActionEvent aEvent)
+ {
+ synchronized(this)
+ {
+ if (m_xFrame==null)
+ return;
+ }
+
+ // define parameters for following dispatch
+ boolean bState = ((JCheckBox)aEvent.getSource()).isSelected();
+
+ // prepare the dispatch
+ com.sun.star.util.URL aURL = FunctionHelper.parseURL(m_sURL);
+ if (aURL==null)
+ return;
+
+ com.sun.star.beans.PropertyValue[] lProperties = new com.sun.star.beans.PropertyValue[1];
+ lProperties[0] = new com.sun.star.beans.PropertyValue();
+ lProperties[0].Name = m_sProp;
+ lProperties[0].Value = Boolean.valueOf(bState);
+
+ // execute (dispatch) it into the frame
+ if (m_xFrame==null)
+ return;
+ FunctionHelper.execute(m_xFrame,aURL,lProperties,null);
+ }
+
+
+
+ /**
+ * callback for disposing events
+ * Internally we save a reference to an office frame.
+ * Of course he can die and inform us then. We should react
+ * and forget his reference.
+ *
+ * @param aEvent
+ * describes the source which fire this event
+ * Must be our internal saved frame. Otherwise
+ * somewhere know us without a registration ...
+ */
+ public void disposing(com.sun.star.lang.EventObject aEvent)
+ {
+ synchronized(this)
+ {
+ m_xFrame = null;
+ }
+ }
+ }
+
+
+
+ /**
+ * If this java application shutdown - we must cancel all current existing
+ * listener connections. Otherwise the office will run into some
+ * DisposedExceptions if it tries to use these forgotten listener references.
+ * And of course it can die doing that.
+ * We are registered at a central object to be informed if the VM will exit.
+ * So we can react.
+ */
+ public void shutdown()
+ {
+ m_aMenuBarListener.shutdown();
+ m_aToolBarListener.shutdown();
+ m_aObjectBarListener.shutdown();
+
+ m_aMenuBarListener = null;
+ m_aToolBarListener = null;
+ m_aObjectBarListener = null;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Desk.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Desk.java
new file mode 100644
index 0000000000..7ce2682fe9
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Desk.java
@@ -0,0 +1,93 @@
+/* -*- 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 __________
+
+// __________ Implementation __________
+
+/**
+ * TODO
+ *
+ */
+public class Desk
+{
+
+
+ /**
+ * main
+ * Establish connection to a remote office and starts the demo application.
+ * User can overwrite some of necessary start options by using command line parameters.
+ *
+ * syntax: Desk [mode={inplace|outplace}] [file=<filename>]
+ *
+ * @param lArguments command line arguments
+ * mode describe using mode of document view {inplace/outplace}
+ * default=inplace
+ * file name of first file which should be open
+ * default="private:factory/swriter" to open empty writer document
+ */
+ public static void main(String[] lArguments)
+ {
+ // Analyze command line parameters.
+ String sMode = "inplace";
+ String sFile = "private:factory/swriter";
+
+ for(int i=0; i<lArguments.length; ++i)
+ {
+ lArguments[i] = lArguments[i].toLowerCase();
+ if(lArguments[i].startsWith("mode="))
+ sMode = lArguments[i].substring(5);
+ else
+ if(lArguments[i].startsWith("file="))
+ sFile = lArguments[i].substring(5);
+ }
+
+ ViewContainer.mbInplace = sMode.equals("inplace");
+
+ // Connect to remote office.
+ OfficeConnect.createConnection();
+
+ // Create first document view.
+ // This one will register himself at the global
+ // ViewContainer. Further views will be open
+ // automatically started from this first one.
+ DocumentView aView = new DocumentView();
+ aView.setVisible(true);
+ aView.createFrame();
+ aView.load(sFile);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/DocumentView.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/DocumentView.java
new file mode 100644
index 0000000000..57ac4e7795
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/DocumentView.java
@@ -0,0 +1,428 @@
+/* -*- 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: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java
new file mode 100644
index 0000000000..fa24cde96e
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/FunctionHelper.java
@@ -0,0 +1,939 @@
+/* -*- 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 com.sun.star.uno.AnyConverter;
+
+import java.awt.*;
+import javax.swing.*;
+import java.io.*;
+import java.net.*;
+
+// __________ Implementation __________
+
+/**
+ * Is a collection of basic features.
+ * This helper shows different functionality of framework api
+ * in an example manner. You can use the follow ones:
+ * (1) parse URL's
+ * (2) create frames (inside/outside a java application)
+ * (3) dispatches (with[out] notifications)
+ * (4) loading/saving documents
+ * (5) convert documents to HTML (if possible)
+ * (6) close documents (and her frames) correctly
+ *
+ * There exist some other helper functionality too, which
+ * doesn't use or demonstrate the office api:
+ * (a) getting file names by using a file chosser
+ */
+public class FunctionHelper
+{
+
+
+ /**
+ * This convert a URL (formatted as a string) to a struct com.sun.star.util.URL.
+ * It use a special service to do that: the URLTransformer.
+ * Because some API calls need it and it's not allowed to set "Complete"
+ * part of the util struct only. The URL must be parsed.
+ *
+ * @param sURL
+ * URL for parsing in string notation
+ *
+ * @return [com.sun.star.util.URL]
+ * URL in UNO struct notation
+ */
+ public static com.sun.star.util.URL parseURL(String sURL)
+ {
+ com.sun.star.util.URL aURL = null;
+
+ if (sURL==null || sURL.equals(""))
+ {
+ System.out.println("wrong using of URL parser");
+ return null;
+ }
+
+ try
+ {
+ com.sun.star.uno.XComponentContext xOfficeCtx =
+ OfficeConnect.getOfficeContext();
+
+ // Create special service for parsing of given URL.
+ com.sun.star.util.XURLTransformer xParser =
+ UnoRuntime.queryInterface(
+ com.sun.star.util.XURLTransformer.class,
+ xOfficeCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.util.URLTransformer", xOfficeCtx));
+
+ // Because it's an in/out parameter we must use an array of URL objects.
+ com.sun.star.util.URL[] aParseURL = new com.sun.star.util.URL[1];
+ aParseURL[0] = new com.sun.star.util.URL();
+ aParseURL[0].Complete = sURL;
+
+ // Parse the URL
+ xParser.parseStrict(aParseURL);
+
+ aURL = aParseURL[0];
+ }
+ catch(com.sun.star.uno.RuntimeException exRuntime)
+ {
+ // Any UNO method of this scope can throw this exception.
+ // Reset the return value only.
+ }
+ catch(com.sun.star.uno.Exception exUno)
+ {
+ // "createInstance()" method of used service manager can throw it.
+ // Then it wasn't possible to get the URL transformer.
+ // Return default instead of really parsed URL.
+ }
+
+ return aURL;
+ }
+
+
+
+ /**
+ * create a new empty target frame
+ * Attention: Currently we must use special service com.sun.star.frame.Task instead of Frame.
+ * Because desktop environment accept this special frame type only as direct children.
+ * Note - This service will be deprecated and must be replaces by com.sun.star.frame.Frame in
+ * further versions. To feature prove we use both service names. If for new versions
+ * the deprecated one not exist we get an empty frame, we can try to use the new service.
+ *
+ * @param xSMGR
+ * we need the remote service manager to create this task/frame service
+ *
+ * @return [com.sun.star.frame.XFrame]
+ * the new created frame reference in case of success or null otherwise
+ */
+ private static com.sun.star.frame.XFrame impl_createEmptyFrame(
+ com.sun.star.uno.XComponentContext xCtx )
+ {
+ com.sun.star.frame.XFrame xFrame = null;
+
+ try{
+ xFrame = UnoRuntime.queryInterface(
+ com.sun.star.frame.XFrame.class,
+ xCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.frame.Task", xCtx));
+ } catch(com.sun.star.uno.Exception ex1) {}
+
+ if (xFrame==null)
+ {
+ try{
+ xFrame = UnoRuntime.queryInterface(
+ com.sun.star.frame.XFrame.class,
+ xCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.frame.Frame", xCtx));
+ } catch(com.sun.star.uno.Exception ex2) {}
+ }
+
+ return xFrame;
+ }
+
+
+
+ /**
+ * create a new window which can be used as container window of an office frame
+ * We know two modes for creation:
+ * - the office window will be a child of one of our java windows
+ * - the office will be a normal system window outside this java application
+ * This behaviour will be regulated by the second parameter of this operation.
+ * If a parentview is given the first mode will be activated - otherwise
+ * the second one.
+ *
+ * Note: First mode (creation of a child window) can be reached by two different
+ * ways.
+ * - pack the required window handle of our java window inside a UNO object
+ * to transport it to the remote office toolkit and get a child office
+ * window.
+ * This is the old way. It's better to use the second one - but to be
+ * future prove this old one should be tried too.
+ * - it's possible to pass the native window handle directly to the toolkit.
+ * A special interface method was enabled to accept that.
+ *
+ * The right way to create an office window should be then:
+ * - try to use second creation mode (directly using of the window handle)
+ * - if it failed ... use the old way by packing the handle inside an object
+ *
+ * @param xSMGR
+ * we need a service manager to be able to create remote office
+ * services
+ *
+ * @param aParentView
+ * the java window as parent for the office window if an inplace office
+ * is required. If it is set to null the created office window will be
+ * a normal system window outside of our java application.
+ *
+ * @return [com.sun.star.awt.XWindow]
+ * The new created office window which can be used to set it as
+ * a ContainerWindow on an empty office frame.
+ */
+ private static com.sun.star.awt.XWindow impl_createWindow(
+ com.sun.star.uno.XComponentContext xCtx, NativeView aParentView )
+ {
+ com.sun.star.awt.XWindow xWindow = null;
+ com.sun.star.awt.XWindowPeer xPeer = null;
+ com.sun.star.awt.XToolkit xToolkit = null;
+
+ // get access to toolkit of remote office to create the container window of
+ // new target frame
+ try{
+ xToolkit = UnoRuntime.queryInterface(
+ com.sun.star.awt.XToolkit.class,
+ xCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.awt.Toolkit", xCtx));
+ }
+ catch(com.sun.star.uno.Exception ex)
+ {
+ return null;
+ }
+
+ // mode 1) create an external system window
+ if (aParentView==null)
+ {
+ // Describe the properties of the container window.
+ com.sun.star.awt.WindowDescriptor aDescriptor =
+ new com.sun.star.awt.WindowDescriptor();
+ aDescriptor.Type = com.sun.star.awt.WindowClass.TOP;
+ aDescriptor.WindowServiceName = "window";
+ aDescriptor.ParentIndex = -1;
+ aDescriptor.Parent = null;
+ aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0);
+ aDescriptor.WindowAttributes = com.sun.star.awt.WindowAttribute.BORDER |
+ com.sun.star.awt.WindowAttribute.MOVEABLE |
+ com.sun.star.awt.WindowAttribute.SIZEABLE |
+ com.sun.star.awt.WindowAttribute.CLOSEABLE;
+
+ try{
+ xPeer = xToolkit.createWindow( aDescriptor );
+ } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {}
+ }
+ // mode 2) create an internal office window as child of our given java
+ // parent window
+ else
+ {
+ // try new version of creation first: directly using of the window
+ // handle. The old implementation of the corresponding toolkit method
+ // requires a process ID. If this id isn't the right one a null object
+ // is returned. But normally nobody outside the office knows this id.
+ // New version of this method ignore the id parameter and creation will
+ // work.
+ // Note: You must be sure if your window handle can be really used by
+ // the remote office. Means if this java client and the remote office
+ // use the same display!
+ com.sun.star.awt.XSystemChildFactory xChildFactory =
+ UnoRuntime.queryInterface(
+ com.sun.star.awt.XSystemChildFactory.class, xToolkit);
+
+ try
+ {
+ Integer nHandle = aParentView.getHWND();
+ short nSystem = (short)aParentView.getNativeWindowSystemType();
+ byte[] lProcID = new byte[0];
+
+ xPeer = xChildFactory.createSystemChild(nHandle,
+ lProcID, nSystem);
+
+ if (xPeer==null)
+ {
+ // mode 3) OK - new version doesn't work. It requires the
+ // process id which we don't have.
+ // So we must use the old way to get the right window peer.
+ // Pack the handle inside a wrapper object.
+ JavaWindowPeerFake aWrapper = new
+ JavaWindowPeerFake(aParentView);
+
+ com.sun.star.awt.XWindowPeer xParentPeer =
+ UnoRuntime.queryInterface(
+ com.sun.star.awt.XWindowPeer.class, aWrapper);
+
+ com.sun.star.awt.WindowDescriptor aDescriptor =
+ new com.sun.star.awt.WindowDescriptor();
+ aDescriptor.Type = com.sun.star.awt.WindowClass.TOP;
+ aDescriptor.WindowServiceName = "workwindow";
+ aDescriptor.ParentIndex = 1;
+ aDescriptor.Parent = xParentPeer;
+ aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0);
+ if (nSystem == com.sun.star.lang.SystemDependent.SYSTEM_WIN32)
+ aDescriptor.WindowAttributes =
+ com.sun.star.awt.WindowAttribute.SHOW;
+ else
+ aDescriptor.WindowAttributes =
+ com.sun.star.awt.WindowAttribute.SYSTEMDEPENDENT;
+
+ try{
+ xPeer = xToolkit.createWindow( aDescriptor );
+ } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {}
+ }
+ }
+ catch(java.lang.RuntimeException exJRun)
+ {
+ // This exception is thrown by the native JNI code if it try to get
+ // the systemw window handle. A possible reason can be an invisible
+ // java window. In this case it should be enough to set return
+ // values to null. All other resources (which was created before)
+ // will be freed automatically if scope will be leaved.
+ System.out.println("May be the NativeView object wasn't really visible at calling time of getNativeWindow()?");
+ xPeer = null;
+ xWindow = null;
+ }
+ }
+
+ // It doesn't matter which way was used to get the window peer.
+ // Cast it to the right return interface and return it.
+ xWindow = UnoRuntime.queryInterface(
+ com.sun.star.awt.XWindow.class,
+ xPeer);
+
+ return xWindow;
+ }
+
+
+
+ /**
+ * This method create a new empty child frame on desktop instance of remote office.
+ * It use a special JNI functionality to pass the office XWindow over a java window.
+ * This java window can be inserted into another java window container for complex layouting.
+ * If this parent java window isn't used, a top level system window will be created.
+ * The resulting office frame isn't plugged into this java application.
+ *
+ * @param sName
+ * name to set it on the new created frame
+ *
+ * @param aParentView
+ * java window which should be used as parent window of new created office frame window
+ * May be set to null.
+ *
+ * @return [com.sun.star.frame.XFrame]
+ * reference to the new created frame for success or null if it failed
+ */
+ public static com.sun.star.frame.XFrame createViewFrame(String sName, NativeView aParentView)
+ {
+ com.sun.star.frame.XFrame xFrame = null;
+
+ try
+ {
+ com.sun.star.uno.XComponentContext xCtx =
+ OfficeConnect.getOfficeContext();
+
+ // create an empty office frame first
+ xFrame = impl_createEmptyFrame(xCtx);
+
+ // create an office window then
+ // Depending from the given parameter aParentView it will be a child or a top level
+ // system window. (see impl method for further information)
+ // But before we call this helper - prepare the possible parent window: show it.
+ // JNI calls to get system window handle of java window can't work without that!
+ if (aParentView!=null)
+ aParentView.setVisible(true);
+ com.sun.star.awt.XWindow xWindow = impl_createWindow(xCtx, aParentView);
+
+ // pass the window the frame as his new container window.
+ // It's necessary to do it first - before you call anything else there.
+ // Otherwise the frame throws some exceptions for "uninitialized state".
+ xFrame.initialize( xWindow );
+
+ // Insert the new frame in desktop hierarchy.
+ // Use XFrames interface to do so. It provides access to the child frame container of that instance.
+ com.sun.star.frame.XFramesSupplier xTreeRoot = UnoRuntime.queryInterface(
+ com.sun.star.frame.XFramesSupplier.class,
+ xCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.frame.Desktop", xCtx));
+ com.sun.star.frame.XFrames xChildContainer = xTreeRoot.getFrames();
+ xChildContainer.append(xFrame);
+
+ // Make some further initializations on frame and window.
+ xWindow.setVisible(true);
+ xFrame.setName(sName);
+ }
+ catch(com.sun.star.uno.RuntimeException exRuntime)
+ {
+ // Any UNO method of this scope can throw this exception.
+ // So the frame can be already created and he must be freed
+ // correctly. May be he was inserted into the desktop tree too ...
+ if(xFrame!=null)
+ {
+ // Try to dispose the frame. He should deregister himself at the desktop object
+ // and free all internal used resources (e.g. the container window) automatically.
+ // It's possible to do that here - because frame has no component inside yet.
+ // So nobody can disagree with that.
+ // After the dispose() call forget all references to this frame and let him die.
+ // If a new exception will occur ... no general solution exist then.
+ // Nobody can guarantee if next call will work or not.
+ com.sun.star.lang.XComponent xComponent = UnoRuntime.queryInterface(
+ com.sun.star.lang.XComponent.class,
+ xFrame);
+ xComponent.dispose();
+ xComponent = null;
+ xFrame = null;
+ }
+ }
+ catch(com.sun.star.uno.Exception exUno)
+ {
+ // "createInstance()" method of used service manager can throw it.
+ // If it occurred during creation of desktop service the frame already was created.
+ // Free it by decreasing his refcount. Changes on the desktop tree couldn't exist.
+ // Without the desktop service that wasn't possible. So no further rollbacks must follow.
+ if(xFrame!=null)
+ {
+ com.sun.star.lang.XComponent xComponent = UnoRuntime.queryInterface(
+ com.sun.star.lang.XComponent.class,
+ xFrame);
+ xComponent.dispose();
+ xComponent = null;
+ xFrame = null;
+ }
+ }
+
+ return xFrame;
+ }
+
+
+
+ /**
+ * Dispatch a URL to given frame.
+ * Caller can register himself for following status events for dispatched
+ * URL too. But nobody guarantee that such notifications will occur.
+ * (see dispatchWithNotification() if you interest on that)
+ * The returned dispatch object should be hold alive by caller
+ * till he doesn't need it any longer. Otherwise the dispatcher can(!)
+ * die by decreasing his refcount.
+ *
+ * @param xFrame frame which should be the target of this dispatch
+ * @param aURL full parsed and converted office URL for dispatch
+ * @param lProperties optional arguments for dispatch
+ * @param xListener optional listener which is registered automatically for status events
+ * (Note: Deregistration is part of this listener himself!)
+ *
+ * @return [XDispatch] It's the used dispatch object and can be used for deregistration of an optional listener.
+ * Otherwise caller can ignore it.
+ */
+ public static com.sun.star.frame.XDispatch execute(com.sun.star.frame.XFrame xFrame ,
+ com.sun.star.util.URL aURL ,
+ com.sun.star.beans.PropertyValue[] lProperties,
+ com.sun.star.frame.XStatusListener xListener )
+ {
+ com.sun.star.frame.XDispatch xDispatcher = null;
+
+ try
+ {
+ // Query the frame for right interface which provides access to all available dispatch objects.
+ com.sun.star.frame.XDispatchProvider xProvider = UnoRuntime.queryInterface(
+ com.sun.star.frame.XDispatchProvider.class,
+ xFrame);
+
+ // Ask him for right dispatch object for given URL.
+ // Force given frame as target for following dispatch by using "".
+ // It means the same like "_self".
+ xDispatcher = xProvider.queryDispatch(aURL,"",0);
+
+ // Dispatch the URL into the frame.
+ if(xDispatcher!=null)
+ {
+ if(xListener!=null)
+ xDispatcher.addStatusListener(xListener,aURL);
+
+ xDispatcher.dispatch(aURL,lProperties);
+ }
+ }
+ catch(com.sun.star.uno.RuntimeException exUno)
+ {
+ // Any UNO method of this scope can throw this exception.
+ // But there will be nothing to do then - because
+ // we haven't changed anything inside the remote objects
+ // except method "addStatusListener().
+ // But in this case the source of this exception has to
+ // rollback all his operations. There is no chance to
+ // make anything right then.
+ // Reset the return value to a default - that's it.
+ exUno.printStackTrace();
+ xDispatcher = null;
+ }
+
+ return xDispatcher;
+ }
+
+
+
+
+
+
+
+ /**
+ * Load document specified by a URL into given frame synchronously.
+ * The result of this operation will be the loaded document for success
+ * or null if loading failed.
+ *
+ * @param xFrame frame which should be the target of this load call
+ * @param sURL unparsed URL for loading
+ * @param lProperties optional arguments
+ *
+ * @return [XComponent] the loaded document for success or null if it's failed
+ */
+ public static com.sun.star.lang.XComponent loadDocument(
+ com.sun.star.frame.XFrame xFrame, String sURL,
+ com.sun.star.beans.PropertyValue[] lProperties)
+ {
+ com.sun.star.lang.XComponent xDocument = null;
+ String sOldName = null;
+
+ try
+ {
+ com.sun.star.uno.XComponentContext xCtx =
+ OfficeConnect.getOfficeContext();
+
+ // First prepare frame for loading
+ // We must address it inside the frame tree without any complications.
+ // So we set an unambiguous (we hope it) name and use it later.
+ // Don't forget to reset original name after that.
+ sOldName = xFrame.getName();
+ String sTarget = "odk_officedev_desk";
+ xFrame.setName(sTarget);
+
+ // Get access to the global component loader of the office
+ // for synchronous loading the document.
+ com.sun.star.frame.XComponentLoader xLoader =
+ UnoRuntime.queryInterface(
+ com.sun.star.frame.XComponentLoader.class,
+ xCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.frame.Desktop", xCtx));
+
+ // Load the document into the target frame by using his name and
+ // special search flags.
+ xDocument = xLoader.loadComponentFromURL(
+ sURL,
+ sTarget,
+ com.sun.star.frame.FrameSearchFlag.CHILDREN,
+ lProperties);
+
+ // don't forget to restore old frame name...
+ xFrame.setName(sOldName);
+ }
+ catch(com.sun.star.io.IOException exIO)
+ {
+ // Can be thrown by "loadComponentFromURL()" call.
+ // The only thing we should do then is to reset changed frame name!
+ exIO.printStackTrace();
+ xDocument = null;
+ if(sOldName!=null)
+ xFrame.setName(sOldName);
+ }
+ catch(com.sun.star.lang.IllegalArgumentException exIllegal)
+ {
+ // Can be thrown by "loadComponentFromURL()" call.
+ // The only thing we should do then is to reset changed frame name!
+ exIllegal.printStackTrace();
+ xDocument = null;
+ if(sOldName!=null)
+ xFrame.setName(sOldName);
+ }
+ catch(com.sun.star.uno.RuntimeException exRuntime)
+ {
+ // Any UNO method of this scope can throw this exception.
+ // The only thing we can try(!) is to reset changed frame name.
+ exRuntime.printStackTrace();
+ xDocument = null;
+ if(sOldName!=null)
+ xFrame.setName(sOldName);
+ }
+ catch(com.sun.star.uno.Exception exUno)
+ {
+ // "createInstance()" method of used service manager can throw it.
+ // The only thing we should do then is to reset changed frame name!
+ exUno.printStackTrace();
+ xDocument = null;
+ if(sOldName!=null)
+ xFrame.setName(sOldName);
+ }
+
+ return xDocument;
+ }
+
+
+
+ /**
+ * Save currently loaded document of given frame.
+ *
+ * @param xDocument document for saving changes
+ */
+ public static void saveDocument(com.sun.star.lang.XComponent xDocument)
+ {
+ try
+ {
+ // Check for supported model functionality.
+ // Normally the application documents (text, spreadsheet ...) do so
+ // but some other ones (e.g. db components) doesn't do that.
+ // They can't be save then.
+ com.sun.star.frame.XModel xModel = UnoRuntime.queryInterface(
+ com.sun.star.frame.XModel.class,
+ xDocument);
+ if(xModel!=null)
+ {
+ // Check for modifications => break save process if there is nothing to do.
+ com.sun.star.util.XModifiable xModified = UnoRuntime.queryInterface(
+ com.sun.star.util.XModifiable.class,
+ xModel);
+ if(xModified.isModified())
+ {
+ com.sun.star.frame.XStorable xStore = UnoRuntime.queryInterface(
+ com.sun.star.frame.XStorable.class,
+ xModel);
+
+ xStore.store();
+ }
+ }
+ }
+ catch(com.sun.star.io.IOException exIO)
+ {
+ // Can be thrown by "store()" call.
+ // But there is nothing we can do then.
+ exIO.printStackTrace();
+ }
+ catch(com.sun.star.uno.RuntimeException exUno)
+ {
+ // Any UNO method of this scope can throw this exception.
+ // But there is nothing we can do then.
+ exUno.printStackTrace();
+ }
+ }
+
+
+
+ /**
+ * It try to export given document in HTML format.
+ * Current document will be converted to HTML and moved to new place on disk.
+ * A "new" file will be created by given URL (may be overwritten
+ * if it already exist). Right filter will be used automatically if factory of
+ * this document support it. If no valid filter can be found for export,
+ * nothing will be done here.
+ *
+ * @param xDocument document which should be exported
+ * @param sURL target URL for converted document
+ */
+ public static void saveAsHTML(com.sun.star.lang.XComponent xDocument,
+ String sURL )
+ {
+ try
+ {
+ // First detect factory of this document.
+ // Ask for the supported service name of this document.
+ // If information is available it can be used to find out which
+ // filter exist for HTML export. Normally this filter should be searched
+ // inside the filter configuration but this little demo doesn't do so.
+ // (see service com.sun.star.document.FilterFactory for further
+ // information too)
+ // Well known filter names are used directly. They must exist in current
+ // office installation. Otherwise this code will fail. But to prevent
+ // this code against missing filters it check for existing state of it.
+ com.sun.star.lang.XServiceInfo xInfo = UnoRuntime.queryInterface(com.sun.star.lang.XServiceInfo.class,
+ xDocument);
+
+ if(xInfo!=null)
+ {
+ // Find out possible filter name.
+ String sFilter = null;
+ if(xInfo.supportsService("com.sun.star.text.TextDocument"))
+ sFilter = "HTML (StarWriter)";
+ else
+ if(xInfo.supportsService("com.sun.star.text.WebDocument"))
+ sFilter = "HTML";
+ else
+ if(xInfo.supportsService("com.sun.star.sheet.SpreadsheetDocument"))
+ sFilter = "HTML (StarCalc)";
+
+ // Check for existing state of this filter.
+ if(sFilter!=null)
+ {
+ com.sun.star.uno.XComponentContext xCtx =
+ OfficeConnect.getOfficeContext();
+
+ com.sun.star.container.XNameAccess xFilterContainer =
+ UnoRuntime.queryInterface(
+ com.sun.star.container.XNameAccess.class,
+ xCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.document.FilterFactory", xCtx));
+
+ if(!xFilterContainer.hasByName(sFilter))
+ sFilter=null;
+ }
+
+ // Use this filter for export.
+ if(sFilter!=null)
+ {
+ // Export can be forced by saving the document and using a
+ // special filter name which can write needed format. Build
+ // necessary argument list now.
+ // Use special flag "Overwrite" too, to prevent operation
+ // against possible exceptions, if file already exist.
+ com.sun.star.beans.PropertyValue[] lProperties =
+ new com.sun.star.beans.PropertyValue[2];
+ lProperties[0] = new com.sun.star.beans.PropertyValue();
+ lProperties[0].Name = "FilterName";
+ lProperties[0].Value = sFilter;
+ lProperties[1] = new com.sun.star.beans.PropertyValue();
+ lProperties[1].Name = "Overwrite";
+ lProperties[1].Value = Boolean.TRUE;
+
+ com.sun.star.frame.XStorable xStore =
+ UnoRuntime.queryInterface(
+ com.sun.star.frame.XStorable.class, xDocument);
+
+ xStore.storeAsURL(sURL,lProperties);
+ }
+ }
+ }
+ catch(com.sun.star.io.IOException exIO)
+ {
+ // Can be thrown by "store()" call.
+ // Do nothing then. Saving failed - that's it.
+ exIO.printStackTrace();
+ }
+ catch(com.sun.star.uno.RuntimeException exRuntime)
+ {
+ // Can be thrown by any uno call.
+ // Do nothing here. Saving failed - that's it.
+ exRuntime.printStackTrace();
+ }
+ catch(com.sun.star.uno.Exception exUno)
+ {
+ // Can be thrown by "createInstance()" call of service manager.
+ // Do nothing here. Saving failed - that's it.
+ exUno.printStackTrace();
+ }
+ }
+
+
+
+
+
+
+
+ /*
+ * Try to close the frame instead of the document.
+ * It shows the possible interface to do so.
+ *
+ * @param xFrame
+ * frame which should be closed
+ *
+ * @return <TRUE/> in case frame could be closed
+ * <FALSE/> otherwise
+ */
+ public static boolean closeFrame(com.sun.star.frame.XFrame xFrame)
+ {
+ boolean bClosed = false;
+
+ try
+ {
+ // first try the new way: use new interface XCloseable
+ // It replace the deprecated XTask::close() and should be preferred ...
+ // if it can be queried.
+ com.sun.star.util.XCloseable xCloseable =
+ UnoRuntime.queryInterface(
+ com.sun.star.util.XCloseable.class, xFrame);
+ if (xCloseable!=null)
+ {
+ // We deliver the ownership of this frame not to the (possible)
+ // source which throw a CloseVetoException. We wish to have it
+ // under our own control.
+ try
+ {
+ xCloseable.close(false);
+ bClosed = true;
+ }
+ catch( com.sun.star.util.CloseVetoException exVeto )
+ {
+ bClosed = false;
+ }
+ }
+ else
+ {
+ // OK: the new way isn't possible. Try the old one.
+ com.sun.star.frame.XTask xTask = UnoRuntime.queryInterface(com.sun.star.frame.XTask.class,
+ xFrame);
+ if (xTask!=null)
+ {
+ // return value doesn't interest here. Because
+ // we forget this task ...
+ bClosed = xTask.close();
+ }
+ }
+ }
+ catch (com.sun.star.lang.DisposedException exDisposed)
+ {
+ // Of course - this task can be already dead - means disposed.
+ // But for us it's not important. Because we tried to close it too.
+ // And "already disposed" or "closed" should be the same ...
+ bClosed = true;
+ }
+
+ return bClosed;
+ }
+
+
+
+ /**
+ * Try to find a unique frame name, which isn't currently used inside
+ * remote office instance. Because we create top level frames
+ * only, it's enough to check the names of existing child frames on the
+ * desktop only.
+ *
+ * should represent a unique frame name, which currently isn't
+ * used inside the remote office frame tree
+ * (Couldn't guaranteed for a real multithreaded environment.
+ * But we try it ...)
+ */
+ private static final String BASEFRAMENAME = "Desk View ";
+
+ public static String getUniqueFrameName()
+ {
+ String sName = null;
+
+ com.sun.star.uno.XComponentContext xCtx = OfficeConnect.getOfficeContext();
+
+ try
+ {
+ com.sun.star.frame.XFramesSupplier xSupplier =
+ UnoRuntime.queryInterface(
+ com.sun.star.frame.XFramesSupplier.class,
+ xCtx.getServiceManager().createInstanceWithContext(
+ "com.sun.star.frame.Desktop", xCtx));
+
+ com.sun.star.container.XIndexAccess xContainer =
+ UnoRuntime.queryInterface(
+ com.sun.star.container.XIndexAccess.class,
+ xSupplier.getFrames());
+
+ int nCount = xContainer.getCount();
+ for (int i=0; i<nCount; ++i )
+ {
+ com.sun.star.frame.XFrame xFrame = (com.sun.star.frame.XFrame)AnyConverter.toObject(new com.sun.star.uno.Type(com.sun.star.frame.XFrame.class), xContainer.getByIndex(i));
+ sName = BASEFRAMENAME+mnViewCount;
+ while(sName.equals(xFrame.getName()))
+ {
+ ++mnViewCount;
+ sName = BASEFRAMENAME+mnViewCount;
+ }
+ }
+ }
+ catch(com.sun.star.uno.Exception exCreateFailed)
+ {
+ sName = BASEFRAMENAME;
+ }
+
+ if (sName==null)
+ {
+ System.out.println("invalid name!");
+ sName = BASEFRAMENAME;
+ }
+
+ return sName;
+ }
+
+
+
+ /**
+ * helper to get a file URL selected by user
+ * This method doesn't show any API concepts...
+ * but is necessary for this demo application.
+ *
+ * @param aParent parent window of this dialog
+ * @param bOpen If it is set to true =>
+ * dialog is opened in "file open" mode -
+ * otherwise in "file save" mode.
+ */
+ public static String askUserForFileURL(Component aParent,boolean bOpen)
+ {
+ String sFileURL = null;
+ int nDecision = JFileChooser.CANCEL_OPTION;
+ JFileChooser aChooser = null;
+
+ // set last visited directory on new file chosser
+ // (if this information is available)
+ if( maLastDir==null )
+ aChooser = new JFileChooser();
+ else
+ aChooser = new JFileChooser(maLastDir);
+
+ // decide between file open/save dialog
+ if( bOpen )
+ nDecision = aChooser.showOpenDialog(aParent);
+ else
+ nDecision = aChooser.showSaveDialog(aParent);
+
+ // react for "OK" result only
+ if(nDecision == JFileChooser.APPROVE_OPTION)
+ {
+ // save current directory as last visited one
+ maLastDir = aChooser.getCurrentDirectory();
+ // get file URL from the dialog
+ try
+ {
+ sFileURL = aChooser.getSelectedFile().toURI().toURL().toExternalForm();
+ }
+ catch( MalformedURLException ex )
+ {
+ ex.printStackTrace();
+ sFileURL = null;
+ }
+ // problem of java: file URL's are coded with 1 slash instead of 3 ones!
+ // => correct this problem first, otherwise office can't use these URL's
+ if(
+ ( sFileURL !=null ) &&
+ ( sFileURL.startsWith("file:/") ) &&
+ ( !sFileURL.startsWith("file://") )
+ )
+ {
+ StringBuffer sWorkBuffer = new StringBuffer(sFileURL);
+ sWorkBuffer.insert(6,"//");
+ sFileURL = sWorkBuffer.toString();
+ }
+ }
+
+ return sFileURL;
+ }
+
+
+
+ /**
+ * @member maLastDir save the last visited directory of used file open/save dialog
+ * @member mnViewCount we try to set unique names on every frame we create (that's why we must count it)
+ */
+ private static File maLastDir = null;
+ private static int mnViewCount = 0 ;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IOnewayLink.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IOnewayLink.java
new file mode 100644
index 0000000000..c6732155d2
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IOnewayLink.java
@@ -0,0 +1,71 @@
+/* -*- 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.
+ *
+ *************************************************************************/
+
+import java.util.ArrayList;
+
+// __________ Implementation __________
+
+/**
+ * We need a generic interface to forward any oneway uno interface method
+ * by using threads to the original object. Reason:
+ * It's not allowed to call synchronous back to the office if a java object
+ * was called in a oneway declared interface method. Then it must be
+ * executed asynchronous. To do so - a thread can be created which use this
+ * interface. It get the object, which has to be called back and the type and
+ * parameter of the original request.
+ *
+ */
+public interface IOnewayLink
+{
+
+
+ /**
+ * @param nRequest
+ * The two user of this callback can define a unique number,
+ * which identify the type of original interface method. So the called
+ * interface object can decide, which action will be necessary.
+ *
+ * @param lParams
+ * If the original method used parameters, they will be coded here in
+ * a generic way. Only the called interface object know (it depends
+ * from the original request - see nRequest too), how this list must
+ * be interpreted.
+ * Note: Atomic types (e.g. int, long) will be transported as objects
+ * too (Integer, Long)!
+ */
+ void execOneway( int nRequest, ArrayList<Object> lParams );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IShutdownListener.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IShutdownListener.java
new file mode 100644
index 0000000000..753d364d03
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/IShutdownListener.java
@@ -0,0 +1,48 @@
+/* -*- 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.
+ *
+ *************************************************************************/
+
+// __________ Implementation __________
+
+/**
+ * Listener interface to get information about application shutdown
+ * if java virtual machine dies.
+ *
+ */
+public interface IShutdownListener
+{
+ void shutdown();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Install.txt b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Install.txt
new file mode 100644
index 0000000000..79a1ee2bfc
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Install.txt
@@ -0,0 +1,10 @@
+(1) goto "./nativelib/<platform>" directory and build it
+(2) build this directory
+(3) expand your class path to include all jar files of an office installation
+ (means all files in path "<officeinst>/program/classes")
+(4) goto "api/<platform>/class"
+(5) copy from an existing java installation the runtime library "jawt" (e.g. jawt.dll for windows)
+ into this directory
+(6) copy "api/<platform>/bin/nativelib.dll" (for windows) to "api/<platform>/class"
+(7) start an office : "soffice --accept=socket,host=localhost,port=2083;urp;"
+(8) goto "api/<platform>/class" and start java applet: "java -jar desktop.jar"
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java
new file mode 100644
index 0000000000..380f8da3cf
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Interceptor.java
@@ -0,0 +1,655 @@
+/* -*- 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 java.util.ArrayList;
+
+import com.sun.star.frame.FrameActionEvent;
+import com.sun.star.uno.UnoRuntime;
+
+// Implementation
+
+/*
+ * This class can be used to intercept dispatched URL's
+ * on any frame used in this demo application.
+ * It intercept all URL's which try to create a new empty frame.
+ * (e.g. "private:factory/swriter")
+ * Nobody can guarantee that this interception will be really used -
+ * because another interceptor (registered at a later time then this one!)
+ * will be called before this one.
+ * Implementation is executed inside a new thread to prevent application
+ * against possible deadlocks. This deadlocks can occur if
+ * synchronous/asynchronous ... normal ones and oneway calls are mixed.
+ * Notifications of listener will be oneway mostly - her reactions can
+ * be synchronous then. => deadlocks are possible
+ */
+public class Interceptor implements com.sun.star.frame.XFrameActionListener,
+ com.sun.star.frame.XDispatchProviderInterceptor,
+ com.sun.star.frame.XDispatch,
+ com.sun.star.frame.XInterceptorInfo,
+ IShutdownListener,
+ IOnewayLink
+{
+
+
+ /**
+ * const
+ * All these URL's are intercepted by this implementation.
+ */
+ private static final String[] INTERCEPTED_URLS = { "private:factory/*" ,
+ ".uno:SaveAs" ,
+ "slot:5300" ,
+ ".uno:Quit" };
+
+
+
+ /*
+ * @member m_xMaster use this interceptor if he doesn't handle queried dispatch request
+ * @member m_xSlave we can forward all unhandled requests to this slave interceptor
+ * @member m_xFrame intercepted frame
+ * @member m_bDead there exist more than one way to finish an object of this class - we must know it sometimes
+ */
+ private com.sun.star.frame.XDispatchProvider m_xMaster ;
+ private com.sun.star.frame.XDispatchProvider m_xSlave ;
+ private com.sun.star.frame.XFrame m_xFrame ;
+ private boolean m_bIsActionListener ;
+ private boolean m_bIsRegistered ;
+ private boolean m_bDead ;
+
+
+
+ /*
+ * ctor
+ * Initialize the new interceptor. Given frame reference can be used to
+ * register this interceptor on it automatically later.
+ *
+ * @seealso startListening()
+ *
+ * @param xFrame
+ * this interceptor will register himself at this frame to intercept dispatched URLs
+ */
+ Interceptor(/*IN*/ com.sun.star.frame.XFrame xFrame)
+ {
+ m_xFrame = xFrame ;
+ m_xSlave = null ;
+ m_xMaster = null ;
+ m_bIsRegistered = false ;
+ m_bIsActionListener = false ;
+ m_bDead = false ;
+ }
+
+
+
+ /*
+ * start working as frame action listener really.
+ * We will be frame action listener here. In case
+ * we get a frame action which indicates, that we should
+ * update our interception. Because such using of an interceptor
+ * isn't guaranteed - in case a newer one was registered...
+ */
+ public void startListening()
+ {
+ com.sun.star.frame.XFrame xFrame = null;
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ if (m_xFrame==null)
+ return;
+ if (m_bIsActionListener)
+ return;
+ xFrame = m_xFrame;
+ }
+ m_xFrame.addFrameActionListener(this);
+ synchronized(this)
+ {
+ m_bIsActionListener=true;
+ }
+ }
+
+
+
+ /*
+ * In case we got a oneway listener callback - we had to use the office
+ * asynchronous then. This method is the callback from the started thread
+ * (started inside the original oneway method). We found all parameters of
+ * the original request packed inside a vector. Here we unpack it and
+ * call the right internal helper method, which implements the right
+ * functionality.
+ *
+ * @seealso frameAction()
+ * @seealso dispatch()
+ *
+ * @param nRequest
+ * indicates, which was the original request (identifies the
+ * original called method)
+ *
+ * @param lParams
+ * the vector with all packed parameters of the original request
+ */
+ public void execOneway(/*IN*/ int nRequest,/*IN*/ ArrayList<Object> lParams )
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+
+ // was it frameAction()?
+ if (nRequest==OnewayExecutor.REQUEST_FRAMEACTION)
+ {
+ impl_frameAction((FrameActionEvent) lParams.get(0));
+ }
+ else
+ // was it dispatch()?
+ if (nRequest==OnewayExecutor.REQUEST_DISPATCH)
+ {
+ com.sun.star.util.URL[] lOutURL = new com.sun.star.util.URL[1];
+ com.sun.star.beans.PropertyValue[][] lOutProps = new com.sun.star.beans.PropertyValue[1][];
+
+ OnewayExecutor.decodeDispatch(
+ lParams ,
+ lOutURL ,
+ lOutProps );
+ impl_dispatch(lOutURL[0],lOutProps[0]);
+ }
+ }
+
+
+
+ /*
+ * callback for frame action events
+ * We use it to update our interception. Because if a new component was loaded into
+ * the frame or another interceptor was registered, we should refresh our connection
+ * to the frame. Otherwise we can't guarantee full functionality here.
+ *
+ * Note: Don't react synchronous in an asynchronous listener callback. So use a thread
+ * here to update anything.
+ *
+ * @seealso impl_frameAction()
+ *
+ * @param aEvent
+ * describes the action
+ */
+ public /*ONEWAY*/ void frameAction(/*IN*/ com.sun.star.frame.FrameActionEvent aEvent)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+
+ boolean bHandle = false;
+ switch(aEvent.Action.getValue())
+ {
+ case com.sun.star.frame.FrameAction.COMPONENT_ATTACHED_value : bHandle=true; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_DETACHING_value : bHandle=true; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_REATTACHED_value : bHandle=true; break;
+ // Don't react for CONTEXT_CHANGED here. Ok it indicates, that may another interceptor
+ // was registered at the frame ... but if we register ourself there - we get a context
+ // changed too :-( Best way to produce a never ending recursion ...
+ // May be that somewhere find a safe mechanism to detect own produced frame action events
+ // and ignore it.
+ case com.sun.star.frame.FrameAction.CONTEXT_CHANGED_value :
+ System.out.println("Time to update interception ... but may it will start a recursion. So I let it :-(");
+ bHandle=false;
+ break;
+ }
+
+ // ignore some events
+ if (! bHandle)
+ return;
+
+ // pack the event and start thread - which call us back later
+ ArrayList<Object> lOutParams = new ArrayList<Object>();
+ lOutParams.add(aEvent);
+
+ OnewayExecutor aExecutor = new OnewayExecutor( this ,
+ OnewayExecutor.REQUEST_FRAMEACTION ,
+ lOutParams );
+ aExecutor.start();
+ }
+
+
+
+ /*
+ * Indicates using of us as an interceptor.
+ * Now we have to react for the requests, we are registered.
+ * That means: load new empty documents - triggered by the new menu of the office.
+ * Because it's oneway - use thread for loading!
+ *
+ * @seealso impl_dispatch()
+ *
+ * @param aURL
+ * describes the document, which should be loaded
+ *
+ * @param lArguments
+ * optional parameters for loading
+ */
+ public /*ONEWAY*/ void dispatch(/*IN*/ com.sun.star.util.URL aURL,/*IN*/ com.sun.star.beans.PropertyValue[] lArguments)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+
+ com.sun.star.util.URL[] lInURL = new com.sun.star.util.URL[1];
+ com.sun.star.beans.PropertyValue[][] lInArguments = new com.sun.star.beans.PropertyValue[1][];
+ lInURL[0] = aURL ;
+ lInArguments[0] = lArguments;
+
+ ArrayList<Object> lOutParams = OnewayExecutor.encodeDispatch(
+ lInURL ,
+ lInArguments );
+ OnewayExecutor aExecutor = new OnewayExecutor( this ,
+ OnewayExecutor.REQUEST_DISPATCH ,
+ lOutParams );
+ aExecutor.start();
+ }
+
+
+
+
+ /*
+ * Internal callback for frame action events, triggered by the used
+ * OnewayExecutor thread we started in frameAction().
+ * We use it to update our interception on the internal saved frame.
+ *
+ * @param aEvent
+ * describes the action
+ */
+ private void impl_frameAction(/*IN*/ com.sun.star.frame.FrameActionEvent aEvent)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+
+ // deregistration will be done every time...
+ // But may it's not necessary to establish a new registration!
+ // Don't look for ignoring actions - it was done already inside original frameAction() call!
+ boolean bRegister = false;
+
+ // analyze the event and decide which reaction is useful
+ switch(aEvent.Action.getValue())
+ {
+ case com.sun.star.frame.FrameAction.COMPONENT_ATTACHED_value : bRegister = true ; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_REATTACHED_value : bRegister = true ; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_DETACHING_value : bRegister = false; break;
+ }
+
+ com.sun.star.frame.XFrame xFrame = null ;
+ boolean bIsRegistered = false;
+ synchronized(this)
+ {
+ bIsRegistered = m_bIsRegistered;
+ m_bIsRegistered = false;
+ xFrame = m_xFrame;
+ }
+
+ com.sun.star.frame.XDispatchProviderInterception xRegistration = UnoRuntime.queryInterface(
+ com.sun.star.frame.XDispatchProviderInterception.class,
+ xFrame);
+
+ if(xRegistration==null)
+ return;
+
+ if (bIsRegistered)
+ xRegistration.releaseDispatchProviderInterceptor(this);
+
+ if (! bRegister)
+ return;
+
+ xRegistration.registerDispatchProviderInterceptor(this);
+ synchronized(this)
+ {
+ m_bIsRegistered = true;
+ }
+ }
+
+
+
+ /*
+ * Implementation of interface XDispatchProviderInterceptor
+ * These functions are used to build a list of interceptor objects
+ * connected in both ways.
+ * Searching for a right interceptor is made by forwarding any request
+ * from toppest master to lowest slave of this hierarchy.
+ * If an interceptor wish to handle the request he can break that
+ * and return himself as a dispatcher.
+ */
+ public com.sun.star.frame.XDispatchProvider getSlaveDispatchProvider()
+ {
+ synchronized(this)
+ {
+ return m_xSlave;
+ }
+ }
+
+
+
+ public void setSlaveDispatchProvider(com.sun.star.frame.XDispatchProvider xSlave)
+ {
+ synchronized(this)
+ {
+ m_xSlave = xSlave;
+ }
+ }
+
+
+
+ public com.sun.star.frame.XDispatchProvider getMasterDispatchProvider()
+ {
+ synchronized(this)
+ {
+ return m_xMaster;
+ }
+ }
+
+
+
+ public void setMasterDispatchProvider(com.sun.star.frame.XDispatchProvider xMaster)
+ {
+ synchronized(this)
+ {
+ m_xMaster = xMaster;
+ }
+ }
+
+
+
+ /*
+ * Implementation of interface XDispatchProvider
+ * These functions are called from our master if he will not handle the outstanding request.
+ * Given parameter should be checked if they are right for us. If it's true, the returned
+ * dispatcher should be this implementation himself; otherwise call should be forwarded
+ * to the slave.
+ *
+ * @param aURL
+ * describes the request, which should be handled
+ *
+ * @param sTarget
+ * specifies the target frame for this request
+ *
+ * @param nSearchFlags
+ * optional search flags, if sTarget isn't a special one
+ *
+ * @return [XDispatch]
+ * a dispatch object, which can handle the given URL
+ * May be NULL!
+ */
+ public com.sun.star.frame.XDispatch queryDispatch(/*IN*/ com.sun.star.util.URL aURL,/*IN*/ String sTarget,/*IN*/ int nSearchFlags)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return null;
+ }
+
+ // intercept loading empty documents into new created frames
+ if(
+ (sTarget.compareTo ("_blank" ) == 0 ) &&
+ (aURL.Complete.startsWith("private:factory"))
+ )
+ {
+ System.out.println("intercept private:factory");
+ return this;
+ }
+
+ // intercept opening the SaveAs dialog
+ if (aURL.Complete.startsWith(".uno:SaveAs"))
+ {
+ System.out.println("intercept SaveAs by returning null!");
+ return null;
+ }
+
+ // intercept "File->Exit" inside the menu
+ if (
+ (aURL.Complete.startsWith("slot:5300")) ||
+ (aURL.Complete.startsWith(".uno:Quit"))
+ )
+ {
+ System.out.println("intercept File->Exit");
+ return this;
+ }
+
+ synchronized(this)
+ {
+ if (m_xSlave!=null)
+ return m_xSlave.queryDispatch(aURL, sTarget, nSearchFlags);
+ }
+
+ return null;
+ }
+
+
+
+ public com.sun.star.frame.XDispatch[] queryDispatches(/*IN*/ com.sun.star.frame.DispatchDescriptor[] lDescriptor)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return null;
+ }
+ // Resolve any request separately by using own "dispatch()" method.
+ // Note: Don't pack return list if "null" objects occur!
+ int nCount = lDescriptor.length;
+ com.sun.star.frame.XDispatch[] lDispatcher = new com.sun.star.frame.XDispatch[nCount];
+ for(int i=0; i<nCount; ++i)
+ {
+ lDispatcher[i] = queryDispatch(lDescriptor[i].FeatureURL ,
+ lDescriptor[i].FrameName ,
+ lDescriptor[i].SearchFlags);
+ }
+ return lDispatcher;
+ }
+
+
+
+ /*
+ * This method is called if this interceptor "wins the request".
+ * We intercepted creation of new frames and loading of empty documents.
+ * Do it now.
+ *
+ * @param aURL
+ * describes the document
+ *
+ * @param lArguments
+ * optional arguments for loading
+ */
+ private void impl_dispatch(/*IN*/ com.sun.star.util.URL aURL,/*IN*/ com.sun.star.beans.PropertyValue[] lArguments)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+
+ if (
+ (aURL.Complete.startsWith("slot:5300")) ||
+ (aURL.Complete.startsWith(".uno:Quit"))
+ )
+ {
+ System.exit(0);
+ }
+ else
+ if (aURL.Complete.startsWith("private:factory"))
+ {
+ // Create view frame for showing loaded documents on demand.
+ // The visible state is necessary for JNI functionality to get the HWND and plug office
+ // inside a java window hierarchy!
+ DocumentView aNewView = new DocumentView();
+ aNewView.setVisible(true);
+ aNewView.createFrame();
+ aNewView.load(aURL.Complete,lArguments);
+ }
+ }
+
+
+
+ /*
+ * Notification of status listener isn't guaranteed (instead of listener on XNotifyingDispatch interface).
+ * So this interceptor doesn't support that really...
+ */
+ public /*ONEWAY*/ void addStatusListener(/*IN*/ com.sun.star.frame.XStatusListener xListener,/*IN*/ com.sun.star.util.URL aURL)
+ {
+/* if (aURL.Complete.startsWith(".uno:SaveAs")==true)
+ {
+ com.sun.star.frame.FeatureStateEvent aEvent = new com.sun.star.frame.FeatureStateEvent(
+ this,
+ aURL,
+ "",
+ false,
+ false,
+ null);
+ if (xListener!=null)
+ {
+ System.out.println("interceptor disable SaveAs by listener notify");
+ xListener.statusChanged(aEvent);
+ }
+ }*/
+ }
+
+
+
+ public /*ONEWAY*/ void removeStatusListener(/*IN*/ com.sun.star.frame.XStatusListener xListener,/*IN*/ com.sun.star.util.URL aURL)
+ {
+ }
+
+
+
+ /*
+ * Implements (optional!) optimization for interceptor mechanism.
+ * Any interceptor which provides this special interface is called automatically
+ * at registration time on this method. Returned URL's will be used to
+ * call this interceptor directly without calling his masters before, IF(!)
+ * following rules will be true:
+ * (1) every master supports this optional interface too
+ * (2) nobody of these masters wish to intercept same URL then this one
+ * This interceptor wish to intercept creation of new documents.
+ */
+ public String[] getInterceptedURLs()
+ {
+ return INTERCEPTED_URLS;
+ }
+
+
+
+ /*
+ * This class listen on the intercepted frame to free all used resources on closing.
+ * We forget the reference to the frame only here. Deregistration
+ * isn't necessary here - because this frame dies and wish to be forgotten.
+ *
+ * @param aSource
+ * must be our internal saved frame, on which we listen for frame action events
+ */
+ public /*ONEAY*/ void disposing(/*IN*/ com.sun.star.lang.EventObject aSource)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ if (m_xFrame!=null && UnoRuntime.areSame(aSource.Source,m_xFrame))
+ {
+ m_bIsActionListener = false;
+ m_xFrame = null ;
+ }
+ }
+ shutdown();
+ }
+
+
+
+ /*
+ * If this java application shutdown - we must cancel all current existing
+ * listener connections. Otherwise the office will run into some
+ * DisposedExceptions if it tries to use these forgotten listener references.
+ * And of course it can die doing that.
+ * We are registered at a central object to be informed if the VM will exit.
+ * So we can react.
+ */
+ public void shutdown()
+ {
+ com.sun.star.frame.XFrame xFrame = null ;
+ boolean bIsRegistered = false;
+ boolean bIsActionListener = false;
+ synchronized(this)
+ {
+ // don't react a second time here!
+ if (m_bDead)
+ return;
+ m_bDead = true;
+
+ bIsRegistered = m_bIsRegistered;
+ m_bIsRegistered = false;
+
+ bIsActionListener = m_bIsActionListener;
+ m_bIsActionListener = false;
+
+ xFrame = m_xFrame;
+ m_xFrame = null;
+ }
+
+ // it's a good idea to cancel listening for frame action events
+ // before(!) we deregister us as an interceptor.
+ // Because registration and deregistration of interceptor objects
+ // will force sending of frame action events...!
+ if (bIsActionListener)
+ xFrame.removeFrameActionListener(this);
+
+ if (bIsRegistered)
+ {
+ com.sun.star.frame.XDispatchProviderInterception xRegistration = UnoRuntime.queryInterface(
+ com.sun.star.frame.XDispatchProviderInterception.class,
+ xFrame);
+
+ if(xRegistration!=null)
+ xRegistration.releaseDispatchProviderInterceptor(this);
+ }
+
+ xFrame = null;
+
+ synchronized(this)
+ {
+ m_xMaster = null;
+ m_xSlave = null;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/JavaWindowPeerFake.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/JavaWindowPeerFake.java
new file mode 100644
index 0000000000..25281ac5f3
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/JavaWindowPeerFake.java
@@ -0,0 +1,109 @@
+/* -*- 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.
+ *
+ *************************************************************************/
+
+
+
+
+/** <p>Class to pass the system window handle to the OpenOffice.org toolkit.</p>
+ */
+class JavaWindowPeerFake implements com.sun.star.awt.XSystemDependentWindowPeer,
+ com.sun.star.awt.XWindowPeer
+{
+ private final NativeView maView;
+
+ public JavaWindowPeerFake(NativeView aNative)
+ {
+ maView = aNative;
+ }
+
+
+ /**
+ * Implementation of XSystemDependentWindowPeer (that's all we really need).
+ * This method is called back from the Office toolkit to retrieve the system data.
+ */
+ public java.lang.Object getWindowHandle(byte[] aProcessId, short aSystem)
+ throws com.sun.star.uno.RuntimeException
+ {
+ Object aReturn = null;
+ if(aSystem==maView.maSystem)
+ aReturn = maView.maHandle;
+ return aReturn;
+ }
+
+ /** not really needed.
+ */
+ public com.sun.star.awt.XToolkit getToolkit()
+ throws com.sun.star.uno.RuntimeException
+ {
+ return null;
+ }
+
+ public void setPointer(com.sun.star.awt.XPointer xPointer)
+ throws com.sun.star.uno.RuntimeException
+ {
+ }
+
+ public void setBackground(int nColor)
+ throws com.sun.star.uno.RuntimeException
+ {
+ }
+
+ public void invalidate(short nFlags)
+ throws com.sun.star.uno.RuntimeException
+ {
+ }
+
+ public void invalidateRect(com.sun.star.awt.Rectangle aRect,short nFlags)
+ throws com.sun.star.uno.RuntimeException
+ {
+ }
+
+ public void dispose()
+ throws com.sun.star.uno.RuntimeException
+ {
+ }
+
+ public void addEventListener(com.sun.star.lang.XEventListener xListener)
+ throws com.sun.star.uno.RuntimeException
+ {
+ }
+
+ public void removeEventListener(com.sun.star.lang.XEventListener xListener)
+ throws com.sun.star.uno.RuntimeException
+ {
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Makefile b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Makefile
new file mode 100644
index 0000000000..5b0462b25e
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/Makefile
@@ -0,0 +1,131 @@
+#*************************************************************************
+#
+# 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.
+#
+#**************************************************************************
+
+# Builds the OfficeDevDesktopEnvironment example of the Developers Guide.
+
+PRJ=../../../..
+SETTINGS=$(PRJ)/settings
+
+include $(SETTINGS)/settings.mk
+include $(SETTINGS)/std.mk
+
+# Define non-platform/compiler specific settings
+EXAMPLE_NAME=OfficeDevDesktopEnv
+OUT_APP_CLASS = $(OUT_CLASS)/$(EXAMPLE_NAME)
+
+APP1_NAME=DesktopExample
+APP1_JAR=$(OUT_APP_CLASS)/$(APP1_NAME).jar
+
+APP1_JAVAFILES = \
+ CustomizeView.java \
+ Desk.java \
+ DocumentView.java \
+ FunctionHelper.java \
+ Interceptor.java \
+ IOnewayLink.java \
+ IShutdownListener.java \
+ JavaWindowPeerFake.java \
+ NativeView.java \
+ OfficeConnect.java \
+ OnewayExecutor.java \
+ StatusListener.java \
+ StatusView.java \
+ ViewContainer.java
+
+APP1_CLASSFILES = $(patsubst %.java,$(OUT_APP_CLASS)/%.class,$(APP1_JAVAFILES))
+APP1_CLASSNAMES = $(patsubst %.java,%.class,$(APP1_JAVAFILES)) \
+ CustomizeView$(QUOTE)$$ClickListener.class \
+ DocumentView$(QUOTE)$$*.class
+
+
+SDK_CLASSPATH = $(subst $(EMPTYSTRING) $(PATH_SEPARATOR),$(PATH_SEPARATOR),$(CLASSPATH)\
+ $(PATH_SEPARATOR)$(OUT_APP_CLASS))
+
+ifeq "$(OS)" "WIN"
+SUBDIR= nativelib/windows
+else
+SUBDIR= nativelib/unix
+endif
+
+# Targets
+.PHONY: ALL
+ifeq "$(OS)" "MACOSX"
+ALL :
+ @printf 'This example does not work on macOS\n'
+else
+ALL : $(SUBDIR) \
+ $(EXAMPLE_NAME)
+endif
+
+include $(SETTINGS)/stdtarget.mk
+
+.PHONY : $(SUBDIR)
+$(SUBDIR) :
+ $(MAKE) -C $@
+
+$(APP1_CLASSFILES) : $(APP1_JAVAFILES)
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ $(SDK_JAVAC) $(JAVAC_FLAGS) -classpath "$(SDK_CLASSPATH)" -d $(OUT_APP_CLASS) $(APP1_JAVAFILES)
+
+$(OUT_APP_CLASS)/$(APP1_NAME).mf :
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ @echo Main-Class: com.sun.star.lib.loader.Loader> $@
+ $(ECHOLINE)>> $@
+ @echo Name: com/sun/star/lib/loader/Loader.class>> $@
+ @echo Application-Class: Desk>> $@
+
+$(APP1_JAR) : $(OUT_APP_CLASS)/$(APP1_NAME).mf $(APP1_CLASSFILES)
+ -$(DEL) $(subst \\,\,$(subst /,$(PS),$@))
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ +cd $(subst /,$(PS),$(OUT_APP_CLASS)) && $(SDK_JAR) cvfm $(@F) $(basename $(@F)).mf $(APP1_CLASSNAMES)
+ +$(SDK_JAR) uvf $@ $(SDK_JAVA_UNO_BOOTSTRAP_FILES)
+
+$(EXAMPLE_NAME) : $(APP1_JAR)
+ @echo --------------------------------------------------------------------------------
+ @echo Please use the following command to execute the example!
+ @echo -
+ @echo $(MAKE) DesktopExample.run
+ @echo ------
+ @echo If you want to run the $(JAR1_JAR) file please set your
+ @echo CLASSPATH = $(SDK_CLASSPATH)
+ @echo Start the example with jar -jar $(JAR1_JAR)
+ @echo --------------------------------------------------------------------------------
+
+%.run: $(OUT_APP_CLASS)/%.jar
+ $(SDK_JAVA) -Dcom.sun.star.lib.loader.unopath="$(OFFICE_PROGRAM_PATH)" -jar $<
+
+.PHONY: clean
+clean :
+ $(MAKE) -C $(SUBDIR) clean
+ -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_APP_CLASS))
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/NativeView.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/NativeView.java
new file mode 100644
index 0000000000..273290e55f
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/NativeView.java
@@ -0,0 +1,186 @@
+/* -*- 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 java.awt.*;
+
+// __________ Implementation __________
+
+/**
+ * Class to pass the system window handle to the OpenOffice.org toolkit.
+ * It use special JNI methods to get the system handle of used java window.
+ *
+ * Attention!
+ * Use JNI functions on already visible canvas objects only!
+ * Otherwise they can make some trouble.
+ *
+ */
+
+public class NativeView extends java.awt.Canvas
+{
+
+
+ /**
+ * ctor
+ * Does nothing really.
+ * We can use our JNI mechanism for an already visible
+ * canvas only. So we override the method for showing ("setVisible()")
+ * and make our initialization there. But we try to show an empty clean
+ * window till there.
+ */
+ public NativeView()
+ {
+ maHandle = null;
+ maSystem = 0;
+ this.setBackground(Color.white);
+ }
+
+
+
+ /**
+ * Override this method to make necessary initializations here.
+ * (e.g. get the window handle and necessary system information)
+ *
+ * Why here?
+ * Because the handle seems to be available for already visible windows
+ * only. So it's the best place to get it. Special helper method
+ * can be called more than ones - but call native code one times only
+ * and safe the handle and the system type on our members maHandle/maSystem!
+ */
+ @Override
+ public void setVisible(boolean bState)
+ {
+ getHWND();
+ }
+
+
+
+ /**
+ * to guarantee right resize handling inside a swing container
+ * (e.g. JSplitPane) we must provide some information about our
+ * preferred/minimum and maximum size.
+ */
+ @Override
+ public Dimension getPreferredSize()
+ {
+ return new Dimension(500,300);
+ }
+
+ @Override
+ public Dimension getMaximumSize()
+ {
+ return new Dimension(1024,768);
+ }
+
+ @Override
+ public Dimension getMinimumSize()
+ {
+ return new Dimension(100,100);
+ }
+
+
+
+ /**
+ * Override paint routine to show provide against
+ * repaint errors if no office view is really plugged
+ * into this canvas.
+ * If handle is present - we shouldn't paint anything further.
+ * May the remote window is already plugged. In such case we
+ * shouldn't paint it over.
+ */
+ @Override
+ public void paint(Graphics aGraphic)
+ {
+ if(maHandle==null)
+ {
+ Dimension aSize = getSize();
+ aGraphic.clearRect(0,0,aSize.width,aSize.height);
+ }
+ }
+
+
+
+ /**
+ * JNI interface of this class
+ * These two methods are implemented by using JNI mechanismen.
+ * The will be used to get the platform dependent window handle
+ * of a java awt canvas. This handle can be used to create an office
+ * window as direct child of it. So it's possible to plug Office
+ * windows in a java UI container.
+ *
+ * Note:
+ * Native code for Windows registers a special function pointer to handle
+ * window messages... But if it doesn't check for an already-registered
+ * instance of this handler it will do it twice and produce a stack overflow
+ * because such method calls itself in a never-ending loop...
+ * So we try to use the JNI code one time only and save already-obtained
+ * information inside this class.
+ */
+ public native int getNativeWindowSystemType();
+ private native long getNativeWindow(); // private! => use getHWND() with cache mechanism!
+
+ public Integer getHWND()
+ {
+ if(maHandle==null)
+ {
+ maHandle = Integer.valueOf((int)getNativeWindow());
+ maSystem = getNativeWindowSystemType();
+ }
+ return maHandle;
+ }
+
+
+
+ /**
+ * for using of the JNI methods it's necessary to load
+ * system library which exports it.
+ */
+ static
+ {
+ System.loadLibrary("nativeview");
+ }
+
+
+
+ /**
+ * @member maHandle system window handle
+ * @member maSystem info about currently used platform
+ */
+ public Integer maHandle ;
+ public int maSystem ;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OfficeConnect.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OfficeConnect.java
new file mode 100644
index 0000000000..617e380471
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OfficeConnect.java
@@ -0,0 +1,127 @@
+/* -*- 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.
+ *
+ *************************************************************************/
+
+
+
+
+// __________ Implementation __________
+
+/**
+ * support ONE singleton uno connection to a running office installation!
+ * Can be used to open/use/close connection to uno environment of an office. If
+ * necessary a new office instance is started.
+ * ctor isn't available from outside. You should call static function
+ * "getConnection()" to open or use internal set connection which is created one
+ * times only.
+ *
+ */
+public class OfficeConnect
+{
+
+
+ /**
+ * At first call we create static connection object and open connection to an
+ * office - a new office instance is started if necessary
+ * Then - and for all further requests we return these static connection member.
+ */
+ public static synchronized void createConnection()
+ {
+ if (maConnection == null)
+ maConnection = new OfficeConnect();
+ }
+
+
+
+
+
+
+
+ /**
+ * ctor
+ * We try to open the connection in our ctor ... transparently for user.
+ * After it was successful you will find an internal set member
+ * m_xRemoteContext which means remote component context of the connected office.
+ * The context can be used to get the remote service manager from the office.
+ * We made it private to support singleton pattern of these implementation.
+ * see getConnection() for further information
+ */
+ private OfficeConnect()
+ {
+ try
+ {
+ // get the remote office context. If necessary a new office
+ // process is started
+ mxOfficeContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
+ System.out.println("Connected to a running office ...");
+ mxServiceManager = mxOfficeContext.getServiceManager();
+ }
+ catch (java.lang.Exception ex)
+ {
+ System.err.println("connection failed" + ex);
+ ex.printStackTrace(System.err);
+ System.exit(1);
+
+ }
+ }
+
+
+
+
+
+
+
+ /**
+ * returns remote component context of the connected office
+ */
+ public static synchronized com.sun.star.uno.XComponentContext getOfficeContext()
+ {
+ return mxOfficeContext;
+ }
+
+
+
+ /**
+ * member
+ */
+ // singleton connection instance
+ private static OfficeConnect maConnection;
+
+ // reference to the office component context
+ private static com.sun.star.uno.XComponentContext mxOfficeContext;
+ // reference to remote service manager of singleton connection object
+ private static com.sun.star.lang.XMultiComponentFactory mxServiceManager;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OnewayExecutor.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OnewayExecutor.java
new file mode 100644
index 0000000000..4eb7f80a76
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/OnewayExecutor.java
@@ -0,0 +1,189 @@
+/* -*- 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.
+ *
+ *************************************************************************/
+
+import java.util.ArrayList;
+
+// __________ Implementation __________
+
+/**
+ * It's not allowed to call synchronous back inside a oneway interface call.
+ * (see IOnewayLink too). So we start a thread (implemented by this class), which
+ * gets all necessary parameters from the original called object and
+ * call it back later inside his run() method. So the execution of such oneway call
+ * will be asynchronous. It works in a generic way and can be used or any type
+ * of oneway request. Because the source and the target of this call-link knows,
+ * which method was used and which parameters must be handled.
+ *
+ */
+class OnewayExecutor extends Thread
+{
+
+
+ /**
+ * const
+ * We define some request for some well known oneway interface
+ * calls here too. So they mustn't be declared more than ones.
+ * Of course it's not necessary to use it ... but why not :-)
+ */
+
+ public static final int REQUEST_FRAMEACTION = 1 ;
+
+
+
+ public static final int REQUEST_DISPATCH = 5 ;
+
+
+
+
+
+
+ /**
+ * @member m_rLink the object, which wishes to be called back by this thread
+ * @member m_nRequest describes the type of the original request (means the
+ * called oneway method)
+ * @member m_lParams list of parameters of the original request
+ */
+ private final IOnewayLink m_rLink ;
+ private final int m_nRequest ;
+ private final ArrayList<Object> m_lParams ;
+
+
+
+ /**
+ * ctor
+ * It's initialize this thread with all necessary parameters.
+ * It gets the object, which wishes to be called back and the type
+ * and parameters of the original request.
+ *
+ * @param nRequest
+ * The two user of this callback can define a unique number,
+ * which identify the type of original interface method.
+ * So the called interface object can decide, which action will be
+ * necessary.
+ *
+ * @param lParams
+ * If the original method used parameters, they will be coded here in
+ * a generic way. Only the called interface object know (it depends
+ * from the original request - see nRequest too), how this list must
+ * be interpreted.
+ * Note: Atomic types (e.g. int, long) will be transported as objects
+ * too (Integer, Long)!
+ */
+ public OnewayExecutor( IOnewayLink rLink ,
+ int nRequest ,
+ ArrayList<Object> lParams )
+ {
+ m_rLink = rLink ;
+ m_nRequest = nRequest;
+ m_lParams = lParams ;
+
+ if (m_rLink==null)
+ System.out.println("ctor ... m_rLink == null");
+ if (m_lParams==null)
+ System.out.println("ctor ... m_lParams == null");
+ }
+
+
+
+ /**
+ * implements the thread function
+ * Here we call the internal set link object back and
+ * give him all necessary parameters.
+ * After that we die by ourselves ...
+ */
+ @Override
+ public void run()
+ {
+ if (m_rLink==null)
+ System.out.println("run ... m_rLink == null");
+ if (m_lParams==null)
+ System.out.println("run ... m_lParams == null");
+
+ if (m_rLink!=null)
+ m_rLink.execOneway( m_nRequest, m_lParams );
+ }
+
+
+
+ /**
+ * static helper!
+ * To make conversion of the generic parameter list to the original
+ * one easier - you can use this helper methods. They know how such list
+ * must be coded. It's not a must to use it - but you can ...
+ */
+
+
+
+ public static ArrayList<Object> encodeDispatch(
+ com.sun.star.util.URL[] aURL,
+ com.sun.star.beans.PropertyValue[][] lArgs)
+ {
+ int nLength = lArgs.length+1;
+ int nPos = 0;
+ ArrayList<Object> lParams = new ArrayList<Object>(nLength);
+
+ lParams.add( aURL[0] );
+ --nLength;
+
+ while (nLength>0)
+ {
+ lParams.add( lArgs[0][nPos] );
+ --nLength;
+ ++nPos ;
+ }
+ return lParams;
+ }
+
+ public static void decodeDispatch(
+ ArrayList<Object> lParams,
+ com.sun.star.util.URL[] aURL,
+ com.sun.star.beans.PropertyValue[][] lArgs)
+ {
+ int nLength = lParams.size()-1;
+ int nPos = 0;
+
+ lArgs[0] = new com.sun.star.beans.PropertyValue[nLength];
+ aURL[0] = (com.sun.star.util.URL) lParams.get(0);
+
+ while (nPos<nLength)
+ {
+ lArgs[0][nPos] = (com.sun.star.beans.PropertyValue)
+ (lParams.get(nPos+1));
+ ++nPos;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java
new file mode 100644
index 0000000000..f037949b05
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusListener.java
@@ -0,0 +1,469 @@
+/* -*- 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 java.awt.Component;
+import java.util.ArrayList;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+
+import com.sun.star.frame.FrameActionEvent;
+import com.sun.star.uno.UnoRuntime;
+
+// __________ Implementation __________
+
+/**
+ * reacts for status events we listen for
+ * We listen for status events to update our UI.
+ * To know which event must be used for which UI control
+ * we use a special class to do that. Otherwise we have
+ * to guess it ...
+ *
+ * Further we are frame action listener too.
+ * So we can update our status listener connections and
+ * internal holded dispatch object automatically.
+ *
+ * Another reason for such extra class for listening:
+ * Most listener callbacks are asynchronous [oneay] requests.
+ * And it's not allowed to call back synchronously there.
+ * So we must start threads for updating something internally.
+ *
+ */
+class StatusListener implements com.sun.star.frame.XStatusListener,
+ com.sun.star.frame.XFrameActionListener,
+ IShutdownListener,
+ IOnewayLink
+{
+
+
+ /**
+ * @member m_rControl reference to the UI control, which should be updated
+ * @member m_sTrueText this text will be shown at the used UI control as description for an enabled status
+ * @member m_sFalseText this text will be shown at the used UI control as description for an disabled status
+ * @member m_xDispatch if we listen for status events, we must hold the dispatch object alive!
+ * @member m_xFrame reference to the frame, which can provide new dispatch objects if it's necessary to update it
+ * @member m_aURL and of course we must be registered for a special URL
+ * @member m_bIsActionListener indicates if we are currently registered as a listener for frame action events or not
+ * @member m_bIsStatusListener indicates if we are currently registered as a listener for status events or not
+ * @member m_bDead there exist more than one way to finish an object of this class - we must know it sometimes
+ */
+ private final Component m_rControl ;
+ private final String m_sTrueText ;
+ private final String m_sFalseText ;
+ private com.sun.star.frame.XDispatch m_xDispatch ;
+ private com.sun.star.frame.XFrame m_xFrame ;
+ private com.sun.star.util.URL m_aURL ;
+ private boolean m_bIsActionListener;
+ private boolean m_bIsStatusListener;
+ private boolean m_bDead ;
+
+
+
+ /**
+ * ctor
+ * It initialize an instance of this class only.
+ * We set all necessary information on our internal member - that's it
+ */
+ StatusListener( /*IN*/ Component rControl ,
+ /*IN*/ String sTrueText ,
+ /*IN*/ String sFalseText ,
+ /*IN*/ com.sun.star.frame.XFrame xFrame ,
+ /*IN*/ String sURL )
+ {
+ m_rControl = rControl ;
+ m_sTrueText = sTrueText ;
+ m_sFalseText = sFalseText ;
+ m_xFrame = xFrame ;
+ m_bIsStatusListener = false ;
+ m_bIsActionListener = false ;
+ m_bDead = false ;
+ // to be perform - we parse the given URL one times only
+ // and use it till we die ...
+ m_aURL = FunctionHelper.parseURL(sURL);
+ }
+
+
+
+ /**
+ * start working as frame action listener really.
+ * In case we get such frame action, it indicates that we should
+ * update our internal saved dispatch object on which we listen
+ * for status events. So we can do it automatically. The outside code
+ * mustn't check such things. We can work with one frame,
+ * till it die. It doesn't matter if he will be used for different
+ * load/save or any other requests. We will be up to date every time.
+ */
+ public void startListening()
+ {
+ com.sun.star.frame.XFrame xFrame = null;
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ if (m_xFrame==null)
+ return;
+ if (m_bIsActionListener)
+ return;
+ xFrame = m_xFrame;
+ }
+ xFrame.addFrameActionListener(this);
+ synchronized(this)
+ {
+ m_bIsActionListener=true;
+ }
+ }
+
+
+
+ /**
+ * In case we got a oneway listener callback - we had to use the office
+ * asynchronous then. This method is the callback from the started thread
+ * (started inside the original oneway method). We found all parameters of
+ * the original request packed inside a vector. Here we unpack it and
+ * call the right internal helper method, which implements the right
+ * functionality.
+ *
+ * @seealso frameAction()
+ * @seealso statusChanged()
+ *
+ * @param nRequest
+ * indicates, which was the original request (identifies the
+ * original called method)
+ *
+ * @param lParams
+ * the vector with all packed parameters of the original request
+ */
+ public void execOneway(/*IN*/ int nRequest,/*IN*/ ArrayList<Object> lParams )
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+ // was it frameAction()?
+ if (nRequest==OnewayExecutor.REQUEST_FRAMEACTION)
+ {
+ impl_frameAction((FrameActionEvent) lParams.get(0));
+ }
+ }
+
+
+
+ /**
+ * This is the callback method for such frame action events, we listen for.
+ * Because it's a oneway method we start a thread as reaction. This thread call
+ * us back and we can do necessary things there.
+ * But we shouldn't start such action - if it's not really necessary.
+ * So we check before, if we are interested on this event really.
+ *
+ * @see #impl_frameAction
+ *
+ * @param aEvent
+ * describes the action, which triggered this event
+ */
+ public /*ONEWAY*/ void frameAction(/*IN*/ com.sun.star.frame.FrameActionEvent aEvent)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+ boolean bHandle = false;
+ switch(aEvent.Action.getValue())
+ {
+ case com.sun.star.frame.FrameAction.COMPONENT_ATTACHED_value : bHandle=true; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_DETACHING_value : bHandle=true; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_REATTACHED_value : bHandle=true; break;
+ case com.sun.star.frame.FrameAction.CONTEXT_CHANGED_value : bHandle=true; break;
+ }
+
+ if (! bHandle)
+ return;
+
+ ArrayList<Object> lOutParams = new ArrayList<Object>();
+ lOutParams.add(aEvent);
+
+ OnewayExecutor aExecutor = new OnewayExecutor( this ,
+ OnewayExecutor.REQUEST_FRAMEACTION ,
+ lOutParams );
+ aExecutor.start();
+ }
+
+
+
+ /**
+ * This is the callback method for the status we listen for and wish to show it
+ * on our UI control. Of course it's a oneway method... but we don't call back
+ * to the office synchronously here. We update our UI only. So we don't leave this
+ * java process. In such case it's not necessary to use threads to decouple it.
+ * Do it here and now...
+ *
+ * @param aEvent
+ * describes the status, we can use to update our UI control
+ */
+ public /*ONEWAY*/ void statusChanged(/*IN*/ com.sun.star.frame.FeatureStateEvent aEvent)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+
+ // enable/disable the control.
+ // Means: if the feature isn't available currently - we can't show a status really here.
+ // Then we should colorize it gray...
+ m_rControl.setEnabled(aEvent.IsEnabled);
+
+ // Only if status is enabled we can look for his value!
+ if (aEvent.IsEnabled)
+ {
+ // look for the right type of the UI control
+ // Following actions depend on it.
+
+
+ // it's a check box
+ if (m_rControl instanceof JCheckBox)
+ {
+ JCheckBox aBox = (JCheckBox)m_rControl;
+
+ // State must be a boolean value too. Otherwise must
+ // ignore this event.
+ if ( ! (aEvent.State instanceof Boolean ) )
+ return;
+
+ boolean bState = ((Boolean)(aEvent.State)).booleanValue();
+ aBox.setSelected(bState);
+ if (bState)
+ aBox.setText(m_sTrueText);
+ else
+ aBox.setText(m_sFalseText);
+ }
+ else
+
+ // it's a label
+ if (m_rControl instanceof JLabel)
+ {
+ JLabel aLabel = (JLabel)m_rControl;
+
+ // Detect type of state value
+ // and set it on internal well known UI control
+ // But do it only, if value really change.
+ if(aEvent.State instanceof String)
+ {
+ String sState = (String)aEvent.State;
+ aLabel.setText(sState);
+ }
+ else
+ if(aEvent.State instanceof Boolean)
+ {
+ boolean bState = ((Boolean)aEvent.State).booleanValue();
+ if (bState)
+ aLabel.setText(m_sTrueText);
+ else
+ aLabel.setText(m_sFalseText);
+ }
+ else
+ if(aEvent.State instanceof Float)
+ {
+ String sState = ((Float)aEvent.State).toString();
+ aLabel.setText(sState);
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * Internal call back for frame action events, triggered by the used
+ * OnewayExecutor thread we started in frameAction().
+ * We use it to update internal saved dispatch object and the corresponding
+ * listener connection for status events.
+ *
+ * @param aEvent
+ * describes the action
+ */
+ private void impl_frameAction(/*IN*/ com.sun.star.frame.FrameActionEvent aEvent)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ }
+ // Don't look for ignoring actions - it was done already inside original frameAction() call!
+ // deregistration as status listener will be done here every time - but registration only, if necessary!
+ boolean bRegister = false;
+ switch(aEvent.Action.getValue())
+ {
+ case com.sun.star.frame.FrameAction.COMPONENT_ATTACHED_value : bRegister=true ; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_DETACHING_value : bRegister=false; break;
+ case com.sun.star.frame.FrameAction.COMPONENT_REATTACHED_value : bRegister=true ; break;
+ case com.sun.star.frame.FrameAction.CONTEXT_CHANGED_value : bRegister=true ; break;
+ }
+
+ boolean bIsStatusListener = false;
+ com.sun.star.frame.XFrame xFrame = null ;
+ com.sun.star.frame.XDispatch xDispatch = null ;
+ com.sun.star.util.URL aURL = null ;
+ synchronized(this)
+ {
+ bIsStatusListener = m_bIsStatusListener;
+ m_bIsStatusListener = false;
+
+ xDispatch = m_xDispatch;
+ m_xDispatch = null;
+
+ aURL = m_aURL;
+ xFrame = m_xFrame;
+ }
+
+ if (bIsStatusListener)
+ xDispatch.removeStatusListener(this,aURL);
+ xDispatch = null;
+
+ if (! bRegister)
+ return;
+
+ com.sun.star.frame.XDispatchProvider xProvider = UnoRuntime.queryInterface(
+ com.sun.star.frame.XDispatchProvider.class,
+ xFrame);
+
+ if (xProvider==null)
+ return;
+
+ xDispatch = xProvider.queryDispatch(aURL,"",0);
+
+ if (xDispatch==null)
+ return;
+
+ xDispatch.addStatusListener(this,aURL);
+ synchronized(this)
+ {
+ m_xDispatch = xDispatch;
+ m_bIsStatusListener = true;
+ }
+ }
+
+
+
+ /**
+ * callback for disposing events
+ * Our dispatch or frame object inform us about his following dead ...
+ * So we must forget his reference. But it's not necessary to
+ * remove listener connections here. Because the broadcaster
+ * forget us automatically. The only thing we have to do: release
+ * his reference and let him die!
+ *
+ * @param aEvent
+ * describes the source which fire this event
+ * Must be our internal saved dispatch or frame. Otherwise
+ * somewhere know us without a registration ...
+ */
+ public /*ONEWAY*/ void disposing(/*IN*/ com.sun.star.lang.EventObject aEvent)
+ {
+ synchronized(this)
+ {
+ if (m_bDead)
+ return;
+ if (m_xFrame!=null && UnoRuntime.areSame(aEvent.Source,m_xFrame))
+ {
+ m_bIsActionListener = false;
+ m_xFrame = null ;
+ }
+ else
+ if (m_xDispatch!=null && UnoRuntime.areSame(aEvent.Source,m_xDispatch))
+ {
+ m_bIsStatusListener = false;
+ m_xDispatch = null ;
+ m_aURL = null ;
+ }
+ }
+ shutdown();
+ }
+
+
+
+ /**
+ * If this java application shutdown - we must cancel all current existing
+ * listener connections. Otherwise the office will run into some
+ * DisposedExceptions if it tries to use these forgotten listener references.
+ * And of course it can die doing that.
+ * We are registered at a central object to be informed if the VM will exit.
+ * So we can react.
+ */
+ public void shutdown()
+ {
+ boolean bIsActionListener = false;
+ boolean bIsStatusListener = false;
+ com.sun.star.frame.XFrame xFrame = null ;
+ com.sun.star.frame.XDispatch xDispatch = null ;
+ com.sun.star.util.URL aURL = null ;
+ synchronized(this)
+ {
+ // don't react a second time here!
+ if (m_bDead)
+ return;
+ m_bDead = true;
+
+ bIsActionListener = m_bIsActionListener;
+ m_bIsActionListener = false;
+
+ bIsStatusListener = m_bIsStatusListener;
+ m_bIsStatusListener = false;
+
+ xFrame = m_xFrame;
+ m_xFrame = null;
+
+ xDispatch = m_xDispatch;
+ m_xDispatch = null;
+
+ aURL = m_aURL;
+ m_aURL = null;
+ }
+
+ if (bIsStatusListener)
+ xDispatch.removeStatusListener(this,aURL);
+ xDispatch = null ;
+ aURL = null ;
+
+ if (bIsActionListener)
+ xFrame.removeFrameActionListener(this);
+ xFrame = null ;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusView.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusView.java
new file mode 100644
index 0000000000..076669014d
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/StatusView.java
@@ -0,0 +1,264 @@
+/* -*- 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 java.awt.*;
+import javax.swing.*;
+
+// __________ Implementation __________
+
+/**
+ * Implement a view to show status information
+ * of currently loaded document of a document view.
+ * It uses separate listener threads to get this information
+ * and actualize it automatically, if frame broadcast changes of
+ * his contained document.
+ * Threads are necessary to prevent this view against deadlocks.
+ * These deadlocks can occur if a listener will be notified
+ * by the office in an "oneway" method and try to call back
+ * to the office by using a synchronous method.
+ * UNO must guarantee order of all these calls ... and if
+ * the source of arrived event holds a mutex and our synchronous
+ * call needs this mutex too => a deadlock occurs.
+ * Why? UNO had created a new thread for our synchronous call
+ * inside the office process and so exist different threads
+ * for this constellation.
+ *
+ */
+public class StatusView extends JPanel
+ implements IShutdownListener
+{
+
+
+ /**
+ * const
+ * These URL's describe available feature states.
+ */
+ private static final String FEATUREURL_FONT = ".uno:CharFontName";
+ private static final String FEATUREURL_SIZE = ".uno:FontHeight";
+ private static final String FEATUREURL_BOLD = ".uno:Bold";
+ private static final String FEATUREURL_ITALIC = ".uno:Italic";
+ private static final String FEATUREURL_UNDERLINE = ".uno:Underline";
+
+
+
+ /**
+ * const
+ * These values are used to show current state of showed feature.
+ */
+ private static final String FONT_OFF = "unknown" ;
+ private static final String SIZE_OFF = "0.0" ;
+ private static final String BOLD_OFF = "-" ;
+ private static final String ITALIC_OFF = "-" ;
+ private static final String UNDERLINE_OFF = "-" ;
+
+ private static final String FONT_ON = "" ;
+ private static final String SIZE_ON = "" ;
+ private static final String BOLD_ON = "X" ;
+ private static final String ITALIC_ON = "X" ;
+ private static final String UNDERLINE_ON = "X" ;
+
+
+
+ /**
+ * @member mlaFontValue shows status of font name
+ * @member mlaSizeValue shows status of font size
+ * @member mlaBoldValue shows status of font style bold
+ * @member mlaUnderlineValue shows status of font style underline
+ * @member mlaItalicValue shows status of font style italic
+ *
+ * @member maFontListener threadsafe(!) helper to listen for status event which describe font name
+ * @member maSizeListener threadsafe(!) helper to listen for status event which describe font size
+ * @member maBoldListener threadsafe(!) helper to listen for status event which describe font style bold
+ * @member maUnderlineListener threadsafe(!) helper to listen for status event which describe font style underline
+ * @member maItalicListener threadsafe(!) helper to listen for status event which describe font style italic
+ */
+ private final JLabel m_laFontValue ;
+ private final JLabel m_laSizeValue ;
+ private final JLabel m_laBoldValue ;
+ private final JLabel m_laUnderlineValue ;
+ private final JLabel m_laItalicValue ;
+
+ private StatusListener m_aFontListener ;
+ private StatusListener m_aSizeListener ;
+ private StatusListener m_aBoldListener ;
+ private StatusListener m_aUnderlineListener ;
+ private StatusListener m_aItalicListener ;
+
+
+
+ /**
+ * ctor
+ * Create view controls on startup and initialize it with default values.
+ * Filling of view items can be done by special set-methods.
+ * We don't start listening here! see setFrame() for that ...
+ */
+ StatusView()
+ {
+ this.setLayout(new GridBagLayout());
+
+ GridBagConstraints aConstraint = new GridBagConstraints();
+ aConstraint.anchor = GridBagConstraints.NORTHWEST;
+ aConstraint.insets = new Insets(2,2,2,2);
+ aConstraint.gridy = 0;
+ aConstraint.gridx = 0;
+
+ JLabel laFont = new JLabel("Font" );
+ JLabel laSize = new JLabel("Size" );
+ JLabel laBold = new JLabel("Bold" );
+ JLabel laUnderline = new JLabel("Underline");
+ JLabel laItalic = new JLabel("Italic" );
+
+ m_laFontValue = new JLabel();
+ m_laSizeValue = new JLabel();
+ m_laBoldValue = new JLabel();
+ m_laUnderlineValue = new JLabel();
+ m_laItalicValue = new JLabel();
+
+ aConstraint.gridx = 0;
+ this.add( laFont, aConstraint );
+ aConstraint.gridx = 1;
+ this.add( m_laFontValue, aConstraint );
+
+ ++aConstraint.gridy;
+
+ aConstraint.gridx = 0;
+ this.add( laSize, aConstraint );
+ aConstraint.gridx = 1;
+ this.add( m_laSizeValue, aConstraint );
+
+ ++aConstraint.gridy;
+
+ aConstraint.gridx = 0;
+ this.add( laSize, aConstraint );
+ aConstraint.gridx = 1;
+ this.add( m_laSizeValue, aConstraint );
+
+ ++aConstraint.gridy;
+
+ aConstraint.gridx = 0;
+ this.add( laBold, aConstraint );
+ aConstraint.gridx = 1;
+ this.add( m_laBoldValue, aConstraint );
+
+ ++aConstraint.gridy;
+
+ aConstraint.gridx = 0;
+ this.add( laUnderline, aConstraint );
+ aConstraint.gridx = 1;
+ this.add( m_laUnderlineValue, aConstraint );
+
+ ++aConstraint.gridy;
+
+ aConstraint.gridx = 0;
+ this.add( laItalic, aConstraint );
+ aConstraint.gridx = 1;
+ this.add( m_laItalicValue, aConstraint );
+
+ m_laFontValue.setEnabled (false);
+ m_laSizeValue.setEnabled (false);
+ m_laBoldValue.setEnabled (false);
+ m_laItalicValue.setEnabled (false);
+ m_laUnderlineValue.setEnabled(false);
+
+ m_laFontValue.setText (FONT_OFF );
+ m_laSizeValue.setText (SIZE_OFF );
+ m_laBoldValue.setText (BOLD_OFF );
+ m_laItalicValue.setText (ITALIC_OFF );
+ m_laUnderlineValue.setText(UNDERLINE_OFF);
+ }
+
+
+
+ /*
+ * Set new frame for this view and start listening for events immediately.
+ * We create one status listener for every control we wish to update.
+ * And because the environment of the frame can be changed - these
+ * listener refresh himself internally for frame action events too.
+ * So we register it as such frame action listener only here.
+ * Rest is done automatically...
+ *
+ * @param xFrame
+ * will be used as source of possible status events
+ */
+ public void setFrame(com.sun.star.frame.XFrame xFrame)
+ {
+ if (xFrame==null)
+ return;
+
+ // create some listener on given frame for available status events
+ // Created listener instances will register themselves on this frame and
+ // show it received information automatically on set UI controls.
+ m_aFontListener = new StatusListener(m_laFontValue ,FONT_ON ,FONT_OFF ,xFrame, FEATUREURL_FONT );
+ m_aSizeListener = new StatusListener(m_laSizeValue ,SIZE_ON ,SIZE_OFF ,xFrame, FEATUREURL_SIZE );
+ m_aBoldListener = new StatusListener(m_laBoldValue ,BOLD_ON ,BOLD_OFF ,xFrame, FEATUREURL_BOLD );
+ m_aItalicListener = new StatusListener(m_laItalicValue ,ITALIC_ON ,ITALIC_OFF ,xFrame, FEATUREURL_ITALIC );
+ m_aUnderlineListener = new StatusListener(m_laUnderlineValue,UNDERLINE_ON,UNDERLINE_OFF,xFrame, FEATUREURL_UNDERLINE);
+
+ m_aFontListener.startListening();
+ m_aSizeListener.startListening();
+ m_aBoldListener.startListening();
+ m_aItalicListener.startListening();
+ m_aUnderlineListener.startListening();
+ }
+
+
+
+ /**
+ * If this java application shutdown - we must cancel all current existing
+ * listener connections. Otherwise the office will run into some
+ * DisposedExceptions if it tries to use these forgotten listener references.
+ * And of course it can die doing that.
+ * We are registered at a central object to be informed if the VM will exit.
+ * So we can react.
+ */
+ public void shutdown()
+ {
+ m_aFontListener.shutdown();
+ m_aSizeListener.shutdown();
+ m_aBoldListener.shutdown();
+ m_aItalicListener.shutdown();
+ m_aUnderlineListener.shutdown();
+
+ m_aFontListener = null;
+ m_aSizeListener = null;
+ m_aBoldListener = null;
+ m_aItalicListener = null;
+ m_aUnderlineListener = null;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/ViewContainer.java b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/ViewContainer.java
new file mode 100644
index 0000000000..d859f20353
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/ViewContainer.java
@@ -0,0 +1,260 @@
+/* -*- 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 java.util.*;
+
+// __________ Implementation __________
+
+/**
+ * It's implement a static container which hold
+ * all opened documents and her views alive.
+ * It's possible to register/deregister such views,
+ * to get information about these and it provides
+ * some global functionality - like termination of
+ * this demo application.
+ *
+ */
+public class ViewContainer extends Thread
+{
+
+
+ /**
+ * provides a singleton view container
+ * Necessary for terminate(9 functionality to be able
+ * to call Runtime.runFinilization().
+ *
+ * @return a reference to the singleton ViewContainer instance
+ */
+ public static synchronized ViewContainer getGlobalContainer()
+ {
+ if (maSingleton==null)
+ maSingleton=new ViewContainer();
+ return maSingleton;
+ }
+
+
+
+ /**
+ * ctor
+ * It's private - because nobody should create any instance
+ * expect the only global one, which will be created by ourself!
+ */
+ private ViewContainer()
+ {
+ mlViews = new ArrayList<Object>();
+ mlListener = new ArrayList<IShutdownListener>();
+ mbShutdownActive = false ;
+ Runtime.getRuntime().addShutdownHook(this);
+ }
+
+
+
+ /**
+ * This register a new view inside this global container
+ * (if it doesn't already exist).
+ *
+ * @param aView view which wishes to be registered inside this container
+ */
+ public void addView(Object aView)
+ {
+ synchronized(mlViews)
+ {
+ if(!mlViews.contains(aView))
+ mlViews.add(aView);
+ }
+ }
+
+
+
+ /**
+ * This deregister a view from this global container.
+ * Normally it should be the last reference to the view
+ * and her finalize() method should be called.
+ * If last view will be closed here - we terminate these
+ * java application too. Because there is no further
+ * visible frame anymore.
+ *
+ * @param aView
+ * view object which wishes to be deregistered
+ */
+ public void removeView(Object aView)
+ {
+ int nViewCount = 0;
+ synchronized(mlViews)
+ {
+ if(mlViews.contains(aView))
+ mlViews.remove(aView);
+
+ nViewCount = mlViews.size();
+
+ if (nViewCount<1)
+ mlViews = null;
+ }
+ // If this view is a registered shutdown listener on this view container
+ // too, we must call his interface and forget him as possible listener.
+ // It's necessary to guarantee his dead ...
+ boolean bShutdownView = false;
+ synchronized(mlListener)
+ {
+ bShutdownView = mlListener.contains(aView);
+ if (bShutdownView)
+ mlListener.remove(aView);
+ }
+ if (bShutdownView)
+ ((IShutdownListener)aView).shutdown();
+
+ // We use a system.exit() to finish the whole application.
+ // And further we have registered THIS instance as a possible shutdown
+ // hook at the runtime class. So our run() method will be called.
+ // Our view container should be empty - but
+ // our listener container can include some references.
+ // These objects will be informed then and release e.g. some
+ // remote references.
+ if (nViewCount<1)
+ {
+ boolean bNecessary = false;
+ synchronized(this)
+ {
+ bNecessary = ! mbShutdownActive;
+ }
+ if (bNecessary)
+ {
+ System.out.println("call exit(0)!");
+ System.exit(0);
+ }
+ }
+ }
+
+
+
+ /**
+ * add/remove listener for possible shutdown events
+ */
+ public void addListener( IShutdownListener rListener )
+ {
+ synchronized(mlListener)
+ {
+ if ( ! mlListener.contains(rListener) )
+ mlListener.add(rListener);
+ }
+ }
+
+
+
+ private void removeListener( IShutdownListener rListener )
+ {
+ synchronized(mlListener)
+ {
+ if ( mlListener.contains(rListener) )
+ mlListener.remove(rListener);
+ }
+ }
+
+
+
+ /**
+ * Is called from current runtime system of the java machine
+ * on shutdown. We inform all current registered listener and
+ * views. They should deinitialize her internal things then.
+ */
+ @Override
+ public void run()
+ {
+ synchronized(this)
+ {
+ if (mbShutdownActive)
+ return;
+ mbShutdownActive=true;
+ }
+
+ while( true )
+ {
+ IShutdownListener aListener = null;
+ synchronized(mlListener)
+ {
+ if (!mlListener.isEmpty())
+ aListener = mlListener.get(0);
+ }
+ if (aListener==null)
+ break;
+
+ aListener.shutdown();
+ // May this listener has deregistered himself.
+ // But if not we must do it for him. Our own
+ // method "removeListener()" ignore requests for
+ // already gone listener objects.
+ removeListener(aListener);
+ }
+
+ if (mlViews!=null)
+ {
+ synchronized(mlViews)
+ {
+ mlViews.clear();
+ mlViews = null;
+ }
+ }
+
+ if (mlListener!=null)
+ {
+ synchronized(mlListener)
+ {
+ mlListener.clear();
+ mlListener = null;
+ }
+ }
+ }
+
+
+
+ /**
+ * @member mbInplace indicates using of inplace office frames instead of outplace ones
+ * @member maSingleton singleton instance of this view container
+ * @member mlViews list of all currently registered document views
+ * @member mlListener list of all currently registered shutdown listener
+ * @member mbShutdownActive if this shutdown hook already was started it's not a good idea to
+ * call System.exit() again for other conditions.
+ * We suppress it by using this variable!
+ */
+ public static boolean mbInplace = false ;
+ private static ViewContainer maSingleton = null ;
+ private ArrayList<Object> mlViews ;
+ private ArrayList<IShutdownListener> mlListener ;
+ private boolean mbShutdownActive ;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/Makefile b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/Makefile
new file mode 100644
index 0000000000..aa7a158b86
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/Makefile
@@ -0,0 +1,72 @@
+#*************************************************************************
+#
+# 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.
+#
+#**************************************************************************
+
+# Builds the OfficeDevDesktopEnvironment native library of the Developers Guide.
+
+PRJ=../../../../../..
+SETTINGS=$(PRJ)/settings
+
+include $(SETTINGS)/settings.mk
+include $(SETTINGS)/std.mk
+
+# Define non-platform/compiler specific settings
+SHL_NAME=nativeview
+SHL_LIBRARY=$(SHAREDLIB_OUT)/$(SHAREDLIB_PRE)$(SHL_NAME).$(SHAREDLIB_EXT)
+
+OUT_SHL_SLO=$(OUT_SLO)/nativeview
+
+CFILES = nativeview.c
+
+SLOFILES = $(patsubst %.c,$(OUT_SHL_SLO)/%.$(OBJ_EXT),$(CFILES))
+
+
+# Targets
+.PHONY: ALL
+ALL : $(SHL_LIBRARY)
+
+include $(SETTINGS)/stdtarget.mk
+
+$(OUT_SHL_SLO)/%.$(OBJ_EXT) : %.c
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ $(CC) $(CC_FLAGS_JNI) $(CC_INCLUDES) $(SDK_JAVA_INCLUDES) $(CC_DEFINES_JNI) $(CC_OUTPUT_SWITCH)$(subst /,$(PS),$@) $<
+
+$(SHAREDLIB_OUT)/$(SHAREDLIB_PRE)$(SHL_NAME).$(SHAREDLIB_EXT) : $(SLOFILES)
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ $(LINK) $(LIBRARY_LINK_FLAGS) $(LINK_LIBS) $(LINK_JAVA_LIBS) -o $@ $< \
+ -ljawt $(CPPUHELPERLIB) $(CPPULIB) $(SALLIB) $(STDC++LIB)
+
+.PHONY: clean
+clean :
+ -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_SHL_SLO))
+ -$(DEL) $(subst /,$(PS),$(SHAREDLIB_OUT))$(PS)*$(SHL_NAME)*.*
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.c b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.c
new file mode 100644
index 0000000000..5343f85e96
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.c
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; 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.
+ *
+ *************************************************************************/
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Intrinsic.h>
+
+#include "jawt.h"
+#include "jawt_md.h"
+#include "nativeview.h"
+
+#define MY_ASSERT(X,S) if (!X) { fprintf(stderr,S); return 0;}
+
+#define SYSTEM_WIN32 1
+#define SYSTEM_WIN16 2
+#define SYSTEM_JAVA 3
+#define SYSTEM_OS2 4
+#define SYSTEM_MAC 5
+#define SYSTEM_XWINDOW 6
+
+/*****************************************************************************/
+/*
+ * Class: NativeView
+ * Method: getNativeWindowSystemType
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_NativeView_getNativeWindowSystemType
+ (JNIEnv * env, jobject obj_this)
+{
+ return SYSTEM_XWINDOW;
+}
+
+/*****************************************************************************/
+/*
+ * Class: NativeView
+ * Method: getNativeWindow
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_NativeView_getNativeWindow
+ (JNIEnv * env, jobject obj_this)
+{
+ jboolean result ;
+ jint lock ;
+ JAWT awt ;
+ JAWT_DrawingSurface* ds ;
+ JAWT_DrawingSurfaceInfo* dsi ;
+ JAWT_X11DrawingSurfaceInfo* dsi_x11 ;
+ Drawable drawable;
+
+ /* Get the AWT */
+ awt.version = JAWT_VERSION_1_3;
+ result = JAWT_GetAWT(env, &awt);
+ MY_ASSERT(result != JNI_FALSE,"wrong jawt version");
+
+ /* Get the drawing surface */
+ if ((ds = awt.GetDrawingSurface(env, obj_this)) == NULL)
+ return 0;
+
+ /* Lock the drawing surface */
+ lock = ds->Lock(ds);
+ MY_ASSERT((lock & JAWT_LOCK_ERROR)==0,"can't lock the drawing surface");
+
+ /* Get the drawing surface info */
+ dsi = ds->GetDrawingSurfaceInfo(ds);
+
+ /* Get the platform-specific drawing info */
+ dsi_x11 = (JAWT_X11DrawingSurfaceInfo*)dsi->platformInfo;
+ drawable = dsi_x11->drawable;
+
+ /* Free the drawing surface info */
+ ds->FreeDrawingSurfaceInfo(dsi);
+ /* Unlock the drawing surface */
+ ds->Unlock(ds);
+ /* Free the drawing surface */
+ awt.FreeDrawingSurface(ds);
+
+ return (jlong)drawable;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.h b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.h
new file mode 100644
index 0000000000..99207192f7
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/unix/nativeview.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; 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.
+ *
+ *************************************************************************/
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_openoffice_OpenOffice */
+
+#ifndef _Included_NativeView
+#define _Included_NativeView
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_openoffice_OpenOffice
+ * Method: getNativeWindowSystemType
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_NativeView_getNativeWindowSystemType(JNIEnv*, jobject);
+
+/*
+ * Class: org_openoffice_OpenOffice
+ * Method: getNativeWindow
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_NativeView_getNativeWindow(JNIEnv*, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/Makefile b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/Makefile
new file mode 100644
index 0000000000..62980a2eed
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/Makefile
@@ -0,0 +1,77 @@
+#*************************************************************************
+#
+# 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.
+#
+#**************************************************************************
+
+# Builds the OfficeDevDesktopEnvironment native library of the Developers Guide.
+
+PRJ=../../../../../..
+SETTINGS=$(PRJ)/settings
+
+include $(SETTINGS)/settings.mk
+include $(SETTINGS)/std.mk
+
+# Define non-platform/compiler specific settings
+SHL_NAME=nativeview
+SHL_LIBRARY=$(SHAREDLIB_OUT)/$(SHAREDLIB_PRE)$(SHL_NAME).$(SHAREDLIB_EXT)
+
+OUT_SHL_SLO=$(OUT_SLO)/nativeview
+OUT_SHL_MISC=$(OUT_MISC)/nativeview
+
+CFILES = nativeview.c
+
+SLOFILES = $(patsubst %.c,$(OUT_SHL_SLO)/%.$(OBJ_EXT),$(CFILES))
+
+# Targets
+.PHONY: ALL
+ALL : \
+ $(SHL_LIBRARY)
+
+include $(SETTINGS)/stdtarget.mk
+
+$(OUT_SHL_SLO)/%.$(OBJ_EXT) : %.c
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ $(CC) $(CC_FLAGS_JNI) $(CC_INCLUDES) $(SDK_JAVA_INCLUDES) $(CC_DEFINES_JNI) $(CC_OUTPUT_SWITCH)$(subst /,$(PS),$@) $<
+
+$(SHAREDLIB_OUT)/$(SHAREDLIB_PRE)$(SHL_NAME).$(SHAREDLIB_EXT) : $(SLOFILES) $(SHL_NAME).def
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ -$(MKDIR) $(subst /,$(PS),$(OUT_SHL_MISC))
+ $(LINK) $(LIBRARY_LINK_FLAGS) /DEF:$(SHL_NAME).def /OUT:$@ \
+ /MAP:$(OUT_SHL_MISC)/$(SHL_NAME).map $(LINK_JAVA_LIBS) \
+ $(SLOFILES) jawt.lib $(LIBO_SDK_LDFLAGS_STDLIBS) user32.lib
+ $(LINK_MANIFEST)
+
+.PHONY: clean
+clean :
+ -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_SHL_SLO))
+ -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_SHL_MISC))
+ -$(DEL) $(subst \\,\,$(subst /,$(PS),$(SHAREDLIB_OUT))$(PS)*$(SHL_NAME)*.*)
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.c b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.c
new file mode 100644
index 0000000000..2de998c694
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.c
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; 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.
+ *
+ *************************************************************************/
+
+#include <windows.h>
+
+#include "jawt.h"
+#include "jawt_md.h"
+#include "NativeView.h"
+
+#define MY_ASSERT(X,S) if (!X) { fprintf(stderr,"%s\n",S); return 0;}
+
+#define SYSTEM_WIN32 1
+#define SYSTEM_WIN16 2
+#define SYSTEM_JAVA 3
+#define SYSTEM_OS2 4
+#define SYSTEM_MAC 5
+#define SYSTEM_XWINDOW 6
+
+// property name to register own window procedure on hwnd
+#define OLD_PROC_KEY "oldwindowproc"
+// signature of this window procedure
+static LRESULT APIENTRY NativeViewWndProc( HWND , UINT , WPARAM , LPARAM );
+
+/*****************************************************************************
+ *
+ * Class : NativeView
+ * Method : getNativeWindowSystemType
+ * Signature : ()I
+ * Description: returns an identifier for the current operating system
+ */
+JNIEXPORT jint JNICALL Java_NativeView_getNativeWindowSystemType
+ (JNIEnv * env, jobject obj_this)
+{
+ return SYSTEM_WIN32;
+}
+
+/*****************************************************************************
+ *
+ * Class : NativeView
+ * Method : getNativeWindow
+ * Signature : ()J
+ * Description: returns the native systemw window handle of this object
+ */
+JNIEXPORT jlong JNICALL Java_NativeView_getNativeWindow
+ (JNIEnv * env, jobject obj_this)
+{
+ jboolean result ;
+ jint lock ;
+ JAWT awt ;
+ JAWT_DrawingSurface* ds ;
+ JAWT_DrawingSurfaceInfo* dsi ;
+ JAWT_Win32DrawingSurfaceInfo* dsi_win ;
+ HDC hdc ;
+ HWND hWnd ;
+ LONG hFuncPtr;
+
+ /* Get the AWT */
+ awt.version = JAWT_VERSION_1_3;
+ result = JAWT_GetAWT(env, &awt);
+ MY_ASSERT(result!=JNI_FALSE,"wrong jawt version");
+
+ /* Get the drawing surface */
+ if ((ds = awt.GetDrawingSurface(env, obj_this)) == NULL)
+ return 0;
+
+ /* Lock the drawing surface */
+ lock = ds->Lock(ds);
+ MY_ASSERT((lock & JAWT_LOCK_ERROR)==0,"can't lock the drawing surface");
+
+ /* Get the drawing surface info */
+ dsi = ds->GetDrawingSurfaceInfo(ds);
+
+ /* Get the platform-specific drawing info */
+ dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
+ hdc = dsi_win->hdc;
+ hWnd = dsi_win->hwnd;
+
+ /* Free the drawing surface info */
+ ds->FreeDrawingSurfaceInfo(dsi);
+ /* Unlock the drawing surface */
+ ds->Unlock(ds);
+ /* Free the drawing surface */
+ awt.FreeDrawingSurface(ds);
+
+ /* Register own window procedure
+ Do it one times only! Otherwise
+ multiple instances will be registered
+ and calls on such construct produce
+ a stack overflow.
+ */
+ if (GetProp( hWnd, OLD_PROC_KEY )==0)
+ {
+ hFuncPtr = SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR)NativeViewWndProc );
+ SetProp( hWnd, OLD_PROC_KEY, (HANDLE)hFuncPtr );
+ }
+
+ return (jlong)hWnd;
+}
+
+/*****************************************************************************
+ *
+ * Class : -
+ * Method : NativeViewWndProc
+ * Signature : -
+ * Description: registered window handler to intercept window messages between
+ * java and office process
+ */
+static LRESULT APIENTRY NativeViewWndProc(
+ HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hFuncPtr;
+
+ /* resize new created child window to fill out the java window complete */
+ if (uMsg==WM_PARENTNOTIFY)
+ {
+ if (wParam == WM_CREATE)
+ {
+ RECT rect;
+ HWND hChild = (HWND) lParam;
+
+ GetClientRect(hWnd, &rect);
+
+ SetWindowPos(hChild,
+ NULL,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOZORDER);
+ }
+ }
+ /* handle normal resize events */
+ else if(uMsg==WM_SIZE)
+ {
+ WORD newHeight = HIWORD(lParam);
+ WORD newWidth = LOWORD(lParam);
+ HWND hChild = GetWindow(hWnd, GW_CHILD);
+
+ if (hChild != NULL)
+ SetWindowPos(hChild, NULL, 0, 0, newWidth, newHeight, SWP_NOZORDER);
+ }
+
+ /* forward request to original handler which is intercepted by this window procedure */
+ hFuncPtr = GetProp(hWnd, OLD_PROC_KEY);
+ MY_ASSERT(hFuncPtr,"lost original window proc handler");
+ return CallWindowProc( hFuncPtr, hWnd, uMsg, wParam, lParam);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.def b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.def
new file mode 100644
index 0000000000..f9ba2a78b6
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.def
@@ -0,0 +1,3 @@
+EXPORTS
+Java_NativeView_getNativeWindowSystemType
+Java_NativeView_getNativeWindow
diff --git a/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.h b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.h
new file mode 100644
index 0000000000..99207192f7
--- /dev/null
+++ b/odk/examples/DevelopersGuide/OfficeDev/DesktopEnvironment/nativelib/windows/nativeview.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; 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.
+ *
+ *************************************************************************/
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_openoffice_OpenOffice */
+
+#ifndef _Included_NativeView
+#define _Included_NativeView
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_openoffice_OpenOffice
+ * Method: getNativeWindowSystemType
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_NativeView_getNativeWindowSystemType(JNIEnv*, jobject);
+
+/*
+ * Class: org_openoffice_OpenOffice
+ * Method: getNativeWindow
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_NativeView_getNativeWindow(JNIEnv*, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */