xref: /titanic_44/usr/src/cmd/krb5/kadmin/gui/dchanger/DateTimeDialog.java (revision fd435bccec40cb841f712413108d8577422fd9ab)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 import java.awt.*;
28 import java.awt.event.*;
29 import java.text.*;
30 import java.util.*;
31 
32 /**
33  * This class creates a dialog box that helps the user enter date and
34  * time with mouse clicks.  The dialog box need only be created
35  * once. The Ok and Cancel buttons merely call setVisible with an
36  *  argument of false.
37  */
38 
39 // The layout will consist of 3 panels: topPanel contains the
40 // different labels and fields. middlePanel contains the buttons
41 // midnight and now. bottomPanel contains the buttons ok, cancel and
42 // help. The last two panels are separated by a LineSeparator.
43 
44 public class DateTimeDialog extends Dialog {
45 
46     private boolean save;
47 
48     private Frame parent;
49 
50     private DCPanel dateDCPanel;
51     private DCPanel yearDCPanel;
52     private DCPanel hourDCPanel;
53     private DCPanel minuteDCPanel;
54     private DCPanel secondDCPanel;
55 
56     private Choice month;
57 
58     private DCCircularTextField date;
59     private DCCircularTextField hour;
60     private DCCircularTextField second;
61     private DCCircularTextField minute;
62     private DCTextField year;
63 
64     private Button ok;
65     private Button cancel;
66     private Button help;
67     private Button now;
68     private Button midnight;
69 
70     private HelpDialog hd = null;
71 
72     private Panel topPanel;
73     private Panel middlePanel;
74     private Panel bottomPanel;
75 
76     private GregorianCalendar calendar = null;
77     private static int MONTH_LEN[] = {31, 28, 31, 30, 31, 30, 31,
78 				    31, 30, 31, 30, 31};
79     private static DateFormat df =
80     DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
81 				 DateFormat.MEDIUM);
82     private static Toolkit toolkit = Toolkit.getDefaultToolkit();
83 
84   // For I18N
85     private static ResourceBundle rb =
86     ResourceBundle.getBundle("GuiResource" /* NOI18N */);
87     private static ResourceBundle hrb =
88     ResourceBundle.getBundle("HelpData" /* NOI18N */);
89 
90     /**
91      * Constructor that lays out the componeents and sets the different
92      * event handlers.
93      */
94     public DateTimeDialog(Frame parent, Color background, Color foreground) {
95     super(parent, getString("SEAM Date/Time Helper"), true);
96 
97     this.parent = parent;
98 
99     setLayout(new GridBagLayout());
100     addLabels();
101     addFields(background, foreground);
102     addDCPanels();
103     addButtons();
104     addFocusListeners();
105     setCurrentTime();
106     setSize(250, 300);
107     setResizable(false);
108 
109     addWindowListener(new DCWindowListener());
110     //	    initializeFocusOnTextField();
111     }
112 
113     /**
114      * Adds the labels only
115      */
116     private void addLabels() {
117 
118     GridBagConstraints gbc = new GridBagConstraints();
119     gbc.weighty = 1;
120 
121     topPanel = new Panel();
122     topPanel.setLayout(new GridBagLayout());
123     gbc.gridwidth = GridBagConstraints.REMAINDER;
124     gbc.fill = GridBagConstraints.BOTH;
125     gbc.anchor = GridBagConstraints.CENTER;
126     gbc.gridx = 0;
127     gbc.gridy = 0;
128     add(topPanel, gbc);
129 
130     gbc.fill = GridBagConstraints.NONE;
131     gbc.anchor = GridBagConstraints.EAST;
132     gbc.gridx = 0;
133     gbc.gridwidth = 1;
134 
135     gbc.gridy = 0;
136     topPanel.add(new Label(getString("Month")), gbc);
137 
138     gbc.gridy = 1;
139     topPanel.add(new Label(getString("Date")), gbc);
140 
141     gbc.gridy = 2;
142     topPanel.add(new Label(getString("Year")), gbc);
143 
144     gbc.gridy = 3;
145     topPanel.add(new Label(getString("Hour")), gbc);
146 
147     gbc.gridy = 4;
148     topPanel.add(new Label(getString("Minute")), gbc);
149 
150     gbc.gridy = 5;
151     topPanel.add(new Label(getString("Second")), gbc);
152     }
153 
154     /**
155      * Adds the fields that will store the month, year, date, hour,
156      * minute and second.
157      */
158     private void addFields(Color background, Color foreground) {
159 
160     GridBagConstraints gbc = new GridBagConstraints();
161     gbc.weighty = 1;
162 
163     month = new Choice();
164     initializeMonth();
165 
166     date = new DCCircularTextField("1", 2);
167     date.setMinimum(1);
168     date.setBackground(background);
169     date.setForeground(foreground);
170 
171     hour = new DCCircularTextField("00", 2);
172     hour.setMaximum(23);
173     hour.setBackground(background);
174     hour.setForeground(foreground);
175     minute = new DCCircularTextField("00", 2);
176     minute.setBackground(background);
177     minute.setForeground(foreground);
178     second = new DCCircularTextField("00", 2);
179     second.setBackground(background);
180     second.setForeground(foreground);
181 
182     year  = new DCTextField("2000", 4);
183     year.setBackground(background);
184     year.setForeground(foreground);
185 
186     Panel tempPanel = new Panel();
187     tempPanel.add(month);
188     gbc.gridwidth = GridBagConstraints.REMAINDER;
189     gbc.fill = GridBagConstraints.HORIZONTAL;
190     gbc.anchor = GridBagConstraints.WEST;
191     gbc.gridx = 1;
192     gbc.gridy = 0;
193     topPanel.add(tempPanel, gbc);
194 
195 
196     // Remaining fields are in topPanel
197     gbc.gridwidth = 1;
198     gbc.fill = GridBagConstraints.NONE;
199     gbc.gridx = 1;
200 
201     gbc.gridy = 1;
202     topPanel.add(date, gbc);
203 
204     gbc.gridy = 2;
205     topPanel.add(year, gbc);
206 
207     gbc.gridy = 3;
208     topPanel.add(hour, gbc);
209 
210     gbc.gridy = 4;
211     topPanel.add(minute, gbc);
212 
213     gbc.gridy = 5;
214     topPanel.add(second, gbc);
215 
216     }
217 
218   // Adds the panels with the +/- buttons for each DCField
219     private void addDCPanels() {
220 
221     GridBagConstraints gbc = new GridBagConstraints();
222     gbc.weighty = 1;
223 
224     gbc.gridx = 2;
225     gbc.gridwidth = GridBagConstraints.REMAINDER;
226     gbc.gridheight = 1;
227     gbc.fill = GridBagConstraints.NONE;
228 
229     dateDCPanel = new DCPanel();
230     yearDCPanel = new DCPanel();
231     hourDCPanel = new DCPanel();
232     minuteDCPanel = new DCPanel();
233     secondDCPanel = new DCPanel();
234 
235     gbc.gridy = 1;
236     topPanel.add(dateDCPanel, gbc);
237 
238     gbc.gridy = GridBagConstraints.RELATIVE;
239     topPanel.add(yearDCPanel, gbc);
240     topPanel.add(hourDCPanel, gbc);
241     topPanel.add(minuteDCPanel, gbc);
242     topPanel.add(secondDCPanel, gbc);
243 
244     dateDCPanel.setListener(date);
245     yearDCPanel.setListener(year);
246     hourDCPanel.setListener(hour);
247     minuteDCPanel.setListener(minute);
248     secondDCPanel.setListener(second);
249 
250     }
251 
252 
253     /**
254      * Sets the strings in the month pull-down menu. Also adds a listener
255      * that will modify the maximum date allowed depending on the month.
256      */
257     private void initializeMonth() {
258     DateFormatSymbols dfSymbols = new DateFormatSymbols();
259     String[] monthStrings = dfSymbols.getMonths();
260 
261 	month.removeAll();
262 
263 	for (int i = 0; i < monthStrings.length; i++) {
264 	month.add(monthStrings[i]);
265 	}
266 
267 	month.addItemListener(new DCMonthChangeListener());
268     }
269 
270   // Adds all the buttons
271     private void addButtons() {
272 
273 	GridBagConstraints gbc = new GridBagConstraints();
274 	gbc.weighty = 1;
275 
276 
277 	middlePanel = new Panel();
278 	now  = new Button(getString("Now"));
279 	midnight	= new Button(getString("Midnight"));
280 	middlePanel.add(midnight);
281 	middlePanel.add(now);
282 	gbc.fill = GridBagConstraints.HORIZONTAL;
283 	gbc.gridwidth = GridBagConstraints.REMAINDER;
284 	gbc.gridx = 0;
285 	gbc.gridy = 1;
286 	add(middlePanel, gbc);
287 
288 	gbc.gridwidth = GridBagConstraints.REMAINDER;
289 	gbc.gridheight = 1;
290 	gbc.fill = GridBagConstraints.BOTH;
291 	gbc.gridx = 0;
292 	gbc.gridy = 2;
293 	add(new LineSeparator(), gbc);
294 
295 	bottomPanel = new Panel();
296 	ok = new Button(getString("OK"));
297 	cancel =	new Button(getString("Cancel"));
298 	help = new Button(getString("Help"));
299 	bottomPanel.add(ok);
300 	bottomPanel.add(cancel);
301 	bottomPanel.add(help);
302 	gbc.fill = GridBagConstraints.HORIZONTAL;
303 	gbc.gridwidth = GridBagConstraints.REMAINDER;
304 	gbc.gridx = 0;
305 	gbc.gridy = 3;
306 	add(bottomPanel, gbc);
307 
308 	DCButtonListener bl = new DCButtonListener();
309 	ok.addActionListener(bl);
310 	cancel.addActionListener(bl);
311 	help.addActionListener(bl);
312 	now.addActionListener(bl);
313 	midnight.addActionListener(bl);
314 
315     }
316 
317     /**
318      * Adds a listener to all the text fields so that when they go out
319      * of focus (by tab or clicking), their values are checked for
320      * errors.
321      */
322     private void addFocusListeners() {
323     FocusListener fl = new DCFocusListener();
324     date.addFocusListener(fl);
325     year.addFocusListener(fl);
326     hour.addFocusListener(fl);
327     minute.addFocusListener(fl);
328     second.addFocusListener(fl);
329     }
330 
331     /**
332      * Closes (hides) the dialog box when the user is done
333      * @param save true if the box is being dismissed by clicking on
334      * "ok" and the user wants to retain the modified value, false
335      * otherwise.
336      */
337     private void dateTimeDialogClose(boolean save) {
338 	if (save == true) {
339 	if (!updateFromGui())
340 	   return;
341     }
342     this.save = save;
343     setVisible(false);
344     }
345 
346     /**
347      * Checks to see is all text fields contain valid values.
348      * @return true if all are valid, false otherwise.
349      */
350     private boolean updateFromGui() {
351 	return (checkErrorAndSet(date) && checkErrorAndSet(year) &&
352 		checkErrorAndSet(hour) && checkErrorAndSet(minute) &&
353 		checkErrorAndSet(second));
354     }
355 
356     /**
357      * Checks the value stored as text in the field and sets its numeric
358      * value to that if it is legitimate.
359      * @return true if the value was legitimate and got set, false
360      * otherwise.
361      */
362     private boolean checkErrorAndSet(DCTextField tf) {
363 	int i = 0;
364 	boolean errorState = false;
365 	try {
366 	i = new Integer(tf.getText().trim()).intValue();
367 	errorState = !tf.checkValue(i);
368 	} catch (NumberFormatException e2) {
369 	errorState =  true;
370 	}
371 	if (errorState) {
372 	tf.selectAll();
373 	toolkit.beep();
374 	}
375 	else
376 	tf.setValue(i);
377 	return !errorState;
378     }
379 
380     /**
381      * Checks if the user requested that the value in this
382      * DateTimeDialog be used e.g., by clicking on "Ok" instead of
383      * "Cancel."
384      * @return true if the user wants to save the value in the
385      * DateTimeDialog, false otherwise.
386      */
387 
388     public boolean isSaved() {
389 	return save;
390     }
391 
392     /**
393      * Sets the date and time in fields to the current date and time.
394      */
395     public void setCurrentTime() {
396 	setDate(new Date());
397     }
398 
399     /**
400      * Sets the current date of the DateTimeDialog and updates the gui
401      *	 components to reflect that.
402      * @param date the Date to set it to.
403      */
404     public void setDate(Date newDate) {
405 	calendar = new GregorianCalendar();
406 	calendar.setTime(newDate);
407 
408     // update gui components now
409 
410     year.setValue(calendar.get(Calendar.YEAR));
411     month.select(calendar.get(Calendar.MONTH));
412     date.setValue(calendar.get(Calendar.DATE));
413 
414     // Make sure the date is in the valid range for the given month
415     fixDateField();
416 
417     hour.setValue(calendar.get(Calendar.HOUR_OF_DAY));
418     minute.setValue(calendar.get(Calendar.MINUTE));
419     second.setValue(calendar.get(Calendar.SECOND));
420 
421     }
422 
423     /**
424      * Set the time fields to midnight, i.e., clears them.
425      */
426     private void setMidnight() {
427 	    hour.setValue(0);
428 	    minute.setValue(0);
429 	    second.setValue(0);
430     }
431 
432     /**
433      * Make sure the date does not exceed the maximum allowable value
434      * for the currently selected month.
435      */
436     private void fixDateField() {
437 	int monthIndex = month.getSelectedIndex();
438 	int max = MONTH_LEN[monthIndex];
439 	date.setMaximum(calendar.isLeapYear(year.getValue()) &&
440 		monthIndex == 1 ? max + 1 : max);
441     }
442 
443   // * **********************************************
444   //	 I N N E R    C L A S S E S   F O L L O W
445   // ***********************************************
446 
447     /**
448      * Listener for closing the dialog box through the window close
449      * menu.
450      */
451     private class DCWindowListener extends WindowAdapter {
452     public  void windowClosing(WindowEvent e) {
453 	dateTimeDialogClose(false);
454 	}
455     }
456 
457     /**
458      * Listener for any change in the month selected through the
459      * pull down menu
460      */
461     private class DCMonthChangeListener implements ItemListener {
462     public void itemStateChanged(ItemEvent e) {
463 	fixDateField();
464     }
465     }
466 
467     /**
468      * Listener for all the buttons. The listener is shared for the sake
469      * of reducing the number of overall listeners.
470      * TBD: I18N the help
471      */
472     private class DCButtonListener implements ActionListener {
473     public void actionPerformed(ActionEvent e) {
474 	if (e.getSource() == ok) {
475 	DateTimeDialog.this.dateTimeDialogClose(true);
476 	}
477 	else
478 	if (e.getSource() == cancel) {
479 	  DateTimeDialog.this.dateTimeDialogClose(false);
480 	}
481 	else
482 	  if (e.getSource() == now) {
483 	    DateTimeDialog.this.setCurrentTime();
484 	  }
485 	  else
486 	    if (e.getSource() == midnight) {
487 		DateTimeDialog.this.setMidnight();
488 	    }
489 	    else
490 		if (e.getSource() == help) {
491 		    if (hd != null)
492 			hd.setVisible(true);
493 		else {
494 		    hd = new
495 		    HelpDialog(DateTimeDialog.this.parent,
496 			getString("Help for Date and Time Dialog"), false);
497 		    hd.setVisible(true);
498 		    hd.setText(getString(hrb, "DateTimeDialogHelp"));
499 		}
500 	    }
501 	} // actionPerformed
502     }
503 
504     /**
505      * Listener for any change in focus with respect to the text
506      * fields. When a text field is going out of focus, it detemines if the
507      * text value in it is valid. If not, it returns focus to that text
508      * field.
509      */
510     private class DCFocusListener extends FocusAdapter {
511 
512 	public void focusLost(FocusEvent e) {
513 	if (!checkErrorAndSet((DCTextField)e.getSource()))
514 	  ((DCTextField)e.getSource()).requestFocus();
515 	}
516     }
517 
518     /**
519      * The string representation of the dialog box.
520      * @return a String which contians the date and time in locale
521      * default format, but to MEDIUM length formatting style.
522      */
523     public String toString() {
524 	calendar = new GregorianCalendar(year.getValue(),
525 					month.getSelectedIndex(),
526 					date.getValue(),
527 					hour.getValue(),
528 					minute.getValue(),
529 					second.getValue());
530 	return df.format(calendar.getTime());
531     }
532 
533     /**
534      * Call rb.getString(), but catch exception and return English
535      * key so that small spelling errors don't cripple the GUI
536      *
537      */
538     private static final String getString(String key) {
539     return (getString(rb, key));
540     }
541 
542     private static final String getString(ResourceBundle rb, String key) {
543     try {
544 	String res = rb.getString(key);
545 	return res;
546     } catch (MissingResourceException e) {
547 	System.out.println("Missing resource "+key+", using English.");
548 	return key;
549 	}
550     }
551 
552     /* BEGIN JSTYLED */
553     /*
554     public static final void main(String args[]) {
555     Frame f = new Frame();
556     //	while (true){
557 	DateTimeDialog d = new DateTimeDialog(f, Color.white, Color.black);
558 	d.setVisible(true);
559 	System.out.println(d.toString());
560       //    }
561     }
562     */
563     /* END JSTYLED */
564 }
565