001 package org.apache.turbine.util; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import java.text.NumberFormat; 023 import java.util.Calendar; 024 import java.util.Date; 025 026 import org.apache.ecs.ConcreteElement; 027 import org.apache.ecs.ElementContainer; 028 import org.apache.ecs.html.Comment; 029 import org.apache.ecs.html.Input; 030 import org.apache.ecs.html.Option; 031 import org.apache.ecs.html.Select; 032 033 /** 034 * TimeSelector is a utility class to handle the creation of a set of 035 * time drop-down menus. The code is broken into a set of static methods 036 * for quick and easy access to the individual select objects: 037 * 038 * <pre> 039 * ElementContainer ec timeSelect = new ElementContainer(); 040 * String myName = "mytime"; 041 * ec.addElement(TimeSelector.getHourSelector(myName)); 042 * ec.addElement(TimeSelector.getMinuteSelector(myName)); 043 * ec.addElement(TimeSelector.getAMPMSelector(myName)); 044 * </pre> 045 * 046 * There are also methods which will use attributes to build a 047 * complete time selector in the default 12hr format (eg HH:MM am/pm): 048 * 049 * <pre> 050 * TimeSelector ts = new TimeSelector(myName); 051 * timeSelect = ts.ecsOutput(); 052 * </pre> 053 * 054 * Minutes/Seconds are by default rounded to the nearest 5 units 055 * although this can be easily changed. 056 * 057 * 24hr TimeSelectors can also be produced. The following example 058 * creates a full precision TimeSelector (eg HH:MM:SS): 059 * 060 * <pre> 061 * TimeSelector ts = new TimeSelector(myName); 062 * ts.setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR); 063 * ts.setMinuteInterval(1); 064 * ts.setSecondInterval(1); 065 * ts.setShowSeconds(true); 066 * timeSelect = ts.toString(); 067 * </pre> 068 * 069 * @author <a href="mailto:ekkerbj@netscape.net">Jeffrey D. Brekke</a> 070 * @author <a href="mailto:rich@thenetrevolution.com">Rich Aston</a> 071 * @version $Id: TimeSelector.java 1078552 2011-03-06 19:58:46Z tv $ 072 */ 073 public class TimeSelector 074 { 075 /** Prefix for time names. */ 076 public static final String DEFAULT_PREFIX = "TimeSelector"; 077 078 /** Suffix for hour parameter. */ 079 public static final String HOUR_SUFFIX = "_hour"; 080 081 /** Suffix for minute parameter. */ 082 public static final String MINUTE_SUFFIX = "_minute"; 083 084 /** Suffix for second parameter. */ 085 public static final String SECOND_SUFFIX = "_second"; 086 087 /** Suffix for am/pm parameter. */ 088 public static final String AMPM_SUFFIX = "_ampm"; 089 090 /** Constant for 12hr format */ 091 public static final int TWELVE_HOUR = 0; 092 093 /** Constant for 24hr format */ 094 public static final int TWENTY_FOUR_HOUR = 1; 095 096 /** TODO: Add ability to specify Locale. */ 097 private static final NumberFormat nbrFmt; 098 099 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 @SuppressWarnings("cast") 415 public static Select getHourSelector(String name, Calendar now, int format) 416 { 417 Select hourSelect = new Select().setName(name); 418 419 if (format == TWENTY_FOUR_HOUR) 420 { 421 for (int currentHour = 0; currentHour <= 23; currentHour++) 422 { 423 Option o = new Option(); 424 o.addElement(nbrFmt.format(currentHour)); 425 o.setValue(currentHour); 426 if (now.get(Calendar.HOUR_OF_DAY) == currentHour) 427 { 428 o.setSelected(true); 429 } 430 hourSelect.addElement(o); 431 } 432 } 433 else 434 { 435 for (int curHour = 1; curHour <= 12; curHour++) 436 { 437 Option o = new Option(); 438 439 o.addElement(nbrFmt.format((long) curHour)); 440 o.setValue(curHour); 441 if (now.get(Calendar.AM_PM) == Calendar.AM) 442 { 443 if (((now.get(Calendar.HOUR_OF_DAY)) == 0) && 444 (curHour == 12)) 445 { 446 o.setSelected(true); 447 } 448 else 449 { 450 if (now.get(Calendar.HOUR_OF_DAY) == curHour) 451 { 452 o.setSelected(true); 453 } 454 } 455 } 456 else 457 { 458 if (((now.get(Calendar.HOUR_OF_DAY)) == 12) && 459 (curHour == 12)) 460 { 461 o.setSelected(true); 462 } 463 else 464 { 465 if (now.get(Calendar.HOUR_OF_DAY) == curHour + 12) 466 { 467 o.setSelected(true); 468 } 469 } 470 } 471 hourSelect.addElement(o); 472 } 473 } 474 return (hourSelect); 475 } 476 477 /** 478 * Return an am/pm selector. 479 * 480 * @param name The name to use for the selected am/pm. 481 * @return A select object with am/pm 482 */ 483 public static Select getAMPMSelector(String name) 484 { 485 Calendar c = Calendar.getInstance(); 486 c.setTime(new Date()); 487 return (getAMPMSelector(name, c)); 488 } 489 490 /** 491 * Return an am/pm selector. 492 * 493 * @param name The name to use for the selected am/pm. 494 * @param now Calendar to start with. 495 * @return A select object with am/pm. 496 */ 497 public static Select getAMPMSelector(String name, 498 Calendar now) 499 { 500 Select ampmSelect = new Select().setName(name); 501 502 Option o = new Option(); 503 o.addElement("am"); 504 o.setValue(Calendar.AM); 505 if (now.get(Calendar.AM_PM) == Calendar.AM) 506 { 507 o.setSelected(true); 508 } 509 ampmSelect.addElement(o); 510 511 o = new Option(); 512 o.addElement("pm"); 513 o.setValue(Calendar.PM); 514 if (now.get(Calendar.AM_PM) == Calendar.PM) 515 { 516 o.setSelected(true); 517 } 518 ampmSelect.addElement(o); 519 520 return (ampmSelect); 521 } 522 523 /** 524 * Used to build the popupmenu in HTML. The properties set in the 525 * object are used to generate the correct HTML. The selName 526 * attribute is used to seed the names of the select lists. The 527 * names will be generated as follows: 528 * 529 * <ul> 530 * <li>selName + "_hour"</li> 531 * <li>selName + "_minute"</li> 532 * <li>selName + "_ampm"</li> 533 * </ul> 534 * 535 * If onChange was set it is also used in the generation of the 536 * output. The output HTML will list the select lists in the 537 * following order: hour minute ampm. 538 * 539 * If setShowSeconds(true) is used then an addition second select box 540 * is produced after the minute select box. 541 * 542 * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then 543 * the ampm select box is omitted. 544 * 545 * @return A String with the correct HTML for the date selector. 546 */ 547 public String output() 548 { 549 return (ecsOutput().toString()); 550 } 551 552 /** 553 * Used to build the popupmenu in HTML. The properties set in the 554 * object are used to generate the correct HTML. The selName 555 * attribute is used to seed the names of the select lists. The 556 * names will be generated as follows: 557 * 558 * <ul> 559 * <li>selName + "_hour"</li> 560 * <li>selName + "_minute"</li> 561 * <li>selName + "_ampm"</li> 562 * </ul> 563 * 564 * If onChange was set it is also used in the generation of the 565 * output. The output HTML will list the select lists in the 566 * following order: hour minute ampm. 567 * 568 * If setShowSeconds(true) is used then an addition second select box 569 * is produced after the minute select box. 570 * 571 * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then 572 * the ampm select box is omitted. 573 * 574 * @return A String with the correct HTML for the date selector. 575 */ 576 @Override 577 public String toString() 578 { 579 return (ecsOutput().toString()); 580 } 581 582 /** 583 * Return an ECS container with the select objects inside. 584 * 585 * @return An ECS container. 586 */ 587 public ElementContainer ecsOutput() 588 { 589 if (this.useDate == null) 590 { 591 this.useDate = Calendar.getInstance(); 592 this.useDate.setTime(new Date()); 593 } 594 595 ConcreteElement secondSelect = null; 596 597 Select ampmSelect = getAMPMSelector(selName + AMPM_SUFFIX, useDate); 598 599 Select hourSelect = getHourSelector(selName + HOUR_SUFFIX, 600 useDate, this.timeFormat); 601 602 Select minuteSelect = getMinuteSelector(selName + MINUTE_SUFFIX, 603 useDate, this.minuteInterval); 604 605 if (this.showSeconds) 606 { 607 Select tmp = getSecondSelector(selName + SECOND_SUFFIX, useDate, 608 this.secondInterval); 609 if (onChangeSet) 610 tmp.setOnChange(onChange); 611 secondSelect = tmp; 612 } 613 else 614 { 615 secondSelect = new Input(Input.hidden, 616 selName + SECOND_SUFFIX, 617 setSeconds); 618 } 619 620 if (onChangeSet) 621 { 622 hourSelect.setOnChange(onChange); 623 minuteSelect.setOnChange(onChange); 624 ampmSelect.setOnChange(onChange); 625 } 626 627 ElementContainer ec = new ElementContainer(); 628 ec.addElement(new Comment( 629 "== BEGIN org.apache.turbine.util.TimeSelector.ecsOutput() ==")); 630 ec.addElement(hourSelect); 631 ec.addElement(":"); 632 ec.addElement(minuteSelect); 633 if (this.showSeconds == true) 634 ec.addElement(":"); 635 ec.addElement(secondSelect); 636 if (this.timeFormat == TimeSelector.TWELVE_HOUR) 637 { 638 ec.addElement(ampmSelect); 639 } 640 ec.addElement(new Comment( 641 "== END org.apache.turbine.util.TimeSelector.ecsOutput() ==")); 642 return (ec); 643 } 644 }