DateTimeDialog.java revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* ident "%Z%%M% %I% %E% SMI"
*
* Copyright (c) 1999-2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
/**
* This class creates a dialog box that helps the user enter date and
* time with mouse clicks. The dialog box need only be created
* once. The Ok and Cancel buttons merely call setVisible with an
* argument of false.
*/
// The layout will consist of 3 panels: topPanel contains the
// different labels and fields. middlePanel contains the buttons
// midnight and now. bottomPanel contains the buttons ok, cancel and
// help. The last two panels are separated by a LineSeparator.
public class DateTimeDialog extends Dialog {
private boolean save;
private Frame parent;
private DCPanel dateDCPanel;
private DCPanel yearDCPanel;
private DCPanel hourDCPanel;
private DCPanel minuteDCPanel;
private DCPanel secondDCPanel;
private Choice month;
private DCCircularTextField date;
private DCCircularTextField hour;
private DCCircularTextField second;
private DCCircularTextField minute;
private DCTextField year;
private Button ok;
private Button cancel;
private Button help;
private Button now;
private Button midnight;
private HelpDialog hd = null;
private Panel topPanel;
private Panel middlePanel;
private Panel bottomPanel;
private GregorianCalendar calendar = null;
private static int MONTH_LEN[] = {31, 28, 31, 30, 31, 30, 31,
31, 30, 31, 30, 31};
private static DateFormat df =
DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
DateFormat.MEDIUM);
private static Toolkit toolkit = Toolkit.getDefaultToolkit();
// For I18N
private static ResourceBundle rb =
ResourceBundle.getBundle("GuiResource" /* NOI18N */);
private static ResourceBundle hrb =
ResourceBundle.getBundle("HelpData" /* NOI18N */);
/**
* Constructor that lays out the componeents and sets the different
* event handlers.
*/
public DateTimeDialog(Frame parent, Color background, Color foreground) {
super(parent, getString("SEAM Date/Time Helper"), true);
this.parent = parent;
setLayout(new GridBagLayout());
addLabels();
addFields(background, foreground);
addDCPanels();
addButtons();
addFocusListeners();
setCurrentTime();
setSize(250, 300);
setResizable(false);
addWindowListener(new DCWindowListener());
// initializeFocusOnTextField();
}
/**
* Adds the labels only
*/
private void addLabels() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 1;
topPanel = new Panel();
topPanel.setLayout(new GridBagLayout());
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx = 0;
gbc.gridy = 0;
add(topPanel, gbc);
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 0;
gbc.gridwidth = 1;
gbc.gridy = 0;
topPanel.add(new Label(getString("Month")), gbc);
gbc.gridy = 1;
topPanel.add(new Label(getString("Date")), gbc);
gbc.gridy = 2;
topPanel.add(new Label(getString("Year")), gbc);
gbc.gridy = 3;
topPanel.add(new Label(getString("Hour")), gbc);
gbc.gridy = 4;
topPanel.add(new Label(getString("Minute")), gbc);
gbc.gridy = 5;
topPanel.add(new Label(getString("Second")), gbc);
}
/**
* Adds the fields that will store the month, year, date, hour,
* minute and second.
*/
private void addFields(Color background, Color foreground) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 1;
month = new Choice();
initializeMonth();
date = new DCCircularTextField("1", 2);
date.setMinimum(1);
date.setBackground(background);
date.setForeground(foreground);
hour = new DCCircularTextField("00", 2);
hour.setMaximum(23);
hour.setBackground(background);
hour.setForeground(foreground);
minute = new DCCircularTextField("00", 2);
minute.setBackground(background);
minute.setForeground(foreground);
second = new DCCircularTextField("00", 2);
second.setBackground(background);
second.setForeground(foreground);
year = new DCTextField("2000", 4);
year.setBackground(background);
year.setForeground(foreground);
Panel tempPanel = new Panel();
tempPanel.add(month);
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 0;
topPanel.add(tempPanel, gbc);
// Remaining fields are in topPanel
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 1;
gbc.gridy = 1;
topPanel.add(date, gbc);
gbc.gridy = 2;
topPanel.add(year, gbc);
gbc.gridy = 3;
topPanel.add(hour, gbc);
gbc.gridy = 4;
topPanel.add(minute, gbc);
gbc.gridy = 5;
topPanel.add(second, gbc);
}
// Adds the panels with the +/- buttons for each DCField
private void addDCPanels() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 1;
gbc.gridx = 2;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.NONE;
dateDCPanel = new DCPanel();
yearDCPanel = new DCPanel();
hourDCPanel = new DCPanel();
minuteDCPanel = new DCPanel();
secondDCPanel = new DCPanel();
gbc.gridy = 1;
topPanel.add(dateDCPanel, gbc);
gbc.gridy = GridBagConstraints.RELATIVE;
topPanel.add(yearDCPanel, gbc);
topPanel.add(hourDCPanel, gbc);
topPanel.add(minuteDCPanel, gbc);
topPanel.add(secondDCPanel, gbc);
dateDCPanel.setListener(date);
yearDCPanel.setListener(year);
hourDCPanel.setListener(hour);
minuteDCPanel.setListener(minute);
secondDCPanel.setListener(second);
}
/**
* Sets the strings in the month pull-down menu. Also adds a listener
* that will modify the maximum date allowed depending on the month.
*/
private void initializeMonth() {
DateFormatSymbols dfSymbols = new DateFormatSymbols();
String[] monthStrings = dfSymbols.getMonths();
month.removeAll();
for (int i = 0; i < monthStrings.length; i++) {
month.add(monthStrings[i]);
}
month.addItemListener(new DCMonthChangeListener());
}
// Adds all the buttons
private void addButtons() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 1;
middlePanel = new Panel();
now = new Button(getString("Now"));
midnight = new Button(getString("Midnight"));
middlePanel.add(midnight);
middlePanel.add(now);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
gbc.gridy = 1;
add(middlePanel, gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 2;
add(new LineSeparator(), gbc);
bottomPanel = new Panel();
ok = new Button(getString("OK"));
cancel = new Button(getString("Cancel"));
help = new Button(getString("Help"));
bottomPanel.add(ok);
bottomPanel.add(cancel);
bottomPanel.add(help);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
gbc.gridy = 3;
add(bottomPanel, gbc);
DCButtonListener bl = new DCButtonListener();
ok.addActionListener(bl);
cancel.addActionListener(bl);
help.addActionListener(bl);
now.addActionListener(bl);
midnight.addActionListener(bl);
}
/**
* Adds a listener to all the text fields so that when they go out
* of focus (by tab or clicking), their values are checked for
* errors.
*/
private void addFocusListeners() {
FocusListener fl = new DCFocusListener();
date.addFocusListener(fl);
year.addFocusListener(fl);
hour.addFocusListener(fl);
minute.addFocusListener(fl);
second.addFocusListener(fl);
}
/**
* Closes (hides) the dialog box when the user is done
* @param save true if the box is being dismissed by clicking on
* "ok" and the user wants to retain the modified value, false
* otherwise.
*/
private void dateTimeDialogClose(boolean save) {
if (save == true) {
if (!updateFromGui())
return;
}
this.save = save;
setVisible(false);
}
/**
* Checks to see is all text fields contain valid values.
* @return true if all are valid, false otherwise.
*/
private boolean updateFromGui() {
return (checkErrorAndSet(date) && checkErrorAndSet(year) &&
checkErrorAndSet(hour) && checkErrorAndSet(minute) &&
checkErrorAndSet(second));
}
/**
* Checks the value stored as text in the field and sets its numeric
* value to that if it is legitimate.
* @return true if the value was legitimate and got set, false
* otherwise.
*/
private boolean checkErrorAndSet(DCTextField tf) {
int i = 0;
boolean errorState = false;
try {
i = new Integer(tf.getText().trim()).intValue();
errorState = !tf.checkValue(i);
} catch (NumberFormatException e2) {
errorState = true;
}
if (errorState) {
tf.selectAll();
toolkit.beep();
}
else
tf.setValue(i);
return !errorState;
}
/**
* Checks if the user requested that the value in this
* DateTimeDialog be used e.g., by clicking on "Ok" instead of
* "Cancel."
* @return true if the user wants to save the value in the
* DateTimeDialog, false otherwise.
*/
public boolean isSaved() {
return save;
}
/**
* Sets the date and time in fields to the current date and time.
*/
public void setCurrentTime() {
setDate(new Date());
}
/**
* Sets the current date of the DateTimeDialog and updates the gui
* components to reflect that.
* @param date the Date to set it to.
*/
public void setDate(Date newDate) {
calendar = new GregorianCalendar();
calendar.setTime(newDate);
// update gui components now
year.setValue(calendar.get(Calendar.YEAR));
month.select(calendar.get(Calendar.MONTH));
date.setValue(calendar.get(Calendar.DATE));
// Make sure the date is in the valid range for the given month
fixDateField();
hour.setValue(calendar.get(Calendar.HOUR_OF_DAY));
minute.setValue(calendar.get(Calendar.MINUTE));
second.setValue(calendar.get(Calendar.SECOND));
}
/**
* Set the time fields to midnight, i.e., clears them.
*/
private void setMidnight() {
hour.setValue(0);
minute.setValue(0);
second.setValue(0);
}
/**
* Make sure the date does not exceed the maximum allowable value
* for the currently selected month.
*/
private void fixDateField() {
int monthIndex = month.getSelectedIndex();
int max = MONTH_LEN[monthIndex];
date.setMaximum(calendar.isLeapYear(year.getValue()) &&
monthIndex == 1 ? max + 1 : max);
}
// * **********************************************
// I N N E R C L A S S E S F O L L O W
// ***********************************************
/**
* Listener for closing the dialog box through the window close
* menu.
*/
private class DCWindowListener extends WindowAdapter {
public void windowClosing(WindowEvent e) {
dateTimeDialogClose(false);
}
}
/**
* Listener for any change in the month selected through the
* pull down menu
*/
private class DCMonthChangeListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
fixDateField();
}
}
/**
* Listener for all the buttons. The listener is shared for the sake
* of reducing the number of overall listeners.
* TBD: I18N the help
*/
private class DCButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == ok) {
DateTimeDialog.this.dateTimeDialogClose(true);
}
else
if (e.getSource() == cancel) {
DateTimeDialog.this.dateTimeDialogClose(false);
}
else
if (e.getSource() == now) {
DateTimeDialog.this.setCurrentTime();
}
else
if (e.getSource() == midnight) {
DateTimeDialog.this.setMidnight();
}
else
if (e.getSource() == help) {
if (hd != null)
hd.show();
else {
hd = new
HelpDialog(DateTimeDialog.this.parent,
getString("Help for Date and Time Dialog"), false);
hd.setVisible(true);
hd.setText(getString(hrb, "DateTimeDialogHelp"));
}
}
} // actionPerformed
}
/**
* Listener for any change in focus with respect to the text
* fields. When a text field is going out of focus, it detemines if the
* text value in it is valid. If not, it returns focus to that text
* field.
*/
private class DCFocusListener extends FocusAdapter {
public void focusLost(FocusEvent e) {
if (!checkErrorAndSet((DCTextField)e.getSource()))
((DCTextField)e.getSource()).requestFocus();
}
}
/**
* The string representation of the dialog box.
* @return a String which contians the date and time in locale
* default format, but to MEDIUM length formatting style.
*/
public String toString() {
calendar = new GregorianCalendar(year.getValue(),
month.getSelectedIndex(),
date.getValue(),
hour.getValue(),
minute.getValue(),
second.getValue());
return df.format(calendar.getTime());
}
/**
* Call rb.getString(), but catch exception and return English
* key so that small spelling errors don't cripple the GUI
*
*/
private static final String getString(String key) {
return (getString(rb, key));
}
private static final String getString(ResourceBundle rb, String key) {
try {
String res = rb.getString(key);
return res;
} catch (MissingResourceException e) {
System.out.println("Missing resource "+key+", using English.");
return key;
}
}
/*
public static final void main(String args[]) {
Frame f = new Frame();
// while (true){
DateTimeDialog d = new DateTimeDialog(f, Color.white, Color.black);
d.setVisible(true);
System.out.println(d.toString());
// }
}
*/
}