The com.sun.star.frame.XDesktop interface defines the primary functionality of the Desktop service. The desktop contains the top-level components that can be viewed in a frame. In other words, it contains and controls the life cycle of the OpenOffice.org documents, help window, Basic IDE, and the other component types.
Tip | For information about the com.sun.star.frame.XDesktop interface, see http://api.openoffice.org/docs/common/ref/com/sun/star/frame/XDesktop.html . |
The desktop is a Frame service so that it can act as the root frame containing all the other frames. The desktop, therefore, has access to and controls all the other frames. This control includes the ability to load documents and the ability to close all frames and exit OOo.
To close the desktop and all the contained frames, call the terminate() method. This method is not guaranteed to close the desktop; it is merely a suggestion (or request) that you would like OOo to close. The methods addTerminateListener() and removeTerminateListener() are defined by the XDesktop interface. Each termination listener has the ability to tell OOo that it should not terminate. When you call the terminate() method, the following sequence of events occurs:
The queryTermination() method is called on each com.sun.star.frame.XTerminateListener that is registered with the desktop. A listener can prevent OOo from terminating by raising a TerminationVetoException.
If no termination listener throws an exception, the notifyTermination() method is called on each registered listener, notifying them that OOo will terminate.
If the termination is aborted, an abortTermination event is broadcast and False is returned.
All the OOo document types support the com.sun.star.util.XCloseable interface. The XCloseable interface defines the method "close(bForce As Boolean)". If bForce is False, the object may refuse to close. If bForce is True, the object is not able to refuse .
According to Mathias Bauer with Sun Communications, the Desktop object does not support the XCloseable interface for legacy reasons. The terminate() method was used before it was determined to be inadequate for closing documents or windows . If the terminate() method was not already implemented, then the desktop would also support the XCloseable interface. The code in Listing 5 demonstrates the safe way to close a document using any version of OOo. If you know that your code will run on OOo 1.1 or later, you can simply use the close() method.
If HasUnoInterfaces(oDoc, "com.sun.star.util.XCloseable") Then oDoc.close(true) Else oDoc.dispose() End If
The code in Listing 5 assumes that the variable oDoc references an OOo document. Some component types do not support the XCloseable interface. One example is the Basic IDE. The desktop contains methods to enumerate the currently open components and to access the current component. These methods are discussed shortly.
The dispose() method automatically discards a document even if it is modified, while the close() method does not. Use setModified(False) to mark a modified document as not modified, thereby preventing the close() method from complaining that you are closing a modified document.
Usually, a component refers to an OOo document, but it may refer to other things, such as the Basic IDE or the included help pages. Use the getComponents() method defined in the XDesktop interface to return an enumeration of the components controlled by the desktop. The returned object supports the interface com.sun.star.container.XEnumerationAccess.
Tip | OOo has many interfaces for returning a list of objects-some methods return an array of objects. In the desktop, XlndexAccess is used to enumerate frames and the XEnumerationAccess interface is used to enumerate components. For a list of the primary container interfaces, see http://api.openoffice.org/docs/common/ref/com/sun/star/container/module-ix.html . |
A component that is also an OOo document supports the XModel interface. The model represents the underlying document data, so if a component doesn't support the XModel interface, it isn't an OOo document. In other words, supporing the XModel interface implies that a component has data; if it doesn't have data, then it isn't a document. Use the HasUnoInterfaces function to check each component to see if it is an OOo document. To find a specific document, search all of the components and check the URL or some other distinguishing characteristic. The code in Listing 6 demonstrates how to enumerate the components.
Sub EnumerateComponentNames Dim vComps 'Enumeration access object Dim vEnumerate 'Enumeration object Dim vComp 'Single component Dim s As String 'Display string REM Load the Tools library because Strings module contains REM the function FileNameOutOfPath() GlobalScope.BasicLibraries.LoadLibrary("Tools") vComps=StarDesktop.getComponents()'com.sun.star.container.XEnumerationAccess If NOT vComps.hasElements() Then 'I do not have to do this, but Print "There are no components" 'this demonstrates that I can Exit Sub End If vEnumerate = vComps.createEnumeration() 'com.sun.star.container.XEnumeration Do While vEnumerate.hasMoreElements() 'Are there any elements to retrieve? vComp = vEnumerate.nextElement() 'Get next element REM Only try to get the URL from document components REM This will skip the IDE, for example If HasUnoInterfaces(vComp, "com.sun.star.frame.XModel") Then s = s & FileNameOutOfPath(vComp.getURL()) & CHR$(10) End If Loop MsgBox s, 0, "Document Names" End Sub
Figure 2, produced by Listing 6, lists the file names of all currently open documents.
Use the getCurrentComponent() method defined in the XDesktop interface to return the currently focused component, which is not necessarily an OOo document. To obtain the most current document, use the globally defined variable ThisComponent (see Listing 7 ).
Print ThisComponent.getURL() 'Works from Basic IDE Print StarDesktop.getCurrentComponent().getURL() 'Fails from Basic IDE
Warning | StarDesktop.getCurrentComponent() returns the currently focused component. If the Basic IDE is open, the Basic IDE component is returned. Use the globally defined variable ThisComponent to return the most current document. |
There are many reasons you might want to obtain the current document. The code in Listing 8 demonstrates only one reason: to display information about the document. The DocumentInfo object contains numerous useful properties as shown in Table 2 . You can always remind yourself what the DocumentInfo object can do by inspecting the string properties dbg_methods and dbg_properties.
Property | Description |
---|---|
Author | Initial author of the document. |
CreationDate | Date and time the document was created. |
Title | The document title. |
Description | Multi-line document description. |
Keywords | Comma-separated list of keywords for the document. |
MIMEType | MIME type of the document's resource. |
ModifiedBy | Name of the last person who modified the document. |
ModifyDate | Date and time the document was last stored. |
PrintedBy | Name of the last person to print the document. |
PrintDate | Date and time the document was last printed. |
Template | The path and name of the template from which the document was created. |
TemplateDate | Date and time when the document was created or last updated from the template. |
AutoloadURL | URL to load automatically a specified time after the document is loaded. |
AutoloadSecs | Number of seconds to wait before auto-loading the AutoloadURL. |
DefaultTarget | Name of the default frame into which links should be loaded if no target is specified. |
Sub DisplayDocModifiedBy Dim vDocInfo 'com.sun.star.document.DocumentInfo service 'This has many useful properties vDocInfo = ThisComponent.getDocumentInfo() Print "ModifiedBy = " & vDocInfo.ModifiedBy End Sub
Tip | Remember that UNO objects, also called services, implement object methods and they contain properties. Object methods are subroutines and functions that the object implements, and object properties are essentially variables contained in the object. The dbg_methods property is a string variable that most UNO objects support. "MsgBox oFrame.dbg_methods" displays the methods supported by the oFrame object. "MsgBox oFrame.dbg_properties" displays the properties supported by the oFrame object. |
Tip | The desktop has a CurrentComponent property. StarDesktop.CurrentComponent is equivalent to StarDesktop.getCurrentComponent(). |
Although StarDesktop.getCurrentComponent() can be used in many situations, it is not a reliable method to obtain the document that most recently had focus. The method getCurrentComponent() returns either the component that currently has focus, or the component that had the focus before control was switched to a different application. This behavior causes problems when attempting to debug Basic programs, because the Basic IDE is the current component. It is therefore preferable to use ThisComponent rather than StarDesktop.CurrentComponent. Forcing a new document's window to become focused does not change the value of ThisComponent. The value of ThisComponent is set once and then it is not changed (see Listing 9 ).
oDoc2.CurrentController.Frame.ContainerWindow.toFront() oDoc2.CurrentController.Frame.Activate()
Tip | When a macro is called because an event occurred, ThisComponent refers to the document that produced the event unless the macro is contained in another document. Therefore, it's better to place global macros that will be called from other documents inside a global library rather than inside a document. |
You can configure OOo to call a BASIC macro when certain events occur. When a macro is called because an event occurred, ThisComponent refers to the document that produced the event even if it isn't the currently focused document; however, these are usually the same document. The variable ThisComponent is available only from BASIC. Obtaining the current document is more difficult from other programming languages and is generally accomplished by searching all of the components for a specific document based on the URL.
Tip | In OOo 1.1, it is possible to run a macro when no document is open, but the macro must reside in the application library rather than in a document. |
Although the Frame service allows the desktop to enumerate the contained frames, it is the XDesktop interface that defines the method getCurrentFrame(). The getCurrentFrame() method returns the frame of the currently focused component.
Note | The component contained in the current frame may, or may not, be an OOo document. |
The code in Listing 10 shows one of many things you can do with the current frame. The macro obtains the current frame, the frame returns the current window, and then the macro reduces the size of the current window.
REM Shrink the current window to 75% of its current size. Sub ShrinkWindowBy75 Dim vFrame 'Current frame Dim vWindow 'container window REM And this is a struct that holds a rectangle object REM I could have also used a Variant or an Object to REM hold the return type, but I know what it is, so I REM defined the correct type to hold it. Dim vRect As New com.sun.star.awt.Rectangle vFrame = StarDesktop.getCurrentFrame() vWindow = vFrame.getContainerWindow() REM As a struct, the object is copied by value, not by reference. REM This means that I can modify vRect and it will not affect REM the position and size of the window. REM In my tests, vRect.X and vRect.Y are zero, which is wrong. REM vRect.Width and vRect.Height are indeed correct. vRect = vWindow.getPosSize() REM When setting the position and size, the last argument specifies REM which of the arguments to use. 'com.sun.star.awt.PosSize.X Set only the X-position 'com.sun.star.awt.PosSize.Y Set only the Y-position 'com.sun.star.awt.PosSize.WIDTH Set only the Width 'com.sun.star.awt.PosSize.HEIGHT Set only the Height 'com.sun.star.awt.PosSize.POS Set only the Position 'com.sun.star.awt.PosSize.SIZE Set only the Size 'com.sun.star.awt.PosSize.POSSIZE Set both the Position and Size vWindow.setPosSize( vRect.X, vRect.Y, 3*vRect.Width/4, 3*vRect.Height/4,_ com.sun.star.awt.PosSize.SIZE ) End Sub