7. WidgetProcessors

This chapter covers each WidgetProcessor in detail. For an explanation of how WidgetProcessors fit into the overall architecture of Metawidget, see Chapter 2, Architecture.

7.1 Desktop WidgetProcessors

Metawidget supports multiple WidgetProcessors for each desktop framework, targeting specific features within each environment.

7.1.1 Swing WidgetProcessors

Property Binding

Swing does not include an automatic JComponent to Object binding mechanism, but Metawidget supports third-party alternatives via addWidgetProcessor.

BeansBindingProcessor

BeansBindingProcessor binds properties using Beans Binding (JSR-295). It supports the various Beans Binding update strategies:

myMetawidget.addWidgetProcessor( new BeansBindingProcessor(
	new BeansBindingProcessorConfig()
		.setUpdateStrategy( UpdateStrategy.READ )) );

If set to READ or READ_WRITE (the default is READ_ONCE), the object being inspected must provide PropertyChangeSupport. If set to READ_WRITE, updates to the UI are automatically sync'ed back to the setToInspect, otherwise the client must manually call save:

myMetawidget.getWidgetProcessor( BeansBindingProcessor.class ).save( myMetawidget )

After JComponents have been generated for the initial setToInspect, clients can load values for a new Object into the same UI without a full re-inspection by using rebind:

myMetawidget.getWidgetProcessor( BeansBindingProcessor.class ).rebind( newObject, myMetawidget )

For more details, see Section 9.5.4, “Rebinding”.

[Important]Make sure you use the correct version of BeansBinding
There are unfortunately two versions of BeansBinding 1.2.1 available. The version at http://repo2.maven.org/maven2/net/java/dev/beansbinding/beansbinding/1.2.1 has serious bugs related to PropertyChangeListeners. The version at http://download.java.net/maven/2/org/jdesktop/beansbinding/1.2.1 is the correct one. This issue has been reported here.
[Tip]Consider BetterBeansBinding
BeansBinding 1.2.1 has known performance issues when working with large numbers of widgets. Consider a more recent JSR-295 implementation such as BetterBeansBinding.
BeanUtilsProcessor

BeanUtilsProcessor binds properties using Apache BeanUtils. It supports arbitrary property styles:

myMetawidget.addWidgetProcessor( new BeanUtilsBindingProcessor(
	new BeanUtilsBindingProcessorConfig()
		.setPropertyStyle( new ScalaPropertyStyle() ) );

Updates to the UI can be saved back to the setToInspect by calling save:

myMetawidget.getWidgetProcessor( BeanUtilsBindingProcessor.class ).save( myMetawidget )

After JComponents have been generated for the initial setToInspect, clients can load values for a new Object into the same UI without a full re-inspection by using rebind:

myMetawidget.getWidgetProcessor( BeanUtilsBindingProcessor.class ).rebind( newObject, myMetawidget )

For more details, see Section 9.5.4, “Rebinding”.

Action Binding

Swing supplies javax.swing.Action for binding JButtons to backing objects, and this is typically combined with Java-based reflection to support runtime binding. This is exactly what the default action binding, ReflectionBinding, does.

However, Metawidget makes action bindings pluggable to support other use cases. In particular, use cases where there is no backing object, and instead the JButton should invoke, say, an RPC call. Implement your own pluggable binding by implementing WidgetProcessor:

public class RpcWidgetProcessor
	implements WidgetBuilder<JComponent, SwingMetawidget> {
										
	JComponent processWidget( JComponent widget, String elementName, Map<String, String> attributes,
									SwingMetawidget metawidget ) {

		...decide whether to attach event handler...
		
		widget.add( new AbstractAction() {
			public void actionPerformed( ActionEvent e ) {
			
				String actionName = attributes.get( NAME );
				...make RPC using actionName...
			}
		}
	}
}

This can be set either in code:

myMetawidget.addWidgetProcessor( new RpcWidgetProcessor() );

Or via metawidget.xml:

<swingMetawidget xmlns="java:org.metawidget.swing">
	<widgetProcessors>
		<array>
			<rpcWidgetProcessor xmlns="java:com.myapp"/>
		</array>
	</widgetProcessors>
</swingMetawidget>

7.1.2 SWT WidgetProcessors

DataBindingProcessor

DataBindingProcessor binds properties using org.eclipse.core.databinding. Once bound, values can be saved back from the UI by calling save:

myMetawidget.getWidgetProcessor( DataBindingProcessor.class ).save( myMetawidget )

ReflectionBindingProcessor

ReflectionBindingProcessor binds Buttons to backing objects using Java-based reflection to support runtime binding.

After JComponents have been generated for the initial setToInspect, clients can load values for a new Object into the same UI without a full re-inspection by using rebind:

myMetawidget.getWidgetProcessor( ReflectionBindingProcessor.class ).rebind( newObject, myMetawidget )

For more details, see Section 9.5.4, “Rebinding”.