Documentation/DevGuide/Forms

Forms offer a method of control-based data input. A form or form document consists of a set of controls, where each one enters a single piece of data. In a simple case, this could be a plain text field allowing you to insert some text without any word breaks. When we speak of forms, we mean forms and controls, because these cannot be divided.

If an internet site asks you for information, for example, for a product registration you are presented with fields to enter your name, your address and other information. These are HTML forms.

Basically, this is what LibreOffice forms do. They enhance nearly every document with controls for data input. This additional functionality put into a document is called the form layer within the scope of this chapter.

The most basic functionality provides the controls for HTML form documents mentioned above: If you open an HTML document with form elements in LibreOffice Writer, these elements are represented by components from com.sun.star.form.

The more enhanced functionality provides support for data-aware forms. These are forms and controls that are bound to a data source registered in LibreOffice to enter data into tables of a database. For more information about data sources and data access in general, refer to the Database Access.

Since OpenOffice.org 2.0.0, form controls also feature a generalization of this concept. They can be bound to external components, which supply an own value. Both values - the one of the external component, and the current value of the control - are synchronized, so that a change in one of them is immediately propagated to the other. This allows new features, where the most notable is that you can bind form controls to spreadsheet cells.

When discussing forms, form documents and logical forms have to be distinguished. The phrase form document refers to a document as a whole, while a logical form is basically a set of controls with additional properties. Within the scope of this chapter, when a "form" is referred to, the logical form is meant.

Models and Views
The model describes appearance and behaviour of the element. The view is the visual representation of the element. The relationship between models and views is important to understand and is described in detail in this section.

The Model-View Paradigm
A basic concept to understand about forms and controls in LibreOffice is the model-view paradigm. For a given element in your document, for example, a text field in your HTML form, it says that you have exactly one model and an arbitrary number of views.

The model is what is part of your document in that it describes how this element looks, and how it behaves. The model even exists when you do not have an open instance of your document. If it is stored in a file, the file contains a description of the model of your element.

The view is a visual representation of your model. It is the component which looks and behaves according to the requirements of the model. You can have multiple views for one model, and they would all look alike as the model describes it. The view is visible to the user. It is for visualizing the model and handles interactions with the user. The model, however, is merely a "dumb" container of data.

A good example to illustrate this is available in LibreOffice. Open an arbitrary document and choose the menu item Window > New Window. A second window is opened showing the same document displayed in the first window. This does not mean that the document was opened twice, it means you opened a second view of the same document, which is a difference. In particular, if you type some text in one of the windows, this change is visible in both windows. That is what the model-view paradigm is about: Keep your document data once in the model, and when you need to visualize the data to the user, or need interaction from the user that modifies the document, create views to the model as needed.

Between model and view a 1:n relationship exists:



Models and Views for Form Controls
Form controls follow the model-view paradigm. This means if you have a form document that contains a control, there is a model describing the control's behavior and appearance, and a view that is the component the user sees.

The base for the controls and models used in the form layer are found in the module com.sun.star.awt, the com.sun.star.awt.UnoControl and com.sun.star.awt.UnoControlModel services. As discussed later, the model hierarchy in com.sun.star.form.component extends the hierarchy of com.sun.star.awt, whereas the control hierarchy in com.sun.star.form.control is small.

Everything from the model-view interaction for form controls is true for other UNO controls and UNO control models, as well. Another example for components that use the model-view paradigm are the controls and control models in LibreOffice Basic dialogs (Dialog Controls).

Model-View Interaction
When model and view collaborate, data transfer is usually required in both directions, from model to view and backwards.

Consider a simple text field. The model for a control implements a com.sun.star.form.component.TextField service. This means it has a property Text, containing the current content of the field, and a property BackgroundColor specifying the color that should be used as background when drawing the text of the control.

First, if the value of the BackgroundColor property is changed, the control is notified of the change. This is done by UNO listener mechanisms, such as the com.sun.star.beans.XPropertyChangeListener allowing the control to listen for changes to model properties and react accordingly. Here the control would have to redraw itself using the new background color.

In fact this is a common mechanism for the communication between model and view: The view adds itself as listener for any aspect of the model which could affect it, and when it is notified of changes, it adjusts itself to the new model state. This means that the model is always the passive part. The model does not know its views, or at least not as views, but only their role as listeners, while the views know their model.

On the other hand, if the view is used for interaction with the user, the data needs to be propagated from the view to the model. The user enters data in a text field, and the change is reflected in the model. Remember that the user sees the control only, and everything affects the control in the first step. If the user interacts with the view with the intention of modifying the model, the view propagates changes to the model.

In our example, the user enters text into the control, the control automatically updates the respective property at the model (Text), thus modifying the document containing the model.

View Modes
An important aspect to know when dealing with forms is that the view for a form layer is in different modes. More precise, there is a design mode available, opposite to a live mode. In design mode, you design your form interactively with LibreOffice by inserting new controls, resizing them, and modifying their properties, together with control models and shapes, although LibreOffice hides this. In live mode, the controls interact with the user for data input.

