Complete example below. Some points of note:
- The example includes a CustomWidgetBuilder that chooses JTextField instead of JSpinner for int fields. Note you shouldn't do this by extending SwingWidgetBuilder! You should just write a lightweight WidgetBuilder for the widget you're interested in, and return null for everything else. Leave CompositeWidgetBuilder to chain all the WidgetBuilders together
- There's a CustomWidgetProcessor that sets all JTextFields to the same preferredSize. It leave other components (such as JCheckBox and JTextArea) alone
- There's a CustomLayout that tweaks org.metawidget.swing.layout.GridBagLayout to honor preferredSize
package com.myapp;
import static org.metawidget.inspector.InspectionResultConstants.*;
import java.awt.*;
import java.util.Map;
import javax.swing.*;
import org.metawidget.inspector.annotation.*;
import org.metawidget.swing.SwingMetawidget;
import org.metawidget.swing.layout.GridBagLayout;
import org.metawidget.swing.widgetbuilder.SwingWidgetBuilder;
import org.metawidget.widgetbuilder.composite.*;
import org.metawidget.widgetbuilder.iface.WidgetBuilder;
import org.metawidget.widgetprocessor.iface.WidgetProcessor;
public class Main {
@SuppressWarnings( "unchecked" )
public static void main( String[] args ) {
// Model
Person person = new Person();
// Metawidget
SwingMetawidget metawidget = new SwingMetawidget();
metawidget.setWidgetBuilder( new CompositeWidgetBuilder<JComponent, SwingMetawidget>(
new CompositeWidgetBuilderConfig<JComponent, SwingMetawidget>().setWidgetBuilders(
new CustomWidgetBuilder(),
new SwingWidgetBuilder() ) ) );
metawidget.addWidgetProcessor( new CustomWidgetProcessor() );
metawidget.setMetawidgetLayout( new CustomLayout() );
metawidget.setToInspect( person );
// Frame
JFrame frame = new JFrame( "Example" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( metawidget );
frame.setSize( 400, 250 );
frame.setVisible( true );
}
/**
* Model
*/
public static class Person {
private String mName;
private int mAge;
private boolean mRetired;
private Address mAddress = new Address();
private String mNotes;
public String getName() {
return mName;
}
public void setName( String name ) {
mName = name;
}
@UiComesAfter( "name" )
public int getAge() {
return mAge;
}
public void setAge( int age ) {
mAge = age;
}
@UiComesAfter( "age" )
public boolean isRetired() {
return mRetired;
}
public void setRetired( boolean retired ) {
mRetired = retired;
}
@UiComesAfter( "retired" )
public Address getAddress() {
return mAddress;
}
public void setAddress( Address address ) {
mAddress = address;
}
@UiLarge
@UiComesAfter( "address" )
public String getNotes() {
return mNotes;
}
public void setNotes( String notes ) {
mNotes = notes;
}
}
static class Address {
private String mStreet;
private String mCity;
private String mState;
public String getStreet() {
return mStreet;
}
public void setStreet( String street ) {
mStreet = street;
}
@UiComesAfter( "street" )
public String getCity() {
return mCity;
}
public void setCity( String city ) {
mCity = city;
}
@UiComesAfter( "city" )
public String getState() {
return mState;
}
public void setState( String state ) {
mState = state;
}
}
/**
* Custom WidgetBuilder.
* <p>
* You don't have to extend <code>SwingWidgetBuilder</code>. You just build the one widget
* you're interested in, and return null for all the rest. Rely on
* <code>CompositeWidgetBuilder</code> to chain WidgetBuilders together.
*/
static class CustomWidgetBuilder
implements WidgetBuilder<JComponent, SwingMetawidget> {
public JComponent buildWidget( String elementName, Map<String, String> attributes, SwingMetawidget metawidget ) {
if ( "int".equals( attributes.get( TYPE ) ) ) {
return new JTextField();
}
return null;
}
}
/**
* Custom WidgetProcessor.
* <p>
* Tweak similar widgets based on their type. For example, set all <code>JTextFields</code> to
* the same preferred size.
*/
static class CustomWidgetProcessor
implements WidgetProcessor<JComponent, SwingMetawidget> {
public JComponent processWidget( JComponent component, String elementName, Map<String, String> attributes, SwingMetawidget metawidget ) {
if ( component instanceof JTextField ) {
component.setPreferredSize( new Dimension( 100, 20 ) );
}
return component;
}
}
/**
* Custom Layout.
* <p>
* Use the new <code>setFillConstraints</code> hook to avoid filling width if
* <code>preferredSize</code> has been set.
*/
static class CustomLayout
extends GridBagLayout {
@Override
protected void setFillConstraints( JComponent component, GridBagConstraints componentConstraints ) {
if ( component.getPreferredSize().getWidth() == 100 ) {
return;
}
super.setFillConstraints( component, componentConstraints );
}
}
}
import static org.metawidget.inspector.InspectionResultConstants.*;
import java.awt.*;
import java.util.Map;
import javax.swing.*;
import org.metawidget.inspector.annotation.*;
import org.metawidget.swing.SwingMetawidget;
import org.metawidget.swing.layout.GridBagLayout;
import org.metawidget.swing.widgetbuilder.SwingWidgetBuilder;
import org.metawidget.widgetbuilder.composite.*;
import org.metawidget.widgetbuilder.iface.WidgetBuilder;
import org.metawidget.widgetprocessor.iface.WidgetProcessor;
public class Main {
@SuppressWarnings( "unchecked" )
public static void main( String[] args ) {
// Model
Person person = new Person();
// Metawidget
SwingMetawidget metawidget = new SwingMetawidget();
metawidget.setWidgetBuilder( new CompositeWidgetBuilder<JComponent, SwingMetawidget>(
new CompositeWidgetBuilderConfig<JComponent, SwingMetawidget>().setWidgetBuilders(
new CustomWidgetBuilder(),
new SwingWidgetBuilder() ) ) );
metawidget.addWidgetProcessor( new CustomWidgetProcessor() );
metawidget.setMetawidgetLayout( new CustomLayout() );
metawidget.setToInspect( person );
// Frame
JFrame frame = new JFrame( "Example" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( metawidget );
frame.setSize( 400, 250 );
frame.setVisible( true );
}
/**
* Model
*/
public static class Person {
private String mName;
private int mAge;
private boolean mRetired;
private Address mAddress = new Address();
private String mNotes;
public String getName() {
return mName;
}
public void setName( String name ) {
mName = name;
}
@UiComesAfter( "name" )
public int getAge() {
return mAge;
}
public void setAge( int age ) {
mAge = age;
}
@UiComesAfter( "age" )
public boolean isRetired() {
return mRetired;
}
public void setRetired( boolean retired ) {
mRetired = retired;
}
@UiComesAfter( "retired" )
public Address getAddress() {
return mAddress;
}
public void setAddress( Address address ) {
mAddress = address;
}
@UiLarge
@UiComesAfter( "address" )
public String getNotes() {
return mNotes;
}
public void setNotes( String notes ) {
mNotes = notes;
}
}
static class Address {
private String mStreet;
private String mCity;
private String mState;
public String getStreet() {
return mStreet;
}
public void setStreet( String street ) {
mStreet = street;
}
@UiComesAfter( "street" )
public String getCity() {
return mCity;
}
public void setCity( String city ) {
mCity = city;
}
@UiComesAfter( "city" )
public String getState() {
return mState;
}
public void setState( String state ) {
mState = state;
}
}
/**
* Custom WidgetBuilder.
* <p>
* You don't have to extend <code>SwingWidgetBuilder</code>. You just build the one widget
* you're interested in, and return null for all the rest. Rely on
* <code>CompositeWidgetBuilder</code> to chain WidgetBuilders together.
*/
static class CustomWidgetBuilder
implements WidgetBuilder<JComponent, SwingMetawidget> {
public JComponent buildWidget( String elementName, Map<String, String> attributes, SwingMetawidget metawidget ) {
if ( "int".equals( attributes.get( TYPE ) ) ) {
return new JTextField();
}
return null;
}
}
/**
* Custom WidgetProcessor.
* <p>
* Tweak similar widgets based on their type. For example, set all <code>JTextFields</code> to
* the same preferred size.
*/
static class CustomWidgetProcessor
implements WidgetProcessor<JComponent, SwingMetawidget> {
public JComponent processWidget( JComponent component, String elementName, Map<String, String> attributes, SwingMetawidget metawidget ) {
if ( component instanceof JTextField ) {
component.setPreferredSize( new Dimension( 100, 20 ) );
}
return component;
}
}
/**
* Custom Layout.
* <p>
* Use the new <code>setFillConstraints</code> hook to avoid filling width if
* <code>preferredSize</code> has been set.
*/
static class CustomLayout
extends GridBagLayout {
@Override
protected void setFillConstraints( JComponent component, GridBagConstraints componentConstraints ) {
if ( component.getPreferredSize().getWidth() == 100 ) {
return;
}
super.setFillConstraints( component, componentConstraints );
}
}
}
0 comments:
Post a Comment