Actually I would do this using a custom converter. Then you don't have 
to decorate it.

You can have a
public class BooleanLabel {
    ...
    IConverter getConverter() {
        return new IConverter() {
                ...
        }
    }
}

In your converter decide how to display the value.
I don't think there is anything wrong with your model, just that the 
custom components like this are IMHO easier to use.

-Matej

Logi Ragnarsson wrote:
> Hello everyone,
> 
> I'm relatively new to wicket, but I'm building a web application where 
> several 
> forms are backed by compound models with boolean and enum constituent models. 
> The straight-forward implementation of this would display true/false values, 
> and the names of the enum values in the code, which is generally not very 
> user friendly (peopel say "yes" and "no" and they don't generally put choices 
> in all upper case) and not internationalized, so Something Must Be Done.
> 
> I'd like to show my solution, with input from Igor Vaynberg, for comment and 
> perhaps re-use. I've only got the boolean case implemented, but the enum case 
> is basically more of the same with more localization resources needing to be 
> loaded.
> 
> The simplest case (and one not worth all this effort) is when displaying a 
> boolean value in a ListView:
>   new Label("active");
> which becomes:
>   new Label("active", new I18nBooleanModelDecorator(item.getModel()));
> where the (attached) I18nBooleanModelDecorator has been applied to the model. 
> This will display "yes" or "no" for the boolean values unless those strings 
> have been replaced by setting the I18nBooleanModelDecorator.TRUE and 
> I18nBooleanModelDecorator.FALSE licalization strings to something else.
> 
> Usually on a form you'd use a check-box for setting boolean values, such as 
> this:
>   new CheckBox("active");
> but for illustrative purposes suppose we have this text field instead:
>   new TextField("active");
> The following will work if the component's compound model has been set before 
> the form is populated with fields and will not be changed later:
>   new TextField("active", new I18nBooleanModelDecorator(getModel()));
> but in reality getModel() is likely to return null or to return a model which 
> is later replaced with another in response to user or application events, so 
> the text field would now either have no underlying model or an out-dated one.
> 
> For this I wrote a ComponentModelDelegator which takes a Component and 
> delegates all model operations to the current model of that component like 
> so:
>   IModel model = new ComponentModelDelegator(this)
>   new TextField("active", new I18nBooleanModelDecorator(model));
> 
> This works like a charm and you can write "nei" in my Icelandic locale to set 
> the value of the active property of my underlying model to false... before 
> you then change the code back to using the much more reasonable CheckBox 
> class.
> 
> Is there anything terribly wrong with this? Would this be useful for other 
> wicket users, probably in combination with the similar decorator for 
> enumerations?
> 
> PS The attached code is hereby published under the Apache license.
> 
> 
> ------------------------------------------------------------------------
> 
> package is.gig.wicket.models;
> 
> import org.apache.log4j.Logger;
> import wicket.Component;
> import wicket.model.IModel;
> 
> /** Model which delegates to the model of a given component. */
> public class ComponentModelDelegator/*T*/
>     implements IModel/*T*/
> {
>     private static final Logger LOG = 
> Logger.getLogger(ComponentModelDelegator.class);
> 
>     private Component component;
> 
>     /** Create a new delegator to the model of the givne component. */
>     public ComponentModelDelegator(Component component) {
>         this.component = component;
>     }
> 
>     public Component getComponent() {
>         return component;
>     }
> 
>     public void setComponent(Component component) {
>         this.component = component;
>     }
> 
>     public IModel /*T*/ getNestedModel() {
>         return component.getModel();
>     }
> 
>     public Object getObject(final Component component) {
>         IModel nested = getNestedModel();
>         if (nested != null) {
>             return nested.getObject(component);
>         } else {
>             return null;
>         }
>     }
> 
>     public void setObject(final Component component, final Object object) {
>         IModel nested = getNestedModel();
>         if (nested != null) {
>             nested.setObject(component, object);
>         }
>     }
> 
>     public void detach() {
>         IModel nested = getNestedModel();
>         if (nested != null) nested.detach();
>     }
> }
> 
> 
> ------------------------------------------------------------------------
> 
> package is.gig.wicket.models.i18n;
> 
> import wicket.Component;
> import wicket.model.IModel;
> 
> /**
>  * Decorator for a boolean model which converts to and from localized and 
> human-friendly display values, falling back to
>  * "yes" and "no".
>  *
>  * <p/>The display values are taken from the localization strings with keys 
> <code>I18nBooleanModelDecorator.TRUE</code>
>  * and <code>I18nBooleanModelDecorator.FALSE</code> respectively.
>  */
> public class I18nBooleanModelDecorator
>     implements IModel/*Boolean*/
> {
>     private static final String I18N_KEY_PREFIX = "I18nBooleanModelDecorator";
> 
>     private IModel /*Boolean*/  nestedModel;
>     private Boolean defaultValue = Boolean.FALSE;
> 
>     // CONSTRUCTION AND CONFIGURATION
> 
>     /**
>      * Create a new i18n decorator.
>      *
>      * @param nestedModel  the model to decorate
>      * @param defaultValue the value to set in the nested model if the 
> display string being set is not recognized.
>      */
>     public I18nBooleanModelDecorator(IModel /*Boolean*/ nestedModel, Boolean 
> defaultValue) {
>         this.defaultValue = defaultValue;
>         this.nestedModel = nestedModel;
>     }
> 
>     /**
>      * Create a new i18n decorator.
>      *
>      * @param nestedModel the model to decorate
>      */
>     public I18nBooleanModelDecorator(IModel /*Boolean*/ nestedModel) {
>         this(nestedModel, Boolean.FALSE);
>     }
> 
>     public IModel /*Boolean*/ getNestedModel() {
>         return nestedModel;
>     }
> 
>     public void setNestedModel(IModel /*Boolean*/ nestedModel) {
>         this.nestedModel = nestedModel;
>     }
> 
>     /** et the value used in the nested model if the display string being set 
> is not recognized. */
>     public Boolean getDefaultValue() {
>         return defaultValue;
>     }
> 
>     /** Set the value to set in the nested model if the display string being 
> set is not recognized. */
>     public void setDefaultValue(Boolean defaultValue) {
>         this.defaultValue = defaultValue;
>     }
> 
>     // MODEL IMPLEMENTATION
> 
>     private String getHumanReadableValue(Component component, boolean b) {
>         if (b) {
>             return component.getString(I18N_KEY_PREFIX + ".TRUE", 
> nestedModel, "yes");
>         } else {
>             return component.getString(I18N_KEY_PREFIX + ".FALSE", 
> nestedModel, "no");
>         }
>     }
> 
>     public Object getObject(final Component component) {
>         Boolean b = (Boolean) nestedModel.getObject(component);
>         if (b == null) return null;
>         return getHumanReadableValue(component, b.booleanValue());
>     }
> 
>     public void setObject(final Component component, final Object object) {
>         if (object == null) nestedModel.setObject(component, null);
>         String str = object.toString();
>         if (getHumanReadableValue(component, true).equalsIgnoreCase(str)) {
>             nestedModel.setObject(component, Boolean.TRUE);
>         } else if (getHumanReadableValue(component, 
> false).equalsIgnoreCase(str)) {
>             nestedModel.setObject(component, Boolean.FALSE);
>         } else {
>             nestedModel.setObject(component, defaultValue);
>         }
>     }
> 
>     public void detach() {
>         nestedModel.detach();
>     }
> }
> 
> 
> ------------------------------------------------------------------------
> 
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share your
> opinions on IT & business topics through brief surveys - and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Wicket-user mailing list
> Wicket-user@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/wicket-user

-- 

     get professional wicket training and consultation
     http://www.wicket-support.com


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user

Reply via email to