1 package org.apache.turbine.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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><SELECT></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 }