Skip Headers
Oracle® Fusion Middleware Developer's Guide for Oracle WebCenter Portal
11g Release 1 (11.1.1.7.0)

Part Number E10148-20
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

20 Extending Runtime Editing Capabilities Using Composer

This chapter describes how to use Composer's declarative and programmable extensibility mechanism to customize runtime capabilities to suit your business needs. It contains the following sections:

20.1 Overview of Extensibility Options

Composer provides a framework on which to build customizable application pages. In addition to its default capabilities, you can extend the Composer framework to augment the runtime capabilities available to end users. You must configure the extensions in your application's adf-config.xml file and the Composer extension file, pe_ext.xml. For information about these files, see Section 20.1.8, "Configuration Files."

This section describes the options available for extending Composer runtime capabilities declaratively. It contains the following subsections:

20.1.1 Composer Add-Ons

The default view of the Composer toolbar (Figure 20-1) includes the following buttons:

  • View: Allows the user to switch between Design and Source view.

  • Page Properties: Opens the Page Properties dialog, allowing the user to edit metadata for the host page.

  • Reset Page: Reverts any changes made to the page in the current edit session.

  • Close: Exits Design view and returns the user to the standard UI.

Figure 20-1 Default Add-Ons on the Composer Toolbar

Description of Figure 20-1 follows
Description of "Figure 20-1 Default Add-Ons on the Composer Toolbar"

The Page Properties and Reset Page buttons are examples of add-ons. Click these buttons to display panels for editing page properties and resetting page customizations. Typically, add-ons are custom task flows that are rendered as buttons on the Composer toolbar in page Edit mode. You can create add-ons that appear along with the Page Properties and Reset Page add-ons. For example, you can create an add-on to display page revision history so that it displays a Revisions button on the Composer toolbar. Clicking this button would display the page's revision history. You can also replace the Page Properties and Reset Page add-ons with custom add-ons that you create.

The process of configuring custom add-ons includes creating the task flows, packaging them into JAR files, and defining them in the Composer extension file. For more information, see Section 20.2, "Creating Composer Add-Ons."

20.1.2 Composer Custom Property Panels

The Component Properties dialog displays categories of attributes on different tabs. Each tab can be referred to as a property panel. The default Component Properties dialog in Composer is analogous to the Oracle JDeveloper Property Inspector. You can create and register custom property panels for a component, populate them with component properties, and display them as tabs along with the default tabs in the Component Properties dialog.

The process of configuring custom property panels includes creating them as task flows, packaging them into JAR files, and defining them in the Composer extension file. For more information, see Section 20.3, "Creating Custom Property Panels."

20.1.3 Composer Events Handlers

Composer provides an intuitive user interface for editing pages at runtime. This includes such UI components as the Save, Close, and Delete buttons. When a user clicks a button or icon in Composer, an event handler ensures that a specific action is performed. An event handler is the code that is called back by Composer when a Composer event is invoked. Each UI event in Composer is associated with an event handler. Sometimes it may be necessary to augment Composer's innate capabilities by performing a different action or multiple actions on invoking an event. For example, when a user clicks Save, in addition to the save operation that Composer provides by default, you might want to configure the application to perform additional tasks such as cleaning up cached information and connections to resources. You can accomplish this with event handlers. For more information, see Section 20.6, "Configuring Event Handlers for Composer UI Events."

20.1.4 Drop Handlers

The Resource Catalog provides resources that users can add to their pages. An Add link next to a resource name enables users to add it to the page. Composer provides drop handlers to handle the add operation in the catalog. By default, a drop handler is configured for each resource in the catalog. If you want to provide complete control of the drop action to the resource, you can create additional drop handlers for that resource. The Add link then displays a context menu with different options for adding the resource to the page. You can create one or more drop handlers to handle different flavors for resources in your catalog.

You can add the following types of drop handlers:

  • Java classes registered with Composer and called when users click an Add link in the Resource Catalog. In this case, the resource is added to the page based on the data flavor selected.

  • Task flows registered with Composer and called when users click an Add link in the Resource Catalog. In this case, a task flow is invoked, which enables users to decide what information from the resource must be displayed on the page.

For more information, see Section 20.7, "Configuring Drop Handlers in the Resource Catalog."

20.1.5 Component Property Filters

The Component Properties dialog displays properties of a selected component. By default, Composer filters certain component properties and displays a subset of properties to users. You can define filters declaratively to further hide properties that the user need not see, or to show properties that are hidden. For more information, see Section 20.8, "Defining Property Filters."

20.1.6 Customization Manager

Customization Manager is a task flow that enables users to download, upload, reset, and delete application customizations on objects like pages and task flows. You can configure the Customization Manager either in Composer or outside of it, on some administrative page. For information about configuring and using Customization Manager, see Section 20.9, "Enabling Parameter Support on the Customization Manager Task Flow."

20.1.7 Composer Toolbar Customization

The default Composer toolbar displays elements on two rows. The first row displays the page name and status indicator, and the second row displays the View menu, Page Properties button, Reset Page button, and Close button, as shown in Figure 20-2.

Figure 20-2 Composer Toolbar with Default Elements

Description of Figure 20-2 follows
Description of "Figure 20-2 Composer Toolbar with Default Elements"

You can customize the toolbar by adding, deleting, or rearranging elements. You can also override existing elements with custom elements. For example, you can remove the message showing the page name if you do not want users to see the name of the page they are editing.

For information about customizing the Composer toolbar, see Section 20.10, "Customizing the Composer Toolbar."

20.1.8 Configuration Files

Before you start with the extensibility configurations described in this chapter, there are two important configuration files that you must know about. Most of the extensions discussed in this chapter are defined in these files:

  • Composer extension file (pe_ext.xml)

    The Composer extension file, pe_ext.xml, enables you to extend the editing capabilities provided by Composer. Within this file you can add elements to register new Composer add-ons and custom property panels, selectively render panels, register event handlers, and define property filters. The pe_ext.xml file is not available in your application by default. You must create it the first time you perform such tasks as including add-ons, property panels, or event handlers. Create this file in the META-INF directory under the project's Web context root or in the application_home/project/src/META-INF directory. When you run the application, the pe_ext.xml file is picked up from the JAR file included in the application classpath. Your application can include more than one extension file. However, you must ensure that the JARs containing the extension files are available on the application classpath so that the pe_ext.xml files are picked up for processing. Every JAR with a pe_ext.xml in its META-INF folder is processed, and the Composer extensions are loaded and combined. For information about the different elements you can define in pe_ext.xml to extend Composer capabilities, see Section B.2.1, "pe_ext.xml."

  • Application's adf-config.xml file

    The adf-config.xml file specifies application-level settings that are usually determined at deployment and often changed at runtime. When you perform such tasks as registering new add-ons and custom property panels in Composer, or creating customization layers, you must add appropriate entries in the adf-config.xml file. The adf-config.xml file is created automatically when you create an application, and when you add a Page Customizable component to the page, certain configurations are added to this file.

    For information about the Composer-specific configurations you can make in adf-config.xml, see Section B.2.2, "adf-config.xml."

20.2 Creating Composer Add-Ons

Composer provides the following default add-ons for runtime editing:

In addition to these, you can register new add-ons with Composer. For example, you can create an add-on to display page revision history so that it displays a Revisions button on the Composer toolbar. Clicking this button would display the page's revision history.

This section contains the following topics:

20.2.1 How to Create and Register Add-Ons

You can create and register custom task flows that can be invoked from buttons on the Composer toolbar. All registered add-ons have an associated button that displays on the toolbar.

This section steps through the procedure of creating an add-on and registering it with Composer. It includes an example that demonstrates how to create an add-on that displays information about the application. The example add-on renders an About button on the Composer toolbar (Figure 20-3) that users can click to invoke a task flow that contains information about the application.

Figure 20-3 About Button on the Composer Toolbar

Description of Figure 20-3 follows
Description of "Figure 20-3 About Button on the Composer Toolbar"

This section contains the following subsections:

20.2.1.1 Creating an Add-On Task Flow

Composer add-ons are task flows you create using JSPX pages or page fragments.

To create an add-on:

  1. In your application project, create a JSFF file called custompanelview.jsff:

    1. From the File menu, select New.

    2. In the New Gallery dialog, expand Web Tier, select JSF, then JSF Page or JSF Fragment.

    3. Click OK.

  2. Design the fragment by adding code similar to what is shown in Example 20-1.

    Example 20-1 Sample code in the JSFF Fragment

    <?xml version='1.0' encoding='UTF-8'?>
    <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
              xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
      <af:panelGroupLayout id="pnlgrp1" layout="vertical" halign="center">
        <af:spacer id="sp1" height="20" />
        <af:image id="customimage"              source="/images/DemoLogo.jpg"
                  shortDesc="Demo Logo"/>
        <af:spacer id="sp2" height="20"/>
        <af:outputText id="output1" value="This is a sample shopping cart application based on Oracle ADF Framework.
    It also uses the Oracle WebCenter Portal: Framework to enable collaboration, application customization and user customization features."/>
        <af:spacer id="sp3" height="20"/>
        <af:outputText id="output2" value="Build : 11.1.1"
                       inlineStyle="font-weight:bold;"/>
      </af:panelGroupLayout>
    </jsp:root>
    

    Note:

    At runtime, the add-on panel is automatically sized to fit the content in this fragment.

  3. Create a task flow definition called custom-panel-task-flow:

    1. From the File menu, choose New.

    2. In the New Gallery dialog, expand Web Tier, select JSF, then ADF Task Flow.

    3. Click OK.

  4. Drop the custompanelview.jsff fragment that you created onto the task flow definition.

  5. Save the task flow definition file.

Optionally, if you create the task flow in one application but want to consume it in another application, you must first package the task flow in an ADF library and add the resulting JAR in the consuming application.

To package the task flow in an ADF library:

  1. Create a deployment profile for the task flow:

    1. Right-click Portal project and choose New.

    2. In the New Gallery, expand General, select Deployment Profile, and then ADF Library JAR File, and click OK.

    3. In the Create Deployment Profile -- ADF Library JAR File dialog, enter a name for your deployment profile and click OK.

    4. In the ADF Library JAR Deployment Profile Properties dialog, click OK.

    5. In the Project Properties dialog, click OK.

  2. In the Application Navigator, right-click the project folder, choose Deploy, deployment profile name, to, and then choose to ADF Library JAR file. This creates a deploy folder including the JAR file, in the project folder located at <Application_Root>\Portal\deploy\.

You can add this JAR file to any application in which you want to consume the add-on.

20.2.1.2 Registering Add-Ons with Composer

After you create the task flows, you must register them with Composer so that they are displayed on the Composer toolbar along with the default options.

To register an add-on with Composer:

  1. If it does not already exist, create the Composer extension file, pe_ext.xml in the META-INF directory under the project's Web context root (for example, in the APPLICATION_HOME\Portal\src\META-INF directory):

    1. From the File menu, select New.

    2. In the New Gallery dialog, expand General, select XML, then XML Document.

    3. Click OK.

    Name the file pe_ext.xml.

  2. Add an <addon-config> element in the file, with a nested <panels> element.

  3. Add one <panel> element for each task flow that you want to register as an add-on.

    Any number of panels can be declared under the <panels> element in the extension file.

    Example 20-2 shows the code of the extension file with a <panel> entry.

    Example 20-2 Composer Extension File

    <?xml version="1.0" encoding="US-ASCII" ?>
    <pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">
      <addon-config>
        <panels>
          <panel name="oracle.custom.panel" title="About"
                 icon="http://myforums.oracle.com/jive3/images/question-pts-available-16x16.gif"
                 taskflow-id="/WEB-INF/custom-panel-task-flow.xml#custom-panel-task-flow" />
        </panels>
      </addon-config>
    </pe-extension>
    

    For more information about the addon-config and other nested elements, see Section B.2.1.1, "addon-config."

  4. Optionally, register event handlers for the custom panel by adding an event-handlers element within the panel element as shown in the following example:

    <event-handlers>
      <event-handler event="close">
        oracle.custom.TaskFlowEventHandler
      </event-handler>
    </event-handlers>
    

    For more information, see Section 20.6, "Configuring Event Handlers for Composer UI Events."

  5. Save the pe_ext.xml file.

20.2.1.3 Registering Add-Ons in adf-config.xml

To register an add-on, you must add a reference to it in the application's adf-config.xml file. Add the addon-panels entry to define new add-ons.

