Community
Participate
Working Groups
1. create CDateTime with style CDT.BORDER | CDT.DROP_DOWN | CDT.DATE_LONG | CDT.COMPACT 2. use drop down to show the date picker 3. use the month or year button of the date picker to select another month resp. year. 4. the date is set/changed in the text field but no selection event is fired.
Created attachment 220717 [details] Testcase
Thanks for the report Michael. Do you have time to provide a patch?
I was trying to understand the cause. I supose it has something to do with the code in DatePicker.createMonths/createYears. In both methods listeners are added to the months resp. year buttons. When such a button is pressed the handleEvent has a conditional expression: if (cdt.field.length == 1 && cdt.getCalendarField(cdt.field[0]) == Calendar.MONTH/.YEAR) In the cases tested cdt.field.length has always been 0. That was the reason why cdt.fireSelectionChanged(true) doesn't fire. Actually I do not understand what cdt.field is all about, why it has length 0 and why it is tested before firing an event. More over, I do not understand why events are not fired from within CDateTime.setSelection at all. To answer your question: I would like to contribute but I am afraid not to really understand the code. I have a workaround implemented in a sub class of CDateTime: /** * {@inheritDoc} */ @Override public void setSelection(Date selection) { Date previous = getSelection(); super.setSelection(selection); if ( previous != selection && ( selection == null || previous == null || ! selection.equals(previous) ) ) { fireSelectionChanged(); } } This work around has the downside that under some circumstance multiple events may be fired (because setSelection and fireSelectionEvent seem to have different call conditions)
I think I got it. Changes pushed to master [1], please review. http://git.eclipse.org/c/nebula/org.eclipse.nebula.git/commit/?id=d3446b606c41f7bf62f752b4c20d05a2e32476fc
The following refers to DatePicker.java (Lines 669 and following)! The expression currently used check whether to send an "cde.fireSelectionEvent(boolean close)" event is as follows if (cdt.field.length == 1 && cdt.getCalendarField(cdt.field[0]) == Calendar.MONTH/.YEAR) The fix provided now triggers the sending of an event, but does not work correctly when using the CDateTime Widget to select a Period such as periodSelection = new CDateTime(container, SWT.BORDER | CDT.DATE_MEDIUM | CDT.DROP_DOWN | CDT.COMPACT ); periodSelection.setPattern("MMMM yyyy"); this opens a drop down with the month panel, but does not close on a month selection because the cdt.field.length is - in this case "2" (month, year). The suggested solution is to close the drop down panel (on a month selection) whenever the field length is either 1 (month) or 2 (month, year). The simplest solution is to check for cdt.field.length < 3. // close the popup when the month field is the first field if (cdt.field.length < 3 && cdt.getCalendarField(cdt.field[0]) == Calendar.MONTH) { cdt.fireSelectionChanged(true); } else { cdt.fireSelectionChanged(); handleHeaderSelection(null); } Note: This is only useful for the "monthPanel", the "yearPanel" (createYears.method) should work since a year selection should close a drop down only when field of interest is the year, e.g. pattern "yyyy" therefore cdt.field.length 1! best
Addon to the comment 5: The simplest solution mentioned before is not necessarily the proper one: having a (possible) pattern like "MMMM dd" will not work correctly, since the month selection should not close the drop down but on the day selection. The proper solution would be to determine the cdt.field which is the "closing" field. Some examples (dates): pattern "dd.mm.yyyy" -> drop down is closed on the day selection pattern "MMMM yyyy" -> drop down is closed on the month selection pattern "MMMM dd" -> drop down is closed on the day selection Therefore, you can use the Calendar Field (YEAR, MONTH, DAY) to identify the closing field and to ask for the month field. // if ( cdt.isClosingField(Calendar.MONTH) ) { cdt.fireSelectionEvent(true); } where cdt.isClosingField(int calendarField) detects the part of the pattern which finally closes the drop down.
I understand. Can you provide a patch because I don't know exactly where to put that snippet.
Created attachment 221378 [details] Patch: implementation of the "isClosingField(int field) method The proposed solution for determining the most concrete portion of the date pattern. The constant values of the Calendar class are used to identify the field. The highest constant value is the most concrete date portion.
Created attachment 221379 [details] usage of the "isClosingField" in the DatePicker panel The usage of the "old" if(cdt.field.length == 1 && cdt.getCalendarField(cdt.field[0]) == Calendar.YEAR) has been replaced with if ( cdt.isClosingField(Calendar.YEAR/.MONTH/.DATE) )
Created attachment 221380 [details] sample snippet with various patterns for checking the drop down panel behaviour Sample snippet with some CDateTime fields & patterns for testing.
(In reply to comment #9) > Created attachment 221379 [details] > usage of the "isClosingField" in the DatePicker panel > The first patch is fine, thanks, but the second one gives me a load of errors. Can you try again or otherwise attach the complete new DatePicker source so that I can make the compare myself. Thanks for the work Dietmar.
Created attachment 221398 [details] Full DatePicker The full DatePicker implementation where the old checks of "cdt.field.length & cdt.getCalendarField(cdt.field[0]) == YEAR/MONTH" are replaced with "cdt.isClosingField(Calendar.YEAR/MONTH/DAY_OF_MONTH/DATE)" Sorry because of the wrong patch ...
thanks Dietmar, Changes pushed to master: http://git.eclipse.org/c/nebula/org.eclipse.nebula.git/commit/?id=6b30b14475bd6f2b25158caa32ade402999b9e8a
Seems ok on Nebula 2.2.0