The live mode is the natural mode for form views, because usually a form is designed once and used again.

The following example switches a given document view between the two modes:

The basic idea is to dispatch the URL " " into the current view. This triggers the same functionality as if the button Design Mode On/Off was pressed in LibreOffice. In fact,  is the UNO name for the slot triggered by this button.

Locating Controls
A common task when working with form documents using the LibreOffice API is to obtain controls. Given that there is a control model, and a view to the document it belongs to, you may want to know the control that is used to represent the model in that view. This is what the interface com.sun.star.view.XControlAccess at the controller of a document view is made for.

Focusing Controls
To focus a specific control in your document, or more precisely, in one of the views of your document:

As you can see, focusing controls is reduced to locating controls. Once you have located the control, the com.sun.star.awt.XWindow interface provides everything needed for focusing.

Form Elements in the Document Model
The model of a document is the data that is made persistent, so that all form elements are a part of it. Refer to chapter Frame-Controller-Model Paradigm in LibreOffice for additional information. This is true for logical forms, as well as for control models. Controls, that is, the view part of form elements, are not made persistent, thus are not accessible in the document model.

A Hierarchy of Models
The components in the form layer are organized hierarchically in an object tree. Their relationship is organized using the standard interfaces, such as com.sun.star.container.XChild and com.sun.star.container.XIndexAccess.

As in every tree, there is a root with inner nodes and leaves. There are different components described below that take on one or several of these roles.

FormComponent Service
The basis for all form related models is the com.sun.star.form.FormComponent service. Its basic characteristics are:


 * it exports the com.sun.star.container.XChild interface
 * it has a property
 * it exports the com.sun.star.lang.XComponent interface

Form components have a parent and a name, and support lifetime control that the common denominator for form elements and logical forms, as well as for control models.

FormComponents Service
In the level above, a single form component is a container for components. Stepping away from the document model, you are looking for a specific form component, such as the model of a control, you pass where all the control models are attached. This is the com.sun.star.form.FormComponents component. The service offers basic container functionality, namely an access to its elements by index or by name), and a possibility to enumerate its elements.

Provided that you have a container at hand, the access to its elements is straightforward. For example, assume you want to enumerate all the elements in the container, and apply a specific action for every element. The  method below does this by recursively enumerating the elements in a com.sun.star.form.FormComponents container.

Logical Forms
Forms as technical objects are also part of the document model. In contrast to control models, forms do not have a view representation. For every control model, there is a control the user interacts with, and presents the data back to the user. For the form, there is no view component.

The basic service for logical forms is com.sun.star.form.component.Form. See below for details regarding this service. For now, we are interested in that it exposes the com.sun.star.form.FormComponent service, as well as the com.sun.star.form.FormComponents service. This means it is part of a form component container, and it is a container. Thus, in our hierarchy of models, it can be any node, such as an inner node having children, that is, other form components, as well as a leaf node having no children, but a parent container. Of course both of these roles are not exclusive. This is how data aware forms implement master-detail relationships. Refer to the Data Awareness.

Forms Container
In our model hierarchy, we have inner nodes called the logical forms, and the basic element called the form component. As in every tree, our hierarchy has a root, that is, an instance of the com.sun.star.form.Forms service. This is nothing more than an instance of com.sun.star.form.FormComponents. In fact, the differentiation exists for a non-ambiguous runtime instantiation of a root.

Actually, it is not necessary for external components to instantiate a service directly. Every document has at least one instance of it. A root forms container is tied to a draw page, which is an element of the document model, as well. Refer to com.sun.star.drawing.DrawPage. A page optionally supports the interface com.sun.star.form.XFormsSupplier giving access to the collection. In the current LibreOffice implementation, Writer and Calc documents fully support draw pages supplying forms.

The following example shows how to obtain a root forms collection, if the document model is known which is denoted with.

Form Control Models
The control models are discussed in these sections. The basic service for a form layer control model is com.sun.star.form.FormControlModel that is discussed in more detail below. A form control model promises to support the com.sun.star.form.FormComponent service, meaning that it can act as a child in our model hierarchy.

In addition, it does not claim that the com.sun.star.form.FormComponents service (plural s) is supported meaning that form control models are leaves in our object tree. The only exception from this is the grid control model. It is allowed to have children representing the models of the columns.

An overview of the whole model tree has been provided. With the code fragments introduced above, the following code dumps a model tree to the console:

Control Models and Shapes
There is more to know about form components in a document.

From Shapes, you already know about shapes. They are also part of a document model. The control shapes, com.sun.star.drawing.ControlShape are made to be tied to control models. They are specialized to fully integrate form control models into a document.

In theory, there can be a control shape without a model tied to it, or a control model which is part of the form component hierarchy, but not associated with any shape. In the first case, an empty shape is displayed in the document view. In the second case, you see nothing. It is possible to have a shape which is properly tied to a control model, but the control model is not part of the form component hierarchy. The model can not interact with the rest of the form layer. For example, it is unable to take advantage of its data awareness capabilities.

A complete object structure in a document model with respect to the components relevant for our form layer looks the following:



