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