A complete builder script

In the previous chapters the various elements that can appear in a builder script - bean declarations, form elements, actions, windows, etc. - have been discussed. There have also been plenty examples demonstrating the usage of the tags provided by the JGUIraffe tag libraries. However, these have only been short code fragments focusing on the element(s) just under discussion. What is missing so far is a full example of a builder script. Such an example is the subject of this chapter.

Having a full example of a builder script is indeed useful because there are certain requirements regarding the order in which elements are declared. The script is processed in a single pass from its beginning to its end. So as a rule of thumb, elements must be declared before they can be referenced by other elements. There are some exceptions from this rule, however. Bean declarations for instance do not create the corresponding objects directly. The creation happens on first access through a BeanContext, and then all dependencies are resolved automatically. As long as there are no cyclic dependencies between beans (refer to the section Cyclic dependencies), dependent beans can be placed in any order.

In the following sub sections a full builder script defining a simple dialog window will be developed. We first present single blocks of the script that deal with a specific topic. At the end of the chapter the script is again printed as a whole. The order of the single blocks can be adapted as a common pattern. It takes logic dependencies between the different elements into account and complies to the ordering requirements mentioned above.

The example script discussed in this chapter has already been partly presented in other chapters of this guide. It defines a dialog window whose purpose it is to create a new text file. The dialog provides the following features:

  • A pretty simple UI consisting mainly of a text field for entering the file name and a text area for defining the content of the file.
  • Buttons for creating the new file and for canceling the operation.
  • Validation support: The input field for the file name is associated with multiple validators. It must be filled out, the entered file name must not aleady exist in the current directory, and it is checked for illegal characters. For the text area just a warning is issued if it is empty. Also, invalid fields should be marked, so that it is easy to recognize that they contain incorrect data.
  • The text area has a popup menu with some operations.
  • Actions are provided for inserting predefined text fragments into the text area. These fragments are also defined in the builder script.
  • The dialog window has a form controller which is responsible for the form's life-cycle. The default FormController class provided by the framework is used, so no controller logic has to be implemented.

The following screenshot shows the example dialog window in action:

Example dialog window

Bean declarations

The builder script starts with the definition of some beans that are used by UI components as helper classes. Such beans do not have references to graphical elements defined in this script. Therefore they can be put at the very top. First the bean acting as the form's model and the command object to be triggered when the user clicks the OK button are defined:

  <!-- The form bean. This object acts as the model of the dialog.-->
  <di:bean name="createFileModel"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.CreateFileData"/>

  <!-- The command to be executed when the OK button is pressed. -->
  <di:bean name="okCommand"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.CreateFileCommand">
    <di:constructor>
      <di:param refName="jguiraffe.applicationContext"/>
      <di:param refName="createFileModel"/>
      <di:param refName="action:editRefreshAction"/>
    </di:constructor>
  </di:bean>
    

The bean named createFileModel is a simple Java bean defining get and set methods corresponding to the input fields of the form. It basically has two properties of type String for the two text fields in the dialog - there is no additional logic. For database-centric applications an entity class could be used, too. Declaring the form model as a bean has the advantage that it is automatically created and is available to all components that need access to it. Note that it is a singleton bean, so only a single instance is created, and all referencing components share the same instance.

Note: What happens if the builder script is executed multiple times, e.g. if the user wants to create a number of files? Will there still be only a single instance of the model bean? The answer is no. Everytime the dialog window is closed all singleton beans in the bean context are freed. The next time the builder script is processed again new instances are created. This is what we want in this case: when the dialog opens it starts with empty input fields. If a dialog's purpose is to edit an existing data object, the model has to be created and populated before the builder script is executed. It can then be passed to the builder as a property of the ApplicationBuilderData object.