Programmatic Creation of Controls
As a consequence from the previous paragraph, we now know that to insert a form control, we need to insert a control shape and control model into the document's model.

The following code fragment accomplishes that:

Looking at the example above, the basic procedure is:


 * create and initialize a shape
 * create a control model
 * announce the control model to the shape
 * insert the shape into the shapes collection of a draw page

The above does not mention inserting the control model into the form component hierarchy, which is a contradiction of our previous discussion. We have previously said that every control model must be part of this hierarchy to prevent corrupted documents, but it is not harmful.

In every document, when a new control shape is inserted into the document, through the API or an interaction with a document's view, the control model is checked if it is a member of the model hierarchy. If it is not, it is automatically inserted. Moreover, if the hierarchy does not exist or is incomplete, for example, if the draw page does not have a forms collection, or this collection does not contain a form, this is also corrected automatically.

With the code fragment above applied to a new document, a logical form is created automatically, inserted into the forms hierarchy, and the control model is inserted into this form.

You may have noticed that there is nothing about the view. We only created a control model. As you can see in the complete example for this chapter, when you have an open document, and insert a model and a shape, a control (the visual representation) is also created or else you would not see anything that looks like a control.

The control and model have a model-view relationship. If the document window is open, this window is the document view. If the document or the model is modified by inserting a control model, the view for every open view for this document reacts appropriately and creates a control as described by the model. The com.sun.star.awt.UnoControlModel:DefaultControl property describes the service to be instantiated when automatically creating a control for a model.

Form Components
According to the different form document types, there are different components in the com.sun.star.form module serving different purposes. Basically, we distinguish between HTML form functionality and data awareness functionality that are covered by the form layer API.

Control Models
As you know from Form Control Models, the base for all our control models is the com.sun.star.form.FormControlModel service. Let us look at the most relevant elements of the declaration of this service and what a component must do to support it:

com.sun.star.awt.UnoControlModel
 * This service specifies that a form control model complies to everything required for a control model by the UNO windowing toolkit as described in module com.sun.star.awt . This means support for the com.sun.star.awt.XControlModel interface, for property access and persistence.

com.sun.star.form.FormComponent
 * This service requires a form control model is part of a form component hierarchy. Refer to chapter A Hierarchy of Models.

com.sun.star.beans.XPropertyState
 * This optional interface allows the control model properties to have a default value. All known implementations of the  service support this interface.

com.sun.star.form.FormControlModel:ClassId
 * This property determines the class of a control model you have, and it assumes a value from the com.sun.star.form.FormComponentType enumeration. The same is done using the com.sun.star.lang.XServiceInfo interface that is supported by every component, and as shown below it can be indispensable. Using the com.sun.star.form.FormControlModel:ClassId property is faster.

The following example shows how to determine the type of a control model using the  property introduced above:

Note the special handling for the value com.sun.star.form.FormComponentType:TEXTFIELD. There are two different services where a component implementing them is required to act as text field, the com.sun.star.form.component.TextField and com.sun.star.form.component.FormattedField. Both services describe a text component, thus both have a class id of com.sun.star.form.FormComponentType:TEXTFIELD. To distinguish between them, ask the components for more details using the com.sun.star.lang.XServiceInfo interface.

Forms
The LibreOffice API features different kinds of forms, namely the com.sun.star.form.component.Form, com.sun.star.form.component.HTMLForm , and com.sun.star.form.component.DataForm. The two different aspects described with these services are HTML forms used in HTML documents, and data aware forms used to access databases. Data awareness is discussed thoroughly in Data Awareness.

The common denominator of HTML forms and data aware forms is described in the com.sun.star.form.component.Form service. It includes the  and   service, in addition to the following elements:

com.sun.star.form.XForm
 * This interface identifies the component as a form that can be done with other methods, such as the com.sun.star.lang.XServiceInfo interface. The com.sun.star.form.XForm interface distinguishes a form component as a form. The  interface inherits from com.sun.star.form.XFormComponent to indicate the difference, and does not add any further operations.

com.sun.star.awt.XTabControllerModel
 * This is used for controlling tab ordering and control grouping. As a logical form is a container for control models, it is a natural place to administer information about the relationship of its control children. The tab order, that is, the order in which the focus travels through the controls associated with the control models when the user presses the key, is a relationship, and thus is maintained on the form.


 * Note that changing the tab order through this interface also affects the models. The com.sun.star.form.FormControlModel service has an optional property  that contains the relative position of the control in the tabbing order. For example, a straightforward implementation of com.sun.star.awt.XTabControllerModel:setControlModels  would be simply to adjust all the   properties of the models passed to this method.

HTML Forms
The com.sun.star.form.component.HTMLForm service reflects the requirements for HTML form documents. Looking at HTML specifications, you can submit forms using different encodings and submit methods, and reset forms. The  service description reflects this by supporting the interfaces com.sun.star.form.XReset and com.sun.star.form.XSubmit, as well as some additional properties related to the submit functionality.

