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