To register add-ons in the adf-config.xml file:

  1. Open the application's adf-config.xml file, located in the ADF META-INF folder under Descriptors in the Application Resources panel.

  2. Add the following namespace within the adf-config element in the file:

    xmlns:pe="http://xmlns.oracle.com/adf/pageeditor/config"
    
  3. Add a <pe:page-editor-config> entry with the namespace and include <pe:addon-panels> inside it.

    When you register a custom add-on, the default add-ons are not displayed in Composer by default. To display all the default add-ons, you must set the show-default-addons attribute on the <pe:addon-panels> tag to true. The default value for this attribute is false.

    Within <pe:addon-panels>, add <pe:addon-panel> entries for the new panels, as shown in Example 20-3.

    The name attribute must contain the name you used to register the panel in the Composer extension file.

    Example 20-3 New Add-On Referenced in adf-config.xml

    <pe:page-editor-config xmlns="http://xmlns.oracle.com/adf/pageeditor/config">
      <pe:addon-panels show-default-addons="true">
      
        <pe:addon-panel name="oracle.custom.panel" />
      
      </pe:addon-panels>
    </pe:page-editor-config>
    

    Note:

    If you do not specify any <addon-panel> entries under <addon-panels>, then only the default options are displayed in Composer.

For information about the Composer-specific configurations you can make in adf-config.xml, see Section B.2.2, "adf-config.xml."

20.2.2 What Happens at Runtime

Custom add-ons that you register with Composer are rendered on the Composer toolbar along with the default add-ons.

In the example, an About button is rendered on the Composer toolbar (Figure 20-4).

Figure 20-4 About Button in Composer Toolbar

Description of Figure 20-4 follows
Description of "Figure 20-4 About Button in Composer Toolbar"

Clicking this button displays the About the Application task flow (Figure 20-5).

Note:

The add-on panel is automatically sized to fit the content inside the task flow.

Figure 20-5 About the Application Task Flow

Description of Figure 20-5 follows
Description of "Figure 20-5 About the Application Task Flow"

20.2.3 How to Exclude Composer Default Add-Ons

You can choose to show or hide the Page Properties, Reset Page, and Customization Manager buttons on Composer toolbar. To hide any of these add-ons, you must set the show-default-addons attribute on <pe:addon-panels> to true, add an entry for the default add-on you want to hide, and set the rendered attribute on that add-on to false.

Example 20-4 shows the code to hide the Page Properties add-on.

Example 20-4 The adf-config.xml File with the Reset Page Option Excluded

<pe:addon-panels show-default-addons="true">
  <!-- Hide the Reset Page add-on -->
  <pe:addon-panel name="oracle.adf.pageeditor.addonpanels.page-reset" rendered="false"/>
  
  . . . 
  
</pe:addon-panels>

The excluded add-on (Reset Page) is not displayed on the Composer toolbar. The other default add-ons are displayed on the toolbar in the default order.

20.2.4 How to Display the Customization Manager Add-On

The Customization Manager is a Composer add-on that enables users to manage application customizations on task flows, pages, and page fragments on a given page. For more information, see Section 17.4.14, "Manage Application Customizations."

The Customization Manager add-on is available in the Composer library, but is not rendered by default. You can enable it by configuring it in your application's adf-config.xml file using a <pe:addon-panel> element inside <pe:page-editor-config>, as shown in the following example:

<pe:page-editor-config xmlns="http://xmlns.oracle.com/adf/pageeditor/config">
  <pe:addon-panels show-default-addons="true">
    <pe:addon-panel name="oracle.adf.pageeditor.addonpanels.customization-manager"/>
  
    . . . 
  
  </pe:addon-panels>
  . . . 
</pe:page-editor-config>

This configuration ensures that the Composer toolbar displays the Customization Manager button as shown in Figure 20-6.

Figure 20-6 Customization Manager Button

Description of Figure 20-6 follows
Description of "Figure 20-6 Customization Manager Button"

20.2.5 How to Selectively Display Add-Ons

Depending on your business requirement, you may need to selectively hide the add-ons available to different users in Composer. To selectively hide an add-on, you must set the show-default-addons attribute on <pe:addon-panels> to true, add an entry for the default add-on you want to hide, and set the rendered attribute for that add-on to false using an EL expression, as shown in Example 20-5.

Example 20-5 rendered Attribute Setting in the adf-config.xml File

<pe:page-editor-config xmlns="http://xmlns.oracle.com/adf/pageeditor/config">
  <pe:addon-panels show-default-addons="true">
    <pe:addon-panel name="oracle.adf.pageeditor.addonpanels.page-reset" 
                 rendered="#{securityBean.userInPageResetRole}" />  
    . . . 
  </pe:addon-panels>
  . . . 
</pe:page-editor-config>

In this example, the securityBean backing bean returns either true or false, depending on the role of the logged-in user. If the returned value is false, Composer does not display the Reset Page button on the Composer toolbar. If the returned value is true, Composer displays the Reset Page button.

Note:

If you hide the Reset Page button on the Composer toolbar, the Reset Task Flow button displayed while editing task flow content is also hidden.

The default value for rendered is true. That is, if you do not specify a rendered attribute for an add-on, the add-on is always displayed.

20.3 Creating Custom Property Panels

Composer displays the properties of a component in the Component Properties dialog when a user clicks the Edit icon on the component. The Component Properties dialog provides a series of tabs. Each tab displays a group of related attributes. The attributes have associated values that control a component's behavior and visual style properties. For example, the Style tab displays the component's style-related properties, such as width, height, and background color.

Similarly, when a user clicks the Page Properties button, a Page Properties dialog opens with its own series of tabs. These tabs contain display-related page properties, page parameters, and security settings.

You can create and register custom property panels to render along with the tabs displayed in the Component Properties or Page Properties dialog. In addition, you can remove the default panels or replace them with custom property panels. For example, you can develop a friendlier property panel for an Image component by displaying a picker for its Source property. This would make it easier for users to select an image from the available options.

This section describes how to create custom property panels. It also describes how to exclude, override, and selectively render default property panels. It contains the following subsections:

20.3.1 How to Create and Register Custom Property Panels

Creating a custom property panel is similar to creating an add-on. That is, you create custom property panels as task flows and register them in the Composer extension file. However, while Composer add-ons are configured using the addon-panels element in the adf-config.xml file, custom property panels are configured using the property-panels element in the extension file itself.

You can configure a custom property panel to display in the Component Properties dialog always. Alternatively, you can configure the panel to display only when a particular component or task flow is selected for editing.

This section describes how to create and register a custom property panel. It contains the following subsections:

20.3.1.1 Creating a Custom Property Panel

Property panels provide a means of editing page or component properties. For example, a user can click the Edit icon on a selected task flow and modify its parameter values and change its visual attributes in the Component Properties dialog.

Composer enables you to associate property panels with components and task flows. When a user clicks the Edit icon on the component or task flow, Composer opens the Component Properties dialog and displays the custom property panels you associated with the object along with the default property panels.

The steps for creating a custom property panel and declaring it in the Composer extension file are similar to those for creating and declaring Composer add-ons. For detailed information, see Section 20.2.1.1, "Creating an Add-On Task Flow" and Section 20.2.1.2, "Registering Add-Ons with Composer."

Example 20-6 shows a sample property panel declaration in the pe_ext.xml file.

Example 20-6 Custom Property Panel Declaration in pe_ext.xml

<pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">
  <addon-config>
    <panels>
      <panel name="sample-panel" title="Sample Panel"
             taskflow-id="/WEB-INF/sample_task_flow.xml#sample_task_flow"/>
    </panels>
  </addon-config>
</pe-extension>

After you create a custom panel and declare it in the pe_ext.xml file, you must configure it using the <property-panels> element, as shown in Example 20-7. This ensures that the panel displays automatically in the Composer Component Properties and Page Properties dialog.

Example 20-7 Custom Property Panel Configuration in pe_ext.xml

<addon-config>
  <panels>
    . . . 
  </panels>
  <property-panels>
    <property-panel name="samplepanel">
      <panel name="sample-panel" rendered="true"/>
    </property-panel>
  </property-panels>
</addon-config>

Use one <panel> element to register each custom panel. A <panel> corresponds to a tab in the Component Properties dialog. You can add any number of <panel> elements.

20.3.1.2 Registering a Custom Property Panel for a Component

When you register a custom panel in the extension file, you can associate the panel with a component or a task flow. The custom property panel then renders only for that component or task flow. This section describes how to register a property panel for a specific component.

To register a property panel for a component:

  1. Create a Composer extension file, pe_ext.xml, if it does not already exist.

    For information about creating the extension file, see Section 20.2.1.2, "Registering Add-Ons with Composer."

  2. Add a <property-panels> element inside the <addon-config> section in the pe_ext.xml file.

  3. Add a <property-panel> declaration within the <property-panels> element.

    You can have multiple <property-panel> entries.

  4. Within the <property-panel> element, add a <component> element to specify the runtime class name of the component (optional) and a <panel> element to specify the name you used to declare the panel in the <addon-config> section of the file.

    Example 20-8 shows a custom property panel that is associated with a Command Button component by specifying the component's fully qualified class name. For information about Oracle ADF components and their runtime classes, see Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

    Example 20-8 Code to Register a Property Panel for a Component

    <pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">
      <addon-config>
        <property-panels>
          <property-panel name="cmdbtn">
            <component>oracle.adf.view.rich.component.rich.nav.RichCommandButton</component>
            <panel name="prop.panel.cmdbtn" />
            <panel name="prop.panel.generic" /> 
          </property-panel>
        </property-panels>
      </addon-config>
      . . . 
    </pe-extension>
    

    Note:

    When registering a property panel, if you do not associate it with a component or task flow (discussed in the next section), the registered panel is rendered at all times in the Component Properties and Page Properties dialogs.

    To configure multiple property panels for a component, you can include multiple <panel> elements within a <property-panel> element. For more information about the <property-panels> element and its nested elements, see Section B.2.1.2, "property-panels."

    All the default panels, such as Child Components, Style, and Parameters, are displayed along with the custom panels you define.

20.3.1.3 Registering a Custom Property Panel for a Task Flow

You can define a custom property panel for a task flow by registering it with the Composer extension file. Example 20-9 shows the sample code used to register a custom property panel for a task flow.

A custom property panel registered for a specific task flow appears only when its associated task flow is selected. Otherwise, default property panels appear.

Note:

Use task flow-specific custom property panels only to customize task flow parameters or any other aspect related to how the task flow works.

A custom property panel does not function if it is associated with a task flow rendered using the Oracle JSF Portlet Bridge.

To register a property panel for a task flow:

  1. Add a <property-panels> element within the <addon-config> element in the pe_ext.xml file.

    For information about creating the extension file, see Section 20.2.1.2, "Registering Add-Ons with Composer."

  2. Add a property-panel declaration within this.

    You can have multiple property-panel entries.

  3. Add taskflow-id and panel elements within the property-panel element.

    Add the taskflow-id element to specify the task flow name. Add the panel element to specify the name you used to declare the property panel in the addon-config section of the file.

    Example 20-9 shows a custom property panel associated with a dashboard task flow.

    Example 20-9 Code to Register a Property Panel for a Task Flow Instance

    <pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">
      <addon-config>
        <property-panels>
          <property-panel name="dashboard">
            <taskflow-id>/WEB-INF/dashboard-taskflow#prop-panel</taskflow-id>
            <panel name="dashboard.prop-panel" />
          </property-panel>
        </property-panels>
      </addon-config>
      . . . 
    </pe-extension>
    

    Notes:

    • If you do not associate a custom property panel with a component or task flow (using the <component> or <taskflow-id> tag), then the registered panel is rendered for all pages, task flows, and components in the Component Properties and Page Properties dialogs.

      You can register multiple panel elements within a property-panel element. For more information about the property-panels element and its nested elements, see Section B.2.1.2, "property-panels."

    • To enable end users to edit the attributes and parameters on a custom property panel, in the panel's task flow fragment you must add a Show Property components for each property that you want to expose. The value attribute on a Show Property component is tied to a managed bean that contains the logic to read and write values for the properties and parameters. For more information, see Section 20.3.6, "How to Display Properties and Parameters in a Custom Property Panel."

20.3.2 What Happens at Runtime

If you associated the custom property panel with a specific component or task flow, at runtime the panel renders as a tab in the Component Properties dialog invoked from the specified component or task flow. If you did not associate the custom property panel with a specific component or task flow, at runtime the custom property panel renders as a tab in both the Page Properties and Component Properties dialogs for all pages, components, and task flows.