The semantics of these interfaces and properties are straightforward.For additional details, refer to the service description, as well as the HTML specification.

Data Awareness
A major feature of forms in LibreOffice is that they can be data aware. You create form documents where the user manipulates data from a database that is accessible in LibreOffice. For more details about data sources, refer to chapter Database Access. This includes data from any table of a database, or data from a query based on one or more tables.

The basic idea is that a logical form is associated with a database result set. A form control model, which is a child of that form, is bound to a field of this result set, exchanging the data entered by the user with the result set field.

Forms
Forms support Row Sets, are loadable, can be filtered and sorted, and have parameters that you can set.

Forms as Row Sets
Besides forms, there is already a component that supports a result set, the com.sun.star.sdb.RowSet .If you look at the com.sun.star.form.component.DataForm, a  also implements the com.sun.star.sdb.RowSet service, and extends it with additional functionality. Row sets are described in The RowSet Service.

Loadable Forms
A major difference of data forms compared to the underlying row set is the that forms are loaded, and provide an interface to manipulate this state.

Loading is the same as executing the underlying row set, that is, invoking the com.sun.star.sdbc.XRowSet:execute method. The com.sun.star.form.XLoadable is designed to fit the needs of a form document, for example, it unloads an already loaded form.

The example above shows how to reload a form. Reloading is executing the row set again. Using  instead of   has the advantage of advanced listener mechanisms:

Look at the com.sun.star.form.XLoadable interface. You can add a com.sun.star.form.XLoadListener. This listener not only tells you when load-related events have occurred that is achieved by the com.sun.star.sdbc.XRowSetListener, but also when they are about to happen. In a complex scenario where different listeners are added to different aspects of a form, you use the com.sun.star.form.XLoadable:reload call to disable all other listeners temporarily. Re-executing a row set is a complex process, thus it triggers a lot of events that are only an after effect of the re-execution.

An additional difference between loading and executing is the positioning of the row set: When using com.sun.star.sdbc.XRowSet:execute, the set is positioned before the first record. When you use com.sun.star.form.XLoadable:load, the set is positioned on the first record, as you would expect from a form.

Sub Forms
A powerful feature of LibreOffice are sub forms. This does not mean that complete form documents are embedded into other form documents, instead sub form relationships are realized by nesting logical forms in the form component hierarchy.

When a form notices that its parent is not the forms container when it is loaded and in live mode, but is dependent on another form, it no longer acts as a top-level form. Whenever the parent or master form moves to another record, the content of the sub or detail form is re-fetched. This way, the content of the sub form is made dependent on the actual value of one or more fields of the parent form.

Typical use for a relationship are tables that are linked through key columns, usually in a 1:n relationship. You use a master form to travel through all records of the table on the 1 side of the relationship, and a detail form that shows the records of the table on the n side of the relationship where the foreign key matches the primary key of the master table.

To create nested forms at runtime, use the following example:

The code snippet works on the following table structure:



The code is straightforward, except for setting up the connection between the two forms. The master form is bound to SALESMEN, and the detail form is bound to a statement that selects all fields from SALES, filtered for records where the foreign key, SALES.SNR, equals a parameter named.

As soon as the  and   properties are set, the two forms are connected. Every time the cursor in the master form moves, the detail form reloads after filling the salesman parameter with the actual value of the master forms SNR column.

Filtering and Sorting
Forms support quick and easy filtering and sorting like the underlying row sets. For this, the properties com.sun.star.sdb.RowSet:Filter, com.sun.star.sdb.RowSet:ApplyFilter and com.sun.star.sdb.RowSet:Order area used.

In this fragment, a filter string is built first. The " " is an example for a filter string. In general, everything that appears after the WHERE clause of an SQL statement is set as a  property value. The same holds true for the  property value and an   clause.

Then the  property is set to. This is for safety, because the value of this property is unknown when creating a new form. Every time you have a form or row set, and you want to change the filter, remember to set the  property at least once. Afterwards,  is called.

In general,  allows the user of a row set to enable or disable the current filter quickly without remembering it. To see what the effects of the current filter are, set  to   and reload the form.

Parameters
Data Aware Forms are based on statements. As with other topics in this chapter, this is not form specific, instead it is a functionality inherited from the underlying com.sun.star.sdb.RowSet. Statements contain parameters where some values are not specified, and are not dependent on actual values in the underlying tables. Instead they have to be filled each time the row set is executed, that is, the form is loaded or reloaded.

A typical example for a statement containing a parameter is

There is a named parameter, which is filled before a row set based on a statement is executed. The orthodox method to use is the com.sun.star.sdbc.XParameters interface, exported by the row set.

However, forms allow another way. They export the com.sun.star.form.XDatabaseParameterBroadcaster interface that allows your component to add itself as a listener for an event which is triggered whenever the form needs parameter values.

