Javazoid Links

Javazoid March 10, 2000

Home of

In Feb 2000, my Java IDE FrenchRoast won honorable mention in the 2nd JavaWorld CodeMasters series.

About Javazoid

Gervase Gallant Resume
Download

Articles
WordFind applet
IO,IO...
Wizard...




Oct 2000
Below is a work in progress... a version of Minesweeper.

Date Chooser

adventures with java.util.Calendar...
This type of Date selection GUI widget is an almost classic exercise for user interface developers. There are several approaches to the development of the interface, which shed a lot of insight into user interface design techniques. Perhaps the most intriguing is a design developed by Alan Cooper, which featured a rolling Calendar instead of a month-by-month display.
This Date Chooser is closer to standard, featuring a single-month display with a "rolling" feature, i.e., last month, next month, last year, next year.

My main interest in the Date Chooser was not the user interface, which I've implemented previously in VB and FoxPro, but instead the Calendar class which provides the data for the front end.
The history of the Calendar class must be an intriguing one. If you every use the java.util.Date class, you'll find the now deprecated String constructor which allowed you to create a date from a String representation. Many programmers complain that it is now deprecated, but the fact is that the code in this constructor is huge, convoluted and -- frankly -- routinely breaks down. The problem is, of course, that there are just too many ways to pass the String parameter and this code simply can't handle them all.
To deal effectively with Date construction from applications, you need to use the java.util.Calendar class, which is owned and copyrighted by IBM's Taligent Inc. I'll admit that it's a dense design, with its Factory approach to object creation and a series of field attributes that allow you to build and manipulate a date. It takes a while to understand the behaviour of the code, but it definitely solves a problem and provides great flexibility in date manipulation.
First of all, don't try to instantiate it. It's abstract. Instead, you should either instantiate a GregorianCalendar or call its getInstance() method, which also provides a new GregorianCalendar. (I think Taligent was anticipating we would need a JulianCalendar or a MartianCalendar or something... but these appear not to have made it to the java.util package just yet).
For starters, the Calendar by default uses today's date. Or you can set the date with the setTime() method. For this implementation, I use today's date. From the variety of Calendar fields, I pull out integers and convert them to Strings.

//set month
monthLabel.setText(months[cal.get(Calendar.MONTH)] + " " + cal.get(Calendar.YEAR));

//set to first day
cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 1);

//now work the day labels
startPos = cal.get(Calendar.DAY_OF_WEEK);

for (int i = startPos - 1; i < days.length; i++) {
days[i].setText(String.valueOf(cal.get(Calendar.DATE)));
cal.roll(Calendar.DATE, true);
if (cal.get(Calendar.DATE) == 1) {
//clear remaining labels going forward
for (int j = i + 1; j < days.length; j++) {
days[j].setText("");
}
break;
}
}


The above code is about all that is necessary to feed the display portion for any given month. The Calendar is nice enough to handle leap years because if the calendar rolls from 28 to 1 during the month of February, it isn't a leap year and the display doesn't worry about it.

The roll method of Calendar is truly cool in the context of Date Chooser, since the same method that tells me to stop labelling days is the same method I use to move from year to year or month to month.

The buttons at the bottom of DateChooser are set to move months or years. The action handler just calls the DateChooser's roll method and it in turn calls the Calendar's roll method.

private void roll(String direction) {
int field;
if (direction.equals(">>")) calendar.roll(Calendar.YEAR,true);
if (direction.equals(">")) calendar.roll(Calendar.MONTH,true);
if (direction.equals("<<")) calendar.roll(Calendar.YEAR,false);
if (direction.equals("<")) calendar.roll(Calendar.MONTH,false);
caption();
}



When the user clicks on a particular day label, the DateChooser hides itself and allows the caller to access the Calendar's date field. The following sets a TextField on the calling frame.

jff.setText("" + dc.getCalendar().getTime());

Download source

Any questions, please contact me ggallant@bigfoot.com .


Copyright (c) Gervase Gallant 1999,2000.