Note:

In the Component Properties and Page Properties dialogs, custom panels are sized by the tab component containing the task flows. The size of the tab component itself is determined by a rule in the currently-applied skin. This rule is called af|panelTabbed.Tab.

20.3.3 How to Override Default Property Panels

The Component Properties dialog in Composer displays the following panels by default: Display Options, Child Components, Events, Style, Content Style, and Parameters. You can override a particular panel by using the default panel's name when you declare and register the custom panel in the pe_ext.xml file. For information about the default panels, see Section B.3, "Composer Default Add-Ons and Property Panels."

Example 20-10 shows the code to override the Display Options panel with a panel defined using a task flow called custom-panel-task-flow.

Example 20-10 Sample Code to Override a Default Panel

<addon-config>
  <panels>
    <panel name="oracle.adf.pageeditor.pane.generic-property-inspector" title="Sample Panel"
           icon="http://myforums.oracle.com/jive3/images/question-pts-available-16x16.gif"
           taskflow-id="/WEB-INF/custom-panel-task-flow.xml#custom-panel-task-flow" />
  </panels>
  <property-panels>
    <property-panel name="samplepanel">
      <panel name="oracle.adf.pageeditor.pane.generic-property-inspector" rendered="true"/>
    </property-panel>
  </property-panels>
</addon-config>

20.3.4 How to Exclude Default Property Panels

Out-of-the-box, all default property panels are displayed along with custom property panels that you configure. To hide a default property panel in the Page Properties or Component Properties dialog, you can add a line specifically for that panel and and set the rendered attribute to false.

Example 20-11 shows the rendered attribute set to false for the Content Style property tab of a Command Button component. For information about default property panels, see Section B.3, "Composer Default Add-Ons and Property Panels."

Example 20-11 rendered Attribute for a Property Panel

<pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">
  <addon-config>
    <property-panels>
      <property-panel name="cmdbtn">
        <component>oracle.rich.CommandButton</component>
        <panel name="prop.panel.cmdbtn" />
        <panel name="oracle.adf.pageeditor.pane.content-style-editor" rendered="false" />
      </property-panel>
    </property-panels>
  </addon-config>
  . . . 
</pe-extension>

20.3.5 How to Selectively Render Property Panels

Custom property panels registered in the application are rendered in the Component Properties dialog when users click the Edit icon on a specified component. You can configure your application to render a property panel selectively based on different criteria like the role of a logged-in user, the page being viewed, and so on. To display property panels selectively, you can use an EL value in the property-panel's rendered attribute as shown in the following example:

<property-panel name="global-but-just" rendered="#{bean.showProperty}">

20.3.6 How to Display Properties and Parameters in a Custom Property Panel

If you are building a custom property panel for a component, you can use Show Property components, available from the Composer tag library, to expose the component's attributes on the custom panel. In the page fragment defining the custom panel task flow, you must add one Show Property component for each attribute that you want to expose. Show Property is a declarative component that reads a property value on the component or task flow (for which you have created the custom panel), and displays an input field for that property in the custom panel. Users can edit property values in the panel using the input fields.

For more information about custom panels, see Section 20.3.1.1, "Creating a Custom Property Panel."

To add a Show Property component:

  1. Open the page fragment that you created for the custom panel task flow.

  2. From the Component Palette, select Composer.

  3. Drag and drop a Show Property component for each component attribute that you want to expose in the custom panel.

  4. To ensure that the attribute displays correctly in the custom panel, set the attributes on each Show Property component by referring to Section B.1.7, "Show Property."

Note:

You can use the Show Property component even on pages outside of Composer.

Example

Consider an example of a weather widget that is included inside a Show Detail Frame component. A custom property panel is created to enable users to edit the Text, Auto Refresh, and Refresh Interval attributes on the weather widget. It includes three fields for users to provide values for these attributes. To enable users to set the three attributes on the weather widget, one Show Property component is added for each attribute that is exposed in the panel. When a user edits the weather widget at runtime, the Component Properties dialog displays the custom panel with the three attributes, as shown in Figure 20-7.

Figure 20-7 Custom Panel to Display Show Detail Frame Component Properties

Panel to Display Show Detail Frame Properties

The weather widget is consumed in a page along with a Poll component as shown in the following example:

<cust:showDetailFrame text="Weather" id="sdf1" contentStyle="height:220.0px;"
                      partialTriggers="p1">
  <af:region value="#{bindings.weathertaskflowdefinition1.regionModel}"
             id="r1"/>
  <af:poll id="p1" interval="60000"/>
</cust:showDetailFrame>

The Poll component is used to deliver refreshed content to the weather widget at fixed intervals. The default interval is 60000 milliseconds.

The custom panel contains three panelLabelandMessage components to provide input fields for the Text, Auto Refresh, and Refresh Interval attributes. The fields on this panel are implemented as follows:

  • A showProperty component is added to each panelLabelandMessage component as shown in the following example:

    <!-- Input field for setting the Text attribute, which displays on the component header -->
    <af:panelLabelAndMessage label="Text" id="plam2">
      <pedc:showProperty label="Text" id="sp1" simple="true"
                         value="#{sdfCustomPanel.text}"/>
    </af:panelLabelAndMessage>
    
    <!-- Checkbox to enable auto refresh, which controls whether the widget must be refreshed -->
    <af:panelLabelAndMessage label="Auto Refresh" id="plam3">
      <pedc:showProperty label="Auto Refresh" id="sp2" simple="true"
                         type="boolean" autoSubmit="true"
                         value="#{sdfCustomPanel.autoRefresh}"/>
    </af:panelLabelAndMessage>
    
    <!-- LOV to display values for Refresh Interval when auto refresh is enabled -->
    <af:panelLabelAndMessage label="Refresh Interval" id="plam4">
      <pedc:showProperty label="Refresh Interval" id="sp3" simple="true"
                         type="list" disabled="#{!sdfCustomPanel.autoRefresh}"
                         value="#{sdfCustomPanel.refreshInterval}"
                         selectItems="#{sdfCustomPanel.selectItems}" 
                         binding="#{sdfCustomPanelRequestBean.refreshIntervalShowProp}"/>
    </af:panelLabelAndMessage>
    

    where sdfCustomPanel references a managed bean, SDFCustomPanelBean.java.

  • The task flow definition of the custom panel contains a reference to the bean:

    <managed-bean id="mb1">
      <managed-bean-name id="mb1_name">sdfCustomPanel</managed-bean-name>
      <managed-bean-class id="mb1_class">portal.weather.panel.SDFCustomPanelBean</managed-bean-class>
      <managed-bean-scope id="mb1scope">session</managed-bean-scope>
    </managed-bean>
    
  • The SDFCustomPanelBean.java bean provides the logic to handle values for the different attributes exposed in the panel. In the bean, the SelectionContext API is used to read and write values for each attribute as follows:

    • Get hold of the selected component, that is, the component on which the properties are displayed; in this example, a Show Detail Frame component, as the weather widget is included inside one.

    • Read the attribute value on the selected component.

    • Get the attribute value that the user specifies and set that value for the component attribute.

    For example, the Refresh Interval attribute is enabled only if Auto Refresh in selected, and it displays a dropdown menu with the values defined in the managed bean. The Poll component on the page is wired to the Show Property component so that the widget refresh is driven by the value of the Show Property component. The code to handle the value for the Refresh Interval property is as follows:

    . . . 
    /** Set the refresh interval attribute value on the component
    public void setRefreshInterval(String _refreshInterval)
    {
      this._refreshInterval = _refreshInterval;
    }
    **/
    
    public String getRefreshInterval()
    {
      if (_autoRefresh == true && _refreshInterval != null)
        return _refreshInterval;
    
      // Get hold of the component whose properties you want to edit
      SelectionContext selCtx =
        Context.getCurrentInstance().getSelectionContext();
      UIComponent selComp = selCtx.getSelectedComponent().getUIComponent();
      if (selComp instanceof ShowDetailFrame)
      {
        // Get the refresh interval value specified for the Poll component 
        RichPoll pollComp = (RichPoll) selComp.findComponent("p1");
        if (_autoRefresh == false)
          _refreshInterval = "Refresh interval not applicable";
        else if (pollComp.getInterval() < 0)
          _refreshInterval = "60000";
        else
          _refreshInterval = Integer.toString(pollComp.getInterval());
      }
    
      return _refreshInterval;
    }
    . . . 
    public List<SelectItem> getSelectItems()
    {
      return _selectItems;
    }
    . . . 
    private static List<SelectItem> _selectItems;
    static
    {
      _selectItems = new ArrayList<SelectItem>();
      SelectItem si = new SelectItem("60000", "1 Minutes");
      _selectItems.add(si);
      si = new SelectItem("120000", "2 Minutes");
      _selectItems.add(si);
      si = new SelectItem("180000", "3 Minutes");
      _selectItems.add(si);
    }
    
  • When a user selects a value for the Refresh Interval property and clicks Apply in the Component Properties dialog, the save listener is called and the save event handler ensures that the value is saved back to the bean. The relevant code in the save event handler implementation is as follows:

    public void save()
    {
      . . . 
      if (_autoRefresh)
      {
        aa = new AttributeComponentChange("interval", Integer.parseInt(_refreshInterval));
        changeManager.addComponentChange(context, pollComp, aa);
        aa.changeComponent(pollComp);
      }
      else
      {
        aa = new AttributeComponentChange("interval", new Integer(-1));
        changeManager.addComponentChange(context, pollComp, aa);
        aa.changeComponent(pollComp);
      }
    }
    

20.4 Extending the Expression Builder

All properties on the Parameters and Display Options tabs in the Component Properties dialog can take Expression Language (EL) expressions. The Expression Builder option available on such parameters opens the Edit dialog, which is a simple expression builder as shown in Figure 20-8. The expression builder is particularly useful when you want a value that is retrievable but otherwise unknown, for example, when you want a value to be the name of the current user or the current application skin.

Figure 20-8 Expression Language Editor

Description of Figure 20-8 follows
Description of "Figure 20-8 Expression Language Editor"

You can customize the expression builder to provide more options by making the necessary entries in the Composer extension file, pe_ext.xml. You can also configure Composer to disable EL or protect existing EL from overwrite.

This section explains how to extend the expression builder to add custom capabilities. It contains the following subsections:

20.4.1 How to Extend the Expression Builder

You can extend the expression builder by adding custom options to the expression value dropdown list. Custom options must be defined and included in the pe_ext.xml file. For each new option you want to add, you must define and include a <selector> element in the pe_ext.xml file.

To configure custom options in the Composer extension file:

  1. Create a Java bean, for example UserInformation.java, with the logic to populate the expression dialog with your custom options. Example 20-12 shows the code of a sample Java bean used to display a new string, User Name, as a custom value in the expression dialog.

    Example 20-12 Sample Code to Add a Custom Value in the Expression Dialog

    package view;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import oracle.adf.view.page.editor.elbuilder.ELParameter;
    import oracle.adf.view.page.editor.elbuilder.ELParameterValue;
    
    public class UserInformation implements ELParameter {
      public String getName() {
        return mName;
      }
    
      public List<ELParameterValue> getValues() {
        if (mValues == null)
          {
            mValues = new ArrayList<ELParameterValue>();
            for(String[] args : mValueList)
              {
                mValues.add(new ELParameterValue(args[0], args[1]));
              }
          }
           return mValues;
      }
      private static String[][] mValueList =    {new String[]{"User Name", "#{securityContext.userName}"}};
      
      private String mName = "User Name";
      private List<ELParameterValue> mValues;  } 
    
  2. Add an <elbuilder-config> element in the pe_ext.xml file to register the bean.

    For information about creating the extension file, see Section 20.2.1.2, "Registering Add-Ons with Composer."

  3. Add a <selector> element within the <elbuilder-config> section, and provide details about the bean you created, as shown in the following example:

    <elbuilder-config>
      <!-- define selector -->
      <selector id="UserInformation">
        view.UserInformation
      </selector>
        
      <!-- include selector -->
      <selectors>
        <selector id="UserInformation" rendered="true"/>
      </selectors>
    </elbuilder-config>
    

    You can have multiple <selector> entries for different custom options.

    Custom options display for all attributes by default. You can use the rendered attribute on <selector> to display an option conditionally, based on specific criteria.

  4. Save the pe_ext.xml file.

20.4.2 How to Protect Expression Language

You can configure Composer to disable EL or protect existing EL from overwrite within an application or a specific .jspx page. This is especially useful when exposing elements to end users in Design view as described in Section 20.11, "Enabling Direct Select in Design View."