After that another bean is defined which serves as the command to be executed when the user clicks the OK button. In this example a custom command implementation, CreateFileCommand is used. We do not show this class here, it is not too complicated. It creates the file as specified by the input fields of the dialog. The directory in which the file is created is obtained from the global ApplicationContext object passed to the constructor - storing global state of the application is a typical use case of the ApplicationContext class. Two points are worth a remark:

  1. The command object is passed the model of the form as constructor argument. This model object contains all information needed by the command to fulfill its task. Therefore no references to other components of the UI are required. Passing the form model to the command object is a pretty straightforward way of interchanging data between the form and the processing command. This is a non-instrusive approach because the command does not need to know the form controller or other framework classes for this purpose. Just the application-specific model object is passed.
  2. In this example, an action is passed to the command object; it is the action for refreshing the current directory. This action is not defined in the current builder script, it stems from the parent bean context. The background is that if a new file is created, the directory listing maintained by the application has to be updated. Therefore the command triggers this action after its successful execution. It is noteworthy how the action is referenced when it is passed as constructor argument to the command bean.

Next there are some bean definitions for validators that will later be used by input components:

  <!-- A validator for required input fields.-->
  <di:bean name="requiredValidator"
    beanClass="net.sf.jguiraffe.transform.RequiredValidator">
  </di:bean>

  <!-- A regular expression validator for validating a file name. Certain
       characters are not allowed in file names.
  -->
  <di:bean name="fileNameValidator"
    beanClass="net.sf.jguiraffe.transform.RegexValidator">
    <di:setProperty property="regex" value="[^\*\\/~\|&lt;&gt;]*"/>
  </di:bean>
    

Validators are normal beans which can be created using the tags of the dependency injection framework. Alternatively, they can be created by <f:validator> tags directly. Using the <di:bean> tag provides more features. Also, because most validators can be shared between multiple components, it makes sense to define them globally and reference them from the corresponding input elements. If an application uses some specialized custom validators, they can be declared in the top-level builder script and are then available in all other builder scripts through the parent bean context.

For this example we define an instance of RequiredValidator which checks that an input field is not empty. Then a specialized validator for checking the file name input field is declared. It ensures that the field does not contain any of the invalid characters. We will see below how these validators are associated with input fields.

Actions and menus

The next block in the builder script is concerned with action definitions. Because the window under construction is just a simple dialog box there is neither a main menu nor a tool bar. However, the text area input element has a popup menu which is defined using actions.

  <!-- Action for clearing the content text field. -->
  <a:action name="clearContentAction" textres="newfile_act_clear_text"
    mnemonicres="newfile_act_clear_mnemo" taskBean="clearTask"/>

  <!-- Action for adding lorem ipsum to the content text field. -->
  <a:action name="addContentLoremIpsumAction" textres="newfile_act_loremipsum_text"
    mnemonicres="newfile_act_loremipsum_mnemo" taskBean="addLoremIpsumTask"/>

  <!-- Action for adding XML to the content text field. -->
  <a:action name="addContentXMLAction" textres="newfile_act_xml_text"
    mnemonicres="newfile_act_xml_mnemo" taskBean="addXMLTask"/>

  <!-- Action for adding HTML to the content text field. -->
  <a:action name="addContentHTMLAction" textres="newfile_act_html_text"
    mnemonicres="newfile_act_html_mnemo" taskBean="addHTMLTask"/>

  <!-- Action data definition for the append sub menu in the popup menu -->
  <a:actionData textres="newfile_men_append_text"
    mnemonicres="newfile_men_append_mnemo" var="menuAppend"/>
    

The actions defined here are related to clearing the text area for the new file's content and for inserting specific text fragments. The <a:action> tags define the typical visual properties of their actions, e.g. a name, a text label, and a mnemonic. Icons are not used here, but would also be allowed.

An interesting point are the references to the actions' tasks specified by the taskBean attributes. The beans referenced here have not yet been declared in the builder script. Actually, action task definitions belong to the exceptional elements in builder scripts that support forward references. There is a good reason for this: Beans used as tasks for actions frequently require access to graphical elements defined in the same builder script - a typical use case for an action is to manipulate parts of the UI. So to create the task beans, references to those elements have to be injected. In such a constellation it is easy to construct cyclic dependencies: Actions reference task beans, task beans reference UI elements, UI elements reference actions. Therefore it is possible to define action tasks at an arbitrary position of the builder script. We will meet them again at the very bottom of the script.

