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