Out of the box, Metawidget supplies UiComesAfter and ComesAfterInspectionResultProcessor to let you order your fields on a 'per domain' basis. But of course there are other approaches.
This one is from the Naked Objects .NET guys. In this presentation you can see how they use a .NET MemberOrder attribute to specify field order as 1, 2, 3 etc. Example implementation below. Some points to note:
- It's in Swing so you can just cut and paste and run it
- It defines a custom annotation (UiOrder) and custom Inspector (OrderInspector) to detect it
- It defines an OrderInspectionResultProcessor that sorts the properties/actions
package com.myapp;
import static org.metawidget.inspector.InspectionResultConstants.*;
import java.lang.annotation.*;
import java.util.*;
import javax.swing.*;
import org.metawidget.inspectionresultprocessor.iface.*;
import org.metawidget.inspector.annotation.*;
import org.metawidget.inspector.composite.*;
import org.metawidget.inspector.impl.*;
import org.metawidget.inspector.propertytype.*;
import org.metawidget.swing.*;
import org.metawidget.util.*;
import org.w3c.dom.*;
public class Main {
public static void main( String[] args ) {
Person person = new Person();
SwingMetawidget metawidget = new SwingMetawidget();
metawidget.setInspector( new CompositeInspector( new CompositeInspectorConfig().setInspectors(
new PropertyTypeInspector(),
new MetawidgetAnnotationInspector(),
new OrderInspector() ) ) );
metawidget.addInspectionResultProcessor( new OrderInspectionResultProcessor() );
metawidget.setToInspect( person );
JFrame frame = new JFrame( "Metawidget Tutorial" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( metawidget );
frame.setSize( 400, 250 );
frame.setVisible( true );
}
static class Person {
@UiOrder( 1 )
public String name;
@UiOrder( 2 )
public int age;
@UiOrder( 3 )
public boolean retired;
@UiOrder( 4 )
@UiLarge
public String notes;
}
@Retention( RetentionPolicy.RUNTIME )
@Target( { ElementType.FIELD, ElementType.METHOD } )
static @interface UiOrder {
int value();
}
static class OrderInspector
extends BaseObjectInspector {
@Override
protected Map<String, String> inspectTrait( Trait trait )
throws Exception {
Map<String, String> attributes = CollectionUtils.newHashMap();
UiOrder order = trait.getAnnotation( UiOrder.class );
if ( order != null ) {
attributes.put( "order", String.valueOf( order.value() ) );
}
return attributes;
}
}
static class OrderInspectionResultProcessor
implements InspectionResultProcessor<SwingMetawidget> {
public String processInspectionResult( String inspectionResult, SwingMetawidget metawidget, Object toInspect, String type, String... names ) {
try {
// Start a new document
//
// (Android 1.1 did not cope well with shuffling the nodes of an existing document)
Document newDocument = XmlUtils.newDocument();
Element newInspectionResultRoot = newDocument.createElementNS( NAMESPACE, ROOT );
Document document = XmlUtils.documentFromString( inspectionResult );
Element inspectionResultRoot = document.getDocumentElement();
XmlUtils.setMapAsAttributes( newInspectionResultRoot, XmlUtils.getAttributesAsMap( inspectionResultRoot ) );
newDocument.appendChild( newInspectionResultRoot );
Element entity = (Element) inspectionResultRoot.getChildNodes().item( 0 );
Element newEntity = newDocument.createElementNS( NAMESPACE, ENTITY );
XmlUtils.setMapAsAttributes( newEntity, XmlUtils.getAttributesAsMap( entity ) );
newInspectionResultRoot.appendChild( newEntity );
// Record all traits (ie. properties/actions) that have an order
Map<Integer, Element> traitsWithOrder = CollectionUtils.newTreeMap();
NodeList traits = entity.getChildNodes();
for ( int loop = 0, length = traits.getLength(); loop < length; loop++ ) {
Node node = traits.item( loop );
if ( !( node instanceof Element ) ) {
continue;
}
Element trait = (Element) node;
// (if no order, move them across to the new document)
if ( !trait.hasAttribute( "order" ) ) {
newEntity.appendChild( XmlUtils.importElement( newDocument, trait ) );
continue;
}
traitsWithOrder.put( Integer.valueOf( trait.getAttribute( "order" ) ), trait );
}
// Output the traits in TreeMap order
for ( Element trait : traitsWithOrder.values() ) {
newEntity.appendChild( XmlUtils.importElement( newDocument, trait ) );
}
// Return the new document
return XmlUtils.documentToString( newInspectionResultRoot.getOwnerDocument(), false );
} catch ( Exception e ) {
throw InspectionResultProcessorException.newException( e );
}
}
}
}
import static org.metawidget.inspector.InspectionResultConstants.*;
import java.lang.annotation.*;
import java.util.*;
import javax.swing.*;
import org.metawidget.inspectionresultprocessor.iface.*;
import org.metawidget.inspector.annotation.*;
import org.metawidget.inspector.composite.*;
import org.metawidget.inspector.impl.*;
import org.metawidget.inspector.propertytype.*;
import org.metawidget.swing.*;
import org.metawidget.util.*;
import org.w3c.dom.*;
public class Main {
public static void main( String[] args ) {
Person person = new Person();
SwingMetawidget metawidget = new SwingMetawidget();
metawidget.setInspector( new CompositeInspector( new CompositeInspectorConfig().setInspectors(
new PropertyTypeInspector(),
new MetawidgetAnnotationInspector(),
new OrderInspector() ) ) );
metawidget.addInspectionResultProcessor( new OrderInspectionResultProcessor() );
metawidget.setToInspect( person );
JFrame frame = new JFrame( "Metawidget Tutorial" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( metawidget );
frame.setSize( 400, 250 );
frame.setVisible( true );
}
static class Person {
@UiOrder( 1 )
public String name;
@UiOrder( 2 )
public int age;
@UiOrder( 3 )
public boolean retired;
@UiOrder( 4 )
@UiLarge
public String notes;
}
@Retention( RetentionPolicy.RUNTIME )
@Target( { ElementType.FIELD, ElementType.METHOD } )
static @interface UiOrder {
int value();
}
static class OrderInspector
extends BaseObjectInspector {
@Override
protected Map<String, String> inspectTrait( Trait trait )
throws Exception {
Map<String, String> attributes = CollectionUtils.newHashMap();
UiOrder order = trait.getAnnotation( UiOrder.class );
if ( order != null ) {
attributes.put( "order", String.valueOf( order.value() ) );
}
return attributes;
}
}
static class OrderInspectionResultProcessor
implements InspectionResultProcessor<SwingMetawidget> {
public String processInspectionResult( String inspectionResult, SwingMetawidget metawidget, Object toInspect, String type, String... names ) {
try {
// Start a new document
//
// (Android 1.1 did not cope well with shuffling the nodes of an existing document)
Document newDocument = XmlUtils.newDocument();
Element newInspectionResultRoot = newDocument.createElementNS( NAMESPACE, ROOT );
Document document = XmlUtils.documentFromString( inspectionResult );
Element inspectionResultRoot = document.getDocumentElement();
XmlUtils.setMapAsAttributes( newInspectionResultRoot, XmlUtils.getAttributesAsMap( inspectionResultRoot ) );
newDocument.appendChild( newInspectionResultRoot );
Element entity = (Element) inspectionResultRoot.getChildNodes().item( 0 );
Element newEntity = newDocument.createElementNS( NAMESPACE, ENTITY );
XmlUtils.setMapAsAttributes( newEntity, XmlUtils.getAttributesAsMap( entity ) );
newInspectionResultRoot.appendChild( newEntity );
// Record all traits (ie. properties/actions) that have an order
Map<Integer, Element> traitsWithOrder = CollectionUtils.newTreeMap();
NodeList traits = entity.getChildNodes();
for ( int loop = 0, length = traits.getLength(); loop < length; loop++ ) {
Node node = traits.item( loop );
if ( !( node instanceof Element ) ) {
continue;
}
Element trait = (Element) node;
// (if no order, move them across to the new document)
if ( !trait.hasAttribute( "order" ) ) {
newEntity.appendChild( XmlUtils.importElement( newDocument, trait ) );
continue;
}
traitsWithOrder.put( Integer.valueOf( trait.getAttribute( "order" ) ), trait );
}
// Output the traits in TreeMap order
for ( Element trait : traitsWithOrder.values() ) {
newEntity.appendChild( XmlUtils.importElement( newDocument, trait ) );
}
// Return the new document
return XmlUtils.documentToString( newInspectionResultRoot.getOwnerDocument(), false );
} catch ( Exception e ) {
throw InspectionResultProcessorException.newException( e );
}
}
}
}
0 comments:
Post a Comment