View Javadoc

1   package org.apache.turbine.util;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.text.NumberFormat;
20  import java.util.Calendar;
21  import java.util.Date;
22  
23  import org.apache.ecs.ConcreteElement;
24  import org.apache.ecs.ElementContainer;
25  import org.apache.ecs.html.Comment;
26  import org.apache.ecs.html.Input;
27  import org.apache.ecs.html.Option;
28  import org.apache.ecs.html.Select;
29  
30  /***
31   * TimeSelector is a utility class to handle the creation of a set of
32   * time drop-down menus.  The code is broken into a set of static methods
33   * for quick and easy access to the individual select objects:
34   *
35   *  <pre>
36   *  ElementContainer ec timeSelect = new ElementContainer();
37   *  String myName = "mytime";
38   *  ec.addElement(TimeSelector.getHourSelector(myName));
39   *  ec.addElement(TimeSelector.getMinuteSelector(myName));
40   *  ec.addElement(TimeSelector.getAMPMSelector(myName));
41   *  </pre>
42   *
43   * There are also methods which will use attributes to build a
44   * complete time selector in the default 12hr format (eg HH:MM am/pm):
45   *
46   *  <pre>
47   *  TimeSelector ts = new TimeSelector(myName);
48   *  timeSelect = ts.ecsOutput();
49   *  </pre>
50   *
51   * Minutes/Seconds are by default rounded to the nearest 5 units
52   * although this can be easily changed.
53   *
54   * 24hr TimeSelectors can also be produced. The following example
55   * creates a full precision TimeSelector (eg HH:MM:SS):
56   *
57   *  <pre>
58   *  TimeSelector ts = new TimeSelector(myName);
59   *  ts.setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR);
60   *  ts.setMinuteInterval(1);
61   *  ts.setSecondInterval(1);
62   *  ts.setShowSeconds(true);
63   *  timeSelect = ts.toString();
64   *  </pre>
65   *
66   * @author <a href="mailto:ekkerbj@netscape.net">Jeffrey D. Brekke</a>
67   * @author <a href="mailto:rich@thenetrevolution.com">Rich Aston</a>
68   * @version $Id: TimeSelector.java 264148 2005-08-29 14:21:04Z henning $
69   */
70  public class TimeSelector
71  {
72      /*** Prefix for time names. */
73      public static final String DEFAULT_PREFIX = "TimeSelector";
74  
75      /*** Suffix for hour parameter. */
76      public static final String HOUR_SUFFIX = "_hour";
77  
78      /*** Suffix for minute parameter. */
79      public static final String MINUTE_SUFFIX = "_minute";
80  
81      /*** Suffix for second parameter. */
82      public static final String SECOND_SUFFIX = "_second";
83  
84      /*** Suffix for am/pm parameter. */
85      public static final String AMPM_SUFFIX = "_ampm";
86  
87      /*** Constant for 12hr format */
88      public static final int TWELVE_HOUR = 0;
89  
90      /*** Constant for 24hr format */
91      public static final int TWENTY_FOUR_HOUR = 1;
92  
93      /*** TODO: Add ability to specify Locale. */
94      private static final NumberFormat nbrFmt;
95  
96      private static final int DEFAULT_MINUTE_INTERVAL = 5;
97      private static final int DEFAULT_SECOND_INTERVAL = 5;
98      private static final int DEFAULT_TIME_FORMAT = TWELVE_HOUR;
99  
100     private int timeFormat = DEFAULT_TIME_FORMAT;
101     private int minuteInterval = DEFAULT_MINUTE_INTERVAL;
102     private int secondInterval = DEFAULT_SECOND_INTERVAL;
103 
104     private Calendar useDate = null;
105     private String selName = null;
106     private String onChange = null;
107     private boolean onChangeSet = false;
108     private boolean showSeconds = false;
109     private int setSeconds = 0;
110 
111     static
112     {
113         nbrFmt = NumberFormat.getInstance();
114         nbrFmt.setMinimumIntegerDigits(2);
115         nbrFmt.setMaximumIntegerDigits(2);
116     }
117 
118     /***
119      * Constructor defaults to current date/time and uses the default
120      * prefix: <pre>TimeSelector.DEFAULT</pre>
121      */
122     public TimeSelector()
123     {
124         this.selName = DEFAULT_PREFIX;
125         this.useDate = Calendar.getInstance();
126         this.useDate.setTime(new Date());
127     }
128 
129     /***
130      * Constructor, uses the date/time set in the calendar
131      * passed in (with the date/time set correctly).
132      *
133      * @param selName A String with the selector name.
134      * @param useDate A Calendar with a date/time.
135      */
136     public TimeSelector(String selName, Calendar useDate)
137     {
138         this.useDate = useDate;
139         this.selName = selName;
140     }
141 
142     /***
143      * Constructor defaults to current date/time.
144      *
145      * @param selName A String with the selector name.
146      */
147     public TimeSelector(String selName)
148     {
149         this.selName = selName;
150         this.useDate = Calendar.getInstance();
151         this.useDate.setTime(new Date());
152     }
153 
154     /***
155      * Adds the onChange to all of <code>&lt;SELECT&gt;</code> tags.
156      * This is limited to one function for all three popups and is only
157      * used when the output() methods are used.  Individual getHour,
158      * getMinute, getSecond, getAMPM static methods will not use this
159      * setting.
160      *
161      * @param onChange A String to use for onChange attribute.  If null,
162      * then nothing will be set.
163      * @return A TimeSelector (self).
164      */
165     public TimeSelector setOnChange(String onChange)
166     {
167         if (onChange != null)
168         {
169             this.onChange = onChange;
170             this.onChangeSet = true;
171         }
172         else
173         {
174             this.onChange = null;
175             this.onChangeSet = false;
176         }
177         return this;
178     }
179 
180     /***
181      * Select the second to be selected if the showSeconds(false) behavior
182      * is used.  Individual getHour, getMinute, getSecond, getAMPM
183      * static methods will not use this setting.
184      *
185      * @param seconds The second.
186      * @return A TimeSelector (self).
187      */
188     public TimeSelector setSeconds(int seconds)
189     {
190         this.setSeconds = seconds;
191         this.showSeconds = false;
192         return this;
193     }
194 
195     /***
196      * Set the interval between options in the minute select box.
197      * Individual getHour, getMinute, getSecond, getAMPM static methods
198      * will not use this setting.
199      *
200      * @param minutes Interval in minutes.
201      * @return A TimeSelector (self).
202      */
203     public TimeSelector setMinuteInterval(int minutes)
204     {
205         this.minuteInterval = minutes;
206         return this;
207     }
208 
209     /***
210      * Set the interval between options in the second select box.
211      * Individual getHour, getMinute, getSecond, getAMPM static methods
212      * will not use this setting.
213      *
214      * @param seconds Interval in seconds.
215      * @return A TimeSelector (self).
216      */
217     public TimeSelector setSecondInterval(int seconds)
218     {
219         this.secondInterval = seconds;
220         return this;
221     }
222 
223     /***
224      * Set the time format to 12 or 24 hour. Individual getHour,
225      * getMinute, getSecond, getAMPM static methods
226      * will not use this setting.
227      *
228      * @param format Time format.
229      * @return A TimeSelector (self).
230      */
231     public TimeSelector setTimeFormat(int format)
232     {
233         this.timeFormat = format;
234         return this;
235     }
236 
237     /***
238      * Whether or not to show the seconds as a popup menu.  The seconds will
239      * be a hidden parameter and the value set with setSeconds is used.
240      * Individual getHour, getMinute, getSecond, getAMPM static methods
241      * will not use this setting.
242      *
243      * @param show True if the second should be shown.
244      * @return A TimeSelector (self).
245      */
246     public TimeSelector setShowSeconds(boolean show)
247     {
248         this.showSeconds = show;
249         return this;
250     }
251 
252     /***
253      * Set the selector name prefix.  Individual getHour, getMinute,
254      * getSeconds, getAMPM static methods will not use this setting.
255      *
256      * @param selname A String with the select name prefix.
257      */
258     public void setSelName(String selName)
259     {
260         this.selName = selName;
261     }
262 
263     /***
264      * Get the selector name prefix.
265      *
266      * @return A String with the select name prefix.
267      */
268     public String getSelName()
269     {
270         return selName;
271     }
272 
273     /***
274      * Return a second selector.
275      *
276      * @param name The name to use for the selected second.
277      * @return A select object with second options.
278      */
279     public static Select getSecondSelector(String name)
280     {
281         return (getSecondSelector(name, Calendar.getInstance()));
282     }
283 
284     /***
285      * Return a second selector.
286      *
287      * @param name The name to use for the selected second.
288      * @param now Calendar to start with.
289      * @return A select object with second options.
290      */
291     public static Select getSecondSelector(String name, Calendar now)
292     {
293         return (getSecondSelector(name, Calendar.getInstance(),
294                 DEFAULT_SECOND_INTERVAL));
295     }
296 
297     /***
298      * Return a second selector.
299      *
300      * @param name The name to use for the selected second.
301      * @param now Calendar to start with.
302      * @param interval Interval between options.
303      * @return A select object with second options.
304      */
305     public static Select getSecondSelector(String name, Calendar now,
306                                            int interval)
307     {
308         Select secondSelect = new Select().setName(name);
309 
310         for (int currentSecond = 0; currentSecond <= 59; currentSecond += interval)
311         {
312             Option o = new Option();
313             o.addElement(nbrFmt.format(currentSecond));
314             o.setValue(currentSecond);
315             int nearestSecond =
316                     ((now.get(Calendar.SECOND) / interval) * interval);
317 
318             if (nearestSecond == currentSecond)
319             {
320                 o.setSelected(true);
321             }
322             secondSelect.addElement(o);
323         }
324         return (secondSelect);
325     }
326 
327     /***
328      * Return a minute selector.
329      *
330      * @param name The name to use for the selected minute.
331      * @return A select object with minute options.
332      */
333     public static Select getMinuteSelector(String name)
334     {
335         return (getMinuteSelector(name, Calendar.getInstance()));
336     }
337 
338     /***
339      * Return a minute selector.
340      *
341      * @param name The name to use for the selected minute.
342      * @return A select object with minute options.
343      */
344     public static Select getMinuteSelector(String name, Calendar now)
345     {
346         return (getMinuteSelector(name, now, DEFAULT_MINUTE_INTERVAL));
347     }
348 
349     /***
350      * Return a minute selector.
351      *
352      * @param name The name to use for the selected minute.
353      * @param now Calendar to start with.
354      * @param interval Interval between options.
355      * @return A select object with minute options.
356      */
357     public static Select getMinuteSelector(String name, Calendar now,
358                                            int interval)
359     {
360         Select minuteSelect = new Select().setName(name);
361 
362         for (int curMinute = 0; curMinute <= 59; curMinute += interval)
363         {
364             Option o = new Option();
365             o.addElement(nbrFmt.format(curMinute));
366             o.setValue(curMinute);
367             int nearestMinute =
368                     ((now.get(Calendar.MINUTE)) / interval) * interval;
369 
370             if (nearestMinute == curMinute)
371             {
372                 o.setSelected(true);
373             }
374             minuteSelect.addElement(o);
375         }
376         return (minuteSelect);
377     }
378 
379     /***
380      * Return an 12 hour selector.
381      *
382      * @param name The name to use for the selected hour.
383      * @return A select object with all the hours.
384      */
385     public static Select getHourSelector(String name)
386     {
387         return (getHourSelector(name, Calendar.getInstance()));
388     }
389 
390     /***
391      * Return an 12 hour selector.
392      *
393      * @param name The name to use for the selected hour.
394      * @param now Calendar to start with.
395      * @return A select object with all the hours.
396      */
397     public static Select getHourSelector(String name, Calendar now)
398     {
399         return (getHourSelector(name, Calendar.getInstance(), TWELVE_HOUR));
400     }
401 
402     /***
403      * Return an hour selector (either 12hr or 24hr depending on
404      * <code>format</code>.
405      *
406      * @param name The name to use for the selected hour.
407      * @param now Calendar to start with.
408      * @param format Time format.
409      * @return A select object with all the hours.
410      */
411     public static Select getHourSelector(String name, Calendar now, int format)
412     {
413         Select hourSelect = new Select().setName(name);
414 
415         if (format == TWENTY_FOUR_HOUR)
416         {
417             for (int currentHour = 0; currentHour <= 23; currentHour++)
418             {
419                 Option o = new Option();
420                 o.addElement(nbrFmt.format(currentHour));
421                 o.setValue(currentHour);
422                 if (now.get(Calendar.HOUR_OF_DAY) == currentHour)
423                 {
424                     o.setSelected(true);
425                 }
426                 hourSelect.addElement(o);
427             }
428         }
429         else
430         {
431             for (int curHour = 1; curHour <= 12; curHour++)
432             {
433                 Option o = new Option();
434 
435                 o.addElement(nbrFmt.format((long) curHour));
436                 o.setValue(curHour);
437                 if (now.get(Calendar.AM_PM) == Calendar.AM)
438                 {
439                     if (((now.get(Calendar.HOUR_OF_DAY)) == 0) &&
440                             (curHour == 12))
441                     {
442                         o.setSelected(true);
443                     }
444                     else
445                     {
446                         if (now.get(Calendar.HOUR_OF_DAY) == curHour)
447                         {
448                             o.setSelected(true);
449                         }
450                     }
451                 }
452                 else
453                 {
454                     if (((now.get(Calendar.HOUR_OF_DAY)) == 12) &&
455                             (curHour == 12))
456                     {
457                         o.setSelected(true);
458                     }
459                     else
460                     {
461                         if (now.get(Calendar.HOUR_OF_DAY) == curHour + 12)
462                         {
463                             o.setSelected(true);
464                         }
465                     }
466                 }
467                 hourSelect.addElement(o);
468             }
469         }
470         return (hourSelect);
471     }
472 
473     /***
474      * Return an am/pm selector.
475      *
476      * @param name The name to use for the selected am/pm.
477      * @return A select object with am/pm
478      */
479     public static Select getAMPMSelector(String name)
480     {
481         Calendar c = Calendar.getInstance();
482         c.setTime(new Date());
483         return (getAMPMSelector(name, c));
484     }
485 
486     /***
487      * Return an am/pm selector.
488      *
489      * @param name The name to use for the selected am/pm.
490      * @param now Calendar to start with.
491      * @return A select object with am/pm.
492      */
493     public static Select getAMPMSelector(String name,
494                                          Calendar now)
495     {
496         Select ampmSelect = new Select().setName(name);
497 
498         Option o = new Option();
499         o.addElement("am");
500         o.setValue(Calendar.AM);
501         if (now.get(Calendar.AM_PM) == Calendar.AM)
502         {
503             o.setSelected(true);
504         }
505         ampmSelect.addElement(o);
506 
507         o = new Option();
508         o.addElement("pm");
509         o.setValue(Calendar.PM);
510         if (now.get(Calendar.AM_PM) == Calendar.PM)
511         {
512             o.setSelected(true);
513         }
514         ampmSelect.addElement(o);
515 
516         return (ampmSelect);
517     }
518 
519     /***
520      * Used to build the popupmenu in HTML.  The properties set in the
521      * object are used to generate the correct HTML.  The selName
522      * attribute is used to seed the names of the select lists.  The
523      * names will be generated as follows:
524      *
525      * <ul>
526      *  <li>selName + "_hour"</li>
527      *  <li>selName + "_minute"</li>
528      *  <li>selName + "_ampm"</li>
529      * </ul>
530      *
531      * If onChange was set it is also used in the generation of the
532      * output.  The output HTML will list the select lists in the
533      * following order: hour minute ampm.
534      *
535      * If setShowSeconds(true) is used then an addition second select box
536      * is produced after the minute select box.
537      *
538      * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then
539      * the ampm select box is omitted.
540      *
541      * @return A String with the correct HTML for the date selector.
542      */
543     public String output()
544     {
545         return (ecsOutput().toString());
546     }
547 
548     /***
549      * Used to build the popupmenu in HTML.  The properties set in the
550      * object are used to generate the correct HTML.  The selName
551      * attribute is used to seed the names of the select lists.  The
552      * names will be generated as follows:
553      *
554      * <ul>
555      *  <li>selName + "_hour"</li>
556      *  <li>selName + "_minute"</li>
557      *  <li>selName + "_ampm"</li>
558      * </ul>
559      *
560      * If onChange was set it is also used in the generation of the
561      * output.  The output HTML will list the select lists in the
562      * following order: hour minute ampm.
563      *
564      * If setShowSeconds(true) is used then an addition second select box
565      * is produced after the minute select box.
566      *
567      * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then
568      * the ampm select box is omitted.
569      *
570      * @return A String with the correct HTML for the date selector.
571      */
572     public String toString()
573     {
574         return (ecsOutput().toString());
575     }
576 
577     /***
578      * Return an ECS container with the select objects inside.
579      *
580      * @return An ECS container.
581      */
582     public ElementContainer ecsOutput()
583     {
584         if (this.useDate == null)
585         {
586             this.useDate = Calendar.getInstance();
587             this.useDate.setTime(new Date());
588         }
589 
590         ConcreteElement secondSelect = null;
591 
592         Select ampmSelect = getAMPMSelector(selName + AMPM_SUFFIX, useDate);
593 
594         Select hourSelect = getHourSelector(selName + HOUR_SUFFIX,
595                 useDate, this.timeFormat);
596 
597         Select minuteSelect = getMinuteSelector(selName + MINUTE_SUFFIX,
598                 useDate, this.minuteInterval);
599 
600         if (this.showSeconds)
601         {
602             Select tmp = getSecondSelector(selName + SECOND_SUFFIX, useDate,
603                     this.secondInterval);
604             if (onChangeSet)
605                 tmp.setOnChange(onChange);
606             secondSelect = tmp;
607         }
608         else
609         {
610             secondSelect = new Input(Input.hidden,
611                     selName + SECOND_SUFFIX,
612                     setSeconds);
613         }
614 
615         if (onChangeSet)
616         {
617             hourSelect.setOnChange(onChange);
618             minuteSelect.setOnChange(onChange);
619             ampmSelect.setOnChange(onChange);
620         }
621 
622         ElementContainer ec = new ElementContainer();
623         ec.addElement(new Comment(
624                 "== BEGIN org.apache.turbine.util.TimeSelector.ecsOutput() =="));
625         ec.addElement(hourSelect);
626         ec.addElement(":");
627         ec.addElement(minuteSelect);
628         if (this.showSeconds == true)
629             ec.addElement(":");
630         ec.addElement(secondSelect);
631         if (this.timeFormat == TimeSelector.TWELVE_HOUR)
632         {
633             ec.addElement(ampmSelect);
634         }
635         ec.addElement(new Comment(
636                 "== END org.apache.turbine.util.TimeSelector.ecsOutput() =="));
637         return (ec);
638     }
639 }