Showing posts with label To Develop UNO Extensions (LibreOffice Extensions or Apache OpenOffice Extensions). Show all posts
Showing posts with label To Develop UNO Extensions (LibreOffice Extensions or Apache OpenOffice Extensions). Show all posts

2017-12-10

34: Let's Create a UNO Extension Project Skeletons (and UNO Additional Data Types Project Skeletons) Maker, Part Two

<The previous article in this series | The table of contents of this series | The next article in this series>

Main Body START

We Created a UNO Extension Project Skeletons (and UNO Additional Data Types Project Skeletons) Maker

About: UNO (Universal Network Objects)

About: LibreOffice

About: Apache OpenOffice

About: Java Programming Language

The Implementation of Our UNO Extension Project Skeletons (and UNO Additional Data Types Project Skeletons) Maker

The same with the previous scene.

-Rebutter

What will be the implementation of our UNO extension project skeletons and UNO additional data types project skeletons maker?

-Hypothesizer

The contents of the files we have to create are mostly fixed, and our tool's task is to imbue some strings at fixed positions in those files. Considering the characteristic of the task, I think, XSLT would be an appropriate thing to use.

-Rebutter

So, will our tool create xml data that consist of the properties described above (actually in the preceding article), and convert the xml data to the objective files based on some style sheets?

-Hypothesizer

Yes. As we can see from the descriptions of the properties above, the properties are appropriate to be organized in xml data: multiple implemented UNO interfaces can be organized as child elements of a defined UNO component, etc.

-Rebutter

Are we creating a single xml tree for all the objective files, or a specific xml tree for each objective file?

-Hypothesizer

Ah, I didn't even think about creating a common single xml tree; of course, doing with creating only one xml tree has a merit, but many objective files wouldn't need most of the tree.

-Rebutter

Hmm, . . . well, OK.

What will the layouts of spread sheets on which the property values of projects are set?

-Hypothesizer

One spread sheet will represent one project, and we will need three types of spread sheets: for UNO extension projects with UNO additional data types, for UNO additional data types projects, and for UNO extension projects (without any UNO additional data type).

-Rebutter

What exactly are they like?

-Hypothesizer opens a spread sheets document file.

-Hypothesizer

This sheet is for UNO extension projects with UNO additional data types.

This sheet is for UNO additional data types projects.

This sheet is for UNO extension projects (without any UNO additional data type).

The name of each sheet is the project name.

-Rebutter look at those spread sheets.

-Rebutter

Green cells explain where we should put each property value in.

-Hypothesizer

Please don't change the text contents and the background colors of those green cells: our tool will see them and judge where parameter values are set, based on them.

-Rebutter

So, if I change the color to red because I hate green, . . .

-Hypothesizer

The tool won't work properly.

-Rebutter

And if I translate the text contents to another language, . . .

-Hypothesizer

The tool won't work properly.

And please don't remove any of those green cells, especially the last one, which says, 'End'. The 'End' cell is the cell at which our tool stops interpreting the sheet. If that cell is removed, our tool will search the sheet for it to the last row of the sheet.

-Rebutter

May I insert a column at the first column?

-Hypothesizer

Definitely not! Our tool will search those green cells in the first column.

-Rebutter

May I insert rows as we need?

-Hypothesizer

Yes. If there are many 'other classes paths', for example, you will have to insert rows.

-Rebutter

If I don't need any 'other classes path', may I remove the empty row under that 'Other Classes Path Expressions' green cell?

-Hypothesizer

No, you may not: that empty row is required. That's the same with the other sections. For example, if there is no defined UNO interface, leave an empty row where there are property values rows in the above image.

-Rebutter

What if I didn't?

-Hypothesizer