In a form, filling parameters is a three-step procedure. Consider a form that needs three parameters for execution.


 * 1) The master-detail relationship is evaluated. If the form's parent is a com.sun.star.form.component.DataForm, then the   and   properties are evaluated to fill in parameter values. For an example of how this relationship is evaluated, refer to chapter Sub Forms.
 * 2) If there are parameter values left, that is, not filled in, the calls to the com.sun.star.sdbc.XParameters interface are examined. All values previously set through this interface are filled in.
 * 3) If there are still parameter values left, the com.sun.star.form.XDatabaseParameterListener s are invoked. Any component can add itself as a listener using the com.sun.star.form.XDatabaseParameterBroadcaster interface implemented by the form. The listeners then have the chance to fill in anything still missing.

Unfortunately, LibreOffice Basic scripts currently cannot follow the last step of this procedure - there is a known implementation issue which prevents this.

Data Aware Controls
The second part of the Data Awareness capabilities of LibreOffice are data aware controls. While a form is always associated with a complete result set, it represents this result set, a single control is bound to one data column that is part of the form which is the control's parent.

As always, the relevant information is stored in the control model. The basic service for control models which are data-aware is com.sun.star.form.DataAwareControlModel.

There are two connections between a control model and the column it is bound to:

DataField
 * This is the property that determines the name of the field to bind to. Upon loading the form, a control model searches the data columns of the form for this name, and connects to it. An explanation for "connects" is provided below.
 * Note that this property is a suggestion only. It tells the control model to connect to the data column, but this connection may fail for various reasons, for example, no such column may exist in the row set.
 * Even if this property is set to a non-empty string, this does not mean anything about the control being connected.

BoundField
 * Once a control model has connected itself to a data column, the respective column object is also remembered. This saves clients of a control model the effort to examine and handle the DataField, they simply rely on BoundField.
 * Opposite to the DataField property, BoundField is reliable in that it is a valid column object if and only if the control is properly connected.

The overall relationship for data awareness is as follows:



Control Models as Bound Components
You expect that the control displays the current data of the column it is tied to. Current data means the data in the row that the com.sun.star.form.component.DataForm is currently located on. Now, the control does not know about data-awareness, only the control model does, but we already have a connection between the model and control: As described in the chapter about model-view interaction, Model-View Interaction, the control listens for changes to the model properties, as well as updates them when a user interacts with the control directly.

For instance, you know the  property of a simple text input field, com.sun.star.form.component.TextField that is updated by the control when the user enters text. When the property is updated through any other means, the control reacts appropriately and adjusts the text it displays.

This mechanism is found in all controls. The only difference is the property used to determine the contents to be displayed. For instance, numeric controls com.sun.star.form.component.NumericField have a property Value representing the current numerical value to be displayed.Although the name differs, all control models have a dedicated content property.

This is where the data-awareness comes in. A data-aware control model bound to a data column uses its content property to exchange data with this column. As soon as the column value changes, the model forwards the new value to its content property, and notifies its listeners. One of these listeners is the control that updates its display:



Committing Controls
The second direction of the data transfer is back from what the user enters into the control. The text entered by a user is immediately forwarded to the value property of the control model. This way, both the control and the control model are always consistent.

Next, the content property is transferred into the data column the control is bound to. As opposed to the first step, this is not done automatically. Instead, this control is committed actively.

Committing is the process of transferring the current value of the control to the database column. The interface used for this is com.sun.star.form.XBoundComponent that provides the method. Note that the  is derived from com.sun.star.form.XUpdateBroadcaster. This means that listeners are added to a component to monitor and veto the committing of data.

The following diagram shows what happens when the user decides to save the current record after changing a control:



Note that in the diagram, there is a controller instance involved. In general, this is any instance capable of controlling the user-form interaction. In LibreOffice, for every document view and form, there is an instance of the com.sun.star.form.FormController service, together with some not-yet UNO-based code that takes on the role of a controller.

External value suppliers
Chapter Data Aware Controls discussed form controls that exchange their value, as entered by the user, with database columns. At certain times, this type of form control initializes itself from the column, or writes its current value into the column.

In addition, list and combo box controls are able to retrieve, in various ways, their list content from a database.

Since OpenOffice.org 2.0.0, it is possible for form controls to exchange data with external components. This is a generalization of the data awareness concept: form controls are now able to bind their value to any external value supplier, without knowing anything about the value supplier except an abstract UNO interface.

Similarly, list and combo boxes can obtain their list content from an external component, as long as they support a certain interface.

The com.sun.star.form.binding module collects all interfaces and services related to this new functionality.

Value Bindings
Unlike the functionality for binding form controls to database columns, value bindings are external to the form control/model. A control that can be bound (note that not all existing controls actually can) supports a certain interface, and a binding supports another one. That is all both parties need to know.

The illustration below shows the most important interfaces and services collaborating here.



Note that there is yet no notion about form controls at all. Those interfaces are only concerned with components representing a value, and components implementing a binding for this value. In fact, the generic mechanism for binding values is described with a complete disregard of form controls. The components supporting the com.sun.star.form.binding.XBindableValue interface are called value components.

The central interface is com.sun.star.form.binding.XValueBinding, which is to be supported by components that want to impose their value on a value component. The following table describes its methods:

The com.sun.star.form.binding.ValueBinding service extends the com.sun.star.form.binding.XValueBinding interface with two aspects:

com.sun.star.util.XModifyBroadcaster
 * This allows a value binding to actively notify changes in its value. A value component can register itself as com.sun.star.util.XModifyListener at the binding. In fact, that is the only way that the relationship between the binding and the value component can become bidirectional. Without the support of the com.sun.star.util.XModifyBroadcaster interface, value components can only actively propagate their value to the binding, but not the reverse.

support for read-only bindings
 * The com.sun.star.form.binding.ValueBinding:ReadOnly property can be used to specify that the value represented by a binding currently cannot be modified. If the read-only state of a binding's value can change during its lifetime, it should allow registering com.sun.star.beans.XPropertyChangeListener s for the com.sun.star.form.binding.ValueBinding:ReadOnly property, so value components using the binding can act on the current state.

Form Controls accepting Value Bindings
How do form controls and value bindings relate to each other? When looking at all the form control functionality that has so far been discussed, the following questions come need to be answered:


 * Which control types do support value bindings?
 * For a given control type, which aspect actually is its value, which is exchanged with an external binding?
 * How do external value bindings interact with data awareness, for example, controls that exchange their value with a database column?
 * What can you do with all this?

The first two questions are easy: Every control that allows user input also supports value bindings. The data that the user entered (this may be, for instance, plain text, or an image, or a check state) is considered the value of the control, and thus exchanged with the external binding.

The basic service is the com.sun.star.form.binding.BindableControlModel, which specifies a control model supporting external value bindings. For a concrete control type, for instance, a check box, a service such as  would be expected, which specifies how a check box control model exchanges its value with an external binding.

However, all controls that potentially could support a binding also are data aware (see Data Aware Controls). Thus, the first step is to answer the third question from above. The service com.sun.star.form.binding.BindableDataAwareControlModel is about data aware control models with value binding capabilities. You are referred to the documentation of the com.sun.star.form.binding.BindableDataAwareControlModel service for all the details, but the two most interesting details are as follows:

Priority External value bindings overrule any active SQL-column binding. If an external component is bound to a control model that currently has an active SQL binding, this SQL binding is suspended until the external binding is revoked.

Immediacy When a com.sun.star.form.binding.BindableDataAwareControlModel is bound to an external value, then every change in the control model's value is immediately reflected in the external binding. This is a difference to SQL bindings of most com.sun.star.form.DataAwareControlModel s, where changes in the model's value are only propagated to the bound column upon explicit request via com.sun.star.form.XBoundComponent:commit.

The illustration below shows the service hierarchy for control models that are also value components. It also shows how concrete control types fit in, for example by using check boxes.



The following covers the last question from the above list: What is this good for?

LibreOffice already contains two practical applications:

Spreadsheet cell bindings
 * In a LibreOffice spreadsheet document, you always could insert form controls. Since version OpenOffice.org 2.0.0, you can, in their properties, bind form controls to arbitrary cells within the document. That is, every change made in this cell is propagated to the control, and vice versa. This is implemented using the value binding mechanism described in this chapter. See com.sun.star.table.CellValueBinding for more details.


 * The following piece of code creates a cell value binding in a spreadsheet document, for cell A1 on the first sheet, and knits it to a numeric control model:

XML form bindings
 * LibreOffice features XML forms. These are form documents whose data model is a DOM tree. They are realized with the usual form controls and logical forms, and this time the controls are bound to DOM nodes using the value binding mechanism.

External List Sources
The previous chapter introduced an abstraction of the data aware mechanism for form controls: They can not exchange their value with database columns or with arbitrary value bindings, without recognizing anything except UNO interfaces.

When you look at what controls can do with database content, you may find list and combo boxes useful. They are able to retrieve the content of their lists from a database.

Similar to the value binding mechanism, there is also an abstraction available for components supplying list entries to form controls: com.sun.star.form.binding.ListEntrySource and com.sun.star.form.binding.XListEntrySink.

The relationship between com.sun.star.form.binding.XListEntrySource s and com.sun.star.form.binding.XListEntrySink s is shown in the illustration below.



As with value bindings, LibreOffice already makes use of this concept in spreadsheet documents. The following piece of code, for instance, creates a com.sun.star.table.CellRangeListSource, and binds it to a list box. After that, the list boxes content will always be synchronized with the content in the chosen cell range.

Note that a com.sun.star.table.CellRangeListSource can not be obtained at a global service manager. Instead, you have to retrieve it from the document to whose cells you want to bind the list box.

Validation
Form controls in LibreOffice always featured a simple type of validation for their value. For instance, for a numeric field you can specify minimum an maximum values ( com.sun.star.awt.UnoControlNumericFieldModel:ValueMin and com.sun.star.awt.UnoControlNumericFieldModel:ValueMax ). However, those validity constraints have some disadvantages:


 * They are enforced as soon as the control loses the focus. That is, if you enter a number into a numeric field that is greater than the allowed maximum, then it is automatically corrected to be the maximum.
 * They are enforced silently. There is no warning to the user, and no visual feedback at the moment the value is invalid, and not yet corrected. In particular, there is no explanation about why a certain input was (or will be) automatically corrected.