To define settings for an application, modify the following elements in adf-config.xml within the <pe:page-editor-config> tag:

  • <pe:allow-el> defines whether or not EL can be run in application pages. The default is true.

  • <pe:protect-el> defines whether or not EL in form elements is read-only. The default is false.

To define behavior for a specific .jspx page, use the following elements within the <pe:pageCustomizable> tag:

  • allowEL (boolean) defines whether or not EL can be run in application pages. The default is true.

  • protectEL (boolean) defines whether or not EL in form elements is read-only. The default is false.

The settings defined in the .jspx page override any settings defined in adf-config.xml.

20.4.3 What Happens at Runtime

The selector in the runtime expression builder displays the custom value along with the default values, as shown in Figure 20-9.

Figure 20-9 Expression Builder Displaying a Custom Value

Description of Figure 20-9 follows
Description of "Figure 20-9 Expression Builder Displaying a Custom Value"

If EL is disabled, the expression builder will not be accessible, and EL will not be allowed in property fields.

If EL is protected, any EL already present as an attribute value cannot be changed in either the Parameters or Display Options tabs. (EL picked from a LOV is allowed.)

20.5 Configuring Custom LOVs or Pickers for Task Flow Parameters

Typically, while editing a task flow parameter in Composer, the user enters a value in the text box provided in the Component Properties dialog, as shown in Figure 20-10. However, many a time the user is confused about what value to specify in a particular field. Rather than leave them guessing, as a developer who knows the values that each parameter can take, you can make it easier for users by listing all valid options, wherever possible. You can configure Composer to display a list of values (LOV) or a picker against any parameter.

Figure 20-10 Parameters Tab on the Component Properties Dialog for a Task Flow

Description of Figure 20-10 follows
Description of "Figure 20-10 Parameters Tab on the Component Properties Dialog for a Task Flow"

You can display a predefined set of values for a parameter using the following options:

This section describes how to configure different types of LOVs for task flow parameters. It contains the following subsections:

Example Used to Describe the Procedures in This Section

Some of the procedures in this section use the example of a simple weather task flow, weather-task-flow-definition, which displays weather information for a selected city, as shown in Figure 20-11.

Figure 20-11 Weather Task Flow

Weather task flow

The task flow provides two parameters, zipCode and tempUnits, that users can modify to display weather details for a selected city and in a selected temperature unit (Fahrenheit or Celsius) respectively. This weather task flow example is used to explain how to configure the following types of LOVs:

The weather task flow includes a task flow definition file, weather-task-flow-definition.xml, with the code shown in Example 20-13.

Example 20-13 The weather-task-flow-definition.xml FIle

<?xml version="1.0" encoding="US-ASCII" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
  <task-flow-definition id="weather-task-flow-definition">
    <default-activity id="defaultactivity1">weather</default-activity>
    <input-parameter-definition id="inputparam1">
      <name id="inputparam1name">zipcode</name>
      <value>#{pageFlowScope.zipcode}</value>
      <class>java.lang.String</class>
      <required/>
    </input-parameter-definition>
    <input-parameter-definition id="inputparam2">
      <name id="ip2name">tempUnits</name>
      <value>#{pageFlowScope.tempUnits}</value>
      <class>java.lang.String</class>
    </input-parameter-definition>
    <view id="weather">
      <page>/weather.jsff</page>
    </view>
    <use-page-fragments/>
  </task-flow-definition>
</adfc-config>

The parameters, shown in bold text, are defined in such a way that values provided by users at runtime are stored in a session bean, pageFlowScope, from where they can be read by other components.

When you edit the task flow at runtime, the Parameters tab displays two input text fields to provide parameter values. The following sections explain how to enable LOVs for these task flow parameters so that users can choose from a list of predefined of options.

20.5.1 How to Configure an LOV

This section describes how to configure different types of LOVs for task flow parameters. It includes the following subsections:

20.5.1.1 Configuring a Static LOV

Use a static LOV to display a list of predefined values against a parameter. You can configure a static LOV by defining an <lov-config> section with nested <enumeration> elements in the Composer extension file, pe_ext.xml. This section uses the weather task flow example and describes how to configure a static LOV for the tempUnits parameter.

To configure a static LOV:

  1. If it does not already exist, create the Composer extension file, pe_ext.xml in the META-INF directory under the project's Web context root (for example, in the APPLICATION_HOME\Portal\adfmsrc\META-INF directory):

    1. From the File menu, select New.

    2. In the New Gallery dialog, expand General, select XML, then XML Document.

    3. Click OK.

    Name the file pe_ext.xml.

  2. Add an <lov-config> section and include the task flow definition with nested <enumeration> elements, as shown in the following code example:

    <lov-config>
      <!-- Entry for the task flow in which you are configuring the LOV -->
      <task-flow-definition taskflow-id="/WEB-INF/weather-task-flow-definition.xml#weather-task-flow-definition">
    
        <!-- Specifying the parameter for which you want to define a static LOV -->
        <input-parameter-definition>
          <name>tempUnits</name>
          <!-- List of values to be displayed for the parameter -->
          <enumeration inline="true">
            <item>
              <name>Celcius</name>
              <value>c</value>
              <description>Temperature in Celcius</description>
            </item>
            <item>
              <name>Fahrenheit</name>
              <value>f</value>
              <description>Temperature in Fahrenheit</description>
            </item>
          </enumeration>
        </input-parameter-definition>
    
      </task-flow-definition>
    </lov-config>
    

    You can configure any number of static LOVs within the <lov-config> section.

    Note:

    To allow translatable strings to be provided for a parameter name, you can use an EL value for the name, for example, #{resourceBundle.temp_units}.

  3. Save the file.

20.5.1.2 Configuring a Dynamic LOV

Use a dynamic LOV to display a list that is generated dynamically at runtime by evaluating an EL value. This section uses the weather task flow example and describes how to configure a dynamic LOV for the zipCode parameter. To keep the example simple, the managed bean only provides static values that are displayed on the Zipcode field at runtime.

To configure a dynamic LOV:

  1. Create a bean, for example, weatherBean, and define the list of values for the Zipcode parameter. The following example shows the relevant code snippet:

    package portal.weather;
    
      . . . 
    
      public List<SelectItem> getCitiesList() {
        return citiesList;
      }
     
      private static final String F = "&deg;F";
      private static final String C = "&deg;C";
      private static final String [][] selectItems = {{"Redwood City", "94065"}, 
                                                      {"Novi, MI", "48375"}, 
                                                      {"Los Angeles", "90001"},
                                                      {"New York", "10036"}};
        
      private static final List<SelectItem> citiesList = new ArrayList<SelectItem>();
        static {
          for (String[] city : selectItems){
            citiesList.add(new SelectItem(city[1], city[0]));
        }
      }
    
  2. Register weatherBean in the application's faces-config.xml file, as shown in the following example:

    <managed-bean>
      <managed-bean-name>weatherBean</managed-bean-name>
      <managed-bean-class>portal.weather.WeatherBean</managed-bean-class>
      <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
    
  3. If it does not already exist, create the Composer extension file, pe_ext.xml in the META-INF directory under the project's Web context root (for example, in the APPLICATION_HOME\Portal\adfmsrc\META-INF directory):

    1. From the File menu, select New.

    2. In the New Gallery dialog, expand General, select XML, then XML Document.

    3. Click OK.

    Name the file pe_ext.xml.

  4. Add an <lov-config> section, include the task flow definition with an <enumeration> element, and reference the managed bean for the parameter value, as shown in the following example:

    <lov-config>
      <task-flow-definition taskflow-id="/WEB-INF/weather-task-flow-definition.xml#weather-task-flow-definition">
        <input-parameter-definition>
          <name>zipcode</name>
          <value>90001</value>
          <enumeration items="#{weatherBean.citiesList}"/>
        <input-parameter-definition>
      </task-flow-definition>
    </lov-config>
    

    You can configure any number of dynamic LOVs within the <lov-config> section.

  5. Save the file.

20.5.1.3 Configuring a Picker

Typically, a picker enables users to select a value from a popup dialog that displays all available options, for example, a color picker or date picker. Configuring a picker for a task flow parameter involves the following high level tasks:

  • Create the picker task flow with a UI of your choice.

  • Define parameters on the picker task flow. These parameters are used to populate the main task flow parameter (the one for which you are configuring the picker).

  • Configure the main task flow parameter to display the picker that you created. You must add this configuration in the pe_ext.xml file.

This section explains these steps in detail using the weather task flow as an example. It shows how to configure a city picker for the zipCode parameter. The picker task flow enables users to specify the city name and get the ZIP code for that place. The ZIP code from the picker is then pushed to the Zipcode field in the weather task flow. This section includes the following subsections:

20.5.1.3.1 Creating the Picker Task Flow

Create a picker task flow with a JSFF fragment. Design the fragment to display fields or options of your choice.

