The default implementation of FeedbackPanel displays messages unsorted.
You can sort messages any way you like by either setting the sortingComparator property of
FeedbackPanel, or to provide a custom implementation of the FeedbackMessagesModel by overriding
FeedbackPanel.getFeedbackMessagesModel().
As an example, let's say we want to sort the messages in the order that we added our components
to a form. For this example, we alter the FormInput example of wicket-examples.
First, use a variable (like a list) to store your order:
private List componentOrder = new ArrayList(); |
Then, override method add to automatically add the order:
/**
* @see wicket.MarkupContainer#add(wicket.Component)
*/
public MarkupContainer add(Component component)
{
super.add(component);
componentOrder.add(component);
return (MarkupContainer)component;
}
|
Now, create a comparator that uses this and set it on the FeedbackPanel:
feedback.setSortingComparator(new Comparator()
{
public int compare(Object o1, Object o2)
{
FeedbackMessage m1 = (FeedbackMessage)o1;
FeedbackMessage m2 = (FeedbackMessage)o2;
int ix1 = componentOrder.indexOf(m1.getReporter());
int ix2 = componentOrder.indexOf(m2.getReporter());
return ix1 - ix2;
}
});
|
That's it! The complete patched version of FormInput (based on v1.41):
package wicket.examples.forminput;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import wicket.Component;
import wicket.FeedbackMessage;
import wicket.MarkupContainer;
import wicket.examples.WicketExamplePage;
import wicket.markup.html.form.CheckBox;
import wicket.markup.html.form.DropDownChoice;
import wicket.markup.html.form.Form;
import wicket.markup.html.form.ImageButton;
import wicket.markup.html.form.ListMultipleChoice;
import wicket.markup.html.form.RadioChoice;
import wicket.markup.html.form.RequiredTextField;
import wicket.markup.html.form.TextField;
import wicket.markup.html.form.model.ChoiceList;
import wicket.markup.html.form.model.IChoice;
import wicket.markup.html.form.validation.IntegerValidator;
import wicket.markup.html.image.Image;
import wicket.markup.html.link.Link;
import wicket.markup.html.panel.FeedbackPanel;
import wicket.model.CompoundPropertyModel;
import wicket.model.PropertyModel;
import wicket.protocol.http.WebRequest;
import wicket.util.convert.IConverter;
/**
* Example for form input.
*
* @author Eelco Hillenius
* @author Jonathan Locke
*/
public class FormInput extends WicketExamplePage
{
/** Relevant locales wrapped in a list. */
private static final List LOCALES = Arrays.asList(new Locale[]
{ Locale.US, new Locale("nl"), Locale.GERMANY , Locale.SIMPLIFIED_CHINESE });
/** available numbers for the radio selection. */
private static final List NUMBERS = Arrays.asList(new String[]{"1", "2", "3"});
/** available sites for the multiple select. */
private static final List SITES = Arrays.asList(
new String[]{"The Server Side", "Java Lobby", "Java.Net"});
/**
* Constructor
*/
public FormInput()
{
Locale locale = getLocale();
// Construct form and feedback panel and hook them up
final FeedbackPanel feedback = new FeedbackPanel("feedback");
add(feedback);
add(new InputForm("inputForm", feedback));
// Dropdown for selecting locale
add(new LocaleDropDownChoice("localeSelect"));
// Link to return to default locale
add(new Link("defaultLocaleLink")
{
public void onClick()
{
WebRequest request = (WebRequest)getRequest();
setLocale(request.getLocale());
}
});
}
/**
* Sets locale for the user's session (getLocale() is inherited from
* Component)
*
* @param locale
* The new locale
*/
public void setLocale(Locale locale)
{
getSession().setLocale(locale);
}
/**
* Form for collecting input.
*/
private class InputForm extends Form
{
/**
* Keeps the add order for sorting messages.
*/
private List componentOrder = new ArrayList();
/**
* Construct.
*
* @param name
* Component name
* @param feedback
* Feedback display for form
*/
public InputForm(String name, FeedbackPanel feedback)
{
super(name, new CompoundPropertyModel(new FormInputModel()), feedback);
feedback.setSortingComparator(new Comparator()
{
public int compare(Object o1, Object o2)
{
FeedbackMessage m1 = (FeedbackMessage)o1;
FeedbackMessage m2 = (FeedbackMessage)o2;
int ix1 = componentOrder.indexOf(m1.getReporter());
int ix2 = componentOrder.indexOf(m2.getReporter());
return ix1 - ix2;
}
});
add(new RequiredTextField("stringProperty"));
add(new RequiredTextField("integerProperty", Integer.class));
add(new RequiredTextField("doubleProperty", Double.class));
add(new RequiredTextField("dateProperty", Date.class));
add(new RequiredTextField("integerInRangeProperty", Integer.class).add(IntegerValidator
.range(0, 100)));
add(new CheckBox("booleanProperty"));
add(new RadioChoice("numberRadioChoice", NUMBERS)
{
protected String getSuffix()
{
return "";
}
});
add(new ListMultipleChoice("siteSelection", SITES));
// as an example, we use a custom converter here.
add(new TextField("urlProperty", URL.class)
{
public IConverter getConverter()
{
return new URLConverter();
}
});
add(new ImageButton("saveButton"));
add(new Link("resetButtonLink")
{
public void onClick()
{
// just call modelChanged so that any invalid input is cleared.
InputForm.this.modelChanged();
}
}.add(new Image("resetButtonImage")));
}
/**
* @see wicket.markup.html.form.Form#onSubmit()
*/
public void onSubmit()
{
// Form validation successful. Display message showing edited model.
info("Saved model " + getModelObject());
}
/**
* @see wicket.MarkupContainer#add(wicket.Component)
*/
public MarkupContainer add(Component component)
{
super.add(component);
componentOrder.add(component);
return (MarkupContainer)component;
}
}
/**
* Dropdown with Locales.
*/
private final class LocaleDropDownChoice extends DropDownChoice
{
/**
* Construct.
* @param id component id
*/
public LocaleDropDownChoice(String id)
{
super(id);
// set the model that gets the current locale, and that is used for updating
// the current locale to property 'locale' of FormInput
setModel(new PropertyModel(FormInput.this, "locale"));
// use a custom implementation of choices, as we want to display
// the choices localized
ChoiceList locales = new ChoiceList(LOCALES)
{
protected IChoice newChoice(Object object, int index)
{
return new LocaleChoice((Locale)object, index);
}
};
setChoices(locales);
}
/**
* @see wicket.markup.html.form.DropDownChoice#wantOnSelectionChangedNotifications()
*/
protected boolean wantOnSelectionChangedNotifications()
{
// we want roundtrips when a the user selects another item
return true;
}
/**
* @see wicket.markup.html.form.DropDownChoice#onSelectionChanged(java.lang.Object)
*/
public void onSelectionChanged(Object newSelection)
{
// note that we don't have to do anything here, as our property model allready
// calls FormInput.setLocale when the model is updated
// setLocale((Locale)newSelection); // so we don't need to do this
}
}
/**
* Choice for a locale.
*/
private final class LocaleChoice implements IChoice
{
/** The index of the choice. */
private final int index;
/** The choice model object. */
private final Locale locale;
/**
* Constructor.
* @param locale The locale
* @param index The index of the object in the choice list
*/
public LocaleChoice(final Locale locale, final int index)
{
this.locale = locale;
this.index = index;
}
/**
* @see wicket.markup.html.form.model.IChoice#getDisplayValue()
*/
public String getDisplayValue()
{
String display = locale.getDisplayName(getLocale());
return display;
}
/**
* @see wicket.markup.html.form.model.IChoice#getId()
*/
public String getId()
{
return Integer.toString(index);
}
/**
* @see wicket.markup.html.form.model.IChoice#getObject()
*/
public Object getObject()
{
return locale;
}
}
}
|