In the following block the actions are used to construct a popup menu:

  <!-- Popup menu handler for the append sub menu -->
  <di:bean name="appendMenu"
    beanClass="net.sf.jguiraffe.gui.builder.action.SimplePopupMenuHandler">
    <di:constructor>
      <di:param>
        <di:list>
          <di:element refName="action:addContentLoremIpsumAction"/>
          <di:element refName="action:addContentXMLAction"/>
          <di:element refName="action:addContentHTMLAction"/>
        </di:list>
      </di:param>
    </di:constructor>
    <di:setProperty property="actionData" refName="menuAppend"/>
  </di:bean>

  <!-- Popup menu handler for the text area's content menu -->
  <di:bean name="fileContentPopupHandler"
    beanClass="net.sf.jguiraffe.gui.builder.action.SimplePopupMenuHandler">
    <di:constructor>
      <di:param>
        <di:list>
          <di:element refName="appendMenu"/>
          <di:element refName="action:clearContentAction"/>
        </di:list>
      </di:param>
    </di:constructor>
  </di:bean>
    

Here two beans of type SimplePopupMenuHandler are defined. The one with the name fileContentPopupHandler represents the actual popup menu. It consists of a menu item for clearing the text area and a sub menu. The sub menu is defined by the other SimplePopupMenuHandler bean. Here the actions for inserting text fragments are contained. This is all this simple dialog box does with its actions. If you were defining a frame window, you could create a main menu as well. A tool bar would be created as part of the window definition.

The form controller

The form controller is a regular bean definition. For this example no specific, UI-related logic is needed; therefore we can go with the default form controller implementation. The whole declaration looks as follows:

  <!-- The bean for the form controller.-->
  <di:bean name="controller"
    beanClass="net.sf.jguiraffe.gui.builder.window.ctrl.FormController">
    <di:setProperty property="btnOkName" value="btnOk"/>
    <di:setProperty property="btnCancelName" value="btnCancel"/>
    <di:setProperty property="okCommand" refName="okCommand"/>
  </di:bean>
    

Here some important properties of the controller are set: the names of the OK and the Cancel buttons, and the command to be executed when the OK button is clicked. We have already seen the declaration of the command bean. The buttons are defined together with the whole UI of the window in the next block.

As we will see in a moment, the controller bean is associated with the dialog window as part of the window declaration. Because of that controller beans are typically defined before the window. In most cases this is not a problem. The FormController class has access to the current ComponentBuilderData object, from which all elements defined by the builder script can be obtained. If a custom controller implementation actually required injection of some UI elements, it is possible to declare the controller bean in the body of the tag defining the window - after the UI-related tags, and before the tag that connects the controller to the window. At this position all UI elements can be referenced.

The window and its content