To create the picker task flow:

  1. In your application project, create an ADF task flow, for example, weather-picker-task-flow-definition:

    1. From the File menu, choose New.

    2. In the New Gallery dialog, expand Web Tier, select JSF, then ADF Task Flow.

    3. Click OK.

  2. Add a view object to the task flow, for example, weatherPicker.

  3. Double-click the view to create the weatherPicker.jsff fragment.

  4. Design the fragment with components of your choice. Example 20-14 shows a sample task flow containing two Input Text components that enable users to search for ZIP codes in an XML file, and two UI controls, OK and Cancel.

    Example 20-14 Sample code in the Picker JSFF Fragment

    <?xml version='1.0' encoding='UTF-8'?>
    <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
              xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
              xmlns:f="http://java.sun.com/jsf/core">
      <af:panelStretchLayout id="psl1">
        <f:facet name="center">
          <af:panelGroupLayout id="pgl1" layout="vertical">
    
            <af:panelGroupLayout id="pgl2" layout="horizontal">
              <!-- Text field and Search button to search for a city by specifying the ZIP code -->
              <af:inputText label="Enter Zip Code" id="it1"
                            value="#{pageFlowScope.weatherPicker.searchZipcode}"/>
              <af:commandButton text="Search By Zipcode" id="cb1"
                                actionListener="#{pageFlowScope.weatherPicker.zipcodeSearch}"/>
            </af:panelGroupLayout>
    
            <af:panelGroupLayout id="pgl3" layout="horizontal">
              <!-- Text field and Search button to search for a city by specifying the city name -->
              <af:inputText label="Enter City" id="it2"                        value="#{pageFlowScope.weatherPicker.searchCity}"/>
              <af:commandButton text="Search By City" id="cb2"
                                actionListener="#{pageFlowScope.weatherPicker.citySearch}"/>
            </af:panelGroupLayout>
    
            <!-- Output components to display the result from the search -->
            <af:outputFormatted value="#{pageFlowScope.weatherPicker.city}"
                                id="of2"/>
            <af:outputFormatted value="#{pageFlowScope.weatherPicker.zipcode}"
                                id="of3"/>
    
          </af:panelGroupLayout>
        </f:facet>
        <f:facet name="bottom">
          <af:panelGroupLayout layout="horizontal" halign="end" id="pkrPgl">
    
            <!-- OK button -->
            <af:commandButton action="ok"
                              actionListener="#{pageFlowScope.weatherPicker.populateReturnValue}"
                              text="#{Bundle.OK_BUTTON_TEXT}" id="okBtn"/>
            <af:spacer width="5" id="s1"/>
    
            <!-- Cancel button -->
            <af:commandButton actionListener="#{pageFlowScope.weatherPicker.closePickerPopup}"
                              text="#{Bundle.CANCEL_BUTTON_TEXT}"
                              id="cnclBtn"/>
          </af:panelGroupLayout>
        </f:facet>
      </af:panelStretchLayout>
    </jsp:root>
    

    The action listeners on the OK and Cancel buttons reference a managed bean, weatherPicker. This bean also contains the logic to populate the parameter on the main task flow with the value specified in the picker.

  5. Create the bean that you referenced in the picker task flow definition and add the logic to return values to the main task flow.

    The following example shows the relevant code snippet of the weatherPicker bean, which contains the logic to search for a city by name and return the ZIP code:

    package portal.weather.picker;
     
    . . . 
    
      public void populateReturnValue(ActionEvent ae) {
        Map map = (Map)RequestContext.getCurrentInstance().getPageFlowScope().get("outParam");
        if (map != null)
          map.put("outParamVal", _zipcode);
      }
     
      public void closePickerPopup(ActionEvent ae) {
        UIComponent component = ae.getComponent();
          while (!(component instanceof RichPopup))
            component = component.getParent();
            if (component != null)
              ((RichPopup)component).cancel();
      }
      . . . 
    
  6. Register the weatherPicker bean in the task flow definition file, as shown in the following example:

    <managed-bean id="pickerbean">
      <managed-bean-name id="pickerbeanname">weatherPicker</managed-bean-name>
      <managed-bean-class id="pickerbeanclass">portal.weather.picker.WeatherPicker</managed-bean-class>
      <managed-bean-scope id="pickerbeanscope">pageFlow</managed-bean-scope>
    </managed-bean>
    
  7. Define two input parameters, inParamVal and outParam, on the picker task flow, as shown in the following example:

    <!-- Parameter used to store the value that must be passed to the main task flow -->
    <input-parameter-definition id="pickerip1">
      <name id="pickerip1name">outParam</name>
      <value>#{pageFlowScope.outParam}</value>
      <class>java.util.Map</class>
    </input-parameter-definition>
    
    <!-- Parameter used to store the value specified by the user in the picker -->
    <input-parameter-definition id="pickerip2">
      <name id="pickerip2name">inParamVal</name>
      <value>#{pageFlowScope.inParamVal}</value>
      <class>java.lang.String</class>
    </input-parameter-definition>
    

    These parameters are referenced in pageFlowScope and will be used to read and populate the main task flow parameter, zipCode. When a user clicks the picker icon next to the Zip Code field, the current value of the field is passed to the session bean using inParamVal. When a user specifies a city name in the picker task flow and clicks OK, the bean gets the ZIP code for that city and passes it to the main weather task flow using outParam.

  8. Define task flow return activities and control flow rules for the OK and Cancel buttons. These activities and rules ensure that control is returned to the task flow when either of the buttons is clicked. You can define task flow return activities and control flow rules as shown in the following example:

    <!-- The outcome to be returned to the task flow if a user clicks OK -->
    <task-flow-return id="ok">
      <outcome id="ok1">
        <name id="okayed">ok</name>
      </outcome>
    </task-flow-return>
    <!-- The outcome to be returned to the task flow if a user clicks Cancel -->
    <task-flow-return id="cancel">
      <outcome id="cancel1">
        <name id="canceled">cancel</name>
      </outcome>
    </task-flow-return>
    
    <!-- Rules to pass control flow to the ok activity if the user clicks OK and to the cancel activity if the user clicks Cancel -->
    <control-flow-rule id="flowrule1">
      <from-activity-id id="fromactivity1">weatherPicker</from-activity-id>
      <control-flow-case id="flowcase1">
        <from-outcome id="fromoutcome1">ok</from-outcome>
        <to-activity-id id="toactivity1">ok</to-activity-id>
      </control-flow-case>
      <control-flow-case id="flowcase2">
        <from-outcome id="fromoutcome2">cancel</from-outcome>
        <to-activity-id id="toactivity2">cancel</to-activity-id>
      </control-flow-case>
    </control-flow-rule>
    

    The task flow definition will now have code similar to the following example:

    <?xml version="1.0" encoding="US-ASCII" ?>
    <adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
      <task-flow-definition id="weather-picker-task-flow-definition">
        <default-activity id="pickeractivity1">weatherPicker</default-activity>
        <input-parameter-definition id="pickerip1">
          <name id="pickerip1name">outParam</name>
          <value>#{pageFlowScope.outParam}</value>
          <class>java.util.Map</class>
        </input-parameter-definition>
        <input-parameter-definition id="pickerip2">
          <name id="pickerip2name">inParamVal</name>
          <value>#{pageFlowScope.inParamVal}</value>
          <class>java.lang.String</class>
        </input-parameter-definition>
        <managed-bean id="pickerbean">
          <managed-bean-name id="pickerbeanname">weatherPicker</managed-bean-name>
          <managed-bean-class id="pickerbeanclass">portal.weather.picker.WeatherPicker</managed-bean-class>
          <managed-bean-scope id="pickerbeanscope">pageFlow</managed-bean-scope>
        </managed-bean>
        <view id="weatherPicker">
          <page>/weatherPicker.jsff</page>
        </view>
        <task-flow-return id="ok">
          <outcome id="ok1">
            <name id="okayed">ok</name>
          </outcome>
        </task-flow-return>
        <task-flow-return id="cancel">
          <outcome id="cancel1">
            <name id="canceled">cancel</name>
          </outcome>
        </task-flow-return>
        <control-flow-rule id="flowrule1">
          <from-activity-id id="fromactivity1">weatherPicker</from-activity-id>
          <control-flow-case id="flowcase1">
            <from-outcome id="fromoutcome1">ok</from-outcome>
            <to-activity-id id="toactivity1">ok</to-activity-id>
          </control-flow-case>
          <control-flow-case id="flowcase2">
            <from-outcome id="fromoutcome2">cancel</from-outcome>
            <to-activity-id id="toactivity2">cancel</to-activity-id>
          </control-flow-case>
        </control-flow-rule>
        <use-page-fragments/>
      </task-flow-definition>
    </adfc-config>
    
  9. Save the task flow definition file.

20.5.1.3.2 Registering the Picker for a Task Flow Parameter

To display a custom picker for a task flow parameter, you must configure the picker for that parameter in the Composer extension file, pe_ext.xml.

To configure a picker for a task flow parameter:

  1. If it does not already exist, create the Composer extension file, pe_ext.xml in the META-INF directory under the project's Web context root (for example, in the APPLICATION_HOME\Portal\adfmsrc\META-INF directory):

    1. From the File menu, select New.

    2. In the New Gallery dialog, expand General, select XML, then XML Document.

    3. Click OK.

    Name the file pe_ext.xml.

  2. Add an <lov-config> section and include the task flow definition with an <enumeration> element referencing the picker task flow, as shown in the following code example:

    <?xml version="1.0" encoding="UTF-8"?>
    <pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">
      <lov-config>
        <task-flow-definition taskflow-id="/WEB-INF/weather-task-flow-definition.xml#weather-task-flow-definition">
          <!-- Parameter for which you defined the picker -->
          <input-parameter-definition>
            <name>zipCode</name>
            <value>null</value>
            <!-- enumeration items coming from the picker task flow -->
            <enumeration picker="/WEB-INF/weather-picker-task-flow-definition.xml#weather-picker-task-flow-definition"/>
          </input-parameter-definition>
        </task-flow-definition>
      </lov-config>
    </pe-extension>
    

    You can configure pickers for any number of parameters within the <lov-config> section.

  3. Save the file.

When you edit the main task flow at runtime, the Component Properties dialog displays a magnifier icon next to that parameter. Clicking the icon invokes the picker task flow, in which users can select a value.

20.5.1.4 Configuring an LOV from a Global List

If you want to reuse an LOV in different task flow parameters within the application, you can define the LOV at a global level and reference it from the task flow parameters.

To configure an LOV from a global list:

  1. If it does not already exist, create the Composer extension file, pe_ext.xml in the META-INF directory under the project's Web context root (for example, in the APPLICATION_HOME\Portal\adfmsrc\META-INF directory):

    1. From the File menu, select New.

    2. In the New Gallery dialog, expand General, select XML, then XML Document.

    3. Click OK.

    Name the file pe_ext.xml.

  2. Add an <lov-config> section and list the values within an <enumeration> element (outside of the task flow definition), as shown in the following code example:

    <lov-config>
    <!-- Global enumerations ->
      <enumeration id="temperature">
        <item>
          <name>Celcius</name>
          <value>c</value>
          <description>Temperature in Celcius</description>
        </item>
        <item>
          <name>Fahrenheit</name>
          <value>f</value>
          <description>Temperature in Fahrenheit</description>
        </item>
      </enumeration>
      <task-flow-definition . . . >
      . . . 
    <lov-config>
    

    You can configure any number of global LOVs within the <lov-config> section.

  3. Reference this global LOV from any input parameter definition in the pe_ext.xml file, as shown in the following example:

    <task-flow-definition taskflow-id="/WEB-INF/weather-task-flow-definition.xml#weather-task-flow-definition">
      <input-parameter-definition>
        <name>tempUnits</name>
        <value>Celsius</value>
        <enumeration ref="temperature"/>
      </input-parameter-definition>
    </task-flow-definition>
    
  4. Save the file.

20.5.2 What Happens at Runtime

Depending on the type of LOV you configured for the task flow parameter, users will see different options to specify parameter values.

The Temp Units field, shown in Figure 20-15, lists values from the static LOV that you defined in the pe_ext.xml file.

Figure 20-15 Static LOV

Dropdown on Temp Units field showing two values.

If you configured a picker for the Zipcode field, the field shows a magnifier icon to its right. This icon invokes a picker, as shown in Figure 20-16, that allows users to select a city by providing a name or ZIP code.

Figure 20-16 Picker Task Flow Configured for the Zipcode Field

Picker Task Flow Configured for the Zipcode Field

20.6 Configuring Event Handlers for Composer UI Events

Event handlers are Java classes registered with Composer and called when a user performs an action on the page. For example, when a user clicks a Save button, Composer calls back into the application code to give the application a chance to respond to the Save event. In addition to the event handlers that Composer provides by default, you can configure additional handlers for application-specific events, for example, saving changes in a custom property panel.

This section describes how to create and register event handlers for UI events in Composer. It contains the following subsections:

20.6.1 How to Create and Register Handlers for Composer UI Events

When you register an event handler with Composer, it is called when the corresponding event is fired in the Composer UI.

This section describes how to create an event handler and register it with Composer. It contains the following subsections:

20.6.1.1 UI Events that Support Event Handler Registration

Table 20-1 lists the UI events for which Composer currently supports registering of handlers.

Table 20-1 Events for Which Registering Handlers are Supported

Event Cause Event Type Listener Interface (oracle.adf.view.page.editor.event) Method Event Interface

Save

Invoked when a user clicks the Save or Save and Label button on the Composer toolbar, or the Apply (save) or OK (save and close) button in the Component Properties dialog or Page Properties dialog.

save

SaveListener

processSave

SaveEvent

Close

Invoked when a user clicks the Close button on the Composer toolbar.

close

CloseListener

processClose

CloseEvent

Deletion

Invoked when a user deletes the component.

delete

DeletionListener

processDeletion

DeletionEvent

Get the deleted component using getComponent.

Addition

Invoked when a user adds a component to the page from the Resource Catalog by clicking the Add button against an item.

add

AdditionListener

processAddition

AdditionEvent

Selection

Invoked when a user selects:

  • The Edit icon on a Panel Customizable or Show Detail Frame component in Design view

  • A component on the page or in the hierarchy in Source view

select

SelectionListener

processSelection

SelectionEvent

Attribute Change

Invoked when a user changes an attribute.

If the attribute change is invalid, the listener should raise an AbortProcessingException and set the severity for the warning message. If the severity is set to FATAL or ERROR (default), the user will be forced to correct the attribute in the property inspector before clicking Apply or OK. All other severities will display a notification popup but allow the user to save without further action.

attribute-change

AttributeChangeListener

processAttributeChange

AttributeChangeEvent

Get and set the warning severity using getMessageSeverity and setMessageSeverity.

Define a message for the warning using setMessageSummary and setMessageDetail. To display a message even if the listener verifies an attribute change with no errors, use setMessageSummary("")
setMessageSeverity(FacesMessage.SEVERITY_INFO);
setShowMessage(true)


20.6.1.2 Creating a Save Event Handler: Example

To register an event with Composer, you must first create a Java class and implement the appropriate listener for the event handler. This section describes the steps to create a Save event handler. You can perform similar steps to create event handlers for all the supported events listed in Table 20-1.

A Save event handler is called when a user clicks the Save button on the Composer toolbar or the Apply or OK button in the Component Properties or Page Properties dialog. A Save event handler must implement oracle.adf.view.page.editor.event.SaveListener. The isCommit method of the Save event can be used to differentiate between changes made to the page and to component properties. A value of true implies that the user clicked the Save button on the Composer toolbar to save changes made to the page. A value of false implies that the user clicked the Apply or OK button in the Component Properties dialog to save changes made to component properties.

