Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 19945

Summary: DCR: date/time widget would be useful
Product: [Eclipse Project] Platform Reporter: Karice McIntyre <Karice_McIntyre>
Component: SWTAssignee: Felipe Heidrich <eclipse.felipe>
Status: RESOLVED FIXED QA Contact:
Severity: enhancement    
Priority: P4 CC: belldj, bogofilter+eclipse.org, boyge03, bradleyjames, brockj, contact, dirk.rademann, dwhare, ebrunetta, ekuleshov, frydzewski, jeremyd, Konstantin.Scheglov, markus.kell.r, mik.kersten, mlists, mseele, nedelec, olibralo, peter, pombredanne, rngadam, robert.elves, rsqrd, snorthov, steven.wasleski, sun, taivo, tbs, thirstynellan, villane, w-zwicky, whtiger
Version: 2.0Keywords: helpwanted
Target Milestone: 3.3 M3   
Hardware: All   
OS: All   
Whiteboard:
Bug Depends on:    
Bug Blocks: 69655    
Attachments:
Description Flags
date-time widget look
none
month calendar
none
using text widget as a datetime picker
none
A Date picker widget
none
datepicker updated
none
Native Date and Time widget for windows none

Description Karice McIntyre CLA 2002-06-11 16:58:57 EDT
I am looking for a widget that a user could use to change date/time.

Windows has a calendar widget (not sure what the deal is on other platforms)
that might be suitable for this purpose.
Comment 1 Karice McIntyre CLA 2002-06-11 16:59:35 EDT
Created attachment 1362 [details]
date-time widget look
Comment 2 Karice McIntyre CLA 2002-06-11 17:05:41 EDT
I have attached what I think the widget might look like.  Each aspect of the 
date/time (month, day, year, hours, minutes, seconds) is a separate editable 
field that the user can navigate through by clicking or using the left/right 
cursors (or perhaps tabbing, I suppose).  Each of the fields can also be edited 
by typing numbers.  

The up/down arrows on the left increment or decrement the number in the 
currently selected field.  The single, larger drop down arrow drops down a 
month calendar which you can scroll through (using left/right arrows) by month 
or by year (using double left/right arrows).  I will also attach a pic of what 
the calendar might look like.
Comment 3 Karice McIntyre CLA 2002-06-11 17:07:11 EDT
Created attachment 1363 [details]
month calendar
Comment 4 Mike Wilson CLA 2002-06-11 17:40:14 EDT
Could be considered as a new custom widget post R2.0. Feel free to contribute 
an implementation as well.
Comment 5 Veronika Irvine CLA 2002-09-11 14:08:18 EDT
Moving from Later.
Comment 6 Steve Northover CLA 2002-09-11 15:25:43 EDT
Chrix, is this the date and time picker thing?  If so, link this bug.
Comment 7 Mark McLaren CLA 2003-05-25 17:05:52 EDT
What's the difference between this and bug 21959?
Comment 8 Christophe Cornu CLA 2003-05-26 09:21:07 EDT
*** Bug 21959 has been marked as a duplicate of this bug. ***
Comment 9 Michael Permana CLA 2005-03-24 01:31:07 EST
Created attachment 19151 [details]
using text widget as a datetime picker

// I use a Text widget as a date-time picker, it does the job:

/*
 * Created on Mar 23, 2005
Michael Permana
mpermana@hotmail.com
Siebel Systems

 */
package com.siebel.analytics.build;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Vector;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

/**
 * @author mpermana
 */
public class DateField {

    Text text;

    GregorianCalendar calendar = new GregorianCalendar();

    DateFormat dateFormat;

    private FieldPosition[] fieldPositions;

    private int[] gregorianFields;

   
    public DateField(DateFormat dateFormat) {
	this.dateFormat = dateFormat;
	fieldPositions = new FieldPosition[] {
		new FieldPosition(DateFormat.YEAR_FIELD),
		new FieldPosition(DateFormat.MONTH_FIELD),
		new FieldPosition(DateFormat.DATE_FIELD),
		new FieldPosition(DateFormat.HOUR_OF_DAY0_FIELD),
		new FieldPosition(DateFormat.HOUR_OF_DAY1_FIELD),
		new FieldPosition(DateFormat.HOUR0_FIELD),
		new FieldPosition(DateFormat.HOUR1_FIELD),
		new FieldPosition(DateFormat.MINUTE_FIELD),
		new FieldPosition(DateFormat.SECOND_FIELD),
		new FieldPosition(DateFormat.AM_PM_FIELD) };

	gregorianFields = new int[] { GregorianCalendar.YEAR,
		GregorianCalendar.MONTH, GregorianCalendar.DAY_OF_MONTH,
		GregorianCalendar.HOUR_OF_DAY, GregorianCalendar.HOUR_OF_DAY,
		GregorianCalendar.HOUR, GregorianCalendar.HOUR,
		GregorianCalendar.MINUTE, GregorianCalendar.SECOND,
		GregorianCalendar.AM_PM, };
    }

