I was recently asked whether Metawidget could 'add an annotation for field/methods to describe a field in the UI with a tooltip'. Here's how to add that:
Step 1: Write the Annotation
You can basically copy @UiLabel:
package com.myapp;
import java.lang.annotation.*;
@Retention( RetentionPolicy.RUNTIME )
@Target( { ElementType.FIELD, ElementType.METHOD } )
public @interface UiDescription {
String value();
}
import java.lang.annotation.*;
@Retention( RetentionPolicy.RUNTIME )
@Target( { ElementType.FIELD, ElementType.METHOD } )
public @interface UiDescription {
String value();
}
Step 2: Write an Inspector for the Annotation
Most of the work is done for you by BasePropertyInspector:
package com.myapp;
import java.util.*;
import org.metawidget.inspector.impl.*;
import org.metawidget.util.*;
public class DescriptionInspector extends BasePropertyInspector {
public DescriptionInspector() {
this( new BasePropertyInspectorConfig() );
}
public DescriptionInspector( BasePropertyInspectorConfig config ) {
super( config );
}
@Override
protected Map<String, String> inspect( Property property, Object toInspect )
throws Exception {
Map<String, String> attributes = CollectionUtils.newHashMap();
UiDescription description = property.getAnnotation( UiDescription.class );
if ( description != null )
attributes.put( "description", description.value() );
return attributes;
}
}
import java.util.*;
import org.metawidget.inspector.impl.*;
import org.metawidget.util.*;
public class DescriptionInspector extends BasePropertyInspector {
public DescriptionInspector() {
this( new BasePropertyInspectorConfig() );
}
public DescriptionInspector( BasePropertyInspectorConfig config ) {
super( config );
}
@Override
protected Map<String, String> inspect( Property property, Object toInspect )
throws Exception {
Map<String, String> attributes = CollectionUtils.newHashMap();
UiDescription description = property.getAnnotation( UiDescription.class );
if ( description != null )
attributes.put( "description", description.value() );
return attributes;
}
}
Step 3: Extend the Metawidget to understand the Inspector
For this example, I'll extend SwingMetawidget:
package com.myapp;
import java.util.Map;
import javax.swing.JComponent;
import org.metawidget.swing.SwingMetawidget;
public class DescriptiveSwingMetawidget extends SwingMetawidget {
@Override
protected JComponent buildActiveWidget( Map attributes )
throws Exception {
JComponent component = super.buildActiveWidget( attributes );
if ( component == null )
return null;
component.setToolTipText( attributes.get( "description" ));
return component;
}
}
import java.util.Map;
import javax.swing.JComponent;
import org.metawidget.swing.SwingMetawidget;
public class DescriptiveSwingMetawidget extends SwingMetawidget {
@Override
protected JComponent buildActiveWidget( Map
throws Exception {
JComponent component = super.buildActiveWidget( attributes );
if ( component == null )
return null;
component.setToolTipText( attributes.get( "description" ));
return component;
}
}
Step 4: Annotate the Business Object
We're done! To test it, first annotate the business object. We'll reuse the business object from the Metawidget tutorial:
package com.myapp;
public class Person {
@UiDescription( "The name of the person" )
public String name;
@UiDescription( "The age of the person" )
public int age;
@UiDescription( "Whether the person is retired" )
public boolean retired;
}
public class Person {
@UiDescription( "The name of the person" )
public String name;
@UiDescription( "The age of the person" )
public int age;
@UiDescription( "Whether the person is retired" )
public boolean retired;
}
Step 5: Use the Business Object
Now use the business object. Again, we'll reuse the Main class from the Metawidget tutorial:
package com.myapp;
import javax.swing.JFrame;
import org.metawidget.inspector.composite.*;
import org.metawidget.inspector.propertytype.*;
public class Main {
public static void main( String[] args ) {
DescriptiveSwingMetawidget metawidget = new DescriptiveSwingMetawidget();
CompositeInspectorConfig config = new CompositeInspectorConfig();
config.setInspectors( new PropertyTypeInspector(), new DescriptionInspector() );
metawidget.setInspector( new CompositeInspector( config ) );
metawidget.setToInspect( new Person() );
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( metawidget );
frame.setSize( 400, 210 );
frame.setVisible( true );
}
}
import javax.swing.JFrame;
import org.metawidget.inspector.composite.*;
import org.metawidget.inspector.propertytype.*;
public class Main {
public static void main( String[] args ) {
DescriptiveSwingMetawidget metawidget = new DescriptiveSwingMetawidget();
CompositeInspectorConfig config = new CompositeInspectorConfig();
config.setInspectors( new PropertyTypeInspector(), new DescriptionInspector() );
metawidget.setInspector( new CompositeInspector( config ) );
metawidget.setToInspect( new Person() );
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( metawidget );
frame.setSize( 400, 210 );
frame.setVisible( true );
}
}
Run it! You'll see the usual Swing tutorial app, but this time with tooltips on all the fields.
Of course, this simple example has its problems. Most notably, you'd probably want some localization on the descriptions. Both @UiLabel and @UiSection do this, but that's for another blog!
0 comments:
Post a Comment