The whole dialog window is defined by a <w:dialog> tag. In the body of this tag tags of the form builder tag library are placed to create the graphical elements comprising the UI. This block looks as follows:

  <w:dialog titleres="newfile_title" center="true" resizable="true">
    <f:borderlayout canShrink="true"/>
    <!-- The main panel -->
    <f:panel>
      <f:borderconstr name="CENTER"/>
      <f:percentlayout columns="4dlu start/preferred 3dlu full/preferred(6cm)/100 4dlu"
        rows="4dlu preferred 3dlu preferred full/preferred(5cm)/100 4dlu"
        canShrink="true"/>
      <f:label textres="newfile_lab_name" mnemonicres="newfile_lab_name_mnemo"
        componentref="fileName">
        <f:percentconstr col="1" row="1"/>
      </f:label>
      <f:textfield name="fileName" displayNameres="newfile_disp_name"
        maxlength="200" tooltipres="newfile_txt_name_tip">
        <f:percentconstr col="3" row="1"/>
        <f:validators phase="syntax">
          <f:validator beanName="requiredValidator"/>
          <f:validator beanName="fileNameValidator">
            <f:properties>
              <f:property property="ERR_PATTERN">
                <f:localized resid="ERR_FILENAME_PATTERN"/>
              </f:property>
            </f:properties>
          </f:validator>
          <f:validator
            class="net.sf.jguiraffe.examples.tutorial.createfile.UniqueFileNameValidator"/>
        </f:validators>
      </f:textfield>
      <f:label textres="newfile_lab_content" mnemonicres="newfile_lab_content_mnemo"
        componentref="fileContent">
        <f:percentconstr col="1" row="3"/>
      </f:label>
      <f:textarea name="fileContent" displayNameres="newfile_disp_content"
        rows="10" columns="50">
        <f:percentconstr col="1" row="4" spanx="3" targetCol="3"/>
        <f:font name="Monospaced" size="13"/>
        <f:validator phase="syntax" beanName="requiredValidator">
          <f:properties>
            <f:property property="errorLevel" value="WARNING"/>
          </f:properties>
        </f:validator>
        <a:popup beanName="fileContentPopupHandler"/>
      </f:textarea>
    </f:panel>

    <!-- The button bar -->
    <f:panel>
      <f:borderconstr name="SOUTH"/>
      <f:buttonlayout/>
      <f:button name="btnOk" textres="newfile_btn_create"
        mnemonicres="newfile_btn_create_mnemo" command="create"/>
      <f:button name="btnCancel" textres="newfile_btn_cancel"
        mnemonicres="newfile_btn_cancel_mnemo"/>
    </f:panel>

    <!-- Connect the form controller -->
    <w:formController beanName="controller" formBeanName="createFileModel">
      <!-- Register the field markers -->
      <w:formControllerListener beanName="jguiraffe.fieldMarker"/>
    </w:formController>
  </w:dialog>
    

This fragment is a bit longer, but there is not that much to say about it. Most of the elements occuring in this script should be familiar after reading the chapter Building user interfaces. The script specifies the layout to use - a border layout with a main panel in the center area and a button panel in the south area; the main panel uses a percent layout - and adds the corresponding UI elements to it. Here are a few remarks:

  • The layout used by the implicit panel associated with the window has to be defined. In this case, a BorderLayout is used. Note how layout constraint tags are used to arrange the single components comprising the window's content (the main panel in the center, and the button bar in the south).
  • The validator definitions are complex in this example, especially for the text field for the file name. Here three different validators are set. Two of them have been defined in the section Bean declarations and are now just referenced. The third one - an instance of the custom validator class UniqueFileNameValidator is directly created by the <f:validator> tag. This is mainly done for demonstration purposes: to show that this way is possible, too. It could as well have been defined as a bean as the other validators. However, because there is only a single instance of this validator which is associated with this text field, it makes sense to define it locally. The UniqueFileNameValidator class is not shown here. Its purpose is to ensure that the user enters a file name which does not exist in the current directory. So it checks the user input against the listing of the current directory. Also notice that for some validators specific properties are set. These properties override the global settings of the validator instance for this specific input field. In this example we set a custom error message for the regular expression validator of the text field and indicate that the required validator of the text area should only produce warning messages.
  • In the button bar the OK and the Cancel button are defined. The names of these buttons must match the names specified in the properties of the declaration of the form controller as shown in the sub section The form controller.
  • The <w:formController> tag establishes the connection between the dialog window and the form controller. It references the controller bean and also specifies the form model. In the body of the tag we also add the standard bean jguiraffe.fieldMarker as event listener to the form controller. This effectively enables the highlighting of input fields containing invalid data.

Action tasks

