Introduction

This is code Donohoe Digital uses for doing a Wicket Integer-based drop down list choice. Feel free to re-use this code.

SelectChoice.java

First, I created a generic class to represent a list choice:

package com.donohoedigital.wicket.common;

import java.io.*;

/**
 * Based class for representing a select list choice.  Represents a user-defined type T and its display value.
 *
 * Can be sorted via Collections.sort if T implements Comparable.
 *
 * @param <T> class of key
 *
 * @author Doug Donohoe
 */
public abstract class SelectChoice<T extends Serializable> implements Serializable, Comparable<SelectChoice<T>>
{
    private static final long serialVersionUID = 42L;

    private T key;
    private String display;

    public SelectChoice(T key, String display)
    {
        this.key = key;
        this.display = display;
    }

    /**
     * @return display value
     */
    public String getDisplay()
    {
        return display;
    }

    /**
     * Set the display value
     * @param display value to set
     */
    public void setDisplay(String display)
    {
        this.display = display;
    }

    /**
     * @return key value
     */
    public T getKey()
    {
        return key;
    }

    /**
     * Set the key value
     * @param key value to set
     */
    public void setKey(T key)
    {
        this.key = key;
    }

    /**
     * @return return String representation of the key
     */
    public String getKeyAsString()
    {
        return key.toString();
    }

    /**
     * Return String version of key so {@link org.apache.wicket.Component#getModelObjectAsString()} returns
     * a sensible value.  Useful if storing the value in {@link org.apache.wicket.PageParameters}.
     *
     * @return {@link #getKeyAsString()}
     */
    @Override
    public String toString()
    {
        return getKeyAsString();
    }

    /**
     * Implementation of Comparable.
     *
     * @param o the item to compare
     * @return this.key.compareTo(o.key)
     * @throws UnsupportedOperationException if the underlying key class does not implement Comparable
     */
    @SuppressWarnings({"unchecked"})
    public int compareTo(SelectChoice<T> o)
    {
        if (!(key instanceof Comparable))
        {
            throw new UnsupportedOperationException("Cannot compare non-comparable object: "+ key.getClass().getName());
        }

        Comparable<T> comparableKey = (Comparable<T>) key;

        return comparableKey.compareTo(o.key);        
    }
}

IntegerSelectChoice.java

Creating an Integer choice is a simple matter:

package com.donohoedigital.wicket.common;

/**
 * Integer select choice
 *
 * @author Doug Donohoe
 */
public class IntegerSelectChoice extends SelectChoice<Integer>
{
    private static final long serialVersionUID = 42L;

    public IntegerSelectChoice(Integer key)
    {
        super (key, key.toString());
    }
    
    public IntegerSelectChoice(Integer key, String display)
    {
        super(key, display);
    }
}

SelectChoiceList.java

Next I created a class to

  • represent a list of choices with some convenience methods
  • implement IChoiceRenderer
package com.donohoedigital.wicket.common;

import org.apache.wicket.markup.html.form.*;

import java.util.*;

/**
 * List of SelectChoice&lt;?&gt; items.
 *
 * @author Doug Donohoe
 */
public class SelectChoiceList<T extends SelectChoice<?>> extends ArrayList<T> implements IChoiceRenderer<T>
{
    /**
     * Create list with initial list of items.
     *
     * @param items initial items
     */
    public SelectChoiceList(T... items)
    {
        Collections.addAll(this, items);
    }

    /**
     * Add item to list if not there and then sort.  Returns pre-existing item (if there) or item passed in.
     *
     * @param item to add to list
     * @return item added
     */
    public T addSorted(T item)
    {
        for (T t : this)
        {
            if (t.getKey().equals(item.getKey())) return t;
        }

        add(item);
        Collections.sort(this);
        return item;
    }

    /**
     * Get the display value from the SelectChoice (what the user sees)
     *
     * @param object a SelectChoice object
     * @return object.getDisplay()
     */
    public Object getDisplayValue(T object)
    {
        return object.getDisplay();
    }

    /**
     * Get key value (what is returned from browser)
     *
     * @param object a SelectChoice object
     * @param index not used
     * @return object.getKeyAsString()
     */
    public String getIdValue(T object, int index)
    {
        return object.getKeyAsString();
    }
}

Usage Example

How it all pulls together:

        ...
        // page param value
        int games = params.getAsInteger(PARAM_GAMES, 5);
        
        // list of values
        SelectChoiceList<IntegerSelectChoice> gamesValues = new SelectChoiceList<IntegerSelectChoice>();
        for (int g : new int[] {1, 5, 10, 15, 20, 25, 30, 40, 50, 100, 150, 200, 250, 300, 500, 1000})
        {
            gamesValues.add(new IntegerSelectChoice(g));
        }
        
        // add user's custom choice to list (if they edited URL directly)
        IntegerSelectChoice gameChoice = gamesValues.addSorted(new IntegerSelectChoice(games)); 

        // model set to current choice
        Model<IntegerSelectChoice> gameModel = new Model<IntegerSelectChoice>(gameChoice);
        
        // drop down choice
        final DropDownChoice<IntegerSelectChoice> gamesC =
                new DropDownChoice<IntegerSelectChoice>("games", gameModel, gamesValues, gamesValues);
        form.add(gamesC);
        ...

Note: The params.getAsInteger() call is using a customization I made to PageParameters that hasn't been incorporated into Wicket yet. I submitted the patch as Jira Issue 1596.

You can also use the other constructor to define the display values:

        int days = params.getAsInteger(PARAM_DAYS, 90);
        SelectChoiceList<IntegerSelectChoice> daysValues = new SelectChoiceList<IntegerSelectChoice>(
                new IntegerSelectChoice(7, "week"),
                new IntegerSelectChoice(14, "two weeks"),
                new IntegerSelectChoice(21, "three weeks"),
                new IntegerSelectChoice(30, "month"),
                new IntegerSelectChoice(60, "two months"),
                new IntegerSelectChoice(90, "three months"),
                new IntegerSelectChoice(180, "six months"),
                new IntegerSelectChoice(365, "year"),
                new IntegerSelectChoice(365*2, "two years"),
                new IntegerSelectChoice(10000, "all games")
                );
        IntegerSelectChoice dayChoice = daysValues.addSorted(new IntegerSelectChoice(days, days + " days"));

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-9) was last changed on 09-May-2008 11:38 by donohoe [RSS]