To create a Save event handler:

  1. In JDeveloper, select the Portal project, and from the File menu, choose New.

  2. In the New Gallery dialog, expand General, select Java, then Java Class, and click OK.

  3. In the Create Java Class dialog, specify a name for the class, for example, SaveHandler.

  4. Under the Optional Attributes section, add the oracle.adf.view.page.editor.event.SaveListener interface.

    Note:

    If you are not able to see the oracle.adf.view.page.editor classpath, make sure that Composer is included in the project's libraries and classpath. To do this, right-click the project in the Application Navigator and select Project Properties. In the Project Properties dialog, select Libraries and Classpath, and add Composer to the list.

  5. Click OK.

    The Java class source looks like the following:

    package view;
    
    import javax.faces.event.AbortProcessingException;
    
    import oracle.adf.view.page.editor.event.SaveEvent;
    import oracle.adf.view.page.editor.event.SaveListener;
    
    public class SaveHandler implements SaveListener {
      public Class1() {
        super();
      }
      public void processSave(SaveEvent saveEvent) throws AbortProcessingException {
    // Your implementation goes here
      }
    }
    

    You must declare the processSave method as throws AbortProcessingException because the method may throw this exception if the event must be canceled. You can include the reason for canceling this event in the Exception object when you create it.

    On throwing this exception, further processing of this event is canceled and the listeners that are in the queue are skipped.

You can create event handlers for all supported events by performing steps similar to these.

Tip:

You can use the SaveEvent.isCommit method to

20.6.1.3 Registering an Event Handler with Composer

After creating and implementing an event handler, you must register it with Composer. Registration is necessary for ensuring that the handler is called back by Composer when the corresponding event occurs in the UI.

Register event handlers in the Composer extension file, /META-INF/pe_ext.xml. For more information about creating this file, see Section 20.2.1.2, "Registering Add-Ons with Composer."

To register an event handler:

  1. In the application's pe_ext.xml file, add the following entries:

    <event-handlers>
      <event-handler event="save">view.SaveHandler</event-handler>
    </event-handlers>
    

    The values you provide for the event attribute and between the event-handler tags are unique to the type of event being entered and the name you specified for the event class.

  2. Save the file.

20.6.2 What Happens When You Create and Register Event Handlers

At runtime, registered event handlers are called according to the sequence in the extension file and according to the order in which they were found on the class path. Composer's native event handler is called last.

On invocation of an event handler's processEventName method, if an event handler throws AbortProcessingException, then the event is canceled and no further event handlers are called, including Composer's native event handlers.If, however, an error occurs while instantiating an event handler, then Composer continues with the next event handler. A warning message is logged.

20.6.3 Additional Composer Event Handler Configurations

For every UI event triggered on the page in Composer, the corresponding event handler calls back a method from a listener registered with the application. By performing some additional configurations, you can specify the sequence in which event handlers are executed and configure a listener to terminate a process or notify Composer that the event has been handled.

20.6.3.1 Specifying a Sequence Number for an Event Handler

By specifying the sequence for event handlers, you can decide on the order in which the event handlers, and therefore the listeners, are called. You can assign a sequence number to a listener or modify the default value by defining a sequence attribute against the registered event handler in the pe_ext.xml file.

To specify a sequence number for a listener:

  1. In the application's pe_ext.xml file, locate the event-handler element for the handler that you want to sequence.

  2. Add a sequence attribute as follows:

    <event-handlers>
      <event-handler event="save" sequence="101">view.SaveHandler</event-handler>
    </event-handlers>
    

    The value for the sequence attribute must be a positive integer. If you do not define this attribute, the event handler is internally assigned a default sequence number of 100.

    Composer built-in listeners and listeners with no sequence numbers are assigned a default sequence number of 100. If you want your event handler to be called before other event handlers, you must specify a value lesser than 100.

  3. Save the file.

20.6.3.2 Terminating Event Processing

You can configure an event handler to terminate processing of the current event and all subsequent events by throwing an exception. For this, you must declare the method used while implementing the listener as throws AbortProcessingException. In addition, you can configure the handler to notify Composer that the event has been processed by using the Event.setEventHandled(true) method.

For example, you can configure a delete event handler to terminate the current event and all pending delete events and throw an exception when a user attempts to delete a component in Composer. To enable this, you must implement the DeletionListener interface as shown in Example 20-15.

Example 20-15 DeletionListener Implementation

public class DeleteHandler implements DeletionListener
{
  ...
  public void processDeletion(DeletionEvent delEvent) throws  AbortProcessingException
  {
    // Get the component that must be deleted
    UIComponent comp = delEvent.getComponent();

    if (comp != null)
    {
      try
      {
        // Assuming that a custom method, handleDelete(comp), handles deletion of
        // a component and returns true on successful deletion and false in case
        // of failure
        boolean deleteSucceeded = handleDelete(comp);

        // If deletion failed, then notify Composer that the delete event
        // has been handled. No further events are processed.
        if (!deleteSucceeded)
          delEvent.setEventHandled(true);
      }

      catch (Exception e)
      {
       // Catch Exception throw by handleDelete(comp) and handle it by throwing
       // AbortProcessingException to stop processing of delete events.
       throw new AbortProcessingException(e)
      }
    }
  }
  ...
}

20.7 Configuring Drop Handlers in the Resource Catalog

Drop handlers are Java classes registered with Composer and called when users click an Add link in the Resource Catalog. A drop handler declares the data flavors it can handle. Each resource in the catalog has a flavor. When a user clicks an Add link next to a resource, Composer queries all the registered drop handlers to check if they can handle the flavor. If only one drop handler can handle that flavor, then control is passed to that drop handler and the resource is added to the page immediately. If more than one drop handler can handle the flavor, then a context menu displays available drop handlers to users. The resource is dropped on the page when a user selects a Java drop handler from the context menu.

An example for a resource with multiple Java drop handlers is the Personal Documents subfolder available within the Documents folder, if you configured the Documents service in your catalog. This subfolder can be added as a Content Presenter, Document List Viewer, or Document Library.

Note:

The AdditionListener mechanism used to handle an Add operation in release 11.1.1.1 is still available, but now Composer calls drop handlers first to handle an Add operation in the catalog. It is recommended that you convert existing AdditionListeners to drop handlers.

This section describes the procedure to create and register drop handlers in your application. It contains the following subsections:

20.7.1 How to Create and Register Java Drop Handlers

This section describes how to create a sample drop handler for adding XML content from the Resource Catalog and register the drop handler with Composer. It includes the following subsections:

20.7.1.1 Creating a Drop Handler

To create a drop handler with Composer, you must first extend the abstract base class, DropHandler, and implement the getName(), getAcceptableFlavors(), and handleDrop() methods. This section describes an example to add an XML component called Test to the Resource Catalog and create a drop handler named Custom XML for adding XML content.