After the definition of the window the most important declarations of the builder script have been discussed. What remains are elements which reference other graphical elements defined so far. Under this category fall event listener declarations and the tasks of actions. Remember that we already mentioned in the sub section Actions and menus that action tags can reference task beans that may be defined later in the script. Here the action tasks manipulate the text area with the content of the new file. Thus a reference to this input element needs to be injected. The following listing shows the definitions for the task beans for clearing the text area and for inserting text fragments:

  <di:bean name="clearTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.ClearTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
    </di:constructor>
  </di:bean>

  <di:bean name="addLoremIpsumTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.AppendTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
      <di:param>
        <di:value>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum quis mauris
in quam mattis dignissim. Integer non nibh purus, vel cursus tortor. Donec quam
orci, tincidunt vitae fringilla vitae, suscipit eu nibh. Etiam fermentum, turpis
ut gravida tempor, nisl lorem malesuada ante, at sodales libero nibh non libero.
Duis vel erat hendrerit neque condimentum imperdiet sit amet id diam. Phasellus
in congue urna. Sed lectus orci, hendrerit eget vehicula sit amet, tempus ac
dui. Aenean nec dolor diam, fermentum venenatis justo. Nunc ac lorem arcu, ut
convallis dui. Nam pretium feugiat felis sit amet consequat. Morbi id nunc
sodales diam pulvinar commodo id ac magna. Donec accumsan rhoncus arcu ut porta.
Donec blandit porta suscipit. Cras sit amet nibh non dui faucibus blandit.
Curabitur tincidunt sagittis neque, ut sagittis magna tempor ut. Vestibulum ante
ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus
egestas iaculis eleifend. Pellentesque dui lacus, fringilla vulputate tempor eu,
pretium non eros. Ut id eros nibh.
        </di:value>
      </di:param>
    </di:constructor>
  </di:bean>

  <di:bean name="addXMLTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.AppendTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
      <di:param>
        <di:value><![CDATA[
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
</root>
        ]] ></di:value>
      </di:param>
    </di:constructor>
  </di:bean>

  <di:bean name="addHTMLTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.AppendTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
      <di:param>
        <di:value><![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>

  <body>
  </body>
</html>
        ]] ></di:value>
      </di:param>
    </di:constructor>
  </di:bean>
    

In this example special action task implementation classes are used. The classes are not shown here, but they are pretty simple. ClearTextActionTask is initialized with a reference to a text component handler in its constructor. It simply sets the data of the handler to null which clears the content of the text field.

The AppendTextActionTask class is used to append a configurable text fragment to the text area. A reference to the component handler of the text area and the text fragment to be appended are passed to the constructor. When triggered AppendTextActionTask reads the current data of the text component handler, appends the text fragment to it, and writes the resulting String back into the handler. The fact that the text fragment to be appended can be configured in the builder script makes this class pretty flexible. However, the declarations tend to become verbose, especially if XML fragments are involved which have to be enclosed in CDATA sections. In this example three instances of the AppendTextActionTask task class are created and initialized with different text fragments: one with the famous lorem ipsum text, one with a skeleton for an XML document, and one with a skeleton for an HTML file. Also note how the references to the text component handlers are passed to the constructor: by using the special prefix comp: followed by the name of the affected input component.

Bringing it all together

We are now complete with our tour through the different sections that can occur in a builder script. You should have gained an understanding about the order in which elements are best placed in such a script. To give the reader a better overview we present the script again as a whole. The different sections are marked with comments.

