Property editor
The property editor in BIRT Report Designer provides a user‑friendly interface for property editing. The property editor controls two types of settings, generic settings for all report items, and specific settings for each report item.
Property Editor, as shown in Figure 23‑32, appears as a separate view having a tabbed style in BIRT Report Designer.
Figure 23‑32 Property Editor for a table element
The horizontal property tabs organize property settings into several pages. The vertical category tabs group properties in a single page into different categories. By default, only the first Properties tab supports categories. You can alter the style and overwrite the logic behind this user interface.
You can create a property editor for the RotatedText report item. The new property editor should create a user interface for the rotated text and rotated angle properties and reuse the generic report item property user interface.
This example uses the FormToolkit class from the org.eclipse.ui.forms library, which must be added to the plug-in dependencies and project libraries.
To support custom property pages, implement the org.eclipse.birt.report
.designer.ui.elementAdapters extension, a generic extension point that BIRT Report Designer uses to support property page and other UI extensions.
In the BIRT model, the org.eclipse.birt.report.model.api.ExtendedItemHandle class represents all custom extended report items. Specify the adaptable class as org.eclipse.birt.report.model.api.ExtendedItemHandle.
The next step is to specify the adapter settings, as shown in Figure 23‑33.
Figure 23‑33 Adapter extension
Table 23‑11 lists and explains the adapter settings.
Table 23‑11 Adapter settings
Property
Value
Description
id
ReportDesign
.AttributeView
.RotatedTextPageGenerator
The adapter unique identifier.
type
org.eclipse.birt.report
.designer.ui.views
.IPageGenerator
The Java class type to which this adapter adapts.
class
 
The Java class for the adapter. The class must have a constructor without any arguments. When using the factory mode, leave it blank.
factory
org.eclipse.birt.sample
.reportitem
.rotatedtext.views
.RotatedTextPage
GeneratorFactory
The Java class for the adapter factory. The class implements the org.eclipse
.core.runtime.IAdapterFactory interface.
singleton
false
Specifies whether the adapter object is a singleton. For a singleton, the adapter object is cached and reused for all matching adaptable objects. Here, because you are using the factory mode, set it to false.
priority
1
Specifies the priority for the adapter. The user interface uses this priority to sort multiple adapters defined for same adaptable. Use the default value.
overwrite
 
Specifies a semicolon separated id list that this adapter overwrites. Leave it blank.
comments
 
