1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  *  The Contents of this file are made available subject to the terms of
4*cdf0e10cSrcweir  *  the BSD license.
5*cdf0e10cSrcweir  *
6*cdf0e10cSrcweir  *  Copyright 2000, 2010 Oracle and/or its affiliates.
7*cdf0e10cSrcweir  *  All rights reserved.
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  *  Redistribution and use in source and binary forms, with or without
10*cdf0e10cSrcweir  *  modification, are permitted provided that the following conditions
11*cdf0e10cSrcweir  *  are met:
12*cdf0e10cSrcweir  *  1. Redistributions of source code must retain the above copyright
13*cdf0e10cSrcweir  *     notice, this list of conditions and the following disclaimer.
14*cdf0e10cSrcweir  *  2. Redistributions in binary form must reproduce the above copyright
15*cdf0e10cSrcweir  *     notice, this list of conditions and the following disclaimer in the
16*cdf0e10cSrcweir  *     documentation and/or other materials provided with the distribution.
17*cdf0e10cSrcweir  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
18*cdf0e10cSrcweir  *     contributors may be used to endorse or promote products derived
19*cdf0e10cSrcweir  *     from this software without specific prior written permission.
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*cdf0e10cSrcweir  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*cdf0e10cSrcweir  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*cdf0e10cSrcweir  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25*cdf0e10cSrcweir  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*cdf0e10cSrcweir  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*cdf0e10cSrcweir  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28*cdf0e10cSrcweir  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29*cdf0e10cSrcweir  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30*cdf0e10cSrcweir  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31*cdf0e10cSrcweir  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*cdf0e10cSrcweir  *
33*cdf0e10cSrcweir  *************************************************************************/
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir // __________ Imports __________
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime;
38*cdf0e10cSrcweir import com.sun.star.uno.AnyConverter;
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir import java.lang.*;
41*cdf0e10cSrcweir import java.awt.*;
42*cdf0e10cSrcweir import javax.swing.*;
43*cdf0e10cSrcweir import java.io.*;
44*cdf0e10cSrcweir import java.net.*;
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir // __________ Implementation __________
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir /**
49*cdf0e10cSrcweir  * Is a collection of basic features.
50*cdf0e10cSrcweir  * This helper shows different functionality of framework api
51*cdf0e10cSrcweir  * in an example manner. You can use the follow ones:
52*cdf0e10cSrcweir  *      (1) parse URL's
53*cdf0e10cSrcweir  *      (2) create frames (inside/outside a java application)
54*cdf0e10cSrcweir  *      (3) dispatches (with[out] notifications)
55*cdf0e10cSrcweir  *      (4) loading/saving documents
56*cdf0e10cSrcweir  *      (5) convert documents to HTML (if possible)
57*cdf0e10cSrcweir  *      (6) close documents (and her frames) correctly
58*cdf0e10cSrcweir  *
59*cdf0e10cSrcweir  * There exist some other helper functionality too, which
60*cdf0e10cSrcweir  * doesn't use or demonstrate the office api:
61*cdf0e10cSrcweir  *      (a) getting file names by using a file chosser
62*cdf0e10cSrcweir  *
63*cdf0e10cSrcweir  * @author     Andreas Schlüns
64*cdf0e10cSrcweir  * @created    28.02.2002 15:31
65*cdf0e10cSrcweir  */
66*cdf0e10cSrcweir public class FunctionHelper
67*cdf0e10cSrcweir {
68*cdf0e10cSrcweir     // ____________________
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir     /**
71*cdf0e10cSrcweir      * This convert an URL (formated as a string) to a struct com.sun.star.util.URL.
72*cdf0e10cSrcweir      * It use a special service to do that: the URLTransformer.
73*cdf0e10cSrcweir      * Because some API calls need it and it's not allowed to set "Complete"
74*cdf0e10cSrcweir      * part of the util struct only. The URL must be parsed.
75*cdf0e10cSrcweir      *
76*cdf0e10cSrcweir      * @param sURL
77*cdf0e10cSrcweir      *          URL for parsing in string notation
78*cdf0e10cSrcweir      *
79*cdf0e10cSrcweir      * @return [com.sun.star.util.URL]
80*cdf0e10cSrcweir      *              URL in UNO struct notation
81*cdf0e10cSrcweir      */
82*cdf0e10cSrcweir     public static com.sun.star.util.URL parseURL(String sURL)
83*cdf0e10cSrcweir     {
84*cdf0e10cSrcweir         com.sun.star.util.URL aURL = null;
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir         if (sURL==null || sURL.equals(""))
87*cdf0e10cSrcweir         {
88*cdf0e10cSrcweir             System.out.println("wrong using of URL parser");
89*cdf0e10cSrcweir             return null;
90*cdf0e10cSrcweir         }
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir         try
93*cdf0e10cSrcweir         {
94*cdf0e10cSrcweir             com.sun.star.uno.XComponentContext xOfficeCtx =
95*cdf0e10cSrcweir                 OfficeConnect.getOfficeContext();
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir             // Create special service for parsing of given URL.
98*cdf0e10cSrcweir             com.sun.star.util.XURLTransformer xParser =
99*cdf0e10cSrcweir                 (com.sun.star.util.XURLTransformer)UnoRuntime.queryInterface(
100*cdf0e10cSrcweir                     com.sun.star.util.XURLTransformer.class,
101*cdf0e10cSrcweir                     xOfficeCtx.getServiceManager().createInstanceWithContext(
102*cdf0e10cSrcweir                         "com.sun.star.util.URLTransformer", xOfficeCtx));
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir             // Because it's an in/out parameter we must use an array of URL objects.
105*cdf0e10cSrcweir             com.sun.star.util.URL[] aParseURL = new com.sun.star.util.URL[1];
106*cdf0e10cSrcweir             aParseURL[0] = new com.sun.star.util.URL();
107*cdf0e10cSrcweir             aParseURL[0].Complete = sURL;
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir             // Parse the URL
110*cdf0e10cSrcweir             xParser.parseStrict(aParseURL);
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir             aURL = aParseURL[0];
113*cdf0e10cSrcweir         }
114*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exRuntime)
115*cdf0e10cSrcweir         {
116*cdf0e10cSrcweir             // Any UNO method of this scope can throw this exception.
117*cdf0e10cSrcweir             // Reset the return value only.
118*cdf0e10cSrcweir             aURL = null;
119*cdf0e10cSrcweir         }
120*cdf0e10cSrcweir         catch(com.sun.star.uno.Exception exUno)
121*cdf0e10cSrcweir         {
122*cdf0e10cSrcweir             // "createInstance()" method of used service manager can throw it.
123*cdf0e10cSrcweir             // Then it wasn't possible to get the URL transformer.
124*cdf0e10cSrcweir             // Return default instead of realy parsed URL.
125*cdf0e10cSrcweir             aURL = null;
126*cdf0e10cSrcweir         }
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir         return aURL;
129*cdf0e10cSrcweir     }
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir     // ____________________
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir     /**
134*cdf0e10cSrcweir      * create a new empty target frame
135*cdf0e10cSrcweir      * Attention: Currently we must use special service com.sun.star.frame.Task instead of Frame.
136*cdf0e10cSrcweir      * Because desktop environment accept this special frame type only as direct children.
137*cdf0e10cSrcweir      * Note - This service will be deprecated and must be replaces by com.sun.star.frame.Frame in
138*cdf0e10cSrcweir      * further versions. To feature prove we use both service names. If for new versions
139*cdf0e10cSrcweir      * the deprecated one not exist we get an empty frame, we can try to use the new service.
140*cdf0e10cSrcweir      *
141*cdf0e10cSrcweir      * @param xSMGR
142*cdf0e10cSrcweir      *          we nee the remote service manager to create this task/frame service
143*cdf0e10cSrcweir      *
144*cdf0e10cSrcweir      * @return [com.sun.star.frame.XFrame]
145*cdf0e10cSrcweir      *          the new created frame reference in case of success or null otherwhise
146*cdf0e10cSrcweir      */
147*cdf0e10cSrcweir     private static com.sun.star.frame.XFrame impl_createEmptyFrame(
148*cdf0e10cSrcweir         com.sun.star.uno.XComponentContext xCtx )
149*cdf0e10cSrcweir     {
150*cdf0e10cSrcweir         com.sun.star.frame.XFrame xFrame = null;
151*cdf0e10cSrcweir 
152*cdf0e10cSrcweir         try{
153*cdf0e10cSrcweir             xFrame = (com.sun.star.frame.XFrame)UnoRuntime.queryInterface(
154*cdf0e10cSrcweir                 com.sun.star.frame.XFrame.class,
155*cdf0e10cSrcweir                 xCtx.getServiceManager().createInstanceWithContext(
156*cdf0e10cSrcweir                     "com.sun.star.frame.Task", xCtx));
157*cdf0e10cSrcweir         } catch(com.sun.star.uno.Exception ex1) {}
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir         if (xFrame==null)
160*cdf0e10cSrcweir         {
161*cdf0e10cSrcweir             try{
162*cdf0e10cSrcweir                 xFrame = (com.sun.star.frame.XFrame)UnoRuntime.queryInterface(
163*cdf0e10cSrcweir                     com.sun.star.frame.XFrame.class,
164*cdf0e10cSrcweir                     xCtx.getServiceManager().createInstanceWithContext(
165*cdf0e10cSrcweir                         "com.sun.star.frame.Frame", xCtx));
166*cdf0e10cSrcweir             } catch(com.sun.star.uno.Exception ex2) {}
167*cdf0e10cSrcweir         }
168*cdf0e10cSrcweir 
169*cdf0e10cSrcweir         return xFrame;
170*cdf0e10cSrcweir     }
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir     // ____________________
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir     /**
175*cdf0e10cSrcweir      * create a new window which can be used as container window of an office frame
176*cdf0e10cSrcweir      * We know two modes for creation:
177*cdf0e10cSrcweir      *   - the office window will be a child of one of our java windows
178*cdf0e10cSrcweir      *   - the office will be a normal system window outside this java application
179*cdf0e10cSrcweir      * This behaviour will be regulated by the second parameter of this operation.
180*cdf0e10cSrcweir      * If a parentview is given the first mode will be activated - otherwhise
181*cdf0e10cSrcweir      * the second one.
182*cdf0e10cSrcweir      *
183*cdf0e10cSrcweir      * Note: First mode (creation of a child window) can be reached by two different
184*cdf0e10cSrcweir      *       ways.
185*cdf0e10cSrcweir      *   - pack the required window handle of our java window inside an UNO object
186*cdf0e10cSrcweir      *     to transport it to the remote office toolkit and get a child office
187*cdf0e10cSrcweir      *     window.
188*cdf0e10cSrcweir      *     This is the old way. It's better to use the second one - but to be
189*cdf0e10cSrcweir      *     future prove this old one should be tried too.
190*cdf0e10cSrcweir      *   - it's possible to pass the native window handle directly to the toolkit.
191*cdf0e10cSrcweir      *     A special interface method was enabled to accept that.
192*cdf0e10cSrcweir      *
193*cdf0e10cSrcweir      *   The right way to create an office window should be then:
194*cdf0e10cSrcweir      *   - try to use second creation mode (directly using of the window handle)
195*cdf0e10cSrcweir      *   - if it failed ... use the old way by packing the handle inside an object
196*cdf0e10cSrcweir      *
197*cdf0e10cSrcweir      * @param xSMGR
198*cdf0e10cSrcweir      *          we need a service manager to be able to create remote office
199*cdf0e10cSrcweir      *          services
200*cdf0e10cSrcweir      *
201*cdf0e10cSrcweir      * @param aParentView
202*cdf0e10cSrcweir      *          the java window as parent for the office window if an inplace office
203*cdf0e10cSrcweir      *          is required. If it is set to null the created office window will be
204*cdf0e10cSrcweir      *          a normal system window outside of our java application.
205*cdf0e10cSrcweir      *
206*cdf0e10cSrcweir      * @return [com.sun.star.awt.XWindow]
207*cdf0e10cSrcweir      *          The new created office window which can be used to set it as
208*cdf0e10cSrcweir      *          a ContainerWindow on an empty office frame.
209*cdf0e10cSrcweir      */
210*cdf0e10cSrcweir     private static com.sun.star.awt.XWindow impl_createWindow(
211*cdf0e10cSrcweir         com.sun.star.uno.XComponentContext xCtx, NativeView aParentView )
212*cdf0e10cSrcweir     {
213*cdf0e10cSrcweir         com.sun.star.awt.XWindow     xWindow  = null;
214*cdf0e10cSrcweir         com.sun.star.awt.XWindowPeer xPeer    = null;
215*cdf0e10cSrcweir         com.sun.star.awt.XToolkit    xToolkit = null;
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir         // get access to toolkit of remote office to create the container window of
218*cdf0e10cSrcweir         // new target frame
219*cdf0e10cSrcweir         try{
220*cdf0e10cSrcweir             xToolkit = (com.sun.star.awt.XToolkit)UnoRuntime.queryInterface(
221*cdf0e10cSrcweir                 com.sun.star.awt.XToolkit.class,
222*cdf0e10cSrcweir                 xCtx.getServiceManager().createInstanceWithContext(
223*cdf0e10cSrcweir                     "com.sun.star.awt.Toolkit", xCtx));
224*cdf0e10cSrcweir         }
225*cdf0e10cSrcweir         catch(com.sun.star.uno.Exception ex)
226*cdf0e10cSrcweir         {
227*cdf0e10cSrcweir             return null;
228*cdf0e10cSrcweir         }
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir         // mode 1) create an external system window
231*cdf0e10cSrcweir         if (aParentView==null)
232*cdf0e10cSrcweir         {
233*cdf0e10cSrcweir             // Describe the properties of the container window.
234*cdf0e10cSrcweir             com.sun.star.awt.WindowDescriptor aDescriptor =
235*cdf0e10cSrcweir                 new com.sun.star.awt.WindowDescriptor();
236*cdf0e10cSrcweir             aDescriptor.Type =   com.sun.star.awt.WindowClass.TOP;
237*cdf0e10cSrcweir             aDescriptor.WindowServiceName = "window";
238*cdf0e10cSrcweir             aDescriptor.ParentIndex = -1;
239*cdf0e10cSrcweir             aDescriptor.Parent = null;
240*cdf0e10cSrcweir             aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0);
241*cdf0e10cSrcweir             aDescriptor.WindowAttributes = com.sun.star.awt.WindowAttribute.BORDER |
242*cdf0e10cSrcweir                 com.sun.star.awt.WindowAttribute.MOVEABLE |
243*cdf0e10cSrcweir                 com.sun.star.awt.WindowAttribute.SIZEABLE |
244*cdf0e10cSrcweir                 com.sun.star.awt.WindowAttribute.CLOSEABLE;
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir             try{
247*cdf0e10cSrcweir                 xPeer = xToolkit.createWindow( aDescriptor );
248*cdf0e10cSrcweir             } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {}
249*cdf0e10cSrcweir         }
250*cdf0e10cSrcweir         // mode 2) create an internal office window as child of our given java
251*cdf0e10cSrcweir         // parent window
252*cdf0e10cSrcweir         else
253*cdf0e10cSrcweir         {
254*cdf0e10cSrcweir             // try new version of creation first: directly using of the window
255*cdf0e10cSrcweir             // handle. The old implementation of the corresponding toolkit method
256*cdf0e10cSrcweir             // requires a process ID. If this id isn't the right one a null object
257*cdf0e10cSrcweir             // is returned. But normaly nobody outside the office knows this id.
258*cdf0e10cSrcweir             // New version of this method ignore the id parameter and creation will
259*cdf0e10cSrcweir             // work.
260*cdf0e10cSrcweir             // Note: You must be shure if your window handle can be realy used by
261*cdf0e10cSrcweir             // the remote office. Means if this java client and the remote office
262*cdf0e10cSrcweir             // use the same display!
263*cdf0e10cSrcweir             com.sun.star.awt.XSystemChildFactory xChildFactory =
264*cdf0e10cSrcweir                 (com.sun.star.awt.XSystemChildFactory)UnoRuntime.queryInterface(
265*cdf0e10cSrcweir                     com.sun.star.awt.XSystemChildFactory.class, xToolkit);
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir             try
268*cdf0e10cSrcweir             {
269*cdf0e10cSrcweir                 Integer nHandle = aParentView.getHWND();
270*cdf0e10cSrcweir                 short   nSystem = (short)aParentView.getNativeWindowSystemType();
271*cdf0e10cSrcweir                 byte[]  lProcID = new byte[0];
272*cdf0e10cSrcweir 
273*cdf0e10cSrcweir                 xPeer = xChildFactory.createSystemChild((Object)nHandle,
274*cdf0e10cSrcweir                                                         lProcID, nSystem);
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir                 if (xPeer==null)
277*cdf0e10cSrcweir                 {
278*cdf0e10cSrcweir                     // mode 3) OK - new version doesn't work. It requires the
279*cdf0e10cSrcweir                     // process id which we doesn't have.
280*cdf0e10cSrcweir                     // So we must use the old way to get the right window peer.
281*cdf0e10cSrcweir                     // Pack the handle inside a wrapper object.
282*cdf0e10cSrcweir                     JavaWindowPeerFake aWrapper = new
283*cdf0e10cSrcweir                         JavaWindowPeerFake(aParentView);
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir                     com.sun.star.awt.XWindowPeer xParentPeer =
286*cdf0e10cSrcweir                         (com.sun.star.awt.XWindowPeer)UnoRuntime.queryInterface(
287*cdf0e10cSrcweir                             com.sun.star.awt.XWindowPeer.class, aWrapper);
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir                     com.sun.star.awt.WindowDescriptor aDescriptor =
290*cdf0e10cSrcweir                         new com.sun.star.awt.WindowDescriptor();
291*cdf0e10cSrcweir                     aDescriptor.Type = com.sun.star.awt.WindowClass.TOP;
292*cdf0e10cSrcweir                     aDescriptor.WindowServiceName = "workwindow";
293*cdf0e10cSrcweir                     aDescriptor.ParentIndex = 1;
294*cdf0e10cSrcweir                     aDescriptor.Parent = xParentPeer;
295*cdf0e10cSrcweir                     aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0);
296*cdf0e10cSrcweir                     if (nSystem == com.sun.star.lang.SystemDependent.SYSTEM_WIN32)
297*cdf0e10cSrcweir                         aDescriptor.WindowAttributes =
298*cdf0e10cSrcweir                             com.sun.star.awt.WindowAttribute.SHOW;
299*cdf0e10cSrcweir                     else
300*cdf0e10cSrcweir                         aDescriptor.WindowAttributes =
301*cdf0e10cSrcweir                             com.sun.star.awt.WindowAttribute.SYSTEMDEPENDENT;
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir                     try{
304*cdf0e10cSrcweir                         xPeer = xToolkit.createWindow( aDescriptor );
305*cdf0e10cSrcweir                     } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {}
306*cdf0e10cSrcweir                 }
307*cdf0e10cSrcweir             }
308*cdf0e10cSrcweir             catch(java.lang.RuntimeException exJRun)
309*cdf0e10cSrcweir             {
310*cdf0e10cSrcweir                 // This exception is thrown by the native JNI code if it try to get
311*cdf0e10cSrcweir                 // the systemw window handle. A possible reason can be an invisible
312*cdf0e10cSrcweir                 // java window. In this case it should be enough to set return
313*cdf0e10cSrcweir                 // values to null. All other ressources (which was created before)
314*cdf0e10cSrcweir                 // will be freed automaticly if scope wil be leaved.
315*cdf0e10cSrcweir                 System.out.println("May be the NativeView object wasn't realy visible at calling time of getNativeWindow()?");
316*cdf0e10cSrcweir                 xPeer   = null;
317*cdf0e10cSrcweir                 xWindow = null;
318*cdf0e10cSrcweir             }
319*cdf0e10cSrcweir         }
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir         // It doesn't matter which way was used to get the window peer.
322*cdf0e10cSrcweir         // Cast it to the right return interface and return it.
323*cdf0e10cSrcweir         xWindow = (com.sun.star.awt.XWindow)UnoRuntime.queryInterface(
324*cdf0e10cSrcweir             com.sun.star.awt.XWindow.class,
325*cdf0e10cSrcweir             xPeer);
326*cdf0e10cSrcweir 
327*cdf0e10cSrcweir         return xWindow;
328*cdf0e10cSrcweir     }
329*cdf0e10cSrcweir 
330*cdf0e10cSrcweir     // ____________________
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir     /**
333*cdf0e10cSrcweir      * This method create a new empty child frame on desktop instance of remote office.
334*cdf0e10cSrcweir      * It use a special JNI functionality to pass the office XWindow over a java window.
335*cdf0e10cSrcweir      * This java window can be inserted into another java window container for complex layouting.
336*cdf0e10cSrcweir      * If this parent java window isn't used, a top level system window will be created.
337*cdf0e10cSrcweir      * The the resulting office frame isn't plugged into this java application.
338*cdf0e10cSrcweir      *
339*cdf0e10cSrcweir      * @param sName
340*cdf0e10cSrcweir      *          name to set it on the new created frame
341*cdf0e10cSrcweir      *
342*cdf0e10cSrcweir      * @param aParentView
343*cdf0e10cSrcweir      *          java window which should be used as parent window of new created office frame window
344*cdf0e10cSrcweir      *          May be set to null.
345*cdf0e10cSrcweir      *
346*cdf0e10cSrcweir      * @return [com.sun.star.frame.XFrame]
347*cdf0e10cSrcweir      *          reference to the new created frame for success or null if it failed
348*cdf0e10cSrcweir      */
349*cdf0e10cSrcweir     public static com.sun.star.frame.XFrame createViewFrame(String sName, NativeView aParentView)
350*cdf0e10cSrcweir     {
351*cdf0e10cSrcweir         com.sun.star.frame.XFrame xFrame = null;
352*cdf0e10cSrcweir 
353*cdf0e10cSrcweir         try
354*cdf0e10cSrcweir         {
355*cdf0e10cSrcweir             com.sun.star.uno.XComponentContext xCtx =
356*cdf0e10cSrcweir                 OfficeConnect.getOfficeContext();
357*cdf0e10cSrcweir 
358*cdf0e10cSrcweir             // create an empty office frame first
359*cdf0e10cSrcweir             xFrame = impl_createEmptyFrame(xCtx);
360*cdf0e10cSrcweir 
361*cdf0e10cSrcweir             // create an office window then
362*cdf0e10cSrcweir             // Depending from the given parameter aParentView it will be a child or a top level
363*cdf0e10cSrcweir             // system window. (see impl method for further informations)
364*cdf0e10cSrcweir             // But before we call this helper - prepare the possible parent window: show it.
365*cdf0e10cSrcweir             // JNI calls to get system window handle of java window can't work without that!
366*cdf0e10cSrcweir             if (aParentView!=null)
367*cdf0e10cSrcweir                 aParentView.setVisible(true);
368*cdf0e10cSrcweir             com.sun.star.awt.XWindow xWindow = impl_createWindow(xCtx, aParentView);
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir             // pass the window the frame as his new container window.
371*cdf0e10cSrcweir             // It's neccessary to do it first  - before you call anything else there.
372*cdf0e10cSrcweir             // Otherwhise the frame throws some exceptions for "uninitialized state".
373*cdf0e10cSrcweir             xFrame.initialize( xWindow );
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir             // Insert the new frame in desktop hierarchy.
376*cdf0e10cSrcweir             // Use XFrames interface to do so. It provides access to the child frame container of that instance.
377*cdf0e10cSrcweir             com.sun.star.frame.XFramesSupplier xTreeRoot = (com.sun.star.frame.XFramesSupplier)UnoRuntime.queryInterface(
378*cdf0e10cSrcweir                 com.sun.star.frame.XFramesSupplier.class,
379*cdf0e10cSrcweir                 xCtx.getServiceManager().createInstanceWithContext(
380*cdf0e10cSrcweir                     "com.sun.star.frame.Desktop", xCtx));
381*cdf0e10cSrcweir             com.sun.star.frame.XFrames xChildContainer = xTreeRoot.getFrames();
382*cdf0e10cSrcweir             xChildContainer.append(xFrame);
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir             // Make some further initializations on frame and window.
385*cdf0e10cSrcweir             xWindow.setVisible(true);
386*cdf0e10cSrcweir             xFrame.setName(sName);
387*cdf0e10cSrcweir         }
388*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exRuntime)
389*cdf0e10cSrcweir         {
390*cdf0e10cSrcweir             // Any UNO method of this scope can throw this exception.
391*cdf0e10cSrcweir             // So the frame can be already created and he must be freed
392*cdf0e10cSrcweir             // correctly. May be he was inserted into the desktop tree too ...
393*cdf0e10cSrcweir             if(xFrame!=null)
394*cdf0e10cSrcweir             {
395*cdf0e10cSrcweir                 // Try to dispose the frame. He should deregister himself at the desktop object
396*cdf0e10cSrcweir                 // and free all internal used ressources (e.g. the container window) automaticly.
397*cdf0e10cSrcweir                 // It's possible to do that here - because frame has no component inside yet.
398*cdf0e10cSrcweir                 // So nobody can disagree with that.
399*cdf0e10cSrcweir                 // After the dispose() call forget all references to this frame and let him die.
400*cdf0e10cSrcweir                 // If a new exception will occure ... no generell solution exist then.
401*cdf0e10cSrcweir                 // Nobody can guarantee if next call will work or not.
402*cdf0e10cSrcweir                 com.sun.star.lang.XComponent xComponent = (com.sun.star.lang.XComponent)UnoRuntime.queryInterface(
403*cdf0e10cSrcweir                     com.sun.star.lang.XComponent.class,
404*cdf0e10cSrcweir                     xFrame);
405*cdf0e10cSrcweir                 xComponent.dispose();
406*cdf0e10cSrcweir                 xComponent = null;
407*cdf0e10cSrcweir                 xFrame     = null;
408*cdf0e10cSrcweir             }
409*cdf0e10cSrcweir         }
410*cdf0e10cSrcweir         catch(com.sun.star.uno.Exception exUno)
411*cdf0e10cSrcweir         {
412*cdf0e10cSrcweir             // "createInstance()" method of used service manager can throw it.
413*cdf0e10cSrcweir             // If it occured during creation of desktop service the frame already was created.
414*cdf0e10cSrcweir             // Free it by decresing his refcount. Changes on the desktop tree couldn't exist.
415*cdf0e10cSrcweir             // Without the desktop service that wasn't possible. So no further rollbacks must follow.
416*cdf0e10cSrcweir             if(xFrame!=null)
417*cdf0e10cSrcweir             {
418*cdf0e10cSrcweir                 com.sun.star.lang.XComponent xComponent = (com.sun.star.lang.XComponent)UnoRuntime.queryInterface(
419*cdf0e10cSrcweir                     com.sun.star.lang.XComponent.class,
420*cdf0e10cSrcweir                     xFrame);
421*cdf0e10cSrcweir                 xComponent.dispose();
422*cdf0e10cSrcweir                 xComponent = null;
423*cdf0e10cSrcweir                 xFrame     = null;
424*cdf0e10cSrcweir             }
425*cdf0e10cSrcweir         }
426*cdf0e10cSrcweir 
427*cdf0e10cSrcweir         return xFrame;
428*cdf0e10cSrcweir     }
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir     // ____________________
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir     /**
433*cdf0e10cSrcweir      * Dispatch an URL to given frame.
434*cdf0e10cSrcweir      * Caller can register himself for following status events for dispatched
435*cdf0e10cSrcweir      * URL too. But nobody guarantee that such notifications will occure.
436*cdf0e10cSrcweir      * (see dispatchWithNotification() if you interest on that)
437*cdf0e10cSrcweir      * The returned dispatch object should be hold alive by caller
438*cdf0e10cSrcweir      * till he deosn't need it any longer. Otherwise the dispatcher can(!)
439*cdf0e10cSrcweir      * die by decreasing his refcount.
440*cdf0e10cSrcweir      *
441*cdf0e10cSrcweir      * @param   xFrame      frame wich should be the target of this dispatch
442*cdf0e10cSrcweir      * @param   aURL        full parsed and converted office URL for dispatch
443*cdf0e10cSrcweir      * @param   lProperties optional arguments for dispatch
444*cdf0e10cSrcweir      * @param   xListener   optional listener which is registered automaticly for status events
445*cdf0e10cSrcweir      *                      (Note: Deregistration is part of this listener himself!)
446*cdf0e10cSrcweir      *
447*cdf0e10cSrcweir      * @return  [XDispatch] It's the used dispatch object and can be used for deregistration of an optional listener.
448*cdf0e10cSrcweir      *                      Otherwhise caller can ignore it.
449*cdf0e10cSrcweir      */
450*cdf0e10cSrcweir     public static com.sun.star.frame.XDispatch execute(com.sun.star.frame.XFrame          xFrame     ,
451*cdf0e10cSrcweir                                                        com.sun.star.util.URL              aURL       ,
452*cdf0e10cSrcweir                                                        com.sun.star.beans.PropertyValue[] lProperties,
453*cdf0e10cSrcweir                                                        com.sun.star.frame.XStatusListener xListener  )
454*cdf0e10cSrcweir     {
455*cdf0e10cSrcweir         com.sun.star.frame.XDispatch xDispatcher = null;
456*cdf0e10cSrcweir 
457*cdf0e10cSrcweir         try
458*cdf0e10cSrcweir         {
459*cdf0e10cSrcweir             // Query the frame for right interface which provides access to all available dispatch objects.
460*cdf0e10cSrcweir             com.sun.star.frame.XDispatchProvider xProvider = (com.sun.star.frame.XDispatchProvider)UnoRuntime.queryInterface(
461*cdf0e10cSrcweir                 com.sun.star.frame.XDispatchProvider.class,
462*cdf0e10cSrcweir                 xFrame);
463*cdf0e10cSrcweir 
464*cdf0e10cSrcweir             // Ask himn for right dispatch object for given URL.
465*cdf0e10cSrcweir             // Force given frame as target for following dispatch by using "".
466*cdf0e10cSrcweir             // It means the same like "_self".
467*cdf0e10cSrcweir             xDispatcher = xProvider.queryDispatch(aURL,"",0);
468*cdf0e10cSrcweir 
469*cdf0e10cSrcweir             // Dispatch the URL into the frame.
470*cdf0e10cSrcweir             if(xDispatcher!=null)
471*cdf0e10cSrcweir             {
472*cdf0e10cSrcweir                 if(xListener!=null)
473*cdf0e10cSrcweir                     xDispatcher.addStatusListener(xListener,aURL);
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir                 xDispatcher.dispatch(aURL,lProperties);
476*cdf0e10cSrcweir             }
477*cdf0e10cSrcweir         }
478*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exUno)
479*cdf0e10cSrcweir         {
480*cdf0e10cSrcweir             // Any UNO method of this scope can throw this exception.
481*cdf0e10cSrcweir             // But there will be nothing to do then - because
482*cdf0e10cSrcweir             // we haven't changed anything inside the remote objects
483*cdf0e10cSrcweir             // except method "addStatusListener().
484*cdf0e10cSrcweir             // But in this case the source of this exception has to
485*cdf0e10cSrcweir             // rollback all his operations. There is no chance to
486*cdf0e10cSrcweir             // make anything right then.
487*cdf0e10cSrcweir             // Reset the return value to a default - that's it.
488*cdf0e10cSrcweir             exUno.printStackTrace();
489*cdf0e10cSrcweir             xDispatcher = null;
490*cdf0e10cSrcweir         }
491*cdf0e10cSrcweir 
492*cdf0e10cSrcweir         return xDispatcher;
493*cdf0e10cSrcweir     }
494*cdf0e10cSrcweir 
495*cdf0e10cSrcweir     // ____________________
496*cdf0e10cSrcweir 
497*cdf0e10cSrcweir     /**
498*cdf0e10cSrcweir      * Dispatch an URL to given frame.
499*cdf0e10cSrcweir      * Caller can register himself for following result events for dispatched
500*cdf0e10cSrcweir      * URL too. Notifications are guaranteed (instead of dispatch())
501*cdf0e10cSrcweir      * Returning of the dispatch object isn't neccessary.
502*cdf0e10cSrcweir      * Nobody must hold it alive longer the dispatch needs.
503*cdf0e10cSrcweir      *
504*cdf0e10cSrcweir      * @param   xFrame      frame wich should be the target of this dispatch
505*cdf0e10cSrcweir      * @param   aURL        full parsed and converted office URL for dispatch
506*cdf0e10cSrcweir      * @param   lProperties optional arguments for dispatch
507*cdf0e10cSrcweir      * @param   xListener   optional listener which is registered automaticly for status events
508*cdf0e10cSrcweir      *                      (Note: Deregistration is not supported. Dispatcher does it automaticly.)
509*cdf0e10cSrcweir      */
510*cdf0e10cSrcweir     public static void executeWithNotification(com.sun.star.frame.XFrame                  xFrame     ,
511*cdf0e10cSrcweir                                                com.sun.star.util.URL                      aURL       ,
512*cdf0e10cSrcweir                                                com.sun.star.beans.PropertyValue[]         lProperties,
513*cdf0e10cSrcweir                                                com.sun.star.frame.XDispatchResultListener xListener  )
514*cdf0e10cSrcweir     {
515*cdf0e10cSrcweir         try
516*cdf0e10cSrcweir         {
517*cdf0e10cSrcweir             // Query the frame for right interface which provides access to all available dispatch objects.
518*cdf0e10cSrcweir             com.sun.star.frame.XDispatchProvider xProvider = (com.sun.star.frame.XDispatchProvider)UnoRuntime.queryInterface(
519*cdf0e10cSrcweir                 com.sun.star.frame.XDispatchProvider.class,
520*cdf0e10cSrcweir                 xFrame);
521*cdf0e10cSrcweir 
522*cdf0e10cSrcweir             // Ask himn for right dispatch object for given URL.
523*cdf0e10cSrcweir             // Force THIS frame as target for following dispatch.
524*cdf0e10cSrcweir             // Attention: The interface XNotifyingDispatch is an optional one!
525*cdf0e10cSrcweir             com.sun.star.frame.XDispatch xDispatcher = xProvider.queryDispatch(aURL,"",0);
526*cdf0e10cSrcweir             com.sun.star.frame.XNotifyingDispatch xNotifyingDispatcher = (com.sun.star.frame.XNotifyingDispatch)UnoRuntime.queryInterface(
527*cdf0e10cSrcweir                 com.sun.star.frame.XNotifyingDispatch.class,
528*cdf0e10cSrcweir                 xDispatcher);
529*cdf0e10cSrcweir 
530*cdf0e10cSrcweir             // Dispatch the URL.
531*cdf0e10cSrcweir             if(xNotifyingDispatcher!=null)
532*cdf0e10cSrcweir                 xNotifyingDispatcher.dispatchWithNotification(aURL,lProperties,xListener);
533*cdf0e10cSrcweir         }
534*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exUno)
535*cdf0e10cSrcweir         {
536*cdf0e10cSrcweir             // Any UNO method of this scope can throw this exception.
537*cdf0e10cSrcweir             // But there is nothing we can do then.
538*cdf0e10cSrcweir             exUno.printStackTrace();
539*cdf0e10cSrcweir         }
540*cdf0e10cSrcweir     }
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir     // ____________________
543*cdf0e10cSrcweir 
544*cdf0e10cSrcweir     /**
545*cdf0e10cSrcweir      * Load document specified by an URL into given frame synchronously.
546*cdf0e10cSrcweir      * The result of this operation will be the loaded document for success
547*cdf0e10cSrcweir      * or null if loading failed.
548*cdf0e10cSrcweir      *
549*cdf0e10cSrcweir      * @param   xFrame          frame wich should be the target of this load call
550*cdf0e10cSrcweir      * @param   sURL            unparsed URL for loading
551*cdf0e10cSrcweir      * @param   lProperties     optional arguments
552*cdf0e10cSrcweir      *
553*cdf0e10cSrcweir      * @return  [XComponent]    the loaded document for success or null if it's failed
554*cdf0e10cSrcweir      */
555*cdf0e10cSrcweir     public static com.sun.star.lang.XComponent loadDocument(
556*cdf0e10cSrcweir         com.sun.star.frame.XFrame xFrame, String sURL,
557*cdf0e10cSrcweir         com.sun.star.beans.PropertyValue[] lProperties)
558*cdf0e10cSrcweir     {
559*cdf0e10cSrcweir         com.sun.star.lang.XComponent xDocument = null;
560*cdf0e10cSrcweir         String                       sOldName  = null;
561*cdf0e10cSrcweir 
562*cdf0e10cSrcweir         try
563*cdf0e10cSrcweir         {
564*cdf0e10cSrcweir             com.sun.star.uno.XComponentContext xCtx =
565*cdf0e10cSrcweir                 OfficeConnect.getOfficeContext();
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir             // First prepare frame for loading
568*cdf0e10cSrcweir             // We must adress it inside the frame tree without any complications.
569*cdf0e10cSrcweir             // So we set an unambigous (we hope it) name and use it later.
570*cdf0e10cSrcweir             // Don't forget to reset original name after that.
571*cdf0e10cSrcweir                    sOldName = xFrame.getName();
572*cdf0e10cSrcweir             String sTarget  = "odk_officedev_desk";
573*cdf0e10cSrcweir             xFrame.setName(sTarget);
574*cdf0e10cSrcweir 
575*cdf0e10cSrcweir             // Get access to the global component loader of the office
576*cdf0e10cSrcweir             // for synchronous loading the document.
577*cdf0e10cSrcweir             com.sun.star.frame.XComponentLoader xLoader =
578*cdf0e10cSrcweir                 (com.sun.star.frame.XComponentLoader)UnoRuntime.queryInterface(
579*cdf0e10cSrcweir                     com.sun.star.frame.XComponentLoader.class,
580*cdf0e10cSrcweir                     xCtx.getServiceManager().createInstanceWithContext(
581*cdf0e10cSrcweir                         "com.sun.star.frame.Desktop", xCtx));
582*cdf0e10cSrcweir 
583*cdf0e10cSrcweir             // Load the document into the target frame by using his name and
584*cdf0e10cSrcweir             // special search flags.
585*cdf0e10cSrcweir             xDocument = xLoader.loadComponentFromURL(
586*cdf0e10cSrcweir                 sURL,
587*cdf0e10cSrcweir                 sTarget,
588*cdf0e10cSrcweir                 com.sun.star.frame.FrameSearchFlag.CHILDREN,
589*cdf0e10cSrcweir                 lProperties);
590*cdf0e10cSrcweir 
591*cdf0e10cSrcweir             // dont forget to restore old frame name ...
592*cdf0e10cSrcweir             xFrame.setName(sOldName);
593*cdf0e10cSrcweir         }
594*cdf0e10cSrcweir         catch(com.sun.star.io.IOException exIO)
595*cdf0e10cSrcweir         {
596*cdf0e10cSrcweir             // Can be thrown by "loadComponentFromURL()" call.
597*cdf0e10cSrcweir             // The only thing we should do then is to reset changed frame name!
598*cdf0e10cSrcweir             exIO.printStackTrace();
599*cdf0e10cSrcweir             xDocument = null;
600*cdf0e10cSrcweir             if(sOldName!=null)
601*cdf0e10cSrcweir                 xFrame.setName(sOldName);
602*cdf0e10cSrcweir         }
603*cdf0e10cSrcweir         catch(com.sun.star.lang.IllegalArgumentException exIllegal)
604*cdf0e10cSrcweir         {
605*cdf0e10cSrcweir             // Can be thrown by "loadComponentFromURL()" call.
606*cdf0e10cSrcweir             // The only thing we should do then is to reset changed frame name!
607*cdf0e10cSrcweir             exIllegal.printStackTrace();
608*cdf0e10cSrcweir             xDocument = null;
609*cdf0e10cSrcweir             if(sOldName!=null)
610*cdf0e10cSrcweir                 xFrame.setName(sOldName);
611*cdf0e10cSrcweir         }
612*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exRuntime)
613*cdf0e10cSrcweir         {
614*cdf0e10cSrcweir             // Any UNO method of this scope can throw this exception.
615*cdf0e10cSrcweir             // The only thing we can try(!) is to reset changed frame name.
616*cdf0e10cSrcweir             exRuntime.printStackTrace();
617*cdf0e10cSrcweir             xDocument = null;
618*cdf0e10cSrcweir             if(sOldName!=null)
619*cdf0e10cSrcweir                 xFrame.setName(sOldName);
620*cdf0e10cSrcweir         }
621*cdf0e10cSrcweir         catch(com.sun.star.uno.Exception exUno)
622*cdf0e10cSrcweir         {
623*cdf0e10cSrcweir             // "createInstance()" method of used service manager can throw it.
624*cdf0e10cSrcweir             // The only thing we should do then is to reset changed frame name!
625*cdf0e10cSrcweir             exUno.printStackTrace();
626*cdf0e10cSrcweir             xDocument = null;
627*cdf0e10cSrcweir             if(sOldName!=null)
628*cdf0e10cSrcweir                 xFrame.setName(sOldName);
629*cdf0e10cSrcweir         }
630*cdf0e10cSrcweir 
631*cdf0e10cSrcweir         return xDocument;
632*cdf0e10cSrcweir     }
633*cdf0e10cSrcweir 
634*cdf0e10cSrcweir     // ____________________
635*cdf0e10cSrcweir 
636*cdf0e10cSrcweir     /**
637*cdf0e10cSrcweir      * Save currently loaded document of given frame.
638*cdf0e10cSrcweir      *
639*cdf0e10cSrcweir      * @param   xDocument   document for saving changes
640*cdf0e10cSrcweir      */
641*cdf0e10cSrcweir     public static void saveDocument(com.sun.star.lang.XComponent xDocument)
642*cdf0e10cSrcweir     {
643*cdf0e10cSrcweir         try
644*cdf0e10cSrcweir         {
645*cdf0e10cSrcweir             // Check for supported model functionality.
646*cdf0e10cSrcweir             // Normaly the application documents (text, spreadsheet ...) do so
647*cdf0e10cSrcweir             // but some other ones (e.g. db components) doesn't do that.
648*cdf0e10cSrcweir             // They can't be save then.
649*cdf0e10cSrcweir             com.sun.star.frame.XModel xModel = (com.sun.star.frame.XModel)UnoRuntime.queryInterface(
650*cdf0e10cSrcweir                 com.sun.star.frame.XModel.class,
651*cdf0e10cSrcweir                 xDocument);
652*cdf0e10cSrcweir             if(xModel!=null)
653*cdf0e10cSrcweir             {
654*cdf0e10cSrcweir                 // Check for modifications => break save process if there is nothing to do.
655*cdf0e10cSrcweir                 com.sun.star.util.XModifiable xModified = (com.sun.star.util.XModifiable)UnoRuntime.queryInterface(
656*cdf0e10cSrcweir                     com.sun.star.util.XModifiable.class,
657*cdf0e10cSrcweir                     xModel);
658*cdf0e10cSrcweir                 if(xModified.isModified()==true)
659*cdf0e10cSrcweir                 {
660*cdf0e10cSrcweir                     com.sun.star.frame.XStorable xStore = (com.sun.star.frame.XStorable)UnoRuntime.queryInterface(
661*cdf0e10cSrcweir                         com.sun.star.frame.XStorable.class,
662*cdf0e10cSrcweir                         xModel);
663*cdf0e10cSrcweir 
664*cdf0e10cSrcweir                     xStore.store();
665*cdf0e10cSrcweir                 }
666*cdf0e10cSrcweir             }
667*cdf0e10cSrcweir         }
668*cdf0e10cSrcweir         catch(com.sun.star.io.IOException exIO)
669*cdf0e10cSrcweir         {
670*cdf0e10cSrcweir             // Can be thrown by "store()" call.
671*cdf0e10cSrcweir             // But there is nothing we can do then.
672*cdf0e10cSrcweir             exIO.printStackTrace();
673*cdf0e10cSrcweir         }
674*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exUno)
675*cdf0e10cSrcweir         {
676*cdf0e10cSrcweir             // Any UNO method of this scope can throw this exception.
677*cdf0e10cSrcweir             // But there is nothing we can do then.
678*cdf0e10cSrcweir             exUno.printStackTrace();
679*cdf0e10cSrcweir         }
680*cdf0e10cSrcweir     }
681*cdf0e10cSrcweir 
682*cdf0e10cSrcweir     // ____________________
683*cdf0e10cSrcweir 
684*cdf0e10cSrcweir     /**
685*cdf0e10cSrcweir      * It try to export given document in HTML format.
686*cdf0e10cSrcweir      * Current document will be converted to HTML and moved to new place on disk.
687*cdf0e10cSrcweir      * A "new" file will be created by given URL (may be overwritten
688*cdf0e10cSrcweir      * if it already exist). Right filter will be used automaticly if factory of
689*cdf0e10cSrcweir      * this document support it. If no valid filter can be found for export,
690*cdf0e10cSrcweir      * nothing will be done here.
691*cdf0e10cSrcweir      *
692*cdf0e10cSrcweir      * @param   xDocument   document which should be exported
693*cdf0e10cSrcweir      * @param   sURL        target URL for converted document
694*cdf0e10cSrcweir      */
695*cdf0e10cSrcweir     public static void saveAsHTML(com.sun.star.lang.XComponent xDocument,
696*cdf0e10cSrcweir                                   String                       sURL     )
697*cdf0e10cSrcweir     {
698*cdf0e10cSrcweir         try
699*cdf0e10cSrcweir         {
700*cdf0e10cSrcweir             // First detect factory of this document.
701*cdf0e10cSrcweir             // Ask for the supported service name of this document.
702*cdf0e10cSrcweir             // If information is available it can be used to find out wich
703*cdf0e10cSrcweir             // filter exist for HTML export. Normaly this filter should be searched
704*cdf0e10cSrcweir             // inside the filter configuration but this little demo doesn't do so.
705*cdf0e10cSrcweir             // (see service com.sun.star.document.FilterFactory for further
706*cdf0e10cSrcweir             // informations too)
707*cdf0e10cSrcweir             // Well known filter names are used directly. They must exist in current
708*cdf0e10cSrcweir             // office installation. Otherwise this code will fail. But to prevent
709*cdf0e10cSrcweir             // this code against missing filters it check for existing state of it.
710*cdf0e10cSrcweir             com.sun.star.lang.XServiceInfo xInfo = (com.sun.star.lang.XServiceInfo)
711*cdf0e10cSrcweir                 UnoRuntime.queryInterface(com.sun.star.lang.XServiceInfo.class,
712*cdf0e10cSrcweir                                           xDocument);
713*cdf0e10cSrcweir 
714*cdf0e10cSrcweir             if(xInfo!=null)
715*cdf0e10cSrcweir             {
716*cdf0e10cSrcweir                 // Find out possible filter name.
717*cdf0e10cSrcweir                 String sFilter = null;
718*cdf0e10cSrcweir                 if(xInfo.supportsService("com.sun.star.text.TextDocument")==true)
719*cdf0e10cSrcweir                     sFilter = new String("HTML (StarWriter)");
720*cdf0e10cSrcweir                 else
721*cdf0e10cSrcweir                 if(xInfo.supportsService("com.sun.star.text.WebDocument")==true)
722*cdf0e10cSrcweir                     sFilter = new String("HTML");
723*cdf0e10cSrcweir                 else
724*cdf0e10cSrcweir                 if(xInfo.supportsService("com.sun.star.sheet.SpreadsheetDocument")==true)
725*cdf0e10cSrcweir                     sFilter = new String("HTML (StarCalc)");
726*cdf0e10cSrcweir 
727*cdf0e10cSrcweir                 // Check for existing state of this filter.
728*cdf0e10cSrcweir                 if(sFilter!=null)
729*cdf0e10cSrcweir                 {
730*cdf0e10cSrcweir                     com.sun.star.uno.XComponentContext xCtx =
731*cdf0e10cSrcweir                         OfficeConnect.getOfficeContext();
732*cdf0e10cSrcweir 
733*cdf0e10cSrcweir                     com.sun.star.container.XNameAccess xFilterContainer =
734*cdf0e10cSrcweir                         (com.sun.star.container.XNameAccess)
735*cdf0e10cSrcweir                         UnoRuntime.queryInterface(
736*cdf0e10cSrcweir                             com.sun.star.container.XNameAccess.class,
737*cdf0e10cSrcweir                             xCtx.getServiceManager().createInstanceWithContext(
738*cdf0e10cSrcweir                                 "com.sun.star.document.FilterFactory", xCtx));
739*cdf0e10cSrcweir 
740*cdf0e10cSrcweir                     if(xFilterContainer.hasByName(sFilter)==false)
741*cdf0e10cSrcweir                         sFilter=null;
742*cdf0e10cSrcweir                 }
743*cdf0e10cSrcweir 
744*cdf0e10cSrcweir                 // Use this filter for export.
745*cdf0e10cSrcweir                 if(sFilter!=null)
746*cdf0e10cSrcweir                 {
747*cdf0e10cSrcweir                     // Export can be forced by saving the document and using a
748*cdf0e10cSrcweir                     // special filter name which can write needed format. Build
749*cdf0e10cSrcweir                     // neccessary argument list now.
750*cdf0e10cSrcweir                     // Use special flag "Overwrite" too, to prevent operation
751*cdf0e10cSrcweir                     // against possible exceptions, if file already exist.
752*cdf0e10cSrcweir                     com.sun.star.beans.PropertyValue[] lProperties =
753*cdf0e10cSrcweir                         new com.sun.star.beans.PropertyValue[2];
754*cdf0e10cSrcweir                     lProperties[0] = new com.sun.star.beans.PropertyValue();
755*cdf0e10cSrcweir                     lProperties[0].Name = "FilterName";
756*cdf0e10cSrcweir                     lProperties[0].Value = sFilter;
757*cdf0e10cSrcweir                     lProperties[1] = new com.sun.star.beans.PropertyValue();
758*cdf0e10cSrcweir                     lProperties[1].Name = "Overwrite";
759*cdf0e10cSrcweir                     lProperties[1].Value = Boolean.TRUE;
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir                     com.sun.star.frame.XStorable xStore =
762*cdf0e10cSrcweir                         (com.sun.star.frame.XStorable)UnoRuntime.queryInterface(
763*cdf0e10cSrcweir                             com.sun.star.frame.XStorable.class, xDocument);
764*cdf0e10cSrcweir 
765*cdf0e10cSrcweir                     xStore.storeAsURL(sURL,lProperties);
766*cdf0e10cSrcweir                 }
767*cdf0e10cSrcweir             }
768*cdf0e10cSrcweir         }
769*cdf0e10cSrcweir         catch(com.sun.star.io.IOException exIO)
770*cdf0e10cSrcweir         {
771*cdf0e10cSrcweir             // Can be thrown by "store()" call.
772*cdf0e10cSrcweir             // Do nothing then. Saving failed - that's it.
773*cdf0e10cSrcweir             exIO.printStackTrace();
774*cdf0e10cSrcweir         }
775*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exRuntime)
776*cdf0e10cSrcweir         {
777*cdf0e10cSrcweir             // Can be thrown by any uno call.
778*cdf0e10cSrcweir             // Do nothing here. Saving failed - that's it.
779*cdf0e10cSrcweir             exRuntime.printStackTrace();
780*cdf0e10cSrcweir         }
781*cdf0e10cSrcweir         catch(com.sun.star.uno.Exception exUno)
782*cdf0e10cSrcweir         {
783*cdf0e10cSrcweir             // Can be thrown by "createInstance()" call of service manager.
784*cdf0e10cSrcweir             // Do nothing here. Saving failed - that's it.
785*cdf0e10cSrcweir             exUno.printStackTrace();
786*cdf0e10cSrcweir         }
787*cdf0e10cSrcweir     }
788*cdf0e10cSrcweir 
789*cdf0e10cSrcweir     // ____________________
790*cdf0e10cSrcweir 
791*cdf0e10cSrcweir     /**
792*cdf0e10cSrcweir      * Try to close the document without any saving of modifications.
793*cdf0e10cSrcweir      * We can try it only! Controller and/or model of this document
794*cdf0e10cSrcweir      * can disagree with that. But mostly they doesn't do so.
795*cdf0e10cSrcweir      *
796*cdf0e10cSrcweir      * @param   xDocument   document which should be clcosed
797*cdf0e10cSrcweir      */
798*cdf0e10cSrcweir     public static void closeDocument(com.sun.star.lang.XComponent xDocument)
799*cdf0e10cSrcweir     {
800*cdf0e10cSrcweir         try
801*cdf0e10cSrcweir         {
802*cdf0e10cSrcweir             // Check supported functionality of the document (model or controller).
803*cdf0e10cSrcweir             com.sun.star.frame.XModel xModel =
804*cdf0e10cSrcweir                 (com.sun.star.frame.XModel)UnoRuntime.queryInterface(
805*cdf0e10cSrcweir                     com.sun.star.frame.XModel.class, xDocument);
806*cdf0e10cSrcweir 
807*cdf0e10cSrcweir             if(xModel!=null)
808*cdf0e10cSrcweir             {
809*cdf0e10cSrcweir                 // It's a full featured office document.
810*cdf0e10cSrcweir                 // Reset the modify state of it and close it.
811*cdf0e10cSrcweir                 // Note: Model can disgree by throwing a veto exception.
812*cdf0e10cSrcweir                 com.sun.star.util.XModifiable xModify =
813*cdf0e10cSrcweir                     (com.sun.star.util.XModifiable)UnoRuntime.queryInterface(
814*cdf0e10cSrcweir                         com.sun.star.util.XModifiable.class, xModel);
815*cdf0e10cSrcweir 
816*cdf0e10cSrcweir                 xModify.setModified(false);
817*cdf0e10cSrcweir                 xDocument.dispose();
818*cdf0e10cSrcweir             }
819*cdf0e10cSrcweir             else
820*cdf0e10cSrcweir             {
821*cdf0e10cSrcweir                 // It's a document which supports a controller .. or may by a pure
822*cdf0e10cSrcweir                 // window only. If it's at least a controller - we can try to
823*cdf0e10cSrcweir                 // suspend him. But - he can disagree with that!
824*cdf0e10cSrcweir                 com.sun.star.frame.XController xController =
825*cdf0e10cSrcweir                     (com.sun.star.frame.XController)UnoRuntime.queryInterface(
826*cdf0e10cSrcweir                         com.sun.star.frame.XController.class, xDocument);
827*cdf0e10cSrcweir 
828*cdf0e10cSrcweir                 if(xController!=null)
829*cdf0e10cSrcweir                 {
830*cdf0e10cSrcweir                     if(xController.suspend(true)==true)
831*cdf0e10cSrcweir                     {
832*cdf0e10cSrcweir                         // Note: Don't dispose the controller - destroy the frame
833*cdf0e10cSrcweir                         // to make it right!
834*cdf0e10cSrcweir                         com.sun.star.frame.XFrame xFrame = xController.getFrame();
835*cdf0e10cSrcweir                         xFrame.dispose();
836*cdf0e10cSrcweir                     }
837*cdf0e10cSrcweir                 }
838*cdf0e10cSrcweir             }
839*cdf0e10cSrcweir         }
840*cdf0e10cSrcweir         catch(com.sun.star.beans.PropertyVetoException exVeto)
841*cdf0e10cSrcweir         {
842*cdf0e10cSrcweir             // Can be thrown by "setModified()" call on model.
843*cdf0e10cSrcweir             // He disagree with our request.
844*cdf0e10cSrcweir             // But there is nothing to do then. Following "dispose()" call wasn't
845*cdf0e10cSrcweir             // never called (because we catch it before). Closing failed -that's it.
846*cdf0e10cSrcweir             exVeto.printStackTrace();
847*cdf0e10cSrcweir         }
848*cdf0e10cSrcweir         catch(com.sun.star.lang.DisposedException exDisposed)
849*cdf0e10cSrcweir         {
850*cdf0e10cSrcweir             // If an UNO object was already disposed before - he throw this special
851*cdf0e10cSrcweir             // runtime exception. Of course every UNO call must be look for that -
852*cdf0e10cSrcweir             // but it's a question of error handling.
853*cdf0e10cSrcweir             // For demonstration this exception is handled here.
854*cdf0e10cSrcweir             exDisposed.printStackTrace();
855*cdf0e10cSrcweir         }
856*cdf0e10cSrcweir         catch(com.sun.star.uno.RuntimeException exRuntime)
857*cdf0e10cSrcweir         {
858*cdf0e10cSrcweir             // Every uno call can throw that.
859*cdf0e10cSrcweir             // Do nothing - closing failed - that's it.
860*cdf0e10cSrcweir             exRuntime.printStackTrace();
861*cdf0e10cSrcweir         }
862*cdf0e10cSrcweir     }
863*cdf0e10cSrcweir 
864*cdf0e10cSrcweir     // ____________________
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir     /**
867*cdf0e10cSrcweir      * Try to close the frame instead of the document.
868*cdf0e10cSrcweir      * It shows the possible interface to do so.
869*cdf0e10cSrcweir      *
870*cdf0e10cSrcweir      * @param xFrame
871*cdf0e10cSrcweir      *          frame which should be clcosed
872*cdf0e10cSrcweir      *
873*cdf0e10cSrcweir      * @return  <TRUE/> in case frame could be closed
874*cdf0e10cSrcweir      *          <FALSE/> otherwise
875*cdf0e10cSrcweir      */
876*cdf0e10cSrcweir     public static boolean closeFrame(com.sun.star.frame.XFrame xFrame)
877*cdf0e10cSrcweir     {
878*cdf0e10cSrcweir         boolean bClosed = false;
879*cdf0e10cSrcweir 
880*cdf0e10cSrcweir         try
881*cdf0e10cSrcweir         {
882*cdf0e10cSrcweir             // first try the new way: use new interface XCloseable
883*cdf0e10cSrcweir             // It replace the deprecated XTask::close() and should be preferred ...
884*cdf0e10cSrcweir             // if it can be queried.
885*cdf0e10cSrcweir             com.sun.star.util.XCloseable xCloseable =
886*cdf0e10cSrcweir                 (com.sun.star.util.XCloseable)UnoRuntime.queryInterface(
887*cdf0e10cSrcweir                     com.sun.star.util.XCloseable.class, xFrame);
888*cdf0e10cSrcweir             if (xCloseable!=null)
889*cdf0e10cSrcweir             {
890*cdf0e10cSrcweir                 // We deliver the owner ship of this frame not to the (possible)
891*cdf0e10cSrcweir                 // source which throw a CloseVetoException. We whishto have it
892*cdf0e10cSrcweir                 // under our own control.
893*cdf0e10cSrcweir                 try
894*cdf0e10cSrcweir                 {
895*cdf0e10cSrcweir                     xCloseable.close(false);
896*cdf0e10cSrcweir                     bClosed = true;
897*cdf0e10cSrcweir                 }
898*cdf0e10cSrcweir                 catch( com.sun.star.util.CloseVetoException exVeto )
899*cdf0e10cSrcweir                 {
900*cdf0e10cSrcweir                     bClosed = false;
901*cdf0e10cSrcweir                 }
902*cdf0e10cSrcweir             }
903*cdf0e10cSrcweir             else
904*cdf0e10cSrcweir             {
905*cdf0e10cSrcweir                 // OK: the new way isn't possible. Try the old one.
906*cdf0e10cSrcweir                 com.sun.star.frame.XTask xTask = (com.sun.star.frame.XTask)
907*cdf0e10cSrcweir                     UnoRuntime.queryInterface(com.sun.star.frame.XTask.class,
908*cdf0e10cSrcweir                                               xFrame);
909*cdf0e10cSrcweir                 if (xTask!=null)
910*cdf0e10cSrcweir                 {
911*cdf0e10cSrcweir                     // return value doesn't interest here. Because
912*cdf0e10cSrcweir                     // we forget this task ...
913*cdf0e10cSrcweir                     bClosed = xTask.close();
914*cdf0e10cSrcweir                 }
915*cdf0e10cSrcweir             }
916*cdf0e10cSrcweir         }
917*cdf0e10cSrcweir         catch (com.sun.star.lang.DisposedException exDisposed)
918*cdf0e10cSrcweir         {
919*cdf0e10cSrcweir             // Of course - this task can be already dead - means disposed.
920*cdf0e10cSrcweir             // But for us it's not important. Because we tried to close it too.
921*cdf0e10cSrcweir             // And "already disposed" or "closed" should be the same ...
922*cdf0e10cSrcweir             bClosed = true;
923*cdf0e10cSrcweir         }
924*cdf0e10cSrcweir 
925*cdf0e10cSrcweir         return bClosed;
926*cdf0e10cSrcweir     }
927*cdf0e10cSrcweir 
928*cdf0e10cSrcweir     // ____________________
929*cdf0e10cSrcweir 
930*cdf0e10cSrcweir     /**
931*cdf0e10cSrcweir      * Try to find an unique frame name, which isn't currently used inside
932*cdf0e10cSrcweir      * remote office instance. Because we create top level frames
933*cdf0e10cSrcweir      * only, it's enough to check the names of existing child frames on the
934*cdf0e10cSrcweir      * desktop only.
935*cdf0e10cSrcweir      *
936*cdf0e10cSrcweir      * @return [String]
937*cdf0e10cSrcweir      *          should represent an unique frame name, which currently isn't
938*cdf0e10cSrcweir      *          used inside the remote office frame tree
939*cdf0e10cSrcweir      *          (Couldn't guaranteed for a real multithreaded environment.
940*cdf0e10cSrcweir      *           But we try it ...)
941*cdf0e10cSrcweir      */
942*cdf0e10cSrcweir     private static final String BASEFRAMENAME = "Desk View ";
943*cdf0e10cSrcweir 
944*cdf0e10cSrcweir     public static String getUniqueFrameName()
945*cdf0e10cSrcweir     {
946*cdf0e10cSrcweir         String sName = null;
947*cdf0e10cSrcweir 
948*cdf0e10cSrcweir         com.sun.star.uno.XComponentContext xCtx = OfficeConnect.getOfficeContext();
949*cdf0e10cSrcweir 
950*cdf0e10cSrcweir         try
951*cdf0e10cSrcweir         {
952*cdf0e10cSrcweir             com.sun.star.frame.XFramesSupplier xSupplier =
953*cdf0e10cSrcweir                 (com.sun.star.frame.XFramesSupplier)UnoRuntime.queryInterface(
954*cdf0e10cSrcweir                     com.sun.star.frame.XFramesSupplier.class,
955*cdf0e10cSrcweir                     xCtx.getServiceManager().createInstanceWithContext(
956*cdf0e10cSrcweir                         "com.sun.star.frame.Desktop", xCtx));
957*cdf0e10cSrcweir 
958*cdf0e10cSrcweir             com.sun.star.container.XIndexAccess xContainer =
959*cdf0e10cSrcweir                 (com.sun.star.container.XIndexAccess)UnoRuntime.queryInterface(
960*cdf0e10cSrcweir                     com.sun.star.container.XIndexAccess.class,
961*cdf0e10cSrcweir                     xSupplier.getFrames());
962*cdf0e10cSrcweir 
963*cdf0e10cSrcweir             int nCount = xContainer.getCount();
964*cdf0e10cSrcweir             for (int i=0; i<nCount; ++i )
965*cdf0e10cSrcweir             {
966*cdf0e10cSrcweir                 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));
967*cdf0e10cSrcweir                                         sName  = new String(BASEFRAMENAME+mnViewCount);
968*cdf0e10cSrcweir                 while(sName.compareTo(xFrame.getName())==0)
969*cdf0e10cSrcweir                 {
970*cdf0e10cSrcweir                     ++mnViewCount;
971*cdf0e10cSrcweir                     sName = new String(BASEFRAMENAME+mnViewCount);
972*cdf0e10cSrcweir                 }
973*cdf0e10cSrcweir             }
974*cdf0e10cSrcweir         }
975*cdf0e10cSrcweir         catch(com.sun.star.uno.Exception exCreateFailed)
976*cdf0e10cSrcweir         {
977*cdf0e10cSrcweir             sName = new String(BASEFRAMENAME);
978*cdf0e10cSrcweir         }
979*cdf0e10cSrcweir 
980*cdf0e10cSrcweir         if (sName==null)
981*cdf0e10cSrcweir         {
982*cdf0e10cSrcweir             System.out.println("invalid name!");
983*cdf0e10cSrcweir             sName = new String(BASEFRAMENAME);
984*cdf0e10cSrcweir         }
985*cdf0e10cSrcweir 
986*cdf0e10cSrcweir         return sName;
987*cdf0e10cSrcweir     }
988*cdf0e10cSrcweir 
989*cdf0e10cSrcweir     // ____________________
990*cdf0e10cSrcweir 
991*cdf0e10cSrcweir     /**
992*cdf0e10cSrcweir      * helper to get a file URL selected by user
993*cdf0e10cSrcweir      * This method doesn't show any API concepts ...
994*cdf0e10cSrcweir      * but is neccessary rof this demo application.
995*cdf0e10cSrcweir      *
996*cdf0e10cSrcweir      * @param   aParent parent window of this dialog
997*cdf0e10cSrcweir      * @param   bOpen   If it is set to true =>
998*cdf0e10cSrcweir      *                  dialog is opend in "file open" mode -
999*cdf0e10cSrcweir      *                  otherwise in "file save" mode.
1000*cdf0e10cSrcweir      */
1001*cdf0e10cSrcweir     public static String askUserForFileURL(Component aParent,boolean bOpen)
1002*cdf0e10cSrcweir     {
1003*cdf0e10cSrcweir         String        sFileURL  = null;
1004*cdf0e10cSrcweir         int           nDecision = JFileChooser.CANCEL_OPTION;
1005*cdf0e10cSrcweir         JFileChooser  aChooser  = null;
1006*cdf0e10cSrcweir 
1007*cdf0e10cSrcweir         // set last visited directory on new file chosser
1008*cdf0e10cSrcweir         // (if this information is available)
1009*cdf0e10cSrcweir         if( maLastDir==null )
1010*cdf0e10cSrcweir             aChooser = new JFileChooser();
1011*cdf0e10cSrcweir         else
1012*cdf0e10cSrcweir             aChooser = new JFileChooser(maLastDir);
1013*cdf0e10cSrcweir 
1014*cdf0e10cSrcweir         // decide between file open/save dialog
1015*cdf0e10cSrcweir         if( bOpen==true )
1016*cdf0e10cSrcweir             nDecision = aChooser.showOpenDialog(aParent);
1017*cdf0e10cSrcweir         else
1018*cdf0e10cSrcweir             nDecision = aChooser.showSaveDialog(aParent);
1019*cdf0e10cSrcweir 
1020*cdf0e10cSrcweir         // react for "OK" result only
1021*cdf0e10cSrcweir         if(nDecision == JFileChooser.APPROVE_OPTION)
1022*cdf0e10cSrcweir         {
1023*cdf0e10cSrcweir             // save current directory as last visited one
1024*cdf0e10cSrcweir             maLastDir = aChooser.getCurrentDirectory();
1025*cdf0e10cSrcweir             // get file URL from the dialog
1026*cdf0e10cSrcweir             try
1027*cdf0e10cSrcweir             {
1028*cdf0e10cSrcweir                 sFileURL = aChooser.getSelectedFile().toURL().toExternalForm();
1029*cdf0e10cSrcweir             }
1030*cdf0e10cSrcweir             catch( MalformedURLException ex )
1031*cdf0e10cSrcweir             {
1032*cdf0e10cSrcweir                 ex.printStackTrace();
1033*cdf0e10cSrcweir                 sFileURL = null;
1034*cdf0e10cSrcweir             }
1035*cdf0e10cSrcweir             // problem of java: file URL's are coded with 1 slash instead of 3 ones!
1036*cdf0e10cSrcweir             // => correct this problem first, otherwise office can't use these URL's
1037*cdf0e10cSrcweir             if(
1038*cdf0e10cSrcweir                 ( sFileURL                      !=null  ) &&
1039*cdf0e10cSrcweir                 ( sFileURL.startsWith("file:/") ==true  ) &&
1040*cdf0e10cSrcweir                 ( sFileURL.startsWith("file://")==false )
1041*cdf0e10cSrcweir               )
1042*cdf0e10cSrcweir             {
1043*cdf0e10cSrcweir                 StringBuffer sWorkBuffer = new StringBuffer(sFileURL);
1044*cdf0e10cSrcweir                 sWorkBuffer.insert(6,"//");
1045*cdf0e10cSrcweir                 sFileURL = sWorkBuffer.toString();
1046*cdf0e10cSrcweir             }
1047*cdf0e10cSrcweir         }
1048*cdf0e10cSrcweir 
1049*cdf0e10cSrcweir         return sFileURL;
1050*cdf0e10cSrcweir     }
1051*cdf0e10cSrcweir 
1052*cdf0e10cSrcweir     // ____________________
1053*cdf0e10cSrcweir 
1054*cdf0e10cSrcweir     /**
1055*cdf0e10cSrcweir      * @member  maLastDir   save the last visited directory of used file open/save dialog
1056*cdf0e10cSrcweir      * @member  mnViewCount we try to set unique names on every frame we create (that's why we must count it)
1057*cdf0e10cSrcweir      */
1058*cdf0e10cSrcweir     private static File maLastDir   = null;
1059*cdf0e10cSrcweir     private static int  mnViewCount = 0   ;
1060*cdf0e10cSrcweir }
1061