001 /* 002 * $Id: JDayChooser.java,v 1.3 2012/02/19 17:35:46 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 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 package edu.wisc.ssec.mcidasv.data.dateChooser; 031 032 import java.awt.BorderLayout; 033 import java.awt.Color; 034 import java.awt.Font; 035 import java.awt.Graphics; 036 import java.awt.GridLayout; 037 import java.awt.Insets; 038 import java.awt.event.ActionEvent; 039 import java.awt.event.ActionListener; 040 import java.awt.event.FocusEvent; 041 import java.awt.event.FocusListener; 042 import java.awt.event.KeyEvent; 043 import java.awt.event.KeyListener; 044 import java.awt.event.MouseListener; 045 046 import java.text.DateFormatSymbols; 047 048 import java.util.Calendar; 049 import java.util.Date; 050 import java.util.Locale; 051 052 import javax.swing.JButton; 053 import javax.swing.JFrame; 054 import javax.swing.JPanel; 055 import javax.swing.UIManager; 056 057 /** 058 * JDayChooser is a bean for choosing a day. 059 * 060 * @author Kai Toedter 061 * @version $LastChangedRevision: 107 $ 062 * @version $LastChangedDate: 2009-05-01 15:48:00 +0200 (Fr, 01 Mai 2009) $ 063 */ 064 public class JDayChooser extends JPanel implements ActionListener, KeyListener, 065 FocusListener { 066 private static final long serialVersionUID = 5876398337018781820L; 067 068 protected JButton[] days; 069 070 protected JButton[] weeks; 071 072 protected JButton selectedDay; 073 074 protected JPanel weekPanel; 075 076 protected JPanel dayPanel; 077 078 protected int day; 079 080 protected Color oldDayBackgroundColor; 081 082 protected Color selectedColor; 083 084 protected Color sundayForeground; 085 086 protected Color weekdayForeground; 087 088 protected Color decorationBackgroundColor; 089 090 protected String[] dayNames; 091 092 protected Calendar calendar; 093 094 protected Calendar today; 095 096 protected Locale locale; 097 098 protected boolean initialized; 099 100 protected boolean weekOfYearVisible; 101 102 protected boolean decorationBackgroundVisible = true; 103 104 protected boolean decorationBordersVisible; 105 106 protected boolean dayBordersVisible; 107 108 private boolean alwaysFireDayProperty; 109 110 protected Date minSelectableDate; 111 112 protected Date maxSelectableDate; 113 114 protected Date defaultMinSelectableDate; 115 116 protected Date defaultMaxSelectableDate; 117 118 protected int maxDayCharacters; 119 120 /** 121 * Default JDayChooser constructor. 122 */ 123 public JDayChooser() { 124 this(false); 125 } 126 127 /** 128 * JDayChooser constructor. 129 * 130 * @param weekOfYearVisible 131 * true, if the weeks of a year shall be shown 132 */ 133 public JDayChooser(boolean weekOfYearVisible) { 134 setName("JDayChooser"); 135 setBackground(Color.blue); 136 this.weekOfYearVisible = weekOfYearVisible; 137 locale = Locale.getDefault(); 138 days = new JButton[49]; 139 selectedDay = null; 140 calendar = Calendar.getInstance(locale); 141 today = (Calendar) calendar.clone(); 142 143 setLayout(new BorderLayout()); 144 145 dayPanel = new JPanel(); 146 dayPanel.setLayout(new GridLayout(7, 7)); 147 148 sundayForeground = new Color(164, 0, 0); 149 weekdayForeground = new Color(0, 90, 164); 150 151 // decorationBackgroundColor = new Color(194, 211, 252); 152 // decorationBackgroundColor = new Color(206, 219, 246); 153 decorationBackgroundColor = new Color(210, 228, 238); 154 155 for (int y = 0; y < 7; y++) { 156 for (int x = 0; x < 7; x++) { 157 int index = x + (7 * y); 158 159 if (y == 0) { 160 // Create a button that doesn't react on clicks or focus 161 // changes. 162 // Thanks to Thomas Schaefer for the focus hint :) 163 days[index] = new DecoratorButton(); 164 } else { 165 days[index] = new JButton("x") { 166 private static final long serialVersionUID = -7433645992591669725L; 167 168 public void paint(Graphics g) { 169 if ("Windows".equals(UIManager.getLookAndFeel() 170 .getID())) { 171 // this is a hack to get the background painted 172 // when using Windows Look & Feel 173 if (selectedDay == this) { 174 g.setColor(selectedColor); 175 g.fillRect(0, 0, getWidth(), getHeight()); 176 } 177 } 178 super.paint(g); 179 } 180 181 }; 182 days[index].addActionListener(this); 183 days[index].addKeyListener(this); 184 days[index].addFocusListener(this); 185 } 186 187 days[index].setMargin(new Insets(0, 0, 0, 0)); 188 days[index].setFocusPainted(false); 189 dayPanel.add(days[index]); 190 } 191 } 192 193 weekPanel = new JPanel(); 194 weekPanel.setLayout(new GridLayout(7, 1)); 195 weeks = new JButton[7]; 196 197 for (int i = 0; i < 7; i++) { 198 weeks[i] = new DecoratorButton(); 199 weeks[i].setMargin(new Insets(0, 0, 0, 0)); 200 weeks[i].setFocusPainted(false); 201 weeks[i].setForeground(new Color(100, 100, 100)); 202 203 if (i != 0) { 204 weeks[i].setText("0" + (i + 1)); 205 } 206 207 weekPanel.add(weeks[i]); 208 } 209 210 Calendar tmpCalendar = Calendar.getInstance(); 211 tmpCalendar.set(1, 0, 1, 1, 1); 212 defaultMinSelectableDate = tmpCalendar.getTime(); 213 minSelectableDate = defaultMinSelectableDate; 214 tmpCalendar.set(9999, 0, 1, 1, 1); 215 defaultMaxSelectableDate = tmpCalendar.getTime(); 216 maxSelectableDate = defaultMaxSelectableDate; 217 218 init(); 219 220 setDay(Calendar.getInstance().get(Calendar.DAY_OF_MONTH)); 221 add(dayPanel, BorderLayout.CENTER); 222 223 if (weekOfYearVisible) { 224 add(weekPanel, BorderLayout.WEST); 225 } 226 initialized = true; 227 updateUI(); 228 } 229 230 /** 231 * Initilizes the locale specific names for the days of the week. 232 */ 233 protected void init() { 234 JButton testButton = new JButton(); 235 oldDayBackgroundColor = testButton.getBackground(); 236 selectedColor = new Color(160, 160, 160); 237 238 Date date = calendar.getTime(); 239 calendar = Calendar.getInstance(locale); 240 calendar.setTime(date); 241 242 drawDayNames(); 243 drawDays(); 244 } 245 246 /** 247 * Draws the day names of the day columnes. 248 */ 249 private void drawDayNames() { 250 int firstDayOfWeek = calendar.getFirstDayOfWeek(); 251 DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(locale); 252 dayNames = dateFormatSymbols.getShortWeekdays(); 253 254 int day = firstDayOfWeek; 255 256 for (int i = 0; i < 7; i++) { 257 if (maxDayCharacters > 0 && maxDayCharacters < 5) { 258 if (dayNames[day].length() >= maxDayCharacters) { 259 dayNames[day] = dayNames[day] 260 .substring(0, maxDayCharacters); 261 } 262 } 263 264 days[i].setText(dayNames[day]); 265 266 if (day == 1) { 267 days[i].setForeground(sundayForeground); 268 } else { 269 days[i].setForeground(weekdayForeground); 270 } 271 272 if (day < 7) { 273 day++; 274 } else { 275 day -= 6; 276 } 277 } 278 } 279 280 /** 281 * Initializes both day names and weeks of the year. 282 */ 283 protected void initDecorations() { 284 for (int x = 0; x < 7; x++) { 285 days[x].setContentAreaFilled(decorationBackgroundVisible); 286 days[x].setBorderPainted(decorationBordersVisible); 287 days[x].invalidate(); 288 days[x].repaint(); 289 weeks[x].setContentAreaFilled(decorationBackgroundVisible); 290 weeks[x].setBorderPainted(decorationBordersVisible); 291 weeks[x].invalidate(); 292 weeks[x].repaint(); 293 } 294 } 295 296 /** 297 * Hides and shows the week buttons. 298 */ 299 protected void drawWeeks() { 300 Calendar tmpCalendar = (Calendar) calendar.clone(); 301 302 for (int i = 1; i < 7; i++) { 303 tmpCalendar.set(Calendar.DAY_OF_MONTH, (i * 7) - 6); 304 305 int week = tmpCalendar.get(Calendar.WEEK_OF_YEAR); 306 String buttonText = Integer.toString(week); 307 308 if (week < 10) { 309 buttonText = "0" + buttonText; 310 } 311 312 weeks[i].setText(buttonText); 313 314 if ((i == 5) || (i == 6)) { 315 weeks[i].setVisible(days[i * 7].isVisible()); 316 } 317 } 318 } 319 320 /** 321 * Hides and shows the day buttons. 322 */ 323 protected void drawDays() { 324 Calendar tmpCalendar = (Calendar) calendar.clone(); 325 tmpCalendar.set(Calendar.HOUR_OF_DAY, 0); 326 tmpCalendar.set(Calendar.MINUTE, 0); 327 tmpCalendar.set(Calendar.SECOND, 0); 328 tmpCalendar.set(Calendar.MILLISECOND, 0); 329 330 Calendar minCal = Calendar.getInstance(); 331 minCal.setTime(minSelectableDate); 332 minCal.set(Calendar.HOUR_OF_DAY, 0); 333 minCal.set(Calendar.MINUTE, 0); 334 minCal.set(Calendar.SECOND, 0); 335 minCal.set(Calendar.MILLISECOND, 0); 336 337 Calendar maxCal = Calendar.getInstance(); 338 maxCal.setTime(maxSelectableDate); 339 maxCal.set(Calendar.HOUR_OF_DAY, 0); 340 maxCal.set(Calendar.MINUTE, 0); 341 maxCal.set(Calendar.SECOND, 0); 342 maxCal.set(Calendar.MILLISECOND, 0); 343 344 int firstDayOfWeek = tmpCalendar.getFirstDayOfWeek(); 345 tmpCalendar.set(Calendar.DAY_OF_MONTH, 1); 346 347 int firstDay = tmpCalendar.get(Calendar.DAY_OF_WEEK) - firstDayOfWeek; 348 349 if (firstDay < 0) { 350 firstDay += 7; 351 } 352 353 int i; 354 355 for (i = 0; i < firstDay; i++) { 356 days[i + 7].setVisible(false); 357 days[i + 7].setText(""); 358 } 359 360 tmpCalendar.add(Calendar.MONTH, 1); 361 362 Date firstDayInNextMonth = tmpCalendar.getTime(); 363 tmpCalendar.add(Calendar.MONTH, -1); 364 365 Date day = tmpCalendar.getTime(); 366 int n = 0; 367 Color foregroundColor = getForeground(); 368 369 while (day.before(firstDayInNextMonth)) { 370 days[i + n + 7].setText(Integer.toString(n + 1)); 371 days[i + n + 7].setVisible(true); 372 373 if ((tmpCalendar.get(Calendar.DAY_OF_YEAR) == today 374 .get(Calendar.DAY_OF_YEAR)) 375 && (tmpCalendar.get(Calendar.YEAR) == today 376 .get(Calendar.YEAR))) { 377 days[i + n + 7].setForeground(sundayForeground); 378 } else { 379 days[i + n + 7].setForeground(foregroundColor); 380 } 381 382 if ((n + 1) == this.day) { 383 days[i + n + 7].setBackground(selectedColor); 384 selectedDay = days[i + n + 7]; 385 } else { 386 days[i + n + 7].setBackground(oldDayBackgroundColor); 387 } 388 389 if (tmpCalendar.before(minCal) || tmpCalendar.after(maxCal)) { 390 days[i + n + 7].setEnabled(false); 391 } else { 392 days[i + n + 7].setEnabled(true); 393 } 394 395 n++; 396 tmpCalendar.add(Calendar.DATE, 1); 397 day = tmpCalendar.getTime(); 398 } 399 400 for (int k = n + i + 7; k < 49; k++) { 401 days[k].setVisible(false); 402 days[k].setText(""); 403 } 404 405 drawWeeks(); 406 } 407 408 /** 409 * Returns the locale. 410 * 411 * @return the locale value 412 * 413 * @see #setLocale 414 */ 415 public Locale getLocale() { 416 return locale; 417 } 418 419 /** 420 * Sets the locale. 421 * 422 * @param locale 423 * the new locale value 424 * 425 * @see #getLocale 426 */ 427 public void setLocale(Locale locale) { 428 if (!initialized) { 429 super.setLocale(locale); 430 } else { 431 this.locale = locale; 432 super.setLocale(locale); 433 init(); 434 } 435 } 436 437 /** 438 * Sets the day. This is a bound property. 439 * 440 * @param d 441 * the day 442 * 443 * @see #getDay 444 */ 445 public void setDay(int d) { 446 if (d < 1) { 447 d = 1; 448 } 449 Calendar tmpCalendar = (Calendar) calendar.clone(); 450 tmpCalendar.set(Calendar.DAY_OF_MONTH, 1); 451 tmpCalendar.add(Calendar.MONTH, 1); 452 tmpCalendar.add(Calendar.DATE, -1); 453 454 int maxDaysInMonth = tmpCalendar.get(Calendar.DATE); 455 456 if (d > maxDaysInMonth) { 457 d = maxDaysInMonth; 458 } 459 460 int oldDay = day; 461 day = d; 462 463 if (selectedDay != null) { 464 selectedDay.setBackground(oldDayBackgroundColor); 465 selectedDay.repaint(); 466 } 467 468 for (int i = 7; i < 49; i++) { 469 if (days[i].getText().equals(Integer.toString(day))) { 470 selectedDay = days[i]; 471 selectedDay.setBackground(selectedColor); 472 break; 473 } 474 } 475 476 if (alwaysFireDayProperty) { 477 firePropertyChange("day", 0, day); 478 } else { 479 firePropertyChange("day", oldDay, day); 480 } 481 } 482 483 /** 484 * this is needed for JDateChooser. 485 * 486 * @param alwaysFire 487 * true, if day property shall be fired every time a day is 488 * chosen. 489 */ 490 public void setAlwaysFireDayProperty(boolean alwaysFire) { 491 alwaysFireDayProperty = alwaysFire; 492 } 493 494 /** 495 * Returns the selected day. 496 * 497 * @return the day value 498 * 499 * @see #setDay 500 */ 501 public int getDay() { 502 return day; 503 } 504 505 /** 506 * Sets a specific month. This is needed for correct graphical 507 * representation of the days. 508 * 509 * @param month 510 * the new month 511 */ 512 public void setMonth(int month) { 513 calendar.set(Calendar.MONTH, month); 514 int maxDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); 515 516 int adjustedDay = day; 517 if (day > maxDays) { 518 adjustedDay = maxDays; 519 setDay(adjustedDay); 520 } 521 522 drawDays(); 523 } 524 525 /** 526 * Sets a specific year. This is needed for correct graphical representation 527 * of the days. 528 * 529 * @param year 530 * the new year 531 */ 532 public void setYear(int year) { 533 calendar.set(Calendar.YEAR, year); 534 drawDays(); 535 } 536 537 /** 538 * Sets a specific calendar. This is needed for correct graphical 539 * representation of the days. 540 * 541 * @param calendar 542 * the new calendar 543 */ 544 public void setCalendar(Calendar calendar) { 545 this.calendar = calendar; 546 drawDays(); 547 } 548 549 /** 550 * Sets the font property. 551 * 552 * @param font 553 * the new font 554 */ 555 public void setFont(Font font) { 556 if (days != null) { 557 for (int i = 0; i < 49; i++) { 558 days[i].setFont(font); 559 } 560 } 561 if (weeks != null) { 562 for (int i = 0; i < 7; i++) { 563 weeks[i].setFont(font); 564 } 565 } 566 } 567 568 /** 569 * Sets the foregroundColor color. 570 * 571 * @param foreground 572 * the new foregroundColor 573 */ 574 public void setForeground(Color foreground) { 575 super.setForeground(foreground); 576 577 if (days != null) { 578 for (int i = 7; i < 49; i++) { 579 days[i].setForeground(foreground); 580 } 581 582 drawDays(); 583 } 584 } 585 586 /** 587 * JDayChooser is the ActionListener for all day buttons. 588 * 589 * @param e 590 * the ActionEvent 591 */ 592 public void actionPerformed(ActionEvent e) { 593 JButton button = (JButton) e.getSource(); 594 String buttonText = button.getText(); 595 int day = new Integer(buttonText).intValue(); 596 setDay(day); 597 } 598 599 /** 600 * JDayChooser is the FocusListener for all day buttons. (Added by Thomas 601 * Schaefer) 602 * 603 * @param e 604 * the FocusEvent 605 */ 606 /* 607 * Code below commented out by Mark Brown on 24 Aug 2004. This code breaks 608 * the JDateChooser code by triggering the actionPerformed method on the 609 * next day button. This causes the date chosen to always be incremented by 610 * one day. 611 */ 612 public void focusGained(FocusEvent e) { 613 // JButton button = (JButton) e.getSource(); 614 // String buttonText = button.getText(); 615 // 616 // if ((buttonText != null) && !buttonText.equals("") && 617 // !e.isTemporary()) { 618 // actionPerformed(new ActionEvent(e.getSource(), 0, null)); 619 // } 620 } 621 622 /** 623 * Does nothing. 624 * 625 * @param e 626 * the FocusEvent 627 */ 628 public void focusLost(FocusEvent e) { 629 } 630 631 /** 632 * JDayChooser is the KeyListener for all day buttons. (Added by Thomas 633 * Schaefer and modified by Austin Moore) 634 * 635 * @param e 636 * the KeyEvent 637 */ 638 public void keyPressed(KeyEvent e) { 639 int offset = (e.getKeyCode() == KeyEvent.VK_UP) ? (-7) : ((e 640 .getKeyCode() == KeyEvent.VK_DOWN) ? (+7) 641 : ((e.getKeyCode() == KeyEvent.VK_LEFT) ? (-1) : ((e 642 .getKeyCode() == KeyEvent.VK_RIGHT) ? (+1) : 0))); 643 644 int newDay = getDay() + offset; 645 646 if ((newDay >= 1) 647 && (newDay <= calendar.getMaximum(Calendar.DAY_OF_MONTH))) { 648 setDay(newDay); 649 } 650 } 651 652 /** 653 * Does nothing. 654 * 655 * @param e 656 * the KeyEvent 657 */ 658 public void keyTyped(KeyEvent e) { 659 } 660 661 /** 662 * Does nothing. 663 * 664 * @param e 665 * the KeyEvent 666 */ 667 public void keyReleased(KeyEvent e) { 668 } 669 670 /** 671 * Enable or disable the JDayChooser. 672 * 673 * @param enabled 674 * The new enabled value 675 */ 676 public void setEnabled(boolean enabled) { 677 super.setEnabled(enabled); 678 679 for (short i = 0; i < days.length; i++) { 680 if (days[i] != null) { 681 days[i].setEnabled(enabled); 682 } 683 } 684 685 for (short i = 0; i < weeks.length; i++) { 686 if (weeks[i] != null) { 687 weeks[i].setEnabled(enabled); 688 } 689 } 690 } 691 692 /** 693 * In some Countries it is often usefull to know in which week of the year a 694 * date is. 695 * 696 * @return boolean true, if the weeks of the year is shown 697 */ 698 public boolean isWeekOfYearVisible() { 699 return weekOfYearVisible; 700 } 701 702 /** 703 * In some Countries it is often usefull to know in which week of the year a 704 * date is. 705 * 706 * @param weekOfYearVisible 707 * true, if the weeks of the year shall be shown 708 */ 709 public void setWeekOfYearVisible(boolean weekOfYearVisible) { 710 if (weekOfYearVisible == this.weekOfYearVisible) { 711 return; 712 } else if (weekOfYearVisible) { 713 add(weekPanel, BorderLayout.WEST); 714 } else { 715 remove(weekPanel); 716 } 717 718 this.weekOfYearVisible = weekOfYearVisible; 719 validate(); 720 dayPanel.validate(); 721 } 722 723 /** 724 * Returns the day panel. 725 * 726 * @return the day panel 727 */ 728 public JPanel getDayPanel() { 729 return dayPanel; 730 } 731 732 /** 733 * Returns the color of the decoration (day names and weeks). 734 * 735 * @return the color of the decoration (day names and weeks). 736 */ 737 public Color getDecorationBackgroundColor() { 738 return decorationBackgroundColor; 739 } 740 741 /** 742 * Sets the background of days and weeks of year buttons. 743 * 744 * @param decorationBackgroundColor 745 * The background to set 746 */ 747 public void setDecorationBackgroundColor(Color decorationBackgroundColor) { 748 this.decorationBackgroundColor = decorationBackgroundColor; 749 750 if (days != null) { 751 for (int i = 0; i < 7; i++) { 752 days[i].setBackground(decorationBackgroundColor); 753 } 754 } 755 756 if (weeks != null) { 757 for (int i = 0; i < 7; i++) { 758 weeks[i].setBackground(decorationBackgroundColor); 759 } 760 } 761 } 762 763 /** 764 * Returns the Sunday foreground. 765 * 766 * @return Color the Sunday foreground. 767 */ 768 public Color getSundayForeground() { 769 return sundayForeground; 770 } 771 772 /** 773 * Returns the weekday foreground. 774 * 775 * @return Color the weekday foreground. 776 */ 777 public Color getWeekdayForeground() { 778 return weekdayForeground; 779 } 780 781 /** 782 * Sets the Sunday foreground. 783 * 784 * @param sundayForeground 785 * The sundayForeground to set 786 */ 787 public void setSundayForeground(Color sundayForeground) { 788 this.sundayForeground = sundayForeground; 789 drawDayNames(); 790 drawDays(); 791 } 792 793 /** 794 * Sets the weekday foreground. 795 * 796 * @param weekdayForeground 797 * The weekdayForeground to set 798 */ 799 public void setWeekdayForeground(Color weekdayForeground) { 800 this.weekdayForeground = weekdayForeground; 801 drawDayNames(); 802 drawDays(); 803 } 804 805 /** 806 * Requests that the selected day also have the focus. 807 */ 808 public void setFocus() { 809 if (selectedDay != null) { 810 this.selectedDay.requestFocus(); 811 } 812 } 813 814 /** 815 * The decoration background is the background color of the day titles and 816 * the weeks of the year. 817 * 818 * @return Returns true, if the decoration background is painted. 819 */ 820 public boolean isDecorationBackgroundVisible() { 821 return decorationBackgroundVisible; 822 } 823 824 /** 825 * The decoration background is the background color of the day titles and 826 * the weeks of the year. 827 * 828 * @param decorationBackgroundVisible 829 * true, if the decoration background shall be painted. 830 */ 831 public void setDecorationBackgroundVisible( 832 boolean decorationBackgroundVisible) { 833 this.decorationBackgroundVisible = decorationBackgroundVisible; 834 initDecorations(); 835 } 836 837 /** 838 * The decoration border is the button border of the day titles and the 839 * weeks of the year. 840 * 841 * @return Returns true, if the decoration border is painted. 842 */ 843 public boolean isDecorationBordersVisible() { 844 return decorationBordersVisible; 845 } 846 847 public boolean isDayBordersVisible() { 848 return dayBordersVisible; 849 } 850 851 /** 852 * The decoration border is the button border of the day titles and the 853 * weeks of the year. 854 * 855 * @param decorationBordersVisible 856 * true, if the decoration border shall be painted. 857 */ 858 public void setDecorationBordersVisible(boolean decorationBordersVisible) { 859 this.decorationBordersVisible = decorationBordersVisible; 860 initDecorations(); 861 } 862 863 public void setDayBordersVisible(boolean dayBordersVisible) { 864 this.dayBordersVisible = dayBordersVisible; 865 if (initialized) { 866 for (int x = 7; x < 49; x++) { 867 if ("Windows".equals(UIManager.getLookAndFeel().getID())) { 868 days[x].setContentAreaFilled(dayBordersVisible); 869 } else { 870 days[x].setContentAreaFilled(true); 871 } 872 days[x].setBorderPainted(dayBordersVisible); 873 } 874 } 875 } 876 877 /** 878 * Updates the UI and sets the day button preferences. 879 */ 880 public void updateUI() { 881 super.updateUI(); 882 setFont(Font.decode("Dialog Plain 11")); 883 884 if (weekPanel != null) { 885 weekPanel.updateUI(); 886 } 887 if (initialized) { 888 if ("Windows".equals(UIManager.getLookAndFeel().getID())) { 889 setDayBordersVisible(false); 890 setDecorationBackgroundVisible(true); 891 setDecorationBordersVisible(false); 892 } else { 893 setDayBordersVisible(true); 894 setDecorationBackgroundVisible(decorationBackgroundVisible); 895 setDecorationBordersVisible(decorationBordersVisible); 896 } 897 } 898 } 899 900 /** 901 * Sets a valid date range for selectable dates. If max is before min, the 902 * default range with no limitation is set. 903 * 904 * @param min 905 * the minimum selectable date or null (then the minimum date is 906 * set to 01\01\0001) 907 * @param max 908 * the maximum selectable date or null (then the maximum date is 909 * set to 01\01\9999) 910 */ 911 public void setSelectableDateRange(Date min, Date max) { 912 if (min == null) { 913 minSelectableDate = defaultMinSelectableDate; 914 } else { 915 minSelectableDate = min; 916 } 917 if (max == null) { 918 maxSelectableDate = defaultMaxSelectableDate; 919 } else { 920 maxSelectableDate = max; 921 } 922 if (maxSelectableDate.before(minSelectableDate)) { 923 minSelectableDate = defaultMinSelectableDate; 924 maxSelectableDate = defaultMaxSelectableDate; 925 } 926 drawDays(); 927 } 928 929 /** 930 * Sets the maximum selectable date. If null, the date 01\01\9999 will be 931 * set instead. 932 * 933 * @param max 934 * the maximum selectable date 935 * 936 * @return the maximum selectable date 937 */ 938 public Date setMaxSelectableDate(Date max) { 939 if (max == null) { 940 maxSelectableDate = defaultMaxSelectableDate; 941 } else { 942 maxSelectableDate = max; 943 } 944 drawDays(); 945 return maxSelectableDate; 946 } 947 948 /** 949 * Sets the minimum selectable date. If null, the date 01\01\0001 will be 950 * set instead. 951 * 952 * @param min 953 * the minimum selectable date 954 * 955 * @return the minimum selectable date 956 */ 957 public Date setMinSelectableDate(Date min) { 958 if (min == null) { 959 minSelectableDate = defaultMinSelectableDate; 960 } else { 961 minSelectableDate = min; 962 } 963 drawDays(); 964 return minSelectableDate; 965 } 966 967 /** 968 * Gets the maximum selectable date. 969 * 970 * @return the maximum selectable date 971 */ 972 public Date getMaxSelectableDate() { 973 return maxSelectableDate; 974 } 975 976 /** 977 * Gets the minimum selectable date. 978 * 979 * @return the minimum selectable date 980 */ 981 public Date getMinSelectableDate() { 982 return minSelectableDate; 983 } 984 985 /** 986 * Gets the maximum number of characters of a day name or 0. If 0 is 987 * returned, dateFormatSymbols.getShortWeekdays() will be used. 988 * 989 * @return the maximum number of characters of a day name or 0. 990 */ 991 public int getMaxDayCharacters() { 992 return maxDayCharacters; 993 } 994 995 /** 996 * Sets the maximum number of characters per day in the day bar. Valid 997 * values are 0-4. If set to 0, dateFormatSymbols.getShortWeekdays() will be 998 * used, otherwise theses strings will be reduced to the maximum number of 999 * characters. 1000 * 1001 * @param maxDayCharacters 1002 * the maximum number of characters of a day name. 1003 */ 1004 public void setMaxDayCharacters(int maxDayCharacters) { 1005 if (maxDayCharacters == this.maxDayCharacters) { 1006 return; 1007 } 1008 1009 if (maxDayCharacters < 0 || maxDayCharacters > 4) { 1010 this.maxDayCharacters = 0; 1011 } else { 1012 this.maxDayCharacters = maxDayCharacters; 1013 } 1014 drawDayNames(); 1015 drawDays(); 1016 invalidate(); 1017 } 1018 1019 /** 1020 * Creates a JFrame with a JDayChooser inside and can be used for testing. 1021 * 1022 * @param s 1023 * The command line arguments 1024 */ 1025 public static void main(String[] s) { 1026 JFrame frame = new JFrame("JDayChooser"); 1027 frame.getContentPane().add(new JDayChooser()); 1028 frame.pack(); 1029 frame.setVisible(true); 1030 } 1031 1032 class DecoratorButton extends JButton { 1033 private static final long serialVersionUID = -5306477668406547496L; 1034 1035 public DecoratorButton() { 1036 setBackground(decorationBackgroundColor); 1037 setContentAreaFilled(decorationBackgroundVisible); 1038 setBorderPainted(decorationBordersVisible); 1039 } 1040 1041 public void addMouseListener(MouseListener l) { 1042 } 1043 1044 public boolean isFocusable() { 1045 return false; 1046 } 1047 1048 public void paint(Graphics g) { 1049 if ("Windows".equals(UIManager.getLookAndFeel().getID())) { 1050 // this is a hack to get the background painted 1051 // when using Windows Look & Feel 1052 if (decorationBackgroundVisible) { 1053 g.setColor(decorationBackgroundColor); 1054 } else { 1055 g.setColor(days[7].getBackground()); 1056 } 1057 g.fillRect(0, 0, getWidth(), getHeight()); 1058 if (isBorderPainted()) { 1059 setContentAreaFilled(true); 1060 } else { 1061 setContentAreaFilled(false); 1062 } 1063 } 1064 super.paint(g); 1065 } 1066 }; 1067 }