Well, I won't elaborate on what would happen when your setting wasn't what the tool expects, for each case. . . . I'm sorry, but I don't intend to make the tool fault-tolerant (making it fault-tolerant would require much more time). So, if you don't set property values as the tool expects, I can't guarantee what would happen . . . (although I don't expect very bad thing to happen)

-Rebutter

Well, such a principle may be permissible according to expected users.

-Hypothesizer

Anyway, there will be no technical problem in implementing our tool. In the perspective of UNO programming, it's just a matter of how to read spread sheet cells.

-Rebutter

OK.

-Hypothesizer begins to implement the tool.

-Hypothesizer

. . .

. . .

. . .

Ah, as I am trying to interpret sections of data on a spread sheet into instances of some structures in Java, it is rather cumbersome. . . . To think of it, as such logics are reusable, I will implement them in a utility class. In fact, the 'thebiasplanet.unoutilities.documentshandling.spreadsheetsdocumentshandling.UnoSpreadSheet' class will have methods that handle them.

-Rebutter

You mean a Map, for example, by 'structure'?

-Hypothesizer

Not all Maps are equal. We need String to Strings-Lists-List Maps, String to String-to-Strings-Lists-Map Maps, and String to String-to-String-Map Maps.

-Rebutter

I don't see what they are, at first glance . . .

-Hypothesizer

Java expressions may be more clear: 'Map <String, List <List <String>>>', 'Map <String, Map <String, List <String>>>', and 'Map <String, Map <String, String>>'.

-Rebutter

I understand them now.

-Hypothesizer

And we will also need 'List <String>'.

-Rebutter

Is 'Map <String, Map <String, List <String>>>' enough? I mean, shouldn't' we generalize it as 'Map <String, List <String>>', 'Map <String, Map <String, List <String>>>', 'Map <String, Map <String, Map <String, List <String>>>>', . . .

-Hypothesizer

Although we need only 'Map <String, Map <String, List <String>>>' in this case, I think, we should generalize it as a utility. And I will also parameterize the String part.

-Rebutter

Ah-ha.

-Hypothesizer begins to implement the utility class.

-Hypothesizer

. . . Well, generics is unhandy in a case like this.

-Rebutter

A case like what?

-Hypothesizer

Well, . . .

As the argument became long, it is described here.

-Hypothesizer

. . . So, it's finished with the utility class. I will return to the implementation of the tool . . .

-Hypothesizer resumes to implement the tool.

-Hypothesizer

All right. It's here, and how to use the zip file is here.

-Hypothesizer builds necessary projects.

-Rebutter

Where is the spread sheets document for setting property values.

-Hypothesizer

It's in the 'execution' directory of the 'projectSkeletonsMakerUnoExtensionToDisclose' project.

And you have to import the Basic library that is in the same directory into LibreOffice, and set values into two variables in the Basic module, 'ProjectSkeletonsMaker'.

-Hypothesizer imports the Basic library, 'TheBiasPlanetBasicLibrary', and opens the 'ProjectSkeletonsMaker' module.

-Rebutter

The first two '???' marks are places where we have to set values, I guess?

-Hypothesizer

Yes. We have to set the directory of the style sheets and the directory of the development base directory.

-Rebutter

The directory of the style sheets is the 'execution' directory of the project, 'projectSkeletonsMakerUnoExtensionToDisclose'; the directory of the development base directory is whatever a directory that we want to be so.

-Hypothesizer

Yes. But as Gradle build scripts and Ant build files that are created by the tool use our common Gradle build scripts and Ant build files, unless those common files exist in the specified development base directory, those Gradle build scripts and Ant build files won't work as they are.

-Hypothesizer sets those values, and opens 'ProjectSettings.ods', and pushes the 'Make' button of the 'projectMakingTestUnoExtension1' sheet.

-Rebutter

. . . Have the files been made?

-Hypothesizer

Yes. They should have been.

-Rebutter

What now?

-Hypothesizer

It's already a valid project that can be built successfully: executing the 'gradle' or 'ant' command on the project will build the project. However, usually, before that, we will want to define some methods in the UNOIDL files and implement those methods in the Java source files.

-Rebutter

Can we also just execute the 'gradle' or 'ant' command on the development base directory?

-Hypothesizer

Hmm, it depends on which types of projects we have created: if we have created a set of a UNO additional data types project and a UNO extension project, we will have to build the UNO additional data types project before the UNO extension project, which an execution of the 'gradle' or 'ant' command on the development base directory doesn't guarantee.

-Rebutter

Ah-ha.

-Hypothesizer

And note that if there already exist UNOIDL files or UNO component Java source files, the tool will give you a java.nio.file.FileAlreadyExistsException error. You know, you won't want a file that has implemented some methods brutally replaced.

-Rebutter

So, the tool doesn't kindly save the existing files and create new files?

-Hypothesizer

Well, it doesn't, at least for now. You will have to rename the existing files yourself.

Main Body END

<The previous article in this series | The table of contents of this series | The next article in this series>

2017-11-26

33: Let's Create a UNO Extension Project Skeletons (and UNO Additional Data Types Project Skeletons) Maker, Part One

<The previous article in this series | The table of contents of this series | The next article in this series>

Main Body START

We Created a UNO Extension Project Skeletons (and UNO Additional Data Types Project Skeletons) Maker

About: UNO (Universal Network Objects)

About: LibreOffice

About: Apache OpenOffice

About: Java Programming Language

The Use of Our UNO Extension Project Skeletons Maker

Here are -Hypothesizer and -Rebutter sitting in front of a computer screen in a room on a brook among some mountains on the Bias planet.

-Hypothesizer

We already know the building blocks of UNO extension projects and the inside structures of those building blocks, but it's cumbersome to make those building blocks: we have to make each name reflected in several places.

-Rebutter

What do you mean by 'each name'?

-Hypothesizer

There are some names that characterize a UNO extension, for example, global UNO service names that are registered by the UNO extension.

-Rebutter

And in how many places, does a global UNO service name have to be reflected?

-Hypothesizer

Well, . . . four places as it has to be written in the UNO component, in the UNO components setting file, and in the 'global UNO service'-specific service instances factory, and has to be reflected as the path of the 'global UNO service'-specific service instances factory source file.

If we happen to make a mistake in one of those places, our program won't work, and we will have to check those places one by one . . .

-Rebutter

Hmm, considering the frequency of creating UNO extensions, it doesn't seem to be an intolerable task to do.

-Hypothesizer

I don't say that it's intolerable, but I feel somewhat disconsolate in doing such a routine chore.

-Rebutter

That's too bad, feeling disconsolate in such a thing.

-Hypothesizer

Anyway, we are going to create a UNO extension skeletons maker, which enables us to avoid such routine chores.

-Rebutter

As a prophylactic for your disconsolation . . .

The Design of Our UNO Extension Project Skeletons (and UNO Additional Data Types Project Skeletons) Maker

The same with the previous scene.

-Rebutter

What is the design of our UNO extension project skeletons maker?

-Hypothesizer

There are some parameters we have to specify for a UNO extension.

-Rebutter

Of course.

-Hypothesizer

We will specify those parameters on a spread sheet, and our UNO extension project skeletons maker will make the building blocks of the UNO extension based on those parameters.

-Rebutter

What are those parameters?

-Hypothesizer

Before I cite them, I would say that you wouldn't understand them if you don't understand basic concepts of UNO.

-Rebutter

Of course. . . . Obviously, we have to build up understandings beginning with basic concepts: I don't demand any thing explained while grudging due efforts, do I?

-Hypothesizer

I didn't say you do: it was just showing the reference where you should go if something is unclear to you.

-Rebutter

All right.

-Hypothesizer

These are the parameters that have to be specified for each project:

  • project name = the name of the project directory (spaces aren't supposed to be included in the name)
  • the target name
  • defined UNO interface names as pairs of a package name and a relative core name (optional)
  • super UNO interface names, with each of which associated with a defined UNO interface
  • the Java package name of all the defined UNO components = the module name of all the defined global UNO services
  • defined UNO component relative core names
  • implemented UNO interface names, with each of which associated with a defined UNO component
  • defined global UNO service relative core names, with each of which associated with a defined UNO component (optional)
  • defined 'global UNO service'-specific service instances factory names as pairs of a package name and a relative core name (optional)
  • return type UNO interface names, with each of which associated with a defined 'global UNO service'-specific service instances factory (only one for a defined 'global UNO service'-specific service instances factory)
  • included jar path expressions (optional)
  • other classes path expressions (optional)
  • referenced project path expressions (optional and effective only for Gradle projects)
-Rebutter

Hmm, there are many.

-Hypothesizer

It's inevitable: I enlisted only independent parameters; we can't spare any parameter that can't be derived from other parameters, logically speaking.

-Rebutter

What are being noted 'optional' are optional . . .

-Hypothesizer

For example, if we are going to create UNO components implementing existing UNO interfaces, we don't need to define any new UNO interface.

-Rebutter

In that case, of course, any super UNO interface name isn't necessary, although they aren't noted as 'optional'.

-Hypothesizer

As for things that are noted as 'with each of which associated with <something>', they are noted as 'optional' only when there can be none of them for a <something>.

-Rebutter

So, if there is a defined UNO interface, there must be at least one super UNO interface name for the defined UNO interface, while even if there is a defined UNO component, there doesn't have to be any defined global UNO service relative core name for the defined UNO component.

-Hypothesizer

Exactly: not all the UNO components have to be registered as UNO services.

-Rebutter

The description, 'the Java package name of all the defined UNO components = the module name of all the defined global UNO services', seems to mean that the Java packages of all the defined UNO components and the modules of all the defined global UNO services have to be the same . . .

-Hypothesizer

That's our convention. Of course, defined UNO components can have different Java package names according to the UNO specifications, but we don't see any necessity to let them do so, and forcing that restriction makes the project more visible, I think.

-Rebutter

More 'visible'?

-Hypothesizer

I mean, the structure of the project will be more easily understood at a glance.

-Rebutter

Hmm, having a base name for UNO component Java packages and UNO service modules seems fine, but if we begin to have many UNO components in a project, we may begin to feel a necessity to classify them in sub packages.

-Hypothesizer

Ah, . . . you are right, but at this point, I don't imagine that we will have many UNO components in a UNO extension project, in the near future. Giving more flexibility is good, but it can complicate the specification of parameters. So, I would like to stick to the design above, at least for now.

-Rebutter

All right. I understand that you are supposing to have multiple UNO extension projects than have multiple sub packages in a UNO extension project.

And what does 'relative core' mean in, for example 'defined UNO component relative core names'?

-Hypothesizer

Ah, 'relative name' means a full class name minus the package part.

-Rebutter

So, for a full class name, 'java.lang.String', the relative name is . . .

-Hypothesizer

'String'. I know that a class relative name is usually called just a 'class name' while a full class name also tends to be called just a 'class name', but as I have a policy of avoiding ambiguous expressions, I must distinguish one from the other. An option is to use 'class name' and 'full class name', but I happened to adopt 'class relative name' and 'class name'.

-Rebutter

So, a 'class name' is always a full class name, at least in this context?

-Hypothesizer

That is my intention.

-Rebutter

What does 'core name' mean?

-Hypothesizer

I'm going to inflict some name conventions: any defined UNO component name has to end with 'UnoComponent', for example. A core name is a name minus the mandatory part.

-Rebutter

So, if a relative core name of a UNO component is 'Test1', the relative name is 'Test1UnoComponent', for example?

-Hypothesizer

Yes. . . . I know I'm a little, or much, obsessed with describing things unambiguously. Anyway, when I am told to specify a class name as a parameter, I have to be told whether it is a full class name or a relative class name, and if it is a core name, I have to be told so.

-Rebutter

Well, to state things explicitly is the first step of avoiding fallacies . . .. And in order to state things explicitly, descriptions can't avoid becoming lengthy, to a certain degree.

-Hypothesizer

I know that the majority of people love simplified, inaccurate descriptions, but my aim is to be accurate, not to pander to the majority of people . . .

Anyway, to add some notes, the target name is used as the base of some file names, for example the jar file.

And note that I used the word 'expression' as in 'included jar path expressions'.

-Rebutter

I noted, but what does it mean?

-Hypothesizer

It means that it isn't the contents of a plain literal, but an expression that specifies a path, for example, 'LIBREOFFICE_CLASSES_BASE_DIRECTORY_NAME + "/unoil.jar"'.

-Rebutter

So, if a term isn't enclosed in double-quotes, the term will be interpreted as a variable, not the contents of a literal string?

-Hypothesizer

Exactly.

-Rebutter

In the second UNO extension sample, we have separated UNOIDL files to another project (we will call such a project a 'UNO additional data types project'). How can we make, say UNO interface source file skeletons, in a UNO additional data types project?

-Hypothesizer

Ah, a UNO additional data types project isn't a UNO extension project, and according to the title of 'UNO Extension Project Skeleton Maker', it comes that it isn't in the scope of our tool . . ., but it would be sad if we couldn't make UNO interface source file skeletons because it's a UNO additional data types project, not a UNO extension project.

-Rebutter

The logic of making UNO interface source file skeletons will be the same whether in a UNO extension project or in a UNO additional data types project, won't it?

-Hypothesizer

It will. So, our UNO extension project skeleton maker will be really a UNO extension project skeletons and UNO additional data types project skeletons maker.

-Rebutter

In fact, it can be a more general project skeletons maker.

-Hypothesizer

It can, but at this point, I don't see significant merits in making a Java project by our tool, and calling our tool just a project skeletons maker would make it obscure: what's special about it?

-Rebutter

When we make a UNO additional data types project, the set of parameters that have to specified is different from the one shown above, isn't it?

-Hypothesizer

Of course. It is like this.

  • project name = the name of the project directory (spaces aren't supposed to be included in the name)
  • the target name
  • defined UNO interface names as pairs of a package name and a relative core name (optional)
  • super UNO interface names, with each of which associated with a defined UNO interface
  • defined 'global UNO service'-specific service instances factory names as pairs of a package name and a relative core name (optional)
  • return type UNO interface names, with each of which associated with a defined 'global UNO service'-specific service instances factory (only one for a defined 'global UNO service'-specific service instances factory)
-Rebutter

You said, "parameters that have to be specified for each project", which seems to imply that there are also some parameters that don't have to be specified for each project.

-Hypothesizer

Yes, it does. There is a parameter that is common to projects: the development base directory path.

-Rebutter

How about relative paths of some directories in a project, for example the relative path of the Java source files base directory?

-Hypothesizer

Actually, they are hard-coded in a source file. If we want to change them, we can do so by modifying the source file. As our Gradle build scripts and Ant build files are based on our common Gradle build scripts and Ant build files, and those relative directory paths are written in those common files, parameterizing those relative directory paths just in this tool didn't make much sense to me.

Main Body END

<The previous article in this series | The table of contents of this series | The next article in this series>

2017-11-12

32: Let's Create a Spread Sheet Cell Editor

<The previous article in this series | The table of contents of this series | The next article in this series>

Main Body START

We Created a Spread Sheet Cell Editor

About: UNO (Universal Network Objects)

About: LibreOffice

About: Apache OpenOffice

About: Java Programming Language

The Use of Our Cell Editor

Here are -Hypothesizer and -Rebutter sitting in front of a computer screen in a room on a brook among some mountains on the Bias planet.

-Hypothesizer

As we know how to implement GUIs in our UNO Extensions, we will create a cell editor. A cell editor is an editor that edits the contents of any spread sheet cell.

-Rebutter

So, our cell editor is to spread sheet cells as usual editors are to files.

-Hypothesizer

Yes. As it is cumbersome to handle long texts inside cells, such a cell editor will be handy when our cells have long texts. You know, a long text doesn't fit even in the pop-up window that is shown by our double-clicking the cell.

-Rebutter

Will we have such long texts in our cells?

-Hypothesizer

Well, . . . I think we can. I mean, if we can handily handle long texts on spread sheets, we can use spread sheets in wider use. That is, we can use spread sheets in any case in which want to organize and handle data in a grid: a long text doesn't need to be fully visible inside the small box of a cell.

-Rebutter

Isn't saying "in any case" an exaggeration?

-Hypothesizer

At this stage, it may, but we could expand our cell editor to make it handle, say images.

-Rebutter

Well, we should say just "wider use" at this stage.

The Design of Our Cell Editor

The same with the previous scene.

-Rebutter

What features will our cell editor have?

-Hypothesizer

We can show the contents of the cell in a wide area, can scroll the text, can see line numbers, can search any specified phrase in the text, can replace any specified phrase in the text with another any specified phrase, can jump to the top or the bottom of the text, can do copying, cutting, pasting, undoing, and redoing, can select the whole of the text, can go to the upper, the lower, the left, or the right cell, . . .

-Rebutter

Are we going to let multiple cell editor windows be shown at the same time?

-Hypothesizer

Well, . . . I thought we would let only one cell editor window be shown at a time: many cell editor windows could clutter the screen . . .

-Rebutter

Two cell editors wouldn't do much harm. I think, it isn't rare that we want to show two cell editor windows at a time, like when we compare the contents of two cells.

-Hypothesizer

Well, if you say so . . .

-Rebutter

On the other hand, we don't have to open a new cell editor window just because we want to edit another cell, do we?

-Hypothesizer

Like I said, we can go to neighboring cells in the existing cell editor window.

-Rebutter

Only neighboring cells?

-Hypothesizer

Well, . . . of course we will also have to able to jump to an arbitrary cell. . . . We will implement a reconnect button, which reconnects the cell editor window to the current cell on the spread sheet.

-Rebutter

Please elaborate on the relationship between the current cell on the spread sheet and the cell that a cell editor window is connected to.

-Hypothesizer

When a cell editor window is newly opened, the cell editor window is connected to the current cell on the spread sheet. Just selecting another cell on the spread sheet doesn't make the cell editor window reconnect to the new current cell. Doing certain operations on the cell editor window make the cell editor reconnect to another cell.

-Rebutter

By certain operations you mean, say clicking a 'Go to the Right Cell' or the reconnect button?

-Hypothesizer

Yes. Clicking a 'Save' button saves the contents to the connected cell, which isn't necessarily the current cell on the spread sheet.

-Rebutter

Can't you let a cell editor window automatically reconnect to the current cell on the spread sheet as the cell selection on the spread sheet is changed?

-Hypothesizer

That would be meaningless when multiple cell editor windows are shown: all the cell editor window would connect to the same cell.

-Rebutter

I didn't tell you to make all the cell editor windows reconnect to the current cell on the spread sheet without question.

-Hypothesizer

Um? . . . Ah, we can implement a check box that specifies whether the cell editor window should automatically reconnect to the current cell on the spread sheet . . .

Well, I would be able to do so, but . . . I would like to put off that feature to the future. I mean, we have to investigate how best we can detect changes of the selection of cells.

-Rebutter

All right.

I wonder whether the cell editor window shouldn't be able to set the contents to a cell that isn't the connected cell . . .

-Hypothesizer

Um? Why won't we reconnect to the cell to which we want to set the contents?

-Rebutter

That will clear the contents of the previously-connected cell on the cell editor window, won't it?

-Hypothesizer

Ah, so, you want to copy the value of a cell to another cell . . .

-Rebutter

I don't particularly want to do so. I just thought that there might be such necessity, in general.

-Hypothesizer

OK. We will implement that feature. Maybe, our cell editor should be able to set the selected text on the cell editor window to the current cell on the spread sheet. If nothing is selected on the cell editor window, the whole text will be set to the current cell on the spread sheet.

-Hypothesizer

At this stage, the outward appearance of our cell editor is this.

-Hypothesizer shows an image of the cell editor on the computer screen.

-Rebutter

. . . It seems difficult to identify which button is of which function . . .

-Hypothesizer

I know. I don't particularly boast that the appearance is slick. Usually, buttons have icons, but I didn't take time to draw appropriate icons. . . . Well, maybe, we would put icons on those buttons, in future.

-Rebutter

There is a button whose caption is 'Go to ...' . . .. Go to where? Where would I be taken to, if I dare to push such an enigmatic button? And there is another button of the same caption beneath it . . .

-Hypothesizer

Ah, I brutally cut short long explanations of buttons. It's a temporary measure before we put on icons. . . . Anyway, hover the mouse cursor over the buttons, and see the tool tips.

-Rebutter

Well, then, I will have to wait until I see the real window.

The Implementation of Our Cell Editor

The same with the previous scene.

-Hypothesizer

As for the implementation, there is nothing to say in respect to UNO: how to read from and write to spread sheet cells are already dealt with; the rest is about just Java, especially Swing, programming. As for some observations we had in the implementation process, we would note them in the series, 'Java Tips'.

-Rebutter

All right.

-Hypothesizer

Our program is here. That is the project we used in the preceding article. How to use the zip file is written there.

-Rebutter

You have replaced the dummy window in the preceding article with the one you have created in this article.

-Hypothesizer

Let's build the projects, and test the cell editor.

-Hypothesizer runs the gradle command, which finishes successfully. -Hypothesizer opens the 'TestSpreadSheetsDocumentForExecutingTests.ods' spread sheets document file. -Hypothesizer clicks the 'Show Test Control Panel' button; a tiny dialog box shows adjacent to the left border of the current LibreOffice frame. -Hypothesizer clicks the 'Edit Cell' button; a cell editor window opens.

-Rebutter

Well, it showed.

-Hypothesizer

Of course . . .

-Rebutter does some operations on the cell editor window.

-Rebutter

Hmm . . .

-Hypothesizer

What?

-Rebutter

When the cell editor window is connected to a date type cell and I edit and save the contents of a legal date, it is saved as a date.

-Hypothesizer

Yes. That is my intention.

-Rebutter

But when I edit and save the contents of an illegal date, for example '2017-13-01', it is saved as a string.

-Hypothesizer

Ah, as we can't convert the text to a date, it is inevitable.

-Rebutter

Warning may be kinder than brutally changing it to a string cell.

-Hypothesizer

Well, it may.

-Rebutter

And when I save a number text, for example '123', to an empty cell, it is saved as a string value.

-Hypothesizer

Well, it is. Any empty cell is treated as a string cell . . .

Hmm, as I have intended our cell editor basically for editing long texts, wanting to save contents as date cells, number cells, etc, wasn't in my expectations, much. Certainly, our cell editor can edit cells that have already date values, etc, with the cell types preserved, but making an empty cell, say a number cell wasn't in my scope. . . . Well, we will improve the cell editor in that respect in future.

-Rebutter

This is just a first version; we can improve it gradually.

By the way, what is this button that has the tool tip of 'Save Compressed'?

-Hypothesizer

That is a button that will save the contents text to the cell with the contents compressed. You know, when a cell has a very long text, LibreOffice program instance can slow down, greatly.

-Rebutter

The button is disabled. Whey will it be enabled?

-Hypothesizer

In future. It isn't implemented yet.

Main Body END

<The previous article in this series | The table of contents of this series | The next article in this series>

2017-11-05

31: How to Use Swing GUIs in UNO Extensions (LibreOffice Extensions or Apache OpenOffice Extensions)

<The previous article in this series | The table of contents of this series | The next article in this series>

Main Body START

To Know How to Use Swing GUIs in UNO Extensions (LibreOffice Extensions or Apache OpenOffice Extensions)

About: UNO (Universal Network Objects)

About: LibreOffice

About: Apache OpenOffice

About: Java Programming Language

In Fact, We Can't Just Use GUIs in UNO Extensions

Here are -Hypothesizer and -Rebutter sitting in front of a computer screen in a room on a brook among some mountains on the Bias planet.

-Hypothesizer

We are going to implement GUIs in our UNO Extensions.

-Rebutter

Well, . . . why not? As we can develop UNO extensions in Java, we can just use JavaFX, Swing, or whatever in them, can't we?

-Hypothesizer

In fact, that isn't the case. There are some things we have to be aware of.

-Rebutter

Oh? What are they?

-Hypothesizer

The most important thing is, we don't seem to be able to use JavaFX in UNO extensions on Linux.

-Rebutter

That seems to imply that we can use JavaFX in UNO extensions on Windows.

-Hypothesizer

Based on the fact that I can show some simple dialogs of JavaFX on Windows, I guess so. In fact, I haven't investigated further because as our main machine is Linux, being able to use it only on Windows isn't helpful for us.

-Rebutter

Why can't we use JavaFX in UNO extensions on Linux?

-Hypothesizer

This is my guess. JavaFX uses GDK while LibreOffice does so too. As JavaFX tries to create its main loop of GDK, the main loop doesn't seem to be able to coexist with the main loop of GDK of LibreOffice in the same process.

-Rebutter

Ah, as JavaFX programs are supposed to be executed as explicit FX program instances, it might be natural that we can't use JavaFX in a JVM that resides in the LibreOffice program instance.

So, what happens if we try to use JavaFX in UNO extensions on Linux?

-Hypothesizer

The initialization of JavaFX freezes without being able to receive some events to be received. So, the whole LibreOffice program instance freezes.

-Rebutter

Hmm, . . . so, isn't there any evasive maneuver?

-Hypothesizer

At least, I don't know one, although there is an ultimate solution.

-Rebutter

What is that?

-Hypothesizer

We can create a GUIs server as a UNO server.

-Rebutter

Ah, as we discussed in the series, 'How to Use UNO (Handle LibreOffice or Apache OpenOffice Documents) in External Java Programs', we can create UNO servers. As a UNO server is an independent Java program, there can't be any restriction in using JavaFX or whatever Java features.

-Hypothesizer

As we can use Swing all right (although there is a pitfall as we will discuss later), we will defer pursuing that solution to another occasion.

-Rebutter

All right.

-Hypothesizer

Note that there is a GUI library that is recommended for use in UNO extensions, but we won't comply because . . .

-Rebutter

. . . we are of warped personalities?

-Hypothesizer

That's not the reason here although we are, to some degree. The reason is that I don't expect that library to be as handy or rich in functionality as Swing or JavaFX is.

-Rebutter

Is that based on some facts?

-Hypothesizer

It's rather a wild guess. . . . Another reason is that I don't want to learn how to use another GUI library just for developing UNO extensions.

-Rebutter

That's understandable.

-Hypothesizer

If necessary, we will opt for the GUIs server solution, not for using that GUI library.

What Is the One Thing We Have to Do Before We Use Swing in UNO Extensions?

The same with the previous scene.

-Hypothesizer

We can use Swing in UNO extensions all right, but there is one thing we have to do before we begin using Swing.

-Rebutter

What is that?

-Hypothesizer opens a Java source file and points to a line.

-Hypothesizer

We have to call this line.

@Java Source Code
  Thread.currentThread ().setContextClassLoader (ClassLoader.getSystemClassLoader ());

-Rebutter

Well, . . . are we registering a class loader into the current thread?

-Hypothesizer

Yes. Swing uses it, but it isn't registered in the JVM prepared by LibreOffice, somehow.

-Rebutter

Hmm. . . . So, once we do that, can we use Swing in UNO extensions with no problem?

-Hypothesizer

As far as I know, yes.

Let's Create a Sample

The same with the previous scene.

-Hypothesizer

We will create a sample.

How about creating a control panel that has buttons, each of which launches a function?

-Rebutter

A control panel is fine, but what functions, for example?

-Hypothesizer

Well, . . . how about a cell editor?

-Rebutter

What do you mean by 'cell editor'?

-Hypothesizer

Spread sheets are handy in organizing data in a grid, but when we put a long text in a cell, it's cumbersome to see or edit the text inside the cell.

-Rebutter

In fact, when we deal with only numbers and short texts, it's fine, but if we have to deal with also long texts, spread sheets tend to be practically unusable.

-Hypothesizer

If we can handle long texts in our cell editor, we will be able to handily use spread sheets also in such cases.

-Rebutter

Hmm . . .

-Hypothesizer

In this article, we will concentrate on creating the control panel: the cell editor is a dummy in this stage.

-Rebutter

Well, as we already know how to read from and write to spread sheet cells, creating a cell editor is just a matter of Java programming, once we know how to use GUIs in UNO extensions.

-Hypothesizer

Exactly.

Showing the control panel is just a matter of Swing programming, but here, we will show the control panel in an appropriate place relative to the current LibreOffice frame.

-Rebutter

Ah, so, we don't want the control panel to be shown at a random or a fixed position on the screen.

-Hypothesizer

We will show the control panel adjacent to the left border of the current LibreOffice frame.

-Rebutter

What if there is no space there?

-Hypothesizer

Then, we will have to show it on the current LibreOffice frame.

-Rebutter

Wherever we want to show it, the matter is how we can get the geometry of the borders of the current LibreOffice frame.

-Hypothesizer

We can get it like this.

-Hypothesizer selects a section of the Java source file.

@Java Source Code
import com.sun.star.awt.XWindow;
import com.sun.star.frame.XDesktop;
import com.sun.star.frame.XFrame;
import thebiasplanet.unoutilities.constantsgroups.*;
import thebiasplanet.unoutilities.serviceshandling.UnoServiceHandler;

    XDesktop l_unoDesktopInXDesktop = (XDesktop) UnoServiceHandler.getServiceInstance (i_componentContextInXComponentContext, UnoServiceNamesConstantsGroup.c_com_sun_star_frame_Desktop, XDesktop.class);
    XFrame l_unoFrameInXFrame = l_unoDesktopInXDesktop.getCurrentFrame ();
    XWindow l_desktopContainerWindowInXWindow = l_unoFrameInXFrame.getContainerWindow ();
    com.sun.star.awt.Rectangle l_desktopContainerWindowBoundary = l_desktopContainerWindowInXWindow.getPosSize ();
    Rectangle l_applicationContainerWindowBoundary = new Rectangle (l_desktopContainerWindowBoundary.X, l_desktopContainerWindowBoundary.Y, l_desktopContainerWindowBoundary.Width, l_desktopContainerWindowBoundary.Height);

-Rebutter

Well, classes under the 'thebiasplanet' package are our utility classes.

-Hypothesizer

As for codes already explained in previous articles, we may not repeat explicitly citing them, but use our utility classes. As our utility classes are included in our zip files, see inside them if necessary.

-Rebutter

All right.

-Hypothesizer

Our sample program is here.

-Rebutter

You have implemented into the sample UNO extension project cited before.

-Hypothesizer

Yes. How to use the zip file is written there. Note that as we add codes into projects cited in some articles, projects cited in an article can include some codes that are irrelevant to the article: those codes have come from other articles.

-Hypothesizer runs the gradle command, which finishes successfully. -Hypothesizer opens the 'TestSpreadSheetsDocumentForExecutingTests.ods' spread sheets document.

-Rebutter

You have added the second button on the sheet.

-Hypothesizer

Yes. Before we push the button, we have to import the LibreOffice Basic library, as described in the previous article.

-Hypothesizer clicks the 'Show Test Control Panel' button; a tiny dialog box shows adjacent to the left border of the current LibreOffice frame.

-Rebutter

. . . It's unimpressive to be called a 'control panel' . . .

-Hypothesizer

Unimpressive or not, it's a control panel. Clicking the 'Edit Cell' button shows the cell editor.

-Hypothesizer clicks the 'Edit Cell' button; a dummy window opens.

-Rebutter

At this stage, the window is a dummy, without showing any cell datum.

Main Body END

<The previous article in this series | The table of contents of this series | The next article in this series>

2017-08-27

30: How to Issue UNO Commands to the Dispatch Mechanism

<The previous article in this series | The table of contents of this series | The next article in this series>

Main body START

To Know How to Call Some Functions That Are Otherwise Unavailable from the Outside of LibreOffice or Apache OpenOffice

Not All Functions Can Be Called from the Outside of LibreOffice or Apache OpenOffice

-Hypothesizer

So far, we have called some functions from our UNO extensions, but not all functions can be called from UNO extensions, or standalone UNO programs.

-Rebutter

I know. We have to have a reference to an UNO object (to be exact, a reference to a UNO proxy of the UNO object) in order to call a function that belongs to the UNO object, but there is no guarantee that we can get the reference.

-Hypothesizer

We can get a reference to an UNO object in this process.

We get the component context; we get UNO objects (the global UNO service manager is one of them) contained in the component context; we get UNO objects from the global UNO service manager; we get UNO objects as return values or output arguments of methods of UNO objects that we already have references to; we get UNO objects as properties or attributes of UNO objects that we already have references to.

-Rebutter

UNO objects can also be gotten as members of return struct values or output struct arguments, etc, but that wouldn't be necessary to mention.

-Hypothesizer

A UNO object that isn't exposed in the process can't be accessed from the outside of LibreOffice or Apache OpenOffice.

-Rebutter

Of course. And a function may not be even implemented as a UNO component method.

-Hypothesizer

Yes. LibreOffice is mostly implemented in C++, and not all C++ classes are UNO components.

-Rebutter

So, there can be some functions we want to call, but can't.

There Is a Mechanism Called 'Dispatch'

-Hypothesizer

However, there is another mechanism by which we can call some functions, which is the dispatch mechanism.

-Rebutter

What is it like?

-Hypothesizer

There are predetermined commands, which are identified by their URLs, and we can call one of them, specifying the URL and some arguments that are specific to the command.

-Rebutter

Can we call all of those commands?

-Hypothesizer

There is no guarantee for that. We may not be able to get a reference to a UNO object that is required as an argument to call a command, and there may be some special conditions that have to be fulfilled in order for it to be called successfully.

-Rebutter

Special conditions?

-Hypothesizer

For example, a dialog window may have to be opened when a command is called.

-Rebutter

Hmm . . .

-Hypothesizer

That's just an example I conceived. There might not be really such cases.

-Rebutter

Ah-ha . . .

How can we know those URLs and specifications of their arguments?

-Hypothesizer

That's the issue. . . . I couldn't find any document that comprehensively explains them.

-Rebutter

Hmm.

-Hypothesizer

So far, my best measure is to see the source codes of LibreOffice. Where and how we should see is the next issue, but we won't delve into it now.

-Rebutter

OK.

-Hypothesizer

By recording macros, we can see some instances of calling commands, but they aren't always perfect.

-Rebutter

How can they be imperfect.

-Hypothesizer

For example, when we export a document as a PDF file, we can sign the PDF file, but the recorded macro doesn't sign the PDF file.

-Rebutter

So, some arguments are just missed?

-Hypothesizer

Or values aren't set for some arguments.

-Rebutter

I see. So, how can we call a command, exactly?

-Hypothesizer

There is a global UNO service named, 'com.sun.star.frame.DispatchHelper', and we can create an instance of the UNO service from the global UNO services manager. The UNO component of the instance implements a UNO interface, 'com.sun.star.frame.XDispatchHelper', which has a method called, 'executeDispatch', which takes the dispatch provider, the command URL, and the command arguments.

-Rebutter

What is the dispatch provider?

-Hypothesizer

Commands aren't executed mystically, but are received and dealt with by an entity, which is the dispatch provider, according to my understanding.

-Rebutter

How can we get the dispatch provider?

-Hypothesizer

Of course, it depends on the command, but in most cases we are concerned now, the frame in which the document resides is the dispatch provider.

-Rebutter

How can we get the frame?

-Hypothesizer

We can get the frame from the controller of the document, using the 'com.sun.star.frame.XController' UNO interface implemented by the controller.

-Rebutter

I see.

-Hypothesizer

After all, I wrote this sample code , where 'componentContext' is the component context in 'com.sun.star.uno.XComponentContext' (see this previous article to know how we got it) and 'l_currentSpreadSheetsDocumentModel' is the spread sheet document UNO object in 'com.sun.star.frame.XModel' (see this previous article to know how we got it).

import com.sun.star.frame.XFrame;
import com.sun.star.frame.XController;
import com.sun.star.frame.XDispatchHelper;
import com.sun.star.frame.XDispatchProvider;
import com.sun.star.beans.PropertyValue;

  XDispatchHelper l_dispatchHelperInXDispatchHelper = (XDispatchHelper) UnoRuntime.queryInterface (XDispatchHelper .class, componentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.frame.DispatchHelper", componentContext));
  XController l_controllerInXController = (XController) UnoRuntime.queryInterface (XController.class, l_currentSpreadSheetsDocumentModel.getCurrentController ());
  l_frameInXDispatchProvider = (XDispatchProvider) UnoRuntime.queryInterface (XDispatchProvider.class, l_controllerInXController.getFrame ());
  PropertyValue [] l_commandProperties = new PropertyValue [1];
  l_commandProperties [0] = new PropertyValue ();
  l_commandProperties [0].Name = "ToPoint";
  l_commandProperties [0].Value = "$B$2";
  l_dispatchHelperInXDispatchHelper.executeDispatch (l_frameInXDispatchProvider, ".uno:GoToCell", "", 0, l_commandProperties);
-Rebutter

What is the command?

-Hypothesizer

That's a command that moves the cell current position to the B2 cell.

-Rebutter

Is that different from selecting the cell?

-Hypothesizer

That's different, at least in appearance. When a cell is selected, the cell is shaded, while when the cell is just current, the cell isn't shaded.

-Rebutter

Well, that is a subtle difference.

-Hypothesizer

And when we export a spread sheet document as a PDF file, a selected cell is recognized as the selection while just a current cell isn't.

-Rebutter

What do you mean by "recognized as the selection"?

-Hypothesizer

When we export a spread sheet document as a PDF file, we can export only the selected part of the document.

-Rebutter

I see.

Main body END

<The previous article in this series | The table of contents of this series | The next article in this series>