An additional field to contain description text for the adapter.
The adapter settings describe the generic behavior of the property editor. The next step is to create custom property pages for the RotatedText item, and set additional constraints for the adaptable object. To accomplish this task, create an enablement element using type test under the adapter node. In the settings, as shown in Figure 23‑34, specify the test property as ExtendItemHandle.extensionName and the value as RotatedText. This approach restricts the adaptable object to be the RotatedText report items only.
Figure 23‑34 Enablement element settings
The code of the factory class is shown in Listing 23‑21.
Listing 23‑21 RotatedTextPageGeneratorFactory class
public class RotatedTextPageGeneratorFactory implements IAdapterFactory
{
public Object getAdapter( Object adaptableObject,
Class adapterType )
{
return new RotatedTextPageGenerator( );
}
 
public Class[] getAdapterList( )
{
return new Class[]{
IPageGenerator.class
};
}
}
The factory class creates a generator instance per call. Each generator implements the org.eclipse.birt.report.designer.ui.views.IPageGenerator interface. Extend the org.eclipse.birt.report.designer.ui.views.attributes.AbstractPageGenerator class to use the basic support for categorized styles created by this class.
The implementation of the RotatedTextPageGenerator class is shown in Listing 23‑22. The class overwrites the General category page in the Properties tab and reuses some of the built-in categories like Border, Margin, and Page Break. The code also adds a Custom property tab to the property editor. The RotatedTextPageGenerator class overwrites three methods, buildItemContent( ), createTabItems( ), and refresh( ). The methods createTabItems( ) and buildItemContent( ) implement the custom logic. The createTabItem( ) method overwrites the creation logic for the General category page to add the reused built-in pages and the new Custom property page. The buildItemContent( ) method contains the code to create the Custom property page.
Listing 23‑22 RotatedTextPageGenerator class
public class RotatedTextPageGenerator
extends AbstractPageGenerator
{
private static final String CUSTOM_PAGE_TITLE = "Custom";
//$NON-NLS-1$
private IPropertyTabUI generalPage;
 
protected void buildItemContent( CTabItem item )
{
if ( itemMap.containsKey( item )
&& itemMap.get( item ) == null )
{
String title = tabFolder.getSelection( ).getText( );
 
if ( CUSTOM_PAGE_TITLE.equals( title ) )
{
TabPage page = new RotatedTextCustomPage( ).getPage( );
if ( page != null )
{
setPageInput( page );
refresh( tabFolder, page, true );
item.setControl( page.getControl( ) );
itemMap.put( item, page );
}
}
}
else if ( itemMap.get( item ) != null )
{
setPageInput( itemMap.get( item ) );
refresh( tabFolder, itemMap.get( item ), false );
}
}
 
public void refresh( )
{
createTabItems( input );
 
generalPage.setInput( input );
addSelectionListener( this );
( (TabPage) generalPage ).refresh( );
}
 
public void createTabItems( List input )
{
if ( generalPage == null
|| generalPage.getControl( ).isDisposed( ) )
{
tabFolder.setLayout( new FillLayout( ) );
generalPage = AttributesUtil.buildGeneralPage( tabFolder,
new String[]{
null,
AttributesUtil.BORDER,
AttributesUtil.MARGIN,
AttributesUtil.SECTION,
AttributesUtil.VISIBILITY,
AttributesUtil.TOC,
AttributesUtil.BOOKMARK,
AttributesUtil.USERPROPERTIES,
AttributesUtil.NAMEDEXPRESSIONS,
AttributesUtil.ADVANCEPROPERTY
},
new String[]{ "General" }, //$NON-NLS-1$
new String[]{ "General" }, //$NON-NLS-1$
new AttributesUtil.PageWrapper[]{
new RotatedTextGeneralPage( )
},
input );
 
CTabItem tabItem = new CTabItem( tabFolder, SWT.NONE );
tabItem.setText( ATTRIBUTESTITLE );
tabItem.setControl( generalPage.getControl( ) );
}
 
this.input = input;
generalPage.setInput( input );
addSelectionListener( this );
( (TabPage) generalPage ).refresh( );
 
createTabItem( CUSTOM_PAGE_TITLE, ATTRIBUTESTITLE );
 
if ( tabFolder.getSelection( ) != null )
{
buildItemContent( tabFolder.getSelection( ) );
}
}
}
The General category page contains two text controls for editing: one for the text content and one for the rotation angle of the RotatedText report item. Listing 23‑23 shows the code.
Listing 23‑23 RotatedTextGeneralPage class
public class RotatedTextGeneralPage
extends AttributesUtil.PageWrapper
{
protected FormToolkit toolkit;
protected Object input;
protected Composite contentpane;
private Text txtText, txtAngle;
 
public void buildUI( Composite parent )
{
if ( toolkit == null )
{
toolkit = new FormToolkit( Display.getCurrent( ) );
toolkit.setBorderStyle( SWT.NULL );
}
 
Control[] children = parent.getChildren( );
 
if ( children != null && children.length > 0 )
{
contentpane = (Composite) children[children.length - 1];
 
GridLayout layout = new GridLayout( 2, false );
layout.marginLeft = 8;
layout.verticalSpacing = 12;
contentpane.setLayout( layout );
 
toolkit.createLabel( contentpane, "Text Content:" );
//$NON-NLS-1$
txtText = toolkit.createText( contentpane, "" );
//$NON-NLS-1$
GridData gd = new GridData( );
gd.widthHint = 200;
 
txtText.setLayoutData( gd );
txtText.addFocusListener( new FocusAdapter( ) {
 
public void focusLost(
org.eclipse.swt.events.FocusEvent e )
{
updateModel( RotatedTextItem.TEXT_PROP );
};
} );
 
toolkit.createLabel( contentpane, "Rotation Angle:" );
//$NON-NLS-1$
txtAngle = toolkit.createText( contentpane, "" );
//$NON-NLS-1$
gd = new GridData( );
gd.widthHint = 200;
 
txtAngle.setLayoutData( gd );
txtAngle.addFocusListener( new FocusAdapter( ) {
 
public void focusLost(
org.eclipse.swt.events.FocusEvent e )
{
updateModel( RotatedTextItem.ROTATION_ANGLE_PROP );
};
} );
}
}
 
public void setInput( Object input )
{
this.input = input;
}
 
public void dispose( )
{
if ( toolkit != null )
{
toolkit.dispose( );
}
}
 
private void adaptFormStyle( Composite comp )
{
Control[] children = comp.getChildren( );
for ( int i = 0; i < children.length; i++ )
{
if ( children[i] instanceof Composite )
{
adaptFormStyle( (Composite) children[i] );
}
}
toolkit.paintBordersFor( comp );
toolkit.adapt( comp );
}
protected RotatedTextItem getItem( )
{
Object element = input;
if ( input instanceof List && ( (List) input ).size( ) > 0 )
{
element = ( (List) input ).get( 0 );
}
if ( element instanceof ExtendedItemHandle )
{
try {
return (RotatedTextItem) (
( ExtendedItemHandle) element ).getReportItem( );
}
catch ( Exception e ) {
e.printStackTrace( );
}
}
return null;
}
public void refresh( )
{
if ( contentpane != null && !contentpane.isDisposed( ) )
{
if ( toolkit == null )
{
toolkit = new FormToolkit( Display.getCurrent( ) );
toolkit.setBorderStyle( SWT.NULL );
}
adaptFormStyle( contentpane );
updateUI( );
}
}
public void postElementEvent( )
{
if ( contentpane != null && !contentpane.isDisposed( ) )
{
updateUI( );
}
}
private void updateModel( String prop )
{
RotatedTextItem item = getItem( );
if ( item != null )
{
try {
if (RotatedTextItem.ROTATION_ANGLE_PROP.equals( prop ))
{
item.setRotationAngle(
Integer.parseInt( txtAngle.getText( ) ) );
}
else if ( RotatedTextItem.TEXT_PROP.equals( prop ) )
{
item.setText( txtText.getText( ) );
}
}
catch ( Exception e ) {
e.printStackTrace( );
}
}
}
protected void updateUI( )
{
RotatedTextItem item = getItem( );
if ( item != null )
{
String text = item.getText( );
txtText.setText( text == null ? "" : text );
 
txtAngle.setText( String.valueOf( item.getRotationAngle( ) ) );
}
}
}
The RotatedTextGeneralPage class uses FormToolkit to achieve the same look and feel as the built-in pages in the property editor. Alternatively, you can design your own UI styles.
The Custom property page, shown in Listing 23‑24, implements a read-only version of the General category page just to illustrate the extension mechanism.
Listing 23‑24 RotatedTextCustomPage class
public class RotatedTextCustomPage extends RotatedTextGeneralPage
{
private Label lbText, lbAngle;
 
public void buildUI( Composite parent )
{
if ( toolkit == null )
{
toolkit = new FormToolkit( Display.getCurrent( ) );
toolkit.setBorderStyle( SWT.NULL );
}
 
Control[] children = parent.getChildren( );
 
if ( children != null && children.length > 0 )
{
contentpane = (Composite) children[children.length - 1];
GridLayout layout = new GridLayout( 2, false );
layout.marginTop = 8;
layout.marginLeft = 8;
layout.verticalSpacing = 12;
contentpane.setLayout( layout );
 
toolkit.createLabel( contentpane, "Text Content:" );
//$NON-NLS-1$
lbText = toolkit.createLabel( contentpane, "" );
//$NON-NLS-1$
GridData gd = new GridData( );
gd.widthHint = 200;
lbText.setLayoutData( gd );
 
toolkit.createLabel( contentpane, "Rotation Angle:" );
//$NON-NLS-1$
lbAngle = toolkit.createLabel( contentpane, "" );
//$NON-NLS-1$
gd = new GridData( );
gd.widthHint = 200;
lbAngle.setLayoutData( gd );
}
}
 
protected void updateUI( )
{
RotatedTextItem item = getItem( );
 
if ( item != null )
{
String text = item.getText( );
lbText.setText( text == null ? "" : text ); //$NON-NLS-1$
lbAngle.setText( String.valueOf(
item.getRotationAngle( ) ) );
}
}
}
The newly designed property editor is shown in Figure 23‑35. The General category page displays the two editable properties.
Figure 23‑35 General category property page for the RotatedText item
The reused Border category brings up the built-in border property page where the report developer can change the report item border settings. The changes immediately appear in the layout editor.
The Custom page, shown in Figure 23‑36, displays the read-only properties.
Figure 23‑36 Custom property page for the RotatedText item