LibreOffice features a mechanism for validating the content of form controls, at the time of user input.

The basic interface for this mechanism is com.sun.star.form.validation.XValidator :

A validator is to be used with a component that can be validated: com.sun.star.form.validation.XValidatable. This interface allows to set and to get a validator instance.

Until now, nothing has been said about form components. You may also note that nothing has been said about the data that is being validated. Though a value is passed to the com.sun.star.form.validation.XValidator:isValid method, there is no explanation about where it originates from. In particular, the com.sun.star.form.validation.XValidatable does not specify a means to obtain its value.

This is where com.sun.star.form.validation.XValidatableFormComponent comes in. Note that it derives from com.sun.star.form.validation.XValidatable.

Now, the overall picture for services and interfaces concerned with form control validation can be seen in the following figure:



Notice the com.sun.star.form.validation.ValidatableControlModel service: It specifies the basic functionality of form control models, which allow their current value to be validated against an external validator.

In LibreOffice, there is one feature that uses the functionality introduced in this chapter: XML form documents. They are implemented using the interfaces and services from com.sun.star.xforms. In particular, an XForms binding ( com.sun.star.xforms.Binding ) is a validator. This way, LibreOffice form controls can be used to enter values for XForms DOM trees, respecting the restrictions imposed on those value as part of the XForms model.

Validation in LibreOffice
The LibreOffice Software Development Kit shows the power of form control validation with an example program. This program creates a form document with various types of controls, most of which are bound to external validators. Those validator objects impose (exemplary and rather arbitrary) restrictions on the control values.

As shown in the example program, the form runtime environment of LibreOffice makes use of several features of the validation API, illustrating the advantage over the old, property-based, built-in validation mentioned in chapter Validation.

For instance, invalid values in form controls, where invalid is defined by the external validator object, are not enforcing a valid value automatically. Instead, the invalidity is shown with a red border around the control. If the control does not allow for a red border, its text is underlined with red waves. Additionally, the explanation why a certain value is invalid appears as tooltip at the respective control.

This way, the user who fills in a form receives immediate feedback about which values and controls need attention, without destroying whatever information has already been entered.

Validations and Bindings
Chapter Value Bindings introduced form components that can exchange the value with external components, as long as those support the com.sun.star.form.binding.XValueBinding interface. Also, chapter Validation introduced form components whose value can be validated by external components.

These concepts can be combined. This way, it is possible to build highly customized form documents.

In fact, this is what the com.sun.star.form.validation.ValidatableBindableControlModel service does: it combines the services com.sun.star.form.binding.BindableControlModel with the com.sun.star.form.validation.ValidatableControlModel.

As soon as you establish a validator at the model ( com.sun.star.form.validation.XValidatable:setValidator ), which is also an com.sun.star.form.binding.XBindableValue, then it is used both as value binding and as validator. Every attempt to establish another binding will be denied, as long as the combined validator/binding is in place.

Scripting and Events
To create form documents that are able to do more than just reading and writing plain data, it is often necessary to enhance the form with scripting functionality. That is, for a given form component, you want to declare that a certain script should be called, when a certain event occurs.

For example, you may need a check box control, which calls a certain macro when its check state changes. Within this macro, you can, for instance, enable or disable other controls that depend on the check box being checked.

One possible solution is to use a completely programmatic approach: just bind a script to the OnLoad event of the whole document, create an com.sun.star.awt.XItemListener, and register it at the check box control in question, using the com.sun.star.awt.XCheckBox interface.

However, this method is inefficient, because the whole scripting engine starts when the document is loaded. The scripting engine should start at the latest possible point, which is the moment the user clicks the check box for the first time.

Form components feature a mechanism that is more efficient. For every form component part of a hierarchy of form components, you can specify a script to be called upon a certain event. You only specify this once, at the time the form component is created and placed in the document.

Look at the com.sun.star.form.FormComponents service, which was encountered previously. The service includes the interface com.sun.star.script.XEventAttacherManager. This interface allows you to manage the events that are associated with the elements in the com.sun.star.form.FormComponents container.

Note that an event together with an associated script is described by the com.sun.star.script.ScriptEventDescriptor, with the following elements:

The following example registers a certain Basic procedure for the event which is triggered when the state of a radio button control changes, for example, when a radio button has been selected or deselected:

For the ith sub component of, this associates the macro  , located in the module   of the application-wide library  , with the com.sun.star.awt.XItemListener:itemStateChanged event. You can use this with every form component which supports notification of com.sun.star.awt.XItemListener s, in particular with radio buttons ( com.sun.star.awt.XRadioButton ) and check boxes ( com.sun.star.awt.XCheckBox ).

Note that simply registering script events at a com.sun.star.form.FormComponents instance does not do anything. In particular, registering script events does not yet mean that the script will be called automatically. In fact, the com.sun.star.script.XEventAttacherManager interface merely acts as a container to remember the associated events. In a living form document, there are controller instances involved, which take care of the scripts that are really being called, by adding themselves as com.sun.star.script.XScriptListener to the event attach manager.