<j:jelly xmlns:j="jelly:core" xmlns:di="diBuilder" xmlns:f="formBuilder"
  xmlns:a="actionBuilder" xmlns:w="windowBuilder">

  <!-- The form bean. This object acts as the model of the dialog.-->
  <di:bean name="createFileModel"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.CreateFileData"/>

  <!-- The command to be executed when the OK button is pressed. -->
  <di:bean name="okCommand"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.CreateFileCommand">
    <di:constructor>
      <di:param refName="jguiraffe.applicationContext"/>
      <di:param refName="createFileModel"/>
      <di:param refName="action:editRefreshAction"/>
    </di:constructor>
  </di:bean>

  <!-- Validators.
       As validators can be shared between components, they can be declared
       globally and then be referenced from the input field declarations.
  -->

  <!-- A validator for required input fields.-->
  <di:bean name="requiredValidator"
    beanClass="net.sf.jguiraffe.transform.RequiredValidator">
  </di:bean>

  <!-- A regular expression validator for validating a file name. Certain
       characters are not allowed in file names.
  -->
  <di:bean name="fileNameValidator"
    beanClass="net.sf.jguiraffe.transform.RegexValidator">
    <di:setProperty property="regex" value="[^\*\\/~\|&lt;&gt;]*"/>
  </di:bean>

  <!-- Action definitions -->

  <!-- Action for clearing the content text field. -->
  <a:action name="clearContentAction" textres="newfile_act_clear_text"
    mnemonicres="newfile_act_clear_mnemo" taskBean="clearTask"/>

  <!-- Action for adding lorem ipsum to the content text field. -->
  <a:action name="addContentLoremIpsumAction" textres="newfile_act_loremipsum_text"
    mnemonicres="newfile_act_loremipsum_mnemo" taskBean="addLoremIpsumTask"/>

  <!-- Action for adding XML to the content text field. -->
  <a:action name="addContentXMLAction" textres="newfile_act_xml_text"
    mnemonicres="newfile_act_xml_mnemo" taskBean="addXMLTask"/>

  <!-- Action for adding HTML to the content text field. -->
  <a:action name="addContentHTMLAction" textres="newfile_act_html_text"
    mnemonicres="newfile_act_html_mnemo" taskBean="addHTMLTask"/>

  <!-- Action data definition for the append sub menu in the popup menu -->
  <a:actionData textres="newfile_men_append_text"
    mnemonicres="newfile_men_append_mnemo" var="menuAppend"/>

  <!-- Popup menu handler for the append sub menu -->
  <di:bean name="appendMenu"
    beanClass="net.sf.jguiraffe.gui.builder.action.SimplePopupMenuHandler">
    <di:constructor>
      <di:param>
        <di:list>
          <di:element refName="action:addContentLoremIpsumAction"/>
          <di:element refName="action:addContentXMLAction"/>
          <di:element refName="action:addContentHTMLAction"/>
        </di:list>
      </di:param>
    </di:constructor>
    <di:setProperty property="actionData" refName="menuAppend"/>
  </di:bean>

  <!-- Popup menu handler for the text area's content menu -->
  <di:bean name="fileContentPopupHandler"
    beanClass="net.sf.jguiraffe.gui.builder.action.SimplePopupMenuHandler">
    <di:constructor>
      <di:param>
        <di:list>
          <di:element refName="appendMenu"/>
          <di:element refName="action:clearContentAction"/>
        </di:list>
      </di:param>
    </di:constructor>
  </di:bean>

  <!-- The bean for the form controller.-->
  <di:bean name="controller"
    beanClass="net.sf.jguiraffe.gui.builder.window.ctrl.FormController">
    <di:setProperty property="btnOkName" value="btnOk"/>
    <di:setProperty property="btnCancelName" value="btnCancel"/>
    <di:setProperty property="okCommand" refName="okCommand"/>
  </di:bean>

  <!-- The dialog window -->
  <w:dialog titleres="newfile_title" center="true" resizable="true">
    <f:borderlayout canShrink="true"/>
    <!-- The main panel -->
    <f:panel>
      <f:borderconstr name="CENTER"/>
      <f:percentlayout columns="4dlu start/preferred 3dlu full/preferred(6cm)/100 4dlu"
        rows="4dlu preferred 3dlu preferred full/preferred(5cm)/100 4dlu"
        canShrink="true"/>
      <f:label textres="newfile_lab_name" mnemonicres="newfile_lab_name_mnemo"
        componentref="fileName">
        <f:percentconstr col="1" row="1"/>
      </f:label>
      <f:textfield name="fileName" displayNameres="newfile_disp_name"
        maxlength="200" tooltipres="newfile_txt_name_tip">
        <f:percentconstr col="3" row="1"/>
        <f:validators phase="syntax">
          <f:validator beanName="requiredValidator"/>
          <f:validator beanName="fileNameValidator">
            <f:properties>
              <f:property property="ERR_PATTERN">
                <f:localized resid="ERR_FILENAME_PATTERN"/>
              </f:property>
            </f:properties>
          </f:validator>
          <f:validator
            class="net.sf.jguiraffe.examples.tutorial.createfile.UniqueFileNameValidator"/>
        </f:validators>
      </f:textfield>
      <f:label textres="newfile_lab_content" mnemonicres="newfile_lab_content_mnemo"
        componentref="fileContent">
        <f:percentconstr col="1" row="3"/>
      </f:label>
      <f:textarea name="fileContent" displayNameres="newfile_disp_content"
        rows="10" columns="50">
        <f:percentconstr col="1" row="4" spanx="3" targetCol="3"/>
        <f:font name="Monospaced" size="13"/>
        <f:validator phase="syntax" beanName="requiredValidator">
          <f:properties>
            <f:property property="errorLevel" value="WARNING"/>
          </f:properties>
        </f:validator>
        <a:popup beanName="fileContentPopupHandler"/>
      </f:textarea>
    </f:panel>

    <!-- The button bar -->
    <f:panel>
      <f:borderconstr name="SOUTH"/>
      <f:buttonlayout/>
      <f:button name="btnOk" textres="newfile_btn_create"
        mnemonicres="newfile_btn_create_mnemo" command="create"/>
      <f:button name="btnCancel" textres="newfile_btn_cancel"
        mnemonicres="newfile_btn_cancel_mnemo"/>
    </f:panel>

    <!-- Connect the form controller -->
    <w:formController beanName="controller" formBeanName="createFileModel">
      <!-- Register the field markers -->
      <w:formControllerListener beanName="jguiraffe.fieldMarker"/>
      <w:formControllerListener beanName="toolTipMarker"/>
    </w:formController>
  </w:dialog>

  <!-- Action task definitions that require references to UI elements -->
  <di:bean name="clearTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.ClearTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
    </di:constructor>
  </di:bean>

  <di:bean name="addLoremIpsumTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.AppendTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
      <di:param>
        <di:value>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum quis mauris
