Search code examples
javagwtevent-handlinggwt2

Customizing GWT DateBox


I am working on customizing GWT 2.5.1's DateBox.

My requirements are: I cannot allow dates past 31/12/9999, I need the date parsing to be strict, always (that is, I need allow dates only in format DD/MM/YYYY, which is the format used by my MyDatePickerFormat format), I need to retrieve parsing errors and propagate errors up to the editor framework (and display it somewhere along my custom Widget, which implements HasEditorErrors).

This is a list of the classes I have created for that purpose:

1. MyDateBox extends DateBox implements ParseEvent.HasParseEventHandlers.
2. MyDatePickerFormat implements Format
3. MyDateBoxEditorDecorator extends Composite implements HasEditorErrors<Date>, HasEnabled, HasValue<Date>,
    IsEditor<LeafValueEditor<Date>>, HasEditorDelegate<Date>

In detail:

1.

public MyDateBox()
{
    super();
    this.getTextBox().setMaxLength(MyDateBox.MyDatePickerFormat.MAX_DATE_LENGTH);
    final MyDatePickerFormat myPickerFormat = new MyDateBox.MyDatePickerFormat();
    setFormat(myPickerFormat);
    ParseEventHandler handler = new ParseEventHandler()
    {
        @Override
        public void onParseEvent(ParseEvent event)
        {
            MyDateBox.this.fireEvent(event);
        }
    };
    myPickerFormat.setParseEventHandler(handler);
}
  1. Instanciates 1 MyDateBox object. Takes a ParseEventHandler to propagate parsing issues.
    Overrides com.google.gwt.user.datepicker.client.DateBox.Format.parse(DateBox, String, boolean) to always call com.google.gwt.i18n.shared.DateTimeFormat.parseStrict(String), and caps the parsed date to 01/01/9999 at most.
    At the end of the parse method, it instanciates a ParseEvent and calls the "parent" ParseEventHandler handler method.

3.

public MyDateBoxEditorDecorator()
{
    dateBox = new MyDateBox();
    dateBox.addParseErrorHandler(new ParseEventHandler()
    {
        @Override
        public void onParseEvent(ParseEvent event)
        {
            MyDateBoxEditorDecorator.this.onParseEvent(event);
        }
    });

    initWidget(Binder.BINDER.createAndBindUi(this));
    contents.add(dateBox);
}

My issues are the following:

  • The event handling seems pretty clumsy to me (an event is instanciated and handled using one handler, which then fires this event at the enclosing Widget level (let's call that widget "w") which is handled by the handlers that were added to w using its 'addParseHandler' method. That final handler calls an instance method on my MyDateBoxEditorDecorator instance. These are many steps, I guess there must be better ways to handle this ? (I am overcomplicating it ?)
  • MyDateBoxEditorDecorator error handling does not integrate well with my editor hierarchy. What happens is that, when the user modifies the date field content (repeatedly...), multiple parsing events are eventually issued. My MyDateBoxEditorDecorator instance (let's call it "myDateBoxEditor") ends up calling its delegate's recordError() multiple times. Then, when I finally call flush() to flush my entire editor hierarchy, myDateBoxEditor's showError(List errors) method gets too many errors as input (all errors since the last call to flush(), I think). What can I do to avoid that ? (would using an additionnal driver with my MyDateBoxEditorDecorator instances and flush it -every time parsing is done- be the right solution for that problem ?)

Thank you.

PS. I don't know much with SO formatting, have done my best (it looks ugly but is readable enough).


Solution

  • Just a heads-up: I have fixed the biggest problem (my editor hierarchy problems with error handling). The cause was I used to call getValue() multiple times during a single editor cycle (every time the user modified the field, for instance), this is what caused duplicate errors to be displayed - according to Valueboxeditordecorator source, one is not supposed to do this. As for the other questions, I wish there were elegant solutions but I think this will do.