Common Tasks
This chapter is dedicated to problems that may arise when you are working with (or script) form documents, and cannot be solved by LibreOffice's built-in methods, but have a solution in the LibreOffice UNO API.

Initializing Bound Controls
All form controls specify a default value that is used when initially displaying the control, and when it is reset. For instance, resetting ( com.sun.star.form.XReset ) happens when a form is moved to the insert row, that allows data to be inserted as a new row into the underlying row set.

Now, you do not want a fixed default value for new records, but a dynamically generated one that is dependent on the actual context at the moment the new record is entered.

Or, you want to have real null values for date fields. This is currently not possible, because the com.sun.star.form.component.DateField service interprets a  default as an instruction to use the current system date. Effectively, you cannot have date fields in forms which default to  on new records, but you can get this by programming the API.

The first decision is where to step in. We chose to add a reset-listener to the form, so that the form is reset as soon as it has been positioned on the new record. The com.sun.star.form.XResetListener:resetted method is called after the positioning is done.

However, resets also occur for various reasons therefore check if the form is really positioned on the insert row, indicated by the  property being.

Now besides retrieving and updating the data column with the desired value, null, there is another obstacle. When the form is moved to the insert row, and some values are initialized, the row should not be modified. This is because a modified row is saved in the database, and we only initialized the new row with the defaults, the user did not enter data. We do not want to store the row, therefore we save and restore the  flag on the form while doing the update.

Automatic Key Generation
Another problem frequently encountered is the automatic generation of unique keys. There are reasons for doing this on the client side, and missing support, for example, auto-increment fields in your database backend, or you need this value before inserting the row. LibreOffice is currently limited in re-fetching the server-side generated value after a record has been inserted.

Assume that you have a method called  to generate a unique key that could be queried from a key generator on a database server, or in a single-user-environment by selecting the maximum of the existing keys and incrementing it by 1. This fragment inserts the generated value into the given column of a given form:

A solution to determine when the insertion is to happen has been introduced in a previous chapter, that is, we could fill in the value as soon as the form is positioned on the insert row, wait for the user's input in the other fields, and save the record.

Another approach is to step in immediately before the record is inserted. For this, the com.sun.star.sdb.XRowSetApproveBroadcaster is used. It notifies listeners when rows are inserted, the listeners can veto this, and final changes can be made to the new record:

Data Validation
If you happen to have a scripting language that is not capable of creating own components, such as StarBasic, then the validation mechanisms described in chapter Validation can not be used: They rely on a component being created that implements the com.sun.star.form.validation.XValidator interface.

If, despite this, you want to validate data in controls bound to a database, then you have two alternative possibilities:


 * From the chapter Committing Controls, you can approve updates, and veto the changes a control wants to write into the data column it is bound to.
 * Additionally, you can step in later. You know how to use a com.sun.star.sdb.XRowSetApproveListener for doing last-minute changes to a record that is about to be inserted.
 * Besides this, you can use the listener to approve changes to the row set data. When the com.sun.star.sdb.RowChangeAction is sent to the listeners, it distinguishes between different kinds of data modification. You can implement listeners that act differently for insertions and simple updates.

Note the important differences between both solutions. Using an com.sun.star.form.XUpdateListener implies that the data operations are vetoed for a given control. Your listener is invoked as soon as the respective control is committed, for instance, when it loses the focus. This implies that changes done to the data column by other means than through this control are not monitored.

The second alternative is using an com.sun.star.sdb.XRowSetApproveListener meaning you veto changes immediately before they are sent to the database. Thus, it is irrelevant where they have been made previously. In addition, error messages that are raised when the user actively tries to save the record are considered less disturbing than error messages raised when the user simply leaves a control.

The example below shows the handling for denying empty values for a given control:

Programmatic Assignment of Scripts to Events
Sometimes, you want to create a document programmatically, including form controls, and assigning certain scripts to certain events for those controls. In the userinterface, this is done by using the property browser. Programmatically, this is somewhat more difficult.

As an example, if you want to programmatically create a document containing radio buttons. When those radio buttons change their state (i.e. are selected), a certain Basic script should be called.

One possibility is to make use of the OnLoad event of the document as a whole. Using this event, you can create a listener of the desired type (in our sample case: com.sun.star.awt.XItemListener ), and register it at the control in question.

This approach has three disadvantages: First, it is expensive. The scripting environment is loaded every time the document is loaded, which is too early. It should be loaded as late as possible, which is when the radio buttons really change their state.

Second, it is error prone. There are certain circumstances where LibreOffice Basic listeners are automatically revoked, without the document being closed. In those cases, you need to manually reload the document, or re-run your OnLoad script for re-creating the listener.

Third, it is complex. You would, in your OnLoad initialization script, need to manually obtain the control in questions, which can involve a large amount of code.

A better solution is to use the event attacher manager mechanism described in Scripting and Events.

The following example creates a text document with three radio buttons, all three calling the same script when being selected.