gwtproject / gwt

GWT Open Source Project
http://www.gwtproject.org
1.5k stars 371 forks source link

CalendarView API not enabling composition #7219

Open dankurka opened 9 years ago

dankurka commented 9 years ago

Originally reported on Google Code with ID 7222


Found in GWT Release (e.g. 2.4.0, 2.5.0 RC):

2.2.0, 2.4.0

Encountered on OS / Browser (e.g. WinXP, IE8-9, FF7):

All

Detailed description (please be as specific as possible):

Provided that:

1. Class com.google.gwt.user.datepicker.client.DatePickerComponent is abstract AND
has a visibility set to package AND has two protected abstract methods: setup() and
refresh();

2. Class com.google.gwt.user.datepicker.client.CalendarView is "public abstract", extends
DatePickerComponent and does not override the above protected methods;

3. Class com.google.gwt.user.datepicker.client.DefaultCalendarView is final so to allow
the framework maintainers to freely change its implementation;

4. The above point IMHO implicitly means the API is encouraging the user to prefer
composition over extension,

we have a method visibility problem. An instance of CalendarView cannot be decorated
by another CalendarView, because the wrapping CalendarView is not able to invoke setup()
and refresh() on the wrapped instance.

If we look at DefaultCalendarView, it can be wrapped because it has public implementations
of setup() and refresh(), but it does not offer API methods to do something with its
grid or to add some custom behaviour, so if for example I try to create my custom CalendarView
and add one more column at the right end of the grid to show the week-in-year numbers,
I still cannot do so even by wrapping DefaultCalendarView.

The only remaining solution is at last to extract the logic implemented in DefaultCalendarView
and put it as a monolithic whole into a custom CalendarView. From that moment on the
entire view code (custom + the refactored copy-paste of DefaultCalendarView) has to
be entirely maintained outside the framework. Also, another problem is that the DefaultCalendarView
code shows up here and there, which may not give problems to the API but it sure gives
problems to its users.

Shortest code snippet which demonstrates issue (please indicate where
actual result differs from expected result):

public class WeekNumbersCalendarView extends CalendarView
{

    private CalendarView wrapped;

    @Override
    public void addStyleToDate(String styleName, Date date)
    {
        wrapped.addStyleToDate(styleName, date);
    }

    @Override
    public Date getFirstDate()
    {
        return wrapped.getFirstDate();
    }

    @Override
    public Date getLastDate()
    {
        return wrapped.getLastDate();
    }

    @Override
    public boolean isDateEnabled(Date date)
    {
        return wrapped.isDateEnabled(date);
    }

    @Override
    public void removeStyleFromDate(String styleName, Date date)
    {
        wrapped.removeStyleFromDate(styleName, date);
    }

    @Override
    public void setEnabledOnDate(boolean enabled, Date date)
    {
        wrapped.setEnabledOnDate(enabled, date);
    }

    @Override
    public void refresh()
    {
        wrapped.refresh(); // method not visible!
        // add my stuff...
    }

    @Override
    public void setup()
    {
        wrapped.setup(); // method not visible!
        // add my stuff...
    }

}

Workaround if you have one:

A very ugly one could be to use the same package "com.google.gwt.user.datepicker.client"
for my custom class. I don't know if it's really feasible however, it may break something
at GWT compile time.

Links to relevant GWT Developer Forum posts:

Link to patch posted at http://gwt-code-reviews.appspot.com:

Reported by marcotrev on 2012-02-29 16:27:46

dankurka commented 9 years ago
Another related problem: class DatePicker.StandardCss is not visible outside its package,
and the same holds for CalendarUtil.isWeekend(int), so if I extract DefaultCalendarView
in a custom class I also have to copy StandardCss and CalendarUtil in my package too.

Reported by marcotrev on 2012-02-29 17:04:55