001/* 002 * $Id: JCalendar.java,v 1.2 2011/03/24 16:06:33 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031package edu.wisc.ssec.mcidasv.data.dateChooser; 032 033import java.awt.BorderLayout; 034import java.awt.Color; 035import java.awt.Font; 036import java.beans.PropertyChangeEvent; 037import java.beans.PropertyChangeListener; 038import java.util.Calendar; 039import java.util.Date; 040import java.util.Locale; 041 042import javax.swing.BorderFactory; 043import javax.swing.JFrame; 044import javax.swing.JPanel; 045 046/** 047 * JCalendar is a bean for entering a date by choosing the year, month and day. 048 * 049 * @author Kai Toedter 050 * @version $LastChangedRevision: 95 $ 051 * @version $LastChangedDate: 2006-05-05 18:43:15 +0200 (Fr, 05 Mai 2006) $ 052 */ 053public class JCalendar extends JPanel implements PropertyChangeListener { 054 private static final long serialVersionUID = 8913369762644440133L; 055 056 private Calendar calendar; 057 058 /** the day chooser */ 059 protected JDayChooser dayChooser; 060 private boolean initialized = false; 061 062 /** indicates if weeks of year shall be visible */ 063 protected boolean weekOfYearVisible = true; 064 065 /** the locale */ 066 protected Locale locale; 067 068 /** the month chooser */ 069 protected JMonthChooser monthChooser; 070 071 private JPanel monthYearPanel; 072 073 /** the year chhoser */ 074 protected JYearChooser yearChooser; 075 076 protected Date minSelectableDate; 077 078 protected Date maxSelectableDate; 079 080 /** 081 * Default JCalendar constructor. 082 */ 083 public JCalendar() { 084 this(null, null, true, true); 085 } 086 087 /** 088 * JCalendar constructor which allows the initial date to be set. 089 * 090 * @param date 091 * the date 092 */ 093 public JCalendar(Date date) { 094 this(date, null, true, true); 095 } 096 097 /** 098 * JCalendar constructor which allows the initial calendar to be set. 099 * 100 * @param calendar 101 * the calendar 102 */ 103 public JCalendar(Calendar calendar) { 104 this(null, null, true, true); 105 setCalendar(calendar); 106 } 107 108 /** 109 * JCalendar constructor allowing the initial locale to be set. 110 * 111 * @param locale 112 * the new locale 113 */ 114 public JCalendar(Locale locale) { 115 this(null, locale, true, true); 116 } 117 118 /** 119 * JCalendar constructor specifying both the initial date and locale. 120 * 121 * @param date 122 * the date 123 * @param locale 124 * the new locale 125 */ 126 public JCalendar(Date date, Locale locale) { 127 this(date, locale, true, true); 128 } 129 130 /** 131 * JCalendar constructor specifying both the initial date and the month 132 * spinner type. 133 * 134 * @param date 135 * the date 136 * @param monthSpinner 137 * false, if no month spinner should be used 138 */ 139 public JCalendar(Date date, boolean monthSpinner) { 140 this(date, null, monthSpinner, true); 141 } 142 143 /** 144 * JCalendar constructor specifying both the locale and the month spinner. 145 * 146 * @param locale 147 * the locale 148 * @param monthSpinner 149 * false, if no month spinner should be used 150 */ 151 public JCalendar(Locale locale, boolean monthSpinner) { 152 this(null, locale, monthSpinner, true); 153 } 154 155 /** 156 * JCalendar constructor specifying the month spinner type. 157 * 158 * @param monthSpinner 159 * false, if no month spinner should be used 160 */ 161 public JCalendar(boolean monthSpinner) { 162 this(null, null, monthSpinner, true); 163 } 164 165 /** 166 * JCalendar constructor with month spinner parameter. 167 * 168 * @param date 169 * the date 170 * @param locale 171 * the locale 172 * @param monthSpinner 173 * false, if no month spinner should be used 174 * @param weekOfYearVisible 175 * true, if weeks of year shall be visible 176 */ 177 public JCalendar(Date date, Locale locale, boolean monthSpinner, boolean weekOfYearVisible) { 178 179 setName("JCalendar"); 180 181 // needed for setFont() etc. 182 dayChooser = null; 183 monthChooser = null; 184 yearChooser = null; 185 this.weekOfYearVisible = weekOfYearVisible; 186 187 this.locale = locale; 188 189 if (locale == null) { 190 this.locale = Locale.getDefault(); 191 } 192 193 calendar = Calendar.getInstance(); 194 195 setLayout(new BorderLayout()); 196 197 monthYearPanel = new JPanel(); 198 monthYearPanel.setLayout(new BorderLayout()); 199 200 monthChooser = new JMonthChooser(monthSpinner); 201 yearChooser = new JYearChooser(); 202 monthChooser.setYearChooser(yearChooser); 203 monthYearPanel.add(monthChooser, BorderLayout.WEST); 204 monthYearPanel.add(yearChooser, BorderLayout.CENTER); 205 monthYearPanel.setBorder(BorderFactory.createEmptyBorder()); 206 207 dayChooser = new JDayChooser(weekOfYearVisible); 208 dayChooser.addPropertyChangeListener(this); 209 monthChooser.setDayChooser(dayChooser); 210 monthChooser.addPropertyChangeListener(this); 211 yearChooser.setDayChooser(dayChooser); 212 yearChooser.addPropertyChangeListener(this); 213 add(monthYearPanel, BorderLayout.NORTH); 214 add(dayChooser, BorderLayout.CENTER); 215 216 // Set the initialized flag before setting the calendar. This will 217 // cause the other components to be updated properly. 218 if (date != null) { 219 calendar.setTime(date); 220 } 221 222 initialized = true; 223 224 setCalendar(calendar); 225 } 226 227 /** 228 * Creates a JFrame with a JCalendar inside and can be used for testing. 229 * 230 * @param s 231 * The command line arguments 232 */ 233 public static void main(String[] s) { 234 JFrame frame = new JFrame("JCalendar"); 235 236 JCalendar jcalendar = new JCalendar(); 237 frame.getContentPane().add(jcalendar); 238 frame.pack(); 239 frame.setVisible(true); 240 } 241 242 /** 243 * Returns the calendar property. 244 * 245 * @return the value of the calendar property. 246 */ 247 public Calendar getCalendar() { 248 return calendar; 249 } 250 251 /** 252 * Gets the dayChooser attribute of the JCalendar object 253 * 254 * @return the dayChooser value 255 */ 256 public JDayChooser getDayChooser() { 257 return dayChooser; 258 } 259 260 /** 261 * Returns the locale. 262 * 263 * @return the value of the locale property. 264 * 265 * @see #setLocale 266 */ 267 public Locale getLocale() { 268 return locale; 269 } 270 271 /** 272 * Gets the monthChooser attribute of the JCalendar object 273 * 274 * @return the monthChooser value 275 */ 276 public JMonthChooser getMonthChooser() { 277 return monthChooser; 278 } 279 280 /** 281 * Gets the yearChooser attribute of the JCalendar object 282 * 283 * @return the yearChooser value 284 */ 285 public JYearChooser getYearChooser() { 286 return yearChooser; 287 } 288 289 /** 290 * Indicates if the weeks of year are visible.. 291 * 292 * @return boolean true, if weeks of year are visible 293 */ 294 public boolean isWeekOfYearVisible() { 295 return dayChooser.isWeekOfYearVisible(); 296 } 297 298 /** 299 * JCalendar is a PropertyChangeListener, for its day, month and year 300 * chooser. 301 * 302 * @param evt 303 * the property change event 304 */ 305 public void propertyChange(PropertyChangeEvent evt) { 306 if (calendar != null) { 307 Calendar c = (Calendar) calendar.clone(); 308 309 if (evt.getPropertyName().equals("day")) { 310 c.set(Calendar.DAY_OF_MONTH, ((Integer) evt.getNewValue()).intValue()); 311 setCalendar(c, false); 312 } else if (evt.getPropertyName().equals("month")) { 313 c.set(Calendar.MONTH, ((Integer) evt.getNewValue()).intValue()); 314 setCalendar(c, false); 315 } else if (evt.getPropertyName().equals("year")) { 316 c.set(Calendar.YEAR, ((Integer) evt.getNewValue()).intValue()); 317 setCalendar(c, false); 318 } else if (evt.getPropertyName().equals("date")) { 319 c.setTime((Date) evt.getNewValue()); 320 setCalendar(c, true); 321 } 322 } 323 } 324 325 /** 326 * Sets the background color. 327 * 328 * @param bg 329 * the new background 330 */ 331 public void setBackground(Color bg) { 332 super.setBackground(bg); 333 334 if (dayChooser != null) { 335 dayChooser.setBackground(bg); 336 } 337 } 338 339 /** 340 * Sets the calendar property. This is a bound property. 341 * 342 * @param c 343 * the new calendar 344 * @throws NullPointerException - 345 * if c is null; 346 * @see #getCalendar 347 */ 348 public void setCalendar(Calendar c) { 349 setCalendar(c, true); 350 } 351 352 /** 353 * Sets the calendar attribute of the JCalendar object 354 * 355 * @param c 356 * the new calendar value 357 * @param update 358 * the new calendar value 359 * @throws NullPointerException - 360 * if c is null; 361 */ 362 private void setCalendar(Calendar c, boolean update) { 363 if (c == null) { 364 setDate(null); 365 } 366 Calendar oldCalendar = calendar; 367 calendar = c; 368 369 if (update) { 370 // Thanks to Jeff Ulmer for correcting a bug in the sequence :) 371 yearChooser.setYear(c.get(Calendar.YEAR)); 372 monthChooser.setMonth(c.get(Calendar.MONTH)); 373 dayChooser.setDay(c.get(Calendar.DATE)); 374 } 375 376 firePropertyChange("calendar", oldCalendar, calendar); 377 } 378 379 /** 380 * Enable or disable the JCalendar. 381 * 382 * @param enabled 383 * the new enabled value 384 */ 385 public void setEnabled(boolean enabled) { 386 super.setEnabled(enabled); 387 388 if (dayChooser != null) { 389 dayChooser.setEnabled(enabled); 390 monthChooser.setEnabled(enabled); 391 yearChooser.setEnabled(enabled); 392 } 393 } 394 395 /** 396 * Returns true, if enabled. 397 * 398 * @return true, if enabled. 399 */ 400 public boolean isEnabled() { 401 return super.isEnabled(); 402 } 403 404 /** 405 * Sets the font property. 406 * 407 * @param font 408 * the new font 409 */ 410 public void setFont(Font font) { 411 super.setFont(font); 412 413 if (dayChooser != null) { 414 dayChooser.setFont(font); 415 monthChooser.setFont(font); 416 yearChooser.setFont(font); 417 } 418 } 419 420 /** 421 * Sets the foreground color. 422 * 423 * @param fg 424 * the new foreground 425 */ 426 public void setForeground(Color fg) { 427 super.setForeground(fg); 428 429 if (dayChooser != null) { 430 dayChooser.setForeground(fg); 431 monthChooser.setForeground(fg); 432 yearChooser.setForeground(fg); 433 } 434 } 435 436 /** 437 * Sets the locale property. This is a bound property. 438 * 439 * @param l 440 * the new locale value 441 * 442 * @see #getLocale 443 */ 444 public void setLocale(Locale l) { 445 if (!initialized) { 446 super.setLocale(l); 447 } else { 448 Locale oldLocale = locale; 449 locale = l; 450 dayChooser.setLocale(locale); 451 monthChooser.setLocale(locale); 452 firePropertyChange("locale", oldLocale, locale); 453 } 454 } 455 456 /** 457 * Sets the week of year visible. 458 * 459 * @param weekOfYearVisible 460 * true, if weeks of year shall be visible 461 */ 462 public void setWeekOfYearVisible(boolean weekOfYearVisible) { 463 dayChooser.setWeekOfYearVisible(weekOfYearVisible); 464 setLocale(locale); // hack for doing complete new layout :) 465 } 466 467 /** 468 * Gets the visibility of the decoration background. 469 * 470 * @return true, if the decoration background is visible. 471 */ 472 public boolean isDecorationBackgroundVisible() { 473 return dayChooser.isDecorationBackgroundVisible(); 474 } 475 476 /** 477 * Sets the decoration background visible. 478 * 479 * @param decorationBackgroundVisible 480 * true, if the decoration background should be visible. 481 */ 482 public void setDecorationBackgroundVisible(boolean decorationBackgroundVisible) { 483 dayChooser.setDecorationBackgroundVisible(decorationBackgroundVisible); 484 setLocale(locale); // hack for doing complete new layout :) 485 } 486 487 /** 488 * Gets the visibility of the decoration border. 489 * 490 * @return true, if the decoration border is visible. 491 */ 492 public boolean isDecorationBordersVisible() { 493 return dayChooser.isDecorationBordersVisible(); 494 } 495 496 /** 497 * Sets the decoration borders visible. 498 * 499 * @param decorationBordersVisible 500 * true, if the decoration borders should be visible. 501 */ 502 public void setDecorationBordersVisible(boolean decorationBordersVisible) { 503 dayChooser.setDecorationBordersVisible(decorationBordersVisible); 504 setLocale(locale); // hack for doing complete new layout :) 505 } 506 507 /** 508 * Returns the color of the decoration (day names and weeks). 509 * 510 * @return the color of the decoration (day names and weeks). 511 */ 512 public Color getDecorationBackgroundColor() { 513 return dayChooser.getDecorationBackgroundColor(); 514 } 515 516 /** 517 * Sets the background of days and weeks of year buttons. 518 * 519 * @param decorationBackgroundColor 520 * the background color 521 */ 522 public void setDecorationBackgroundColor(Color decorationBackgroundColor) { 523 dayChooser.setDecorationBackgroundColor(decorationBackgroundColor); 524 } 525 526 /** 527 * Returns the Sunday foreground. 528 * 529 * @return Color the Sunday foreground. 530 */ 531 public Color getSundayForeground() { 532 return dayChooser.getSundayForeground(); 533 } 534 535 /** 536 * Returns the weekday foreground. 537 * 538 * @return Color the weekday foreground. 539 */ 540 public Color getWeekdayForeground() { 541 return dayChooser.getWeekdayForeground(); 542 } 543 544 /** 545 * Sets the Sunday foreground. 546 * 547 * @param sundayForeground 548 * the sundayForeground to set 549 */ 550 public void setSundayForeground(Color sundayForeground) { 551 dayChooser.setSundayForeground(sundayForeground); 552 } 553 554 /** 555 * Sets the weekday foreground. 556 * 557 * @param weekdayForeground 558 * the weekdayForeground to set 559 */ 560 public void setWeekdayForeground(Color weekdayForeground) { 561 dayChooser.setWeekdayForeground(weekdayForeground); 562 } 563 564 /** 565 * Returns a Date object. 566 * 567 * @return a date object constructed from the calendar property. 568 */ 569 public Date getDate() { 570 return new Date(calendar.getTimeInMillis()); 571 } 572 573 /** 574 * Sets the date. Fires the property change "date". 575 * 576 * @param date 577 * the new date. 578 * @throws NullPointerException - 579 * if tha date is null 580 */ 581 public void setDate(Date date) { 582 Date oldDate = calendar.getTime(); 583 calendar.setTime(date); 584 int year = calendar.get(Calendar.YEAR); 585 int month = calendar.get(Calendar.MONTH); 586 int day = calendar.get(Calendar.DAY_OF_MONTH); 587 588 yearChooser.setYear(year); 589 monthChooser.setMonth(month); 590 dayChooser.setCalendar(calendar); 591 dayChooser.setDay(day); 592 593 firePropertyChange("date", oldDate, date); 594 } 595 596 /** 597 * Sets a valid date range for selectable dates. If max is before 598 * min, the default range with no limitation is set. 599 * 600 * @param min 601 * the minimum selectable date or null (then the minimum date is 602 * set to 01\01\0001) 603 * @param max 604 * the maximum selectable date or null (then the maximum date is 605 * set to 01\01\9999) 606 */ 607 public void setSelectableDateRange(Date min, Date max) { 608 dayChooser.setSelectableDateRange(min, max); 609 }; 610 611 /** 612 * Gets the minimum selectable date. 613 * 614 * @return the minimum selectable date 615 */ 616 public Date getMaxSelectableDate() { 617 return dayChooser.getMaxSelectableDate(); 618 } 619 620 /** 621 * Gets the maximum selectable date. 622 * 623 * @return the maximum selectable date 624 */ 625 public Date getMinSelectableDate() { 626 return dayChooser.getMinSelectableDate(); 627 } 628 629 /** 630 * Sets the maximum selectable date. 631 * 632 * @param max maximum selectable date 633 */ 634 public void setMaxSelectableDate(Date max) { 635 dayChooser.setMaxSelectableDate(max); 636 } 637 638 /** 639 * Sets the minimum selectable date. 640 * 641 * @param min minimum selectable date 642 */ 643 public void setMinSelectableDate(Date min) { 644 dayChooser.setMinSelectableDate(min); 645 } 646 647 /** 648 * Gets the maximum number of characters of a day name or 0. If 0 is 649 * returned, dateFormatSymbols.getShortWeekdays() will be used. 650 * 651 * @return the maximum number of characters of a day name or 0. 652 */ 653 public int getMaxDayCharacters() { 654 return dayChooser.getMaxDayCharacters(); 655 } 656 657 /** 658 * Sets the maximum number of characters per day in the day bar. Valid 659 * values are 0-4. If set to 0, dateFormatSymbols.getShortWeekdays() will be 660 * used, otherwise theses strings will be reduced to the maximum number of 661 * characters. 662 * 663 * @param maxDayCharacters 664 * the maximum number of characters of a day name. 665 */ 666 public void setMaxDayCharacters(int maxDayCharacters) { 667 dayChooser.setMaxDayCharacters(maxDayCharacters); 668 } 669}