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