Writing Professional Components

From Apache OpenOffice Wiki
Revision as of 12:41, 19 August 2009 by SergeMoutou (Talk | contribs)

Jump to: navigation, search
Documentation caution.png This chapter is under construction for a while because I don't master all the topics evocated here at the moment. SergeMoutou 12:20, 3 August 2009 (UTC)

Writing components is not as easy as developping binary executable. When an exception occurs in your component a recovery process of your document begins. This process is too long to try some code and correct the errors. When designing a component, it would be a good idea to conceive it as a binary executable before to change it into a component. In this chapter we will discuss this idea and also the exceptions. But before starting we examine at first the inspection tools. why ? Because there is a lot of things you cannot do without an inspection tool. In fact there is always an other way : to read the documentation but it can take hours and hours to solve your problem with reading documentation and only ten minutes with an inspection tool.

Java Inspector

I have already tackled Java Inspector in this document (see here). But we used in fact the addon part of the component because it was called with the corresponding button, not with code. In this section we will discuss how we can use Java Inspector in a component, to put it differently, how to call Java inspector with C++ code ?

Creating the Header Files

Creating header files could be done with exporting the Inspector.uno.rdb with extension manager. This task was easy with old versions (I think before 3.0) because a tree was available in the extension manager and this is no more the case. When done, use the cppumaker tool. Because the service name is "org.openoffice.InstanceInspector" put the created header files in "<OOo_SDK>/includes/org/openoffice/" folder. You can then use :

// C++
// Listing 1
// Java Inspector
#include <org/openoffice/XInstanceInspector.hpp>

in your component.

Creating the corresponding Service

This is done with :

// C++
// Listing 2
// If you want to use java Inspector
	m_xInspector = Reference< XInstanceInspector > (m_xMCF->createInstanceWithContext( 
			OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.InstanceInspector" ) ),
			m_xContext),
			UNO_QUERY_THROW );

where you see a member data "m_xInspector" has to be added in your component class. The good place for this code is naturally in the constructor of your component class.

Calling the corresponding Interface

If you want to call and see the Java Inspector Dialog, you have to put a code as follows

// C++
// Listing 3
// Java Introspection
	any <<= somethingToInspect;
// name of the tab : inspector
	m_xInspector->inspect(any,OUString::createFromAscii("Inspector"));        
	xParentNode->appendChild(xChildMutTreeNode);

where you have to adapt the "somethingToInspect".

My own Inspector

I have already presented in this document my own inspector but it wasn't a component. Then it was only valuable when writing binary executable, not for components. In this section I will show how to transform it as a component. Because Java Inspector is more advanced than my component it is only interesting when using old and inefficient computers where Java runs slowly. But for me it represents the only experience with writing a great component.

Documentation caution.png The code presented here is not safe. You can see many "FIXME" in the code. At the moment the version is labelled 0.4

This component is composed with two separate class (at the moment)

The ReflectionHelper class

This class is composed with two source files. See the corresponding code. This class is under construction particularly the

// C++
// Listing 
void getTypeAndValue(Any toInspect);

method. Its code is running but this method has to be the main entry of the class. And it is also called every time you invoke (see below) and this is not a good thing because it is perturbing the member data of the class. In other word there is a problem of conception here !

The Component

See the corresponding code.

The OOoBasic Code and Result

Calling this component is done with the code as follows :

'Listing 6
REM  *****  BASIC  *****
 
Sub demonstrateSimpleComponent
    Dim oSimpleComponent
	oSimpleComponent = CreateUnoService( "foo.Counter" )
	oSimpleComponent.myInspect(oSimpleComponent)
End Sub

which yields :

Our Inspector dialog

When invoking the selected "getSupportedMethodNames()" you see the result in the text control : "LosingFocus" and "Invoke". That means invoke is partially working.

General Remarks

Please read carefully the code and search the "FIXME" to see what the limitations are. If you never press the "invoke" button, all is OK. If you want to see what happens when invoking please read below.

Documentation caution.png The "Invoke" button is not safe. Because starting with a Tree selection, I have to parse this selection to retrieve the name of the method. The parsing code provided only works when no argument is present in the method. Don't invoke myInspect for instance because it has an any variable as argument : it will start an exception in OpenOffice.org

Template:Documentation/Note Template:Documentation/Note

Managing exceptions

For the first time I want to deal with exception. This problem is not simple when writing component. The question is : what we have to do in the "catch" part of the exception ? When writing binary executable you can print on the terminal screen all what you want. But in a component ? If possible, when writing a component you have to avoid exceptions. In fact every time you use an OpenOffice Interface you can rise an exception. For instance in my inspector the getXIdlMethodByName(OUString aMethodName) can rise an exception if the aMethodName string is not a correct method name. You have two possibilities to work around :

  • to write your own search of a method name and when not found to make something which is not an exception,
  • to carefuly design your dialog (and the corresponding code) to be almost sure the method name is coming from a "method selection" and not from a user choice.

Because writing new code is never safe the second way is the best in my opinion. But I think it's not always possible to design a dialog to always avoid exception.

TO DO

Transforming a component

When transforming a component in a binary executable, the first problem is the service manager. The component context allows you to retrieve a com.sun.star.lang.XMultiComponentFactory while a binary executable only works with com.sun.star.lang.XMultiServiceFactory. I have encounter this problem when developping my C++ inspection tool. TO DO going further...

The transformation is not always as easy as we can imagine. For instance I have worked in this document many times around the counter : how can I transform the counter into a binary executable ? If the answer is not so simple, is it only because the counter is not an OpenOffice component ? (I mean the counter code doesn't need OpenOffice to run, it only uses the dialog of OpenOffice, then XWindows, Windows can be used). When can we really start to call a component an OpenOffice component ?

See The Component Helper and the Binary Executable Helper.

What I am : a Component or an Add-on ?

In many situations you are unable to say if your code has to belong to a component or to an add-on. It's only because the distinction between both situation is only a terminology problem. In practical components it's a good idea to call it with a menu. Then your component becomes an add-on with no IDL-file. But you can encounter more complex situations. For instance a scriptable component (with IDL file) but with a configuration dialog called with a menu.

TO DO

Packaging a Dialog and a Dynamic Library in an oxt File

Home Page

HomePageCpp.png Return to Document Home page

See also

Personal tools