in quam mattis dignissim. Integer non nibh purus, vel cursus tortor. Donec quam
orci, tincidunt vitae fringilla vitae, suscipit eu nibh. Etiam fermentum, turpis
ut gravida tempor, nisl lorem malesuada ante, at sodales libero nibh non libero.
Duis vel erat hendrerit neque condimentum imperdiet sit amet id diam. Phasellus
in congue urna. Sed lectus orci, hendrerit eget vehicula sit amet, tempus ac
dui. Aenean nec dolor diam, fermentum venenatis justo. Nunc ac lorem arcu, ut
convallis dui. Nam pretium feugiat felis sit amet consequat. Morbi id nunc
sodales diam pulvinar commodo id ac magna. Donec accumsan rhoncus arcu ut porta.
Donec blandit porta suscipit. Cras sit amet nibh non dui faucibus blandit.
Curabitur tincidunt sagittis neque, ut sagittis magna tempor ut. Vestibulum ante
ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus
egestas iaculis eleifend. Pellentesque dui lacus, fringilla vulputate tempor eu,
pretium non eros. Ut id eros nibh.
        </di:value>
      </di:param>
    </di:constructor>
  </di:bean>

  <di:bean name="addXMLTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.AppendTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
      <di:param>
        <di:value><![CDATA[
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
</root>
        ]] ></di:value>
      </di:param>
    </di:constructor>
  </di:bean>

  <di:bean name="addHTMLTask"
    beanClass="net.sf.jguiraffe.examples.tutorial.createfile.AppendTextActionTask">
    <di:constructor>
      <di:param refName="comp:fileContent"/>
      <di:param>
        <di:value><![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>

  <body>
  </body>
</html>
        ]] ></di:value>
      </di:param>
    </di:constructor>
  </di:bean>
</j:jelly>