Migrating test editor extensibility

Changes in the performance testing editor base framework package are provided in this release to support more standardized ways of handling model element attributes.

Details area contents and layout (attribute field support)

You can now manage the layout and contents of the Details area in the test editor (schedule and test editors) that developers had to manage in earlier versions. In this version, you can manipulate the contents by using the abstraction called AttributeField. This construct hides much of the required behavior from developers, and enables a great deal of extensibility. Updates to AttributeField can coexist with the user interfaces of existing editors or protocol extensions, provided that some minor adjustments are made. Classes derived from AttributeField must be used whenever an attribute from a model element is displayed. Do not use the AttributeField for any other information presented to the user in the Details area. Instead, use regular Eclipse widgets.

Behavior

The getXXXvalue(), setXXXValue(), and getFieldName() classes and APIs provide a way to link model data with their user-interface representation, and at the same time hide related low-level maintenance work from the developer.

These classes are abstract. When a developer chooses one of them to display their model data, only a small number of methods need to be implemented to define the default behavior of the attribute field. If more customized behavior is needed, other methods are available for overriding. Refer to the Javadoc HTML documentation for more information.

The smallest set of methods that a developer must implement are as follows:
  • getXXXValue(): Retrieves and returns a value from model element. XXX signifies a type of an attribute. For example, when extending IntegerAttributeField, the name of the method is getIntegerValue().
  • setXXXValue(): Sends a value obtained from the UI to the model element. The meaning of XXX is the same as above.
  • getFieldName(): Returns the name of the field. Names make a field addressable for navigation.
    Note: Before version 7.0, field names were optional; in this version they are mandatory.

Classes

The following table is a hierarchy of the AttributeField related classes that are available to editor and protocol developers. The list includes descriptions about which classes to use in specific situations.
Note: These classes have limited functionality because they must support classes and APIs from versions earlier than 7.0.
AttributeField class Description
OptionsComboField This class is used to display a set of options to a user. Options are presented in a combination box. When extending this class, you must provide an index of the option currently selected in the model element. When a user chooses a different value from the combination box, the new index is passed to the derived class, in order to update the model. The class developer needs to understand the meaning of the index in the context of the model.
OptionsRadioField The same provision that applies to OptionsComboField applies to OptionsRadioField. The following exception, however, applies: options are displayed as a set of radio buttons in a group. A user must select one of the radio buttons to indicate the index of the selected option.
BooleanAttributeField This class is used when the model element attribute is a Boolean value. The value is displayed as a check box. The developer must provide a Boolean value from a model element and accept a new Boolean value from the user interface to update the model element.
IntegerAttributeField This class is used when the model element attribute holds an integer value. The field can represent an integer value in several ways. The following control types are available for representation:
  • StyledText
  • Spinner
  • Slider
  • Scale
Note: This class is subject to change in the future.
TextAttributeField Use this field when there is text data in the model element.
FilteredTextAttibuteField This class extends the behavior of TextAttributeField by enabling condition checking and displaying alternative text (message) to the user. For example, the developer might want to filter binary data, or filter text that is too long for convenient display.
DataCorrelatingTextAttrField Use this class when the text data can be either substituted, data correlated, used as a reference, or configured in any combination of these.

Porting code from layoutProvider

The following is a short guide to porting existing code, typically found in the layoutProvider class, to the new function.

Previous implementation:
class MyLayoutProvider extends ExtlayoutProvider
{
	layoutControls( CBActionElement element )
	{
			super.layoutControls( element ); // call super first.
			createWidgets(); // create all the UI for display
			refreshWidgets(); // call refreshLayout to populate UI
			return true; // return true is success.
	}

	createWidgets()
	{
			new StyledText();
			new Button();
	}

	refreshControls( CBActionElement element )
	{
			super.refreshControls( element ); // call super first
			// grab data from model element and apply it to UI widgets
			applyModelDataToWidgets();
			return true; // return true if success.
	}

	/* because the ExtLayoutProvider is SelectionListener, 
	this method is called when Buttons, ComboBoxes and 
	such are modified. */
	widgetSelected( SelectionEvent event )
	{
			// find the widget, get its value and apply it to model 
			applyUiDataToModelElement();
			// call super to update the editor.
			super.widgetSelected();
	}

	/* because the ExtLayoutProvider is ModifyListener, 
	this method is called when StyledText is modified. */
	modifyText( ModifyEvent event )
	{
			// find relevant StyledText control and apply 
			// its value to the model element.
			applyTextUiDataToModelElement();
			super.modifyText();
			}

}
Current® implementation:
class MyLayoutProvider extends ExtlayoutProvider
{
			// class declared as internal.
			class MyTextField extends TextFieldAttribute
			{
					String getTextValue(){
							return ((MyModelElement)getSelection()).getTextAttr();
					}
					setTextValue( String newVal ){
							((MyModelElement)getSelection()).setTextAttr( newVal );
					}
					String getFieldName(){
							return MY_FIELD_NAME; // defined elsewhere
					}
			};
	
			MyTextField m_fldText;
			MyDataCorrelationField m_DcField; // declared outside.

			layoutControls( CBActionElement element )
			{
					createWidgetsAndFields(); // create all the UI for display
					updateNonFieldWidgets(); // update non-model widgets 
					// always call super at the end.
					return super.layoutControls( element ); 
			}

			createWidgetsAndFields()
			{
					// create UI widgets for displaying non-model info
					…
					// create Fields
					m_fldText = new MyTextField( this );
					m_fldText.createLabel( … );
					m_fldText.createControl( …. );

					// create more UI widgets for displaying non-model info

					m_DcField = new MyDataCorrelationField( this );
					m_DcField.createLabel( … );
					m_DcField.createControl( …. );

			}

			refreshControls( CBActionElement element )
			{
					// update NON-UI widgets only.
					applyModelDataToWidgets();
					//always call super at the end.
					return super.refreshControls( element ); 
}

			/*You do not have to have this method unless you want 
			to update NON-model widgets/data. */
			widgetSelected( SelectionEvent event )
			{
					// find the widget and do whatever you need, but 
					// do not update the model. 
					applyUiDataTo_NON_ModelElement();
					// DO NOT call super to update the editor.
			}

			/* You do not need to have this method unless you 
			want to update non-model widgets/data. */
			modifyText( ModifyEvent event )
			{
					// find the widget and do whatever you need, but do not 
					// update the model. 
					applyTextUiDataToModelElement();
					// DO NOT call super to update the editor.

			}

}