    public DateField() {
	this(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT,

		Locale.US));
    }

    /**
     * @param shell
     */
    public Text create(Composite composite) {

	text = new Text(composite, SWT.BORDER | SWT.READ_ONLY);
	text.setBackground(new Color(null, 255,255,255));
	text.setToolTipText("Use arrow key to ");
	onDateChange();

	KeyListener keyListener = new KeyListener() {

	    public void keyPressed(KeyEvent e) {
		int multiply = 1;
		switch (e.keyCode) {
		case SWT.ARROW_DOWN:
		    multiply = -1;
		case SWT.ARROW_UP:
		    addCalendar(multiply, 0 < (e.stateMask & SWT.CONTROL));
		    e.doit = false;
		    break;

		case SWT.ARROW_LEFT:
		    selectDateFormatField(nextDateFormatField(
			    getDateFormatField(text.getSelection().x), -1));
		    e.doit = false;
		    break;
		case SWT.ARROW_RIGHT:
		    selectDateFormatField(nextDateFormatField(
			    getDateFormatField(text.getSelection().x), 1));
		    e.doit = false;
		    break;
		}
	    }

	    public void keyReleased(KeyEvent e) {
	    }

	};
	text.addKeyListener(keyListener);

	return text;
    }

    /**
     * @param b
     *	
     */
    protected void addCalendar(int amount, boolean big) {
	int x = text.getSelection().x;
	int dateFormatField = getDateFormatField(x);
	int gregorianField = dateFormatFieldToGregorianField(dateFormatField);
	if (GregorianCalendar.AM_PM == gregorianField) {
	    calendar.set(gregorianField, 1 - calendar.get(gregorianField));
	} else if (-1 != gregorianField) {
	    int value = calendar.get(gregorianField);
	    calendar.set(gregorianField, value + amount);
	}
	onDateChange();
	selectDateFormatField(dateFormatField);
    }

    /**
     * @param dateFormatField
     * @return
     */
    private int dateFormatFieldToGregorianField(int dateFormatField) {
	for (int i = 0; i < fieldPositions.length; i++) {
	    if (fieldPositions[i].getField() == dateFormatField)
		return gregorianFields[i];
	}
	return -1;
    }

    /**
     * @param dateFormatField
     */
    private void selectDateFormatField(int dateFormatField) {
	int correctPosition = 0;
	for (int i = 0; i < fieldPositions.length; i++) {
	    if (fieldPositions[i].getField() == dateFormatField)
		correctPosition = fieldPositions[i].getBeginIndex();
	}
	text.setSelection(correctPosition);
    }

    /**
     * @return DateFormat.HOUR0_FIELD etc..
     */
    protected int getDateFormatField(int position) {
	for (int i = 0; i < fieldOrder.size(); i++) {
	    int[] fieldPosition = (int[]) fieldOrder.get(i);
	    int beginIndex = fieldPosition[1];
	    int endIndex = fieldPosition[2];
	    if (beginIndex <= position && position < endIndex)
		return fieldPosition[3];
	}
	return -1;
    }

    Vector fieldOrder = new Vector();

    public void onDateChange() {
	fieldOrder.removeAllElements();

	Date date = calendar.getTime();

	for (int i = 0; i < fieldPositions.length; i++) {
	    FieldPosition fieldPosition = fieldPositions[i];
	    dateFormat.format(date, new StringBuffer(), fieldPosition);
	    if (fieldPosition.getBeginIndex() < fieldPosition.getEndIndex())
		addFieldOrder(gregorianFields[i], fieldPosition);
	}

	text.setText(dateFormat.format(calendar.getTime()));
    }

    /**
     * @param year
     * @param beginIndex
     */
    private void addFieldOrder(int field, FieldPosition fieldPosition) {
	int[] entry = new int[] { field, fieldPosition.getBeginIndex(),
		fieldPosition.getEndIndex(), fieldPosition.getField() };
	for (int i = 0; i < fieldOrder.size(); i++) {
	    int[] fieldPositions = (int[]) fieldOrder.get(i);
	    if (fieldPosition.getBeginIndex() < fieldPositions[1]) {
		fieldOrder.add(i, entry);
		return;
	    }
	}
	fieldOrder.add(entry);
    }

    private int nextDateFormatField(int dateFormatField, int step) {
	for (int i = 0; i < fieldOrder.size(); i++) {
	    int[] fieldPosition = (int[]) fieldOrder.get(i);
	    if (fieldPosition[3] == dateFormatField) {
		return ((int[]) fieldOrder.get((i + fieldOrder.size() + step)
			% fieldOrder.size()))[3];
	    }
	}
	return -1;
    }

    /**
     * @return Returns the dateFormat.
     */
    public DateFormat getDateFormat() {
	return dateFormat;
    }

    /**
     * @param dateFormat
     *		  The dateFormat to set.
     */
    public void setDateFormat(DateFormat dateFormat) {
	this.dateFormat = dateFormat;
    }

    /**
     * @return Returns the calendar.
     */
    public GregorianCalendar getCalendar() {
	return calendar;
    }

    /**
     * @param calendar
     *		  The calendar to set.
     */
    public void setCalendar(GregorianCalendar calendar) {
	this.calendar = calendar;
    }

    public static void main(String[] args) {
	Display display = new Display();
	Shell shell = new Shell(display);
	GridLayout gridLayout = new GridLayout();
	gridLayout.numColumns = 3;
	shell.setLayout(gridLayout);

	try {

	    Locale[] locales = { Locale.CHINA, Locale.US, Locale.KOREA,
		    Locale.JAPAN };
	    DateField dateField;
	    GridData gridData;
	    int width = 150;
	    for (int i = 0; i < locales.length; i++) {

		dateField = new DateField(DateFormat.getDateInstance(
			DateFormat.SHORT, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);
		dateField = new DateField(DateFormat.getDateInstance(
			DateFormat.MEDIUM, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);
		dateField = new DateField(DateFormat.getDateInstance(
			DateFormat.LONG, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);

		dateField = new DateField(DateFormat.getTimeInstance(
			DateFormat.SHORT, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);
		dateField = new DateField(DateFormat.getTimeInstance(
			DateFormat.MEDIUM, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);
		dateField = new DateField(DateFormat.getTimeInstance(
			DateFormat.LONG, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);

		dateField = new DateField(DateFormat.getDateTimeInstance(
			DateFormat.SHORT, DateFormat.SHORT, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);
		dateField = new DateField(DateFormat.getDateTimeInstance(
			DateFormat.MEDIUM, DateFormat.MEDIUM, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);
		dateField = new DateField(DateFormat.getDateTimeInstance(
			DateFormat.LONG, DateFormat.LONG, locales[i]));
		gridData = new GridData();
		gridData.widthHint = width;
		dateField.create(shell).setLayoutData(gridData);

	    }

	    // createScheduleSection(shell);
	} catch (Exception e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}

	shell.pack();
	shell.open();
	while (!shell.isDisposed()) {
	    if (!display.readAndDispatch())
		display.sleep();
	}
	display.dispose();

    }
}
Comment 10 Steve Northover CLA 2005-04-11 21:52:49 EDT
It's possible that we will add a native date/time picker widget to SWT in the 
future.  Assigning to FH.
Comment 11 Bahadir Yagan CLA 2005-06-22 04:50:56 EDT
Created attachment 23709 [details]
A Date picker widget

I wrote a datepicker widget, hope it is useful for others until the native
widget is out.
Comment 12 Bahadir Yagan CLA 2005-06-29 10:10:04 EDT
Created attachment 24129 [details]
datepicker updated

Updated the widget. Some small fixes.
Comment 13 Karice McIntyre CLA 2005-08-15 15:43:53 EDT
*** Bug 87505 has been marked as a duplicate of this bug. ***
Comment 14 Marcos César de Oliveira CLA 2005-08-23 20:57:22 EDT
Created attachment 26397 [details]
Native Date and Time widget for windows

I create a very simple native Date and Time widget.
It works in win32 OS only.
Feel free to use and to improve it.
Comment 15 Dirk Rademann CLA 2005-12-09 06:00:49 EST
Hello,
is there any progress on the date widget issue? This is really a needed widget, we notice this all the time in our own Eclipse RCP project ;-) Other solutions on the market are usually not that good as none of those we found uses the native (Windows) Date Picker. 
We tried Oliveira's native widget, but while it runs okay in its own main() test method, we couldn't get it run in our Eclipse RCP application as it seems the widget ain't visible outside its plugin. It's declared in org.eclipse.swt.widgets but in our own plugin of course (we didn't hack the eclipse swt.jar ;-) Guess the plugin classloader does not see it (..?)

Any progress on a Eclipse' provided widget? :)
Comment 16 Michael Seele CLA 2006-01-11 05:12:54 EST
is there any possibility to get it in 3.2 ?
Comment 17 Peter Centgraf CLA 2006-03-16 17:39:20 EST
On Mac OS X, there is a new "Date Picker" control as of 10.4.  It provides a native implementation of both text-box-like and graphical controls for dates and times.  Unfortunately, it's in Cocoa only!  There is a Carbon clock control, but it only supports limited text-box-like functionality.  (It cannot combine both date and time into a single control, and it lacks support for custom formats other than by changing the system-wide locale settings.)  We can only hope that the Cocoa version is eventually ported.

http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGControls/chapter_18_section_3.html#//apple_ref/doc/uid/TP30000359-DontLinkElementID_2

Summary of native functionality on various platforms, with functionality implemented by a single control grouped by parentheses:

GD - Graphical Date
GT - Graphical Time
GC - Graphical Date/Time Combo
TD - Textual Date
TT - Textual Time
TC - Textual Date/Time Combo

Mac OS X (Cocoa) - (All)
Mac OS X (Carbon) - (TD, TT)
Windows (95+/NT4+) - (TD, TT, TC), (GD)
GTK (2.x) - (GD)
Motif - None

Given all of this, I recommend that the SWT API should expose two Controls -- one for the text-based date/time and one for the graphical date.  On every platform except Windows, the text-based date/time will need to be simulated by other controls. If custom date format support is abandoned on the Mac, it can use a native control.  Motif and Mac will need simulated graphical date controls.
Comment 18 Susan McCourt CLA 2006-06-15 21:35:34 EDT
*** Bug 147359 has been marked as a duplicate of this bug. ***
Comment 19 Peter Centgraf CLA 2006-07-31 02:35:11 EDT
With the recent fixes to the SWT_AWT support on Mac OS, it should be possible to use the graphical calendar from Cocoa in a child Shell.  This would work like the child shells used for autocomplete results.  The only tricky part would be doing this in a thread-safe way from the perspective of the SWT Display, since the calendar control would be in its own Cocoa window on a different event queue.
Comment 20 Jeremy Dowdall CLA 2006-07-31 10:13:15 EDT
After reviewing the native widgets for Windows and GTK, it does not look like native backed SWT widgets will work for my application. So I'm wondering if there are plans for a custom version (like with the CTabFoler), perhaps even an extendible one?  Would Nebula be the place for this?

Also, is there an API, or any other specification, that the SWT team has been working on which I could use to make my CDatepicker/Combo code like the forthcoming components?  (has a name for the components been settled on?)

Thus far my API is as shown here:
http://calypsorcp.sourceforge.net/widgets.php?detail=cdatepicker#api
http://calypsorcp.sourceforge.net/widgets.php?detail=cdatepickercombo#api
I would be interested in hearing what others have done in this regard.

cheers
Comment 21 Ricky Ng-Adam CLA 2006-08-02 10:04:11 EDT
Existing alternatives for SWT date picker
(http://www.eclipsezone.com/eclipse/forums/t62966.rhtml)

http://swtcalendar.sourceforge.net/demos.html
SWTCalendar is a port of Kai Toedter's JCalendar to SWT
0.5 2004-01-26:2006-05-19 [GPL, LGPL]

http://www.cwroethel.com/Projects/JPopupCalendar/
An SWT version of JPopupCalendar is now available. 
V02-02pre, 2005-12-17, EPL

http://sourceforge.net/projects/twist/
swt-datepicker; Twist is an open-source Java add-on collection for the Standard Widget Toolkit (SWT) 
1.3, 2004-05-18, [BSD, CPL, GPL, LGPL]

http://www.jaret.de/datechooser.html
The jaret datechooser is a classic drop down date chooser widget for use with the SWT toolkit.
0.96, 2004-12-24:2006-05-03, CPL

http://gface.sourceforge.net/
Date Picker - UI widget for visually picking a day in a month.
0.9.1, 2005-07-05:2006-05-06, EPL
Comment 22 Ricky Ng-Adam CLA 2006-08-02 12:31:30 EDT
Jeremy Dowdall  (comment #20): how does your CDatepickerCombo fit with GFace Date Picker/Date Combo/Hour Selection Combo? GFace is also talking about donating to the Nebula project, maybe you could work together...

http://jroller.com/page/nirpaz?entry=gface_update

"I contacted Chris Gross the leader of the Nebula project in eclipse and offered to merge GFace into the Nebula project. Chris was very excited, and once the project will get organized we‘ll examine together what is the best way to donate GFace to eclipse."

This bug has been opened since 2002 for something pretty basic so it would be great if it would be solved before the next eclipse...
Comment 23 Jeremy Dowdall CLA 2006-08-02 14:14:27 EDT
Ricky Ng-Adam (comment #22)
> Jeremy Dowdall  (comment #20): how does your CDatepickerCombo fit with GFace
> Date Picker/Date Combo/Hour Selection Combo?

First impressions:
 The CDatepickerCombo is masked and editable, so the user can enter a date textually in a number of ways, either with the keyboard or the mouse, and it will always be a valid date/time in the format set - date, time, both, or any pattern possible with SimpleDateFormat.  When the CDatepickerCombo is not of a DROP_DOWN style, it has a spinner to inc/dec calendar fields.
 The CDatepicker, which is the drop component of the CDatepickerCombo, uses (as best it can) the native colors and native buttons for the dates (a button is visible under the cursor as the user moves the mouse over the days - similar to how most toolbars look). It can also scroll its days vertically, edit the year via keyboad, and has an analog clock for graphically selecting times (click and drag the clock hands).
More complete descriptions of the CDatepicker and CDatepickerCombo are on the website given above.  Overall, I greatly appreciated comment #17 by Peter Centgraf and tried to take as much there to heart as possible.  Unfortunately though, I also need these widgets to support some additional features: durations, timespans, and ordinals - "A 1 hour Meeting Starting at 10:45 on Friday, August 4th".  I also need the graphical date picker's calendar to show tasks/workload per day and the clock to show durations.

> donating to the Nebula project, maybe you could work together...

That is always a good thing, and the reason I posted here. I don't see why we shouldn't all be working together on this, like you said: "This bug has been opened since 2002".  More and more I think that this shouldn't be a native solution... IMHO of course :)

So, to finish, I have a question:
What is the best way to set the format to be used by the textual date picker?
Presently, the CDatepickerCombo uses four methods, which were supposed to coorespond to the date formatter object being used internally:
 setDateStyle(int)
 setDateTimeStyle(int, int)
 setTimeStyle(int)
 setPattern(String)
This seems unnecessarily confusing and should be reduced to an overloaded method such as:
 setFormat(int, int) - replaces setDateStyle and setTimeStyle
 setFormat(int, int, int) - replaces setDateTimeStyle
 setFormat(String) - replaces setPattern

thoughts?
Comment 24 Peter Centgraf CLA 2006-08-02 21:17:34 EDT
Jeremy, could you explain your proposed API a bit?  It's hard to comment on the appropriateness of a bunch of unlabeled int params.  ;-)  For example, why three params for the setFormat() that replaces setDateTimeStyle()?

I like your implementation a lot.  If I have to use custom code, I'll probably go with yours.  My recommendation for the API would be to stick to SWT conventions as much as possible.  To me, that means using a single packed-int style param for as much as possible and also exposing typed get/set methods for things that can be changed after construction.  AFAIK, all of the current controls have just the one style param.  Personally, I prefer consistency over optimality for this situation.

As for the native/custom debate, I would prefer a native solution whenever possible, even if that is somewhat limiting in the breadth of features.  I buy the founding arguments of the SWT project -- catching up with platform integration is an unwinnable race.  (For example, when will CCombo get fixed to respond to keyboard events like a native Windows Combo?)  Just writing wrappers for native features is hard enough to keep up with.  More power to you if you want a custom implementation, but that doesn't solve the core SWT problem, IMHO.

Like I said, though, CDatepickerCombo looks pretty darn good.  It will also be the only game in town for some platforms.  Don't stop working on it or anything.  :-)

Glad to be helpful, btw.  Thanks for doing the difficult part.
Comment 25 Dirk Rademann CLA 2006-08-03 03:35:10 EDT
I agree with Peter, first and foremost we need a wrapper to the native widget, and  maybe a custom implementation for platforms not providing a native date/time control. 

I also can't understand why this is taking so long, as was said, this bug has been here since 2002 . With RCP out and running, it still comes without date/time picker, a control almost every business application needs. This should have a much higher priority, IMHO.
Comment 26 Michael Seele CLA 2006-08-03 03:38:51 EDT
they said in a newsgroup it is planned for 3.3 to support a native calendar widget. 

@eclipse: is that right?
Comment 27 Ricky Ng-Adam CLA 2006-08-03 09:50:35 EDT
comment #26: do you mean this?

http://dev.eclipse.org/newslists/news.eclipse.platform/msg56450.html

"This was submitted as a proposed 3.3 plan item, but is subject to PMC
approval.  I believe that a first kick of the 3.3 plan will be available
quite soon."

the plan is here but there isn't much yet:

http://www.eclipse.org/swt/R3_3/plan.html

comment #23: Jeremy, I've tried your widget and really like it - in fact, we will use it in our application until Eclipse RCP provides a standard one.  I think I would also prefer the API as it is instead of a more complicated setFormat() method that does it all.  

I did also find another (!) calendar/date chooser widget: 

http://www.wdev91.com/comp4swt
CCalendar : Calendar widget 
DateChooser : Date field editor that combine a text field and a popup calendar. 
0.9.1, 2006-05-21:2006-07-28, EPL
Comment 28 Jeremy Dowdall CLA 2006-08-03 10:26:27 EDT
(In reply to comment #24)
> appropriateness of a bunch of unlabeled int params.  ;-)  For example, why
> three params for the setFormat() that replaces setDateTimeStyle()?

I'm afraid the best reasoning I can come up with is that I've been inside the
widget for so long that I had trouble looking at it from the outside :)

> I like your implementation a lot.

Thanks - always great to hear (though critism and bugs are helpfull, so is
inspiration!)

> My recommendation for the API would be to stick to SWT
> conventions as much as possible.  To me, that means using a single packed-int
> style param for as much as possible and also exposing typed get/set methods
> for things that can be changed after construction.  AFAIK, all of the current
> controls have just the one style param.  Personally, I prefer consistency over
> optimality for this situation.

Agreed, and this could give us the following:
 setFormat(int format)
 setFormat(String pattern)

possible bits for the "format" parameter:
 DATE_SHORT
 DATE_MEDIUM
 DATE_LONG
 TIME_SHORT
 TIME_MEDIUM
 (too my knowledge a TIME_LONG is not supported in java)
Only one of the date and one of the time bits would be valid at a time and if
no valid bits were sent nothing would be changed.  Initial setting upon
construction will be DATE_SHORT unless the contstructor's style int contains
valid format bits.  Setting the format this way will null the internal
"pattern" String.
The "pattern" parameter, in the second set method, is the pattern which will be
used to set the format with SimpleDateFormat.  When setting the format this
way, the internal format int (as to be returned with getFormat() ) should be
set with one of the following, as appropriate for the given pattern:
 DATE_CUSTOM
 TIME_CUSTOM

I also propose that the date picker (CDatepicker in my case) follow the same
suit and use: setFormat(int format) to determine whether or not to show its
calendar, clock, or both.  This would have the added advantage that in order to
sync styles with the combo, you can simply do:
 CDatepicker.setFormat(CDatepickerCombo.getFormat());

As a note, the way the current API is, CDatepickerCombo does not have a get
method for its format - not good.  With this change the get methods, int
getFormat() and String getPattern() can be implemented.

> As for the native/custom debate
I should choose my words more carefully :)
Seriously though, I too am a big believer in the founding args of SWT (SWT is
actually why I started using Eclipse) and have plenty of frustration with
CCombo (like when will it work outside of Windows!).  However, unlike buttons
and combos, date selection widgets are not very well implemented across
different platforms.  This will require custom widgetry at some point
regardless and therefore why not bring out a custom widget first, rather than
continuing to wait?  My guess is that once it is out they can't change the API
and want to see how others will implement it, but overall I feel pretty in the
dark on this whole issue.

> Don't stop working on it or anything.  :-)
No worries there - Calypso doesn't like the GTK or Windows date pickers :)
Comment 29 Jeremy Dowdall CLA 2006-08-03 10:29:43 EDT
(In reply to comment #27)
Apparently we were replying at the same time - how does the updated version(s) of setFormat look to you.  A big part for me is the get method.
Comment 30 Jeremy Dowdall CLA 2006-08-03 10:51:53 EDT
New Question:
What is the best way to handle the case when setting one field can influence another?  Part 1: when setting the field via direct keyboard input; 2. when using an Increment/Decrement method (arrow keys, mouse wheel, spinner, etc.)

Example 1:
 An end user types "21" into the month field.

Example 2:
 An end user selects the month field, which is currently 5, and clicks the increment part of the spinner 8 times.  Are they indicating they want the date "8 months later", or are they just trying to scroll the month field back to 1?

Possible Solutions:
 1. Consider this value out of range and throw it away; 
 2. Consider this value out of range and set the field to its maximum (12);
 3. Consider this value out of range and set the field to its minimum (1) thus        allowing it wrap-around; or
 4. Go ahead and set the internal MONTH field to the out of range value, which will have the side affect of incrementing the YEAR field.

Present Solution in CDatepickerCombo:
 Leave it up to the programmer and provide the following set method:
  setLinkFields(boolean link)
If link is true, the fields are "linked" and setting one can influence the others (solution #4).
If link is false, the fields are "not linked" and setting one cannot influence the others; for this case solution #3 is used (eg: holding the up arrow key just continually cycles through all values of the selected field).
The present solution does not distinguish between the two parts of the question.

thoughts and opinions?
Comment 31 Peter Centgraf CLA 2006-08-03 11:00:38 EDT
Jeremy, is there a more appropriate place for bug/RFE submissions for CDatepicker?  I'd be happy to summarize some features from platform widgets for you to prioritize.
Comment 32 Peter Centgraf CLA 2006-08-03 11:33:55 EDT
Interpreting keyboard input on a date field is context-dependent.  In your example, there is no valid interpretation of "21", but the user could have attempted to follow an initial "Febuary" with "2001".  Keyboard input should never "wrap", since the user intention is much more likely to be a straightforward multi-field date entry.  E.g. in the US, "1265" means "December 6, 2005" not "Febuary 3".  In the UK, that string would be interpreted as "12 June, 2005" not "12 May".  Some users get in the habit of typing delimiters to disambiguate, so you should handle various non-numeric characters as part of the input.

Have you surveyed the natives on how they handle increment?  Of the non-standard apps I have handy, iCal wraps, the Windows "Date and Time" control panel does not, and Mozilla Sunbird 0.2 has no increment at all.

P.S. The more I survey current apps, the more I understand why SWT has no widget for this.  There's very little consistency on any platform.  Windows is the only platform where the widget has been available for any length of time, and Windows apps aren't exactly prized for standards-compliance.  You're in a good position to create a custom widget that surpasses all of the attempts I've seen.
Comment 33 Peter Centgraf CLA 2006-08-03 11:38:15 EDT
I should amend my last comment.  A lot of motor memory has been developed based on the Visual Basic date widget.  Maintaining keyboard-stream compatibility with that widget would be a worthwhile goal, since I suspect many RCP apps are targeted to replace VB predecessors.
Comment 34 Jeremy Dowdall CLA 2006-08-03 12:03:10 EDT
(In reply to comment #31)
> Jeremy, is there a more appropriate place for bug/RFE submissions for
> CDatepicker?  I'd be happy to summarize some features from platform widgets 
> for you to prioritize.

Thank you for the offer, this is very helpfull (especially Mac, to which I have no access).

There is always the Sourceforge site:
 http://sourceforge.net/projects/calypsorcp

But both Felipe and Grant have pointed people to this Bug for question regarding date selectors, so unless it is really CDatepicker specific, perhaps this is the better place...
Comment 35 Steve Northover CLA 2006-08-03 17:57:18 EDT
Nice to see all this great discussion going on here.  I'm working to get a native verion of this widget on the 3.3 plan.
Comment 36 Jeremy Dowdall CLA 2006-08-04 08:46:37 EDT
(In reply to comment #32)
> Keyboard input should never "wrap", since the user intention is much more 
> likely to be a straightforward multi-field date entry.

Agreed.

> Have you surveyed the natives on how they handle increment?  Of the
> non-standard apps I have handy, iCal wraps, the Windows "Date and Time" 
> control panel does not, and Mozilla Sunbird 0.2 has no increment at all.

I have surveyed more end users than appliations as most of my target audience is non-technical, and so far they've all expected it to wrap (they also couldn't remember where they'd seen a date widget before - if anything, Quicken was mentioned).

My conclusion at this point is to remove setLinkFields from the API (keeping it simple) and use Solution #1 for keyboard entry and Solution #3 for incrementing & decrementing.

> Some users get in the habit of typing delimiters to disambiguate, so you 
> should handle various non-numeric characters as part of the input.

Very true; here are my current navigation and edit thoughts:
Focus:
 When the widget gains focus, by a means other than a mouse click (such as tabbing through a form), its entire text area is selected. The intent is to allow it to be copied and has the side affect that no field is actually selected, and thus the widget cannot be edited. When the widget looses focus, by any means, all fields are unselected and again, the widget cannot be edited. 

Navigation:
 Before editing, an individual field must be selected; the primary way is to simply select the field to be edited by clicking on it with the mouse.
Once the widget has focus, however, there are also many other ways of moving between and selecting fields:
* Clicking the center mouse button will cycle through the fields
* The left and right arrow keys move one field at time
* Typing the first character of the next separation sequence will move to the
  next field.
  For example, given the pattern "MM/dd/yy", pressing the '/' key will move to 
  the next field.
  Likewise, given the pattern "MM'long separation sequence'dd'another long 
  sequence'yy", typing 'l' when on the "MM" field will move to the "dd" field, 
  and then typing 'a' will move to the last field.
* If the user is entering the field's value via the keyboard and the maximum 
  number of digits for that field have been typed, selection is automatically 
  moved to the next field.  Note that two digit fields will always require two 
  digits to be input: the first day must be entered as "01" unless the user 
  wishes to move fields by the above method: "1/", for example.

Editing:
 Once the user has navigated to a field they want to change, they again have multiple options:
* A Spinner, which will be present if the CDatepickerCombo is not of DROP_DOWN 
  style, can be used to increment and decrement the field's value
* Scrolling with the mouse wheel will increase and decrease the field
* The Up and Down arrow keys will increment and decrement the field
* Enter the value directly with the keyboard
Comment 37 Jeremy Dowdall CLA 2006-08-04 08:56:24 EDT
(In reply to comment #35)
> Nice to see all this great discussion going on here.  I'm working to get a
> native verion of this widget on the 3.3 plan.
> 

Good to hear.  Does this mean you've been thinking about the current discusion topics for awhile now, or are you in the proposal paperwork stage?
Comment 38 Steve Northover CLA 2006-08-04 09:30:39 EDT
I've been following a long a bit, however, the API and functionality of the SWT widget will need to take into account all of the platforms.  An emulated widget doesn't need to do this.

Felipe looked into this a while back and had a few initial hacks but 3.2 work ate him.  Hopefully, it the same thing won't happen for 3.3.
Comment 39 Peter Centgraf CLA 2006-08-04 10:22:17 EDT
Tidbits from the VB DateTimePicker widget (testing VS 2003 aka: .NET 1.1):

Cycling focus via tab will initially select the first field of the widget.  If the user changes the active field and cycles focus out and back, they will return to the same field.  E.g. in a US short date: tab in, type "/", tab, shift-tab, and you're back to the month field.  If you click the drop-down and then tab out+back, you'll end up with a mystery focus in the limbo state between the last field and the first field.

Various symbol characters will advance to the next field, regardless of the current display pattern: ",./" and non-keypad "-".  Most other symbols just cause a system beep.  Keypad + and - act as increment and decrement.  You can also move between fields via left and right arrows, or inc/dec with up and down arrows.

Attempts to use clipboard commands in the text part will cause a system beep.  Attempts in the calendar drop-down silently do nothing.  There is no contextual menu on the main combo, but there is a "Go to Today" item (all by itself) on the calendar.

Field inc/dec is "unlinked", except when a change violates a calendar constraint.  For example, if a US "2/29/2004" is selected, and the user inc.s the year field, the date will become "2/28/2005".  These constraint-avoidance tweaks are one-way, i.e. the day field will never automatically return to "29".

Min and max allowable values can be provided as properties.  When this is done, field inc/dec will attempt to avoid constraint violations by setting all fields to the closest valid date to the one that would have been displayed by an unconstrained widget.  For example, if the max date is "8/5/2006" and the user attempts to inc the year from "3/4/2006", the date will become "8/5/2006".

The control can optionally include a checkbox, which acts as the first field for navigation order.  If it is unchecked, the text portion of the widget is disabled, but clicking the drop-down will set it checked automatically.

The VB date widget is a very odd beast, IMHO.

----

Given the above, Jeremy's proposed behavior seems mostly fine.  Only two things might be odd for previous VB users: the control should always accept [.,/-] as valid separator characters, and the entire widget should be considered a single stop on the tab cycle.  I personally think that returning the focus to exactly the field that was left is odd, but it's probably a good idea to keep compatibility.  Everything else proposed would be non-disruptive icing on the cake.

Stay tuned for my next installment, where I describe the madness that is the VB MonthCalendar control....
Comment 40 Peter Centgraf CLA 2006-08-04 10:24:54 EDT
I forgot to mention: the DateTimePicker also supports validation events.  This works very much like the VetoableChangeListener mechanism.
Comment 41 Carolyn MacLeod CLA 2006-10-31 10:23:16 EST
Fixed > 20061030 (will be in 3.3 M3)

Native controls used wherever possible: calendar, date, and time all native on Win; date and time native on Mac; calendar native on gtk. All other areas are emulated.

Some things still need to be implemented, notably adding a setFormat API or style, accounting for locale changes (some things will currently only work well in EN_US locale), and possibly adding the "drop-down calendar" style. For anything else, please open a new bug report.
Comment 42 Karice McIntyre CLA 2006-10-31 10:59:37 EST
That's great - is this currently or going to be part of the SWT examples?
Comment 43 Carolyn MacLeod CLA 2006-10-31 13:54:23 EST
It is currently in ControlExample, on DateTime tab.
Comment 44 Sebastian Davids CLA 2006-11-13 06:42:42 EST
>>possibly adding the "drop-down calendar" style
Would be highly appreciated.

And thanks for the good work!
Comment 45 Sun Seng David TAN CLA 2006-11-14 00:12:58 EST
That's very nice.
Would it be possible to select multiple dates with this Calendar widget ?
Comment 46 Ivan Mising name CLA 2006-11-22 19:24:03 EST
Nice if it display '0' instead of empty space in no value area.
example :-

  /  /   -> 00/00/00
 1/12/ 6 -> 01/12/06

with zero look nicer and more proper... 

Any ideas ?
Comment 47 Geoff Draper CLA 2006-11-27 17:04:46 EST
I would like the DateTime public API extended so that we can get/set the value using either a Date or Calendar object, rather than dealing with individual fields (month, day, year, hour, minute, second).
Comment 48 Ivan Mising name CLA 2006-12-17 22:41:33 EST
Medium and Long date not working in Mac.
Comment 49 Steve Northover CLA 2006-12-18 12:17:37 EST
This bug report is closed (a native date/time widget has been implemented).  Enter a new bug report describing the problem you are seeing.
Comment 50 Benjamin Cabé CLA 2007-03-13 14:30:29 EDT
+1

should a RFE be opened ?



(In reply to comment #47)
> I would like the DateTime public API extended so that we can get/set the value
> using either a Date or Calendar object, rather than dealing with individual
> fields (month, day, year, hour, minute, second).
> 

Comment 51 Robert Elves CLA 2007-03-27 19:56:46 EDT
Carolyn, why was 'Today' functionality removed from the DateTime widget. It seemed like a useful feature. Platform consistency?
Comment 52 Michael Seele CLA 2007-03-28 01:41:10 EDT
why does the date widget not support the "combo-box style" (SysDateTimePick32)? is it because platform consistency, too?