To create a drop handler:

  1. In JDeveloper, select the Portal project, and from the File menu, choose New.

  2. In the New Gallery dialog, expand General, select Java, then Java Class, and click OK.

  3. In the Create Java Class dialog, specify a name for the class, for example, TestDropHandler.

  4. In the Extends field, enter or browse to select the Drophandler class, oracle.adf.view.page.editor.drophandler.DropHandler.

    Note:

    If you are not able to see the oracle.adf.view.page.editor classpath, make sure that Composer is included in the project's libraries and classpath. To do this, right-click the project in the Application Navigator and select Project Properties. In the Project Properties dialog, select Libraries and Classpath, and add Composer to the list.

  5. Add the required import statements and click OK.

    The Java class source must look like the following:

    package test;
    
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    
    import java.io.ByteArrayInputStream;
    
    import javax.faces.component.UIComponent;
    import javax.faces.context.FacesContext;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    
    import oracle.adf.rc.component.XmlComponentFactory;
    import oracle.adf.view.page.editor.drophandler.DropEvent;
    import oracle.adf.view.page.editor.drophandler.DropHandler;
    
    import org.apache.myfaces.trinidad.change.AddChildDocumentChange;
    import org.apache.myfaces.trinidad.change.ChangeManager;
    import org.apache.myfaces.trinidad.change.DocumentChange;
    import org.apache.myfaces.trinidad.context.RequestContext;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.DocumentFragment;
    
    public class TestDropHandler extends DropHandler {
        public TestDropHandler() {
            super();
        }
    
        public String getName() {
            return null;
        }
    
        public DataFlavor[] getAcceptableFlavors() {
            return new DataFlavor[0];
        }
    
        public boolean handleDrop(DropEvent dropEvent) {
            return false;
        }
    }
    
  6. Implement the getName() method as follows to return the name of the drop handler:

    public class TestDrophandler extends DropHandler {
        public TestDrophandler() {
            super();
        }
    
        public String getName() {
            return "Custom XML";
        }
    . . . 
    

    This value (Custom XML) appears in the context menu on the Add link next to the XML component in the Resource Catalog.

  7. Implement the getAcceptableFlavors() method as follows to get a list of supported data flavors for the XML component:

    public class TestDropHandler extends DropHandler
    {
      private static final DataFlavor[] ACCEPTABLE_FLAVORS =
      { XmlComponentFactory.XML_STRING_FLAVOR };
    
        . . . 
        
        public DataFlavor[] getAcceptableFlavors() {
        return ACCEPTABLE_FLAVORS;
        }
        . . .
    
  8. Implement the handleDrop(DropEvent) method as shown in the following sample file to handle the drop event and add the XML component to the page.

    public class TestDropHandler extends DropHandler
    {
      . . . 
    
      public boolean handleDrop(DropEvent de) {
        Transferable transferable = de.getTransferable();
        UIComponent container = de.getContainer();
        int index = de.getDropIndex();
     
        try {
            FacesContext context = FacesContext.getCurrentInstance();
            RequestContext rctx = RequestContext.getCurrentInstance();
     
            String fragMarkup = null;
     
            // Get the TransferData from the Transferable (expecting a String)
            Object data = getTransferData(transferable);
            if (data instanceof String) {
              fragMarkup = "<?xml version='1.0' encoding='UTF-8'?>" + (String)data;
            } else {
                return false;
            }
     
            // Get a DocumentBuilder
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            factory.setValidating(false);
            DocumentBuilder builder = factory.newDocumentBuilder();
     
            // Parse the xml string into a Document object using DocumentBuilder
            byte[] markupBytes = fragMarkup.getBytes();
            Document newDoc =
            builder.parse(new ByteArrayInputStream(markupBytes));
     
            // Transform the Document into a DocumentFragment
            DocumentFragment docFrag = newDoc.createDocumentFragment();
            docFrag.appendChild(newDoc.getDocumentElement());
     
            // Create an "add child" document change, that is, insert the fragment
            DocumentChange change = null;
            if (index < container.getChildCount()) {
            // Get the ID of the component we'll be adding just before
               String insertBeforeId = container.getChildren().get(index).getId();
               change = new AddChildDocumentChange(insertBeforeId, docFrag);
            } else {
                change = new AddChildDocumentChange(docFrag);
            }
     
            // Apply the "add child" DocumentChange using ChangeManager
            ChangeManager changeManager = rctx.getChangeManager();
            changeManager.addDocumentChange(context, container, change);
     
            // Refresh the target container using PPR
            rctx.addPartialTarget(container);
     
            // Mark the drop as completed.
            return true;
            } catch (Exception e) {
                return false;
            }
        }
    

    In this example, a DropEvent parameter is passed to the handleDrop method. This parameter has three attributes that can be described as follows:

    • transferable, like DataFlavor, is a standard Java class that contains the data being added.

    • container is the container into which component must be dropped.

    • index is the position of the component inside the container. For example, first, second, and so on.

  9. Save the TestDropHandler.java file.

20.7.1.2 Registering a Drop Handler with Composer

After implementing the drop handler, you must register it with Composer. Registration is necessary for ensuring that the handler is called by Composer when a user clicks an Add link in the catalog. Register drop handlers in the Composer extension file, /META-INF/pe_ext.xml. For more information about creating this file, see Section 20.2.1.2, "Registering Add-Ons with Composer."

To register a drop handler:

  1. In the pe_ext.xml file, add the following entries:

    <drop-handlers>
      <drop-handler>test.TestDropHandler</drop-handler>
    </drop-handlers>
    

    where TestDropHandler is the name of the drop handler implementation.

  2. Save the file.

You can register any number of drop handlers in the extension file by adding that many <drop-handler> elements.

20.7.1.3 Adding an XML Component to the Resource Catalog

Since you created a drop handler for XML components generated by the XmlComponentFactory class, you can test how the drop handler works at runtime by adding an XML component to the Resource Catalog and then adding that component to your page at runtime.

To add an XML component to the catalog:

  1. Open the default catalog definition file, default-catalog.xml.

    For information about the location of this file, see Section 15.2.7, "How to Configure the Default Resource Catalog for an Application or Page."

  2. Add the following code within the <contents> section of the file:

    <component id="pc" factoryClass="oracle.adf.rc.component.XmlComponentFactory">
      <attributes>
        <attribute attributeId="Title" value="Test"/>
        <attribute attributeId="Description" value="XML content you can add to application pages"/>
        <attribute attributeId="IconURI" value="/adf/pe/images/elementtext_qualifier.png"/>
        </attributes>
        <parameters>
          <parameter id="xml">
            <af:outputText value="Hello!" xmlns:af="http://xmlns.oracle.com/adf/faces/rich"/>
          </parameter>
        </parameters>
    </component>
    
  3. Save the default-catalog.xml file.

    At runtime, the Resource Catalog shows the XML component, as shown in Figure 20-17. For more information, see Section 15.2.3.4, "Adding a Component."

    Figure 20-17 XML Component in the Catalog

    Description of Figure 20-17 follows
    Description of "Figure 20-17 XML Component in the Catalog"

20.7.2 What Happens at Runtime

When a user clicks the Add link against a component in the catalog, all drop handlers supporting that flavor are displayed as options on the context menu of the Add link. However, if only a single drop handler is available to handle that flavor, then the resource is added to the page immediately.

Figure 20-18 shows the context menu displayed on clicking the Add link of the Test XML component with the Custom XML option and the default XML option.

Figure 20-18 Drop Handlers on an XML Component in the Catalog

Description of Figure 20-18 follows
Description of "Figure 20-18 Drop Handlers on an XML Component in the Catalog"

20.8 Defining Property Filters

Some component properties are not displayed in Composer's Component Properties dialog because they are filtered out by default. The default filters are defined in the <filter-config> section of the Composer's extension file (/META-INF/pe_ext.xml).

Global filters filter attributes for all components. They are defined using the <global-attribute-filter> tag. Tag-level filters filter attributes for a specified component only. They are defined using the <taglib-filter> tag.

Note:

In an extension file, you can have any number of <taglib-filter> tags under <filter-config>, but you can have only one <global-attribute-filter> tag to define all global attribute filters.

You can define additional filters to hide more properties in the Component Properties dialog. This section describes how. It contains the following subsections:

20.8.1 How to Define Property Filters

Composer defines a built-in filter configuration. You can use the extension file, pe_ext.xml, to define additional property filters and to delete filters. You can define any number of filters, even for a single tag, in different extension files. Composer merges the filtering information from all the extension files.

Note:

For information about creating the pe_ext.xml file, see Section 20.2.1.2, "Registering Add-Ons with Composer."

To define property filters in an extension file, use the filter-config element. The following elements are defined for the contained attribute tags.

  • The label element allows you to override the default label for the element in the UI. You can use EL to retrieve localized strings or display different labels in design and source view.

  • The view element can be used to filter attributes in specific tags for a specific view (design or source).

  • The filtered element can be used to display an attribute even if it is globally filtered. To restore a globally filtered element, use filtered="false".

In the pe_ext.xml file, add the filter-config element as shown in the following example:

<filter-config>
   <global-attribute-filter>
    <attribute name="readOnly" filtered="false" label="Read Only"/>
    <attribute name="required" filtered="false" label="Mandatory"/>
    <attribute name="shortDesc" filtered="false" label="#{Bundle.PNL_TB_SHORTDESC}"/>
  </global-attribute-filter>
 
  <taglib-filter namespace="http://xmlns.oracle.com/adf/faces/rich">
    <tag name="goLink">
      <attribute name="accessKey" view="design"/>
      <attribute name="targetFrame" filtered="false" view="source"/>
      <attribute name="destination" filtered="false" label="#{pageEditorPanelBean.layoutView ?  'Where do you want to surf?' : 'Destination'}"/>
    </tag>
    <tag name="inputText">
      <attribute name="all" view="design"/>
      <attribute name="label" label="Field Name" filtered="false" />
      <attribute name="readOnly" filtered="false" />
      <attribute name="required" filtered="false" />
      <attribute name="rendered" filtered="false" />
      <attribute name="wrap" filtered="false" />
    </tag>
  </taglib-filter>
</filter-config>

Save the file.

20.8.2 What Happens at Runtime

At runtime, when you edit a component's properties, the properties that were filtered out are not rendered in the Component Properties dialog.

20.8.3 How to Remove Property Filters

You can remove global and tag-level filters so that previously filtered properties are now rendered in the Component Properties dialog. This is useful for displaying properties that are filtered out by Composer's built-in filters or by another extension file defined elsewhere the application.

Note:

After you remove a property filter, it is rendered in the Component Properties dialog even if a filter is defined for that property in another extension file.

To remove a property filter:

  1. Edit the Composer extension file, pe_ext.xml, available in the META-INF directory.

    You can remove property filters by editing entries in this file.

  2. Search for the attribute from which to remove the filter, and set filtered to false in the <attribute> tag as shown in the following example:

    <pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">
    . . . 
    <filter-config>
      <global-attribute-filter> 
        <attribute name="accessKey" filtered="false" />
        <attribute name="attributeChangeListener" />
        . . . 
      </global-attribute-filter>
      <taglib-filter namespace="http://xmlns.oracle.com/adf/faces/rich">
        <tag name="activeCommandToolbarButton">
          . . . 
          <attribute name="windowWidth" filtered="false"/>
        </tag>
      </taglib-filter>
    </filter-config>
    </pe-extension>
    
  3. Save the file.

20.9 Enabling Parameter Support on the Customization Manager Task Flow

If you enable parameter passing on the task flow, administrators can customize Customization Manager by setting certain parameters. By default, an administrator cannot pass parameters to the Customization Manager task flow in Composer. Table 20-2 describes the parameters supported by the Customization Manager task flow.

Table 20-2 Customization Manager Task Flow Parameters

Parameter Name Value Description

defaultPage

Page URI

Used to specify the default page to be managed. If this value is null, the current page will be used.

dynamicNodeMap

Map<String,List<CustomizationManagerNode>>

Used to return a list of pages, XML documents, or task flows on a given page or fragment, using the following format:

Page1.jspx -> List of {CustomizationManagerTaskFlowNode or CustomizationManagerPageNode or CustomizationManagerXMLNode}

Use CustomizationManagerTaskFlowNode to pass dynamic taskflows in that page.

Use CustomizationManagerPageNode to pass page template of the page.

Use CustomizationManagerXMLNode to pass any XML documents owned by this page.

showBase

true/false

Default: false

Used to show or hide the column for the base document.

showCurrentLayers

true/false

Default: true

Used to show or hide the column showing details about the currently used layer.

showAllLayers

true/false

Default: true

Used to show or hide the column showing details about layers other than the current one.

showLayersforCurrent

Map<String,List<String>>

Used to specify a list of layers that must be available in the Current Context column.

This parameter takes the layer name and list of layer values and patterns that must be shown in the Current Context column. See Example 20-16 for more information.

showLayersforAll

Map<String,List<String>>

Used to specify a list of layers that must be available in the All Layers column.

This parameter takes the layer name and list of layer values and patterns that must be shown in the All Layers column. See Example 20-16 for more information.

labelPrefixes

List<String>

Used to specify a list of space-separated label prefixes that must be displayed in the Promote dialog. Only those labels created with the specified prefixes are displayed in the Promote dialog.

By default, all the labels are displayed.

maxDepth

String

Used to restrict the depth of a task flow hierarchy in the Customization Manager.

The default value is 10. Consequently, if you have a task flow with cyclic dependency, this parameter prevents a stack overflow by limiting the depth to ten nested task flows.

You can display a maximum nesting of 10 task flows. Customization Manager displays only a depth of 10 even if you specify avalue higher than 10.

showDownload

true/false

Default: true

Used to show or hide the Download link.

showUpload

true/false

Default: true

Used to show or hide the Upload link.

showDelete

true/false

Default: true

Used to show or hide the Delete link.

showPromote

true/false

Default: true

Used to show or hide the Promote link.


Note:

The implementation of Map and List must be Serializable for Customization Manager to work correctly in a cluster-based environment. Typically, ArrayList and HashMap are Serializable.

This section describes the steps to enable parameter editing on the Customization Manager task flow. It contains the following subsections:

20.9.1 How to Set the Customization Manager Task Flow Parameters

To pass parameters to the Customization Manager task flow, you must define the parameters attribute as part of the Customization Manager add-on panel configuration in your application's adf-config.xml file.

To enable parameter editing on the task flow:

  1. Open the application's adf-config.xml file, located in the ADF META-INF folder under Descriptors in the Application Resources panel.

  2. Add the following namespace within the adf-config element in the file:

    xmlns:pe="http://xmlns.oracle.com/adf/pageeditor/config"
    
  3. Add a <pe:page-editor-config> entry with the namespace and include an <pe:addon-panels> entry.

    Within <pe:addon-panels>, add an <pe:addon-panel> entry for the default Customization Manager panel and define the parameters attribute by setting it to appUtilBean.customizationManagerParams, as shown in Example 20-16.

    Example 20-16 Customization Manager Add-On Referenced in adf-config.xml

    <pe:page-editor-config xmlns="http://xmlns.oracle.com/adf/pageeditor/config">
      <pe:addon-panels>
        <pe:addon-panel name="oracle.adf.pageeditor.addonpanels.customization-manager" parameters="#{AppUtilBean.customizationManagerParams}"/>
        . . .
      </pe:addon-panels>
    </pe:page-editor-config>
    

    where AppUtilBean is a sample implementation of the AppUtilBean class, and is as shown in the following example:

    public Map<String, Object> getCustomizationManagerParams()
    {
      Map<String, Object> paramMap = new HashMap<String, Object>();
      Map<String, List<String>> showLayersForCurrent = new HashMap<String, List<String>>();
      showLayersForCurrent.put("user", Arrays.asList("admin%", "weblogic"));
      paramMap.put("showLayersForCurrent", showLayersForCurrent);
     
      Map<String, List<String>> showLayersForAll = new HashMap<String, List<String>>();
      showLayersForAll.put("enterprise", Arrays.asList("Frys"));
      paramMap.put("showLayersForAll", showLayersForAll);
     
      return paramMap;
    }
    
  4. Save the adf-config.xml file.

20.9.2 What Happens When You Enable Parameter Support

Customization Manager displays options to users based on the new parameter settings.

20.10 Customizing the Composer Toolbar

You can customize the default Composer toolbar by adding, removing, or rearranging elements and overriding existing elements. To enable toolbar extensibility, the Composer toolbar elements have been grouped into sections. You can work with these sections to customize your toolbar. Each section has a specific name and contains one or more elements inside it, as shown in Figure 20-19.

Figure 20-19 Composer Toolbar

Description of Figure 20-19 follows
Description of "Figure 20-19 Composer Toolbar"

Notes:

The Save button is displayed on the toolbar only if the application is configured to use a sandbox. For more information, see Section 22.2, "Using Composer Sandbox."

The Help icon is displayed on the toolbar only if you have configured a help provider in your application or hooked up help from Composer panels or dialogs.

The Composer toolbar is created using the ADF Faces Toolbox tag. Each row in the toolbar is a Toolbar tag. Consequently, UI components such as separator bars are inherited from the Toolbar component.

Table 20-3 describes the toolbar areas.

Table 20-3 Toolbar Areas

Section or Area Description

message

Area containing the message with the page name.

statusindicator

Area containing the status indicator.

menu

Area containing the View menu that allows users to switch between Design view and Source view.

addonpanels

Area containing Composer add-ons. The add-ons are all displayed in a sequence within this area. For more information, see Section 20.2, "Creating Composer Add-Ons."

help

Area containing the Help icon.

button

Area containing the Save and Close buttons.

stretch

Wide space between two sections.

newline

A line break between sections. All sections after a line break are pushed to a new line on the toolbar.


Using toolbar sections, you can customize the Composer toolbar in the following ways:

This section describes the steps to customize the Composer toolbar. It contains the following sections:

20.10.1 How to Rearrange or Hide Toolbar Elements

Use the toolbarLayout attribute on a Page Customizable component to control which toolbar sections are displayed and the order in which they appear.

To customize the toolbar for all editable pages in the application, you can create a template, add a Page Customizable component to the template, and specify the toolbarLayout attribute against the Page Customizable component. You can then base all the pages in the application on that template.

If you do not specify a value for toolbarLayout, this attribute is internally set to message stretch statusindicator newline menu addonpanels stretch help button, which is the default layout for the Composer toolbar sections.

To customize the toolbar on an application page:

  1. Open your customizable JSPX page in JDeveloper and select the Page Customizable component in the Structure window.

  2. In the Property Inspector, specify space-separated values for the toolbarLayout attribute.

    The section names in Table 20-3 are valid values for this attribute.

    Note:

    You can add only one stretch value per row on the toolbar. If you add more than one stretch value, only the first one is displayed; all others are ignored.

    In Source view, the toolbarLayout attribute appears as shown in the following example:

    <pe:pageCustomizable id="pageCustomizable1"
                         toolbarLayout="button stretch statusindicator menu"
      <cust:panelCustomizable id="panelCustomizable1" layout="scroll"/>
      <f:facet name="editor">
        <pe:pageEditorPanel id="pep1"/>
      </f:facet>
    </pe:pageCustomizable>
    
  3. Save the JSPX file.

20.10.2 What Happens at Runtime

At runtime, the toolbar displays the sections you specified in the order you specified them (Figure 20-20).

Figure 20-20 Customized Composer Toolbar

Description of Figure 20-20 follows
Description of "Figure 20-20 Customized Composer Toolbar"

20.10.3 How to Add New Sections to the Toolbar

You can add custom sections by creating facets and specifying the facet names in the toolbarLayout attribute. Populate the new facets with elements you want to display on the toolbar. The following example shows you how to create a section; specifically, how to add a Report a Bug button that opens a popup that enables users to report a bug.

To add a custom section:

  1. Open the JPSX page for which you want to customize the toolbar.

  2. Add a facet inside the Page Customizable and name it bugreport.

  3. Add a Command Toolbar Button component inside the facet and set the text attribute to Report a Bug.

  4. To add an image to the button, specify the path to the image using the icon attribute.

  5. Add the Show Popup Behavior component to invoke a popup on clicking the Command Toolbar Button.

    In Source view, the Page Customizable would appear as follows:

    <pe:pageCustomizable id="pageCustomizable1"
                 toolbarLayout="message stretch bugrep newline menu stretch button"
      <f:facet name="bugrep">
        <af:commandToolbarButton id="cmd1" text="Report a bug"
                                 icon="/images/bug.png" 
                                 clientComponent="true">
          <af:showPopupBehavior popupId="p1" triggerType="action"/>
        </af:commandToolbarButton>
      </f:facet>
    . . . 
      <af:popup id="p1">
        <af:dialog id="dlg1" title="File a Bug"
                   affirmativeTextAndAccessKey="File">
          <af:panelFormLayout labelWidth="30%" id="pfl1">
            <af:inputText id="it0" maximumLength="80"
                          label="Product/Component" required="true"/>
            <af:inputText id="it1" maximumLength="80" label="Subject"
                          required="true"/>
            <af:inputText id="it2" rows="3" label="Problem" required="true"/>
            <af:inputText id="it3" rows="3" label="Steps" required="true"/>
          </af:panelFormLayout>
        </af:dialog>
      </af:popup>
      . . . 
    </pe:pageCustomizable>
    
  6. Save the page.

    At runtime, the Composer toolbar displays a Report a Bug button, as shown in Figure 20-21.

    Figure 20-21 Composer Toolbar with Custom Section

    Description of Figure 20-21 follows
    Description of "Figure 20-21 Composer Toolbar with Custom Section"

    Clicking the Report a Bug button displays the File a Bug dialog that enables users to report a bug.

20.10.4 How to Override a Toolbar Section to Display Custom Content

You can display custom content in a default toolbar section by adding a facet of the same name as the section and populating it with custom content. The facet content overrides the content of the default section. For example, to display a custom message to users in place of the Editing Page: Page_Name message, you can create a custom facet named message and include an Output Text component with the text you want to display to users. The Output Text component then displays in place of the default message. The following example shows a Page Customizable component with a custom toolbar message:

<pe:pageCustomizable id="pageCustomizable1"
                     toolbarLayout="message newline button stretch statusindicator menu"
  <cust:panelCustomizable id="panelCustomizable1" layout="scroll"/>
  <f:facet name="message">
    <af:outputText value="Welcome!"/>
  </f:facet>
  <f:facet name="editor">
    <pe:pageEditorPanel id="pep1"/>
  </f:facet>
</pe:pageCustomizable>

Figure 20-22 shows the Composer toolbar displayed for the page at runtime.

Figure 20-22 Composer Toolbar with a Custom Message

Description of Figure 20-22 follows
Description of "Figure 20-22 Composer Toolbar with a Custom Message"

20.11 Enabling Direct Select in Design View

Direct select allows you to extend specific customization capabilities from Composer Source view to Design view, allowing users to modify elements from within the page at runtime. This allows you to put more control in the hands of the business user, while creating a safe environment where no damage can be done to the underlying application.

All direct select functionality is available in Source view, but business users do not have the knowledge or experience to use Source view safely and effectively. These users could easily break the page and circumvent application logic.

Using direct select, you can enable a small number of chosen components to be selectable and editable. For example, changing the order of fields in a form, changing the labels on form fields, changing column names in a table, or hiding specific fields in a form.

For more information on direct select functionality, see Section 20.11.2, "What Happens at Runtime."

20.11.1 How to Enable and Configure Direct Select

This section explains how to enable and configure direct select in your application.

  1. First you must enable direct select for the Design view in Composer. In adf-config.xml, inside the <pe:page-editor-config> tag, add the <pe:enable-design-views> tag to define the available views. The possible constant values are:

    • all: Makes all views available and displays a toolbar with buttons to switch between views.

    • add-content (default): Makes the legacy Design view the only available view.

    • select: Makes the Select view the only available view.

    • select add-content: Limits the available views to only the Select and legacy Design views (additional views will be added in future releases). Displays the toolbar with buttons to switch between views.

    You can also use EL to determine the appropriate view, as shown in the example below:

    <pe:enable-design-views>#{testBean.designViews}</pe:enable-design-views>
    

    Note:

    This setting defines the default for the application. You can override this setting in any pageCustomizable tag using the designViews="" attribute.

    By default the hot key to open and close Design view is Ctrl-Shift-S. To change or disable the hot key, add a <pe:component-view-switch-key> tag inside the <pe:page-editor-config> tag. For example:

    <pe:component-view-switch-key>
      <pe:enabled>true</pe:enabled>
      <pe:key-sequence>ctrl shift l</pe:key-sequence>
    </pe:component-view-switch-key>
    
  2. In pe-ext.xml, add the <selection-config> tag to enable or disable direct select for specific components and define associated operations. To make a component selectable, you must define operations within this tag. (If no operations are defined and selection is enabled for a component, selecting the component will display an empty frame.)

    Within the <selection-config> tag, you can configure direct select globally using <global-filter> and by namespace and tag using <selection-taglib-filter>. The <selection> tag has two required attributes:

    • view: Defines the view to be configured in the tag. In the current release, the only accepted value is design (direct select cannot be disabled in source view).

    • enabled: Sets whether or not direct select is enabled in the specified view.

    Available operations are defined within <operation> tags under each specific component. The following elements are used to define operations:

    • name: Defines the operation (standard or custom) to be executed. The operation name is the same as the property panel ID. For a list of standard operations, see Section B.3.2, "Default Property Panels." For custom operations, the name is the same as the custom panel ID. For details on custom operations, see Section 20.3, "Creating Custom Property Panels."

    • label (optional): Sets the tab label in the popup window. The default label is the operation name.

    • filtered: Set to false to include the operation in the popup window.

    Note:

    It is a recommended practice to provide selection for a small number of components at first, then add more as functionality is tested and learned. This can be done easily by globally disabling selection in the <global-filter> tag and enabling selection for individual components using <selection-taglib-filter> as shown in the example that follows.

    <selection-config>
      <global-filter>
        <selection view="design" enabled="false"/>
      </global-filter>
     
      <selection-taglib-filter 
    
       namespace="http://xmlns.oracle.com/adf/faces/customizable">
        <tag name="showDetailFrame">
          <selection view="design" enabled="true"/>
          <operation name="oracle.adf.pageeditor.pane.sdfprop"
                     label="SDF Change Property"
                     filtered="false"/>
        </tag>
      </selection-taglib-filter>
     
      <selection-taglib-filter namespace="http://xmlns.oracle.com/adf/faces/rich">
        <tag name="goLink">
          <selection view="design" enabled="true"/>
          <operation name="oracle.adf.pageeditor.pane.generic-property-inspector"
                     label="Change Property"
                     filtered="false"/>
          <operation name="oracle.adf.pageeditor.pane.inline-style-editor"
                     label="Inline Style"
                     filtered="false"/>
        </tag>
        <tag name="commandButton">
          <selection view="design" enabled="true"/>
          <operation name="oracle.adf.pageeditor.pane.generic-property-inspector"
                     label="Change Property"
                     filtered="false"/>
        </tag>
      </selection-taglib-filter>
    </selection-config>
    

    To further simplify the user experience, direct select allows you to filter specific attributes for a tag so that a smaller set is displayed. For details, see Section 20.8.1, "How to Define Property Filters."

  3. To enable or disable direct select for a specific component within a .jspx page, add the <f:attribute name="pe-select" value="true|false"> tag within the component tag as shown in the example that follows. The setting in this tag overrides the setting in the <selection-config> for the component in the pe_ext.xml file. (As noted above, to enable direct select, operations must be defined for the component in the pe_ext.xml file, or selecting it will open an empty dialog.)

    <af:panelGroupLayout id="pgl2" layout="vertical">
    <f:attribute name="pe-select" value="false"/>
      <af:inputText id="it6" label="Unselectable" value="Enter here..."/>
      <af:goLink id="gl1" destination="http://www.oracle.com" text="Oracle"/>
      <af:inputText id="it7" label="Selectable(override)" value="Enter here...">
        <f:attribute name="pe-select" value="true"/>
      </af:inputText>
    </af:panelGroupLayout>
    
  4. To disallow the use of Expression Language in form fields and protect existing EL from overwrite, see Section 20.4.2, "How to Protect Expression Language."

For more information on specific elements, see the following sections in Appendix B, "Composer Component Properties and Files":

20.11.2 What Happens at Runtime

When direct select is enabled, the outward presentation of the page at runtime does not appear any different to the end user. When a user with the appropriate permissions clicks Ctrl-Shift-S, the page opens in Design view.

This image shows a simple form opened in Design view.

Design view includes the Composer toolbar. If more than one view is enabled, the page also includes a second toolbar with Design and Select buttons to switch between views, as shown in the image above. If only a single view is enabled, these buttons are not displayed.

Note:

If 'select' is defined as the only available view, users have no way to add content from Design view. If 'add-content' is defined as the only available view, the user experience is the same as if direct select was not enabled.

To edit the properties for a component, the user selects an enabled element and clicks Edit Component or Edit Parent Component (when applicable).

Description of jpsdg_page_editor_adv_pop.gif follows
Description of the illustration jpsdg_page_editor_adv_pop.gif

The Component Properties popup window allows the user to edit properties defined for the component and access other operations configured for the component. If the user chose Edit Parent Component, a Manage Children tab is included in the window. If EL is not allowed or is protected from overwrite, the Expression Builder and Override options are not available, as shown in the image below. This image also includes an example of a field that is protected from edit (Show Component).

Description of jpsdg_page_editor_adv_prop.gif follows
Description of the illustration jpsdg_page_editor_adv_prop.gif

Multiple operations are shown in tabs in the popup window. The order of tabs is defined in the panel registration. If an operation references a panel that is not registered for the enclosing component, the tab for that operation will not be displayed. For details on panel registration, see Section 20.3, "Creating Custom Property Panels."

20.12 Troubleshooting Problems with Composer Extensibility Features

This section provides information to assist you in troubleshooting problems you may encounter while using the Composer extensibility features.

For information about configuring logging, see Chapter 19, "Enabling Runtime Editing of Pages Using Composer.".

Problem

You created an add-on, but it does not appear on the Composer toolbar.

Solution

Ensure the following:

For information about add-ons, see Section 20.2, "Creating Composer Add-Ons."

Problem

You have registered a custom property panel. However, it does not appear in the Component Properties dialog when your select a component to display its properties.

Solution

Ensure the following:

For information about custom property panels, see Section 20.3, "Creating Custom Property Panels."

Problem

You do not see some properties of a component in the Component Properties dialog.

Solution

Ensure that the component properties are not filtered or restricted. For more information, see Section 20.8.1, "How to Define Property Filters" and Section 23.4, "Applying Attribute-Level Security."