Source for org.jfree.ui.SerialDateChooserPanel

   1: /* ========================================================================
   2:  * JCommon : a free general purpose class library for the Java(tm) platform
   3:  * ========================================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  * 
   7:  * Project Info:  http://www.jfree.org/jcommon/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  * 
  27:  * ---------------------------
  28:  * SerialDateChooserPanel.java
  29:  * ---------------------------
  30:  * (C) Copyright 2001-2005, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: SerialDateChooserPanel.java,v 1.6 2005/11/16 15:58:41 taqua Exp $
  36:  *
  37:  * Changes
  38:  * -------
  39:  * 08-Dec-2001 : Version 1 (DG);
  40:  * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  41:  *
  42:  */
  43: 
  44: package org.jfree.ui;
  45: 
  46: import java.awt.BorderLayout;
  47: import java.awt.Color;
  48: import java.awt.Font;
  49: import java.awt.GridLayout;
  50: import java.awt.Insets;
  51: import java.awt.event.ActionEvent;
  52: import java.awt.event.ActionListener;
  53: import java.util.Calendar;
  54: import java.util.Date;
  55: import java.util.Enumeration;
  56: import java.util.Vector;
  57: 
  58: import javax.swing.BorderFactory;
  59: import javax.swing.JButton;
  60: import javax.swing.JComboBox;
  61: import javax.swing.JLabel;
  62: import javax.swing.JPanel;
  63: import javax.swing.SwingConstants;
  64: 
  65: import org.jfree.date.SerialDate;
  66: 
  67: /**
  68:  * A panel that allows the user to select a date.
  69:  * <P>
  70:  * This class is incomplete and untested.  You should not use it yet...
  71:  *
  72:  * @author David Gilbert
  73:  */
  74: public class SerialDateChooserPanel extends JPanel implements ActionListener {
  75: 
  76:     /** The default background color for the selected date. */
  77:     public static final Color DEFAULT_DATE_BUTTON_COLOR = Color.red;
  78: 
  79:     /** The default background color for the current month. */
  80:     public static final Color DEFAULT_MONTH_BUTTON_COLOR = Color.lightGray;
  81: 
  82:     /** The date selected in the panel. */
  83:     private SerialDate date;
  84: 
  85:     /** The color for the selected date. */
  86:     private Color dateButtonColor;
  87: 
  88:     /** The color for dates in the current month. */
  89:     private Color monthButtonColor;
  90: 
  91:     /** The color for dates that are visible, but not in the current month. */
  92:     private Color chosenOtherButtonColor = Color.darkGray;
  93: 
  94:     /** The first day-of-the-week. */
  95:     private int firstDayOfWeek = Calendar.SUNDAY;
  96: 
  97:     /** The range used for selecting years. */
  98:     private int yearSelectionRange = 20;
  99: 
 100:     /** The font used to display the date. */
 101:     private Font dateFont = new Font("SansSerif", Font.PLAIN, 10);
 102: 
 103:     /** A combo for selecting the month. */
 104:     private JComboBox monthSelector = null;
 105: 
 106:     /** A combo for selecting the year. */
 107:     private JComboBox yearSelector = null;
 108: 
 109:     /** A button for selecting today's date. */
 110:     private JButton todayButton = null;
 111: 
 112:     /** An array of buttons used to display the days-of-the-month. */
 113:     private JButton[] buttons = null;
 114: 
 115:     /** A flag that indicates whether or not we are currently refreshing the buttons. */
 116:     private boolean refreshing = false;
 117: 
 118:     /**
 119:      * Constructs a new date chooser panel, using today's date as the initial selection.
 120:      */
 121:     public SerialDateChooserPanel() {
 122: 
 123:         this(SerialDate.createInstance(new Date()), false,
 124:              DEFAULT_DATE_BUTTON_COLOR,
 125:              DEFAULT_MONTH_BUTTON_COLOR);
 126: 
 127:     }
 128: 
 129:     /**
 130:      * Constructs a new date chooser panel.
 131:      *
 132:      * @param date  the date.
 133:      * @param controlPanel  a flag that indicates whether or not the 'today' button should
 134:      *                      appear on the panel.
 135:      */
 136:     public SerialDateChooserPanel(final SerialDate date, final boolean controlPanel) {
 137: 
 138:         this(date, controlPanel,
 139:              DEFAULT_DATE_BUTTON_COLOR,
 140:              DEFAULT_MONTH_BUTTON_COLOR);
 141: 
 142:     }
 143: 
 144:     /**
 145:      * Constructs a new date chooser panel.
 146:      *
 147:      * @param date  the date.
 148:      * @param controlPanel  the control panel.
 149:      * @param dateButtonColor  the date button color.
 150:      * @param monthButtonColor  the month button color.
 151:      */
 152:     public SerialDateChooserPanel(final SerialDate date, final boolean controlPanel,
 153:                                   final Color dateButtonColor, final Color monthButtonColor) {
 154: 
 155:         super(new BorderLayout());
 156: 
 157:         this.date = date;
 158:         this.dateButtonColor = dateButtonColor;
 159:         this.monthButtonColor = monthButtonColor;
 160: 
 161:         add(constructSelectionPanel(), BorderLayout.NORTH);
 162:         add(getCalendarPanel(), BorderLayout.CENTER);
 163:         if (controlPanel) {
 164:             add(constructControlPanel(), BorderLayout.SOUTH);
 165:         }
 166: 
 167:     }
 168: 
 169:     /**
 170:      * Sets the date chosen in the panel.
 171:      *
 172:      * @param date  the new date.
 173:      */
 174:     public void setDate(final SerialDate date) {
 175: 
 176:         this.date = date;
 177:         this.monthSelector.setSelectedIndex(date.getMonth() - 1);
 178:         refreshYearSelector();
 179:         refreshButtons();
 180: 
 181:     }
 182: 
 183:     /**
 184:      * Returns the date selected in the panel.
 185:      *
 186:      * @return the selected date.
 187:      */
 188:     public SerialDate getDate() {
 189:         return this.date;
 190:     }
 191: 
 192:     /**
 193:      * Handles action-events from the date panel.
 194:      *
 195:      * @param e information about the event that occurred.
 196:      */
 197:     public void actionPerformed(final ActionEvent e) {
 198: 
 199:         if (e.getActionCommand().equals("monthSelectionChanged")) {
 200:             final JComboBox c = (JComboBox) e.getSource();
 201:             this.date = SerialDate.createInstance(
 202:                 this.date.getDayOfMonth(), c.getSelectedIndex() + 1, this.date.getYYYY()
 203:             );
 204:             refreshButtons();
 205:         }
 206:         else if (e.getActionCommand().equals("yearSelectionChanged")) {
 207:             if (!this.refreshing) {
 208:                 final JComboBox c = (JComboBox) e.getSource();
 209:                 final Integer y = (Integer) c.getSelectedItem();
 210:                 this.date = SerialDate.createInstance(
 211:                     this.date.getDayOfMonth(), this.date.getMonth(), y.intValue()
 212:                 );
 213:                 refreshYearSelector();
 214:                 refreshButtons();
 215:             }
 216:         }
 217:         else if (e.getActionCommand().equals("todayButtonClicked")) {
 218:             setDate(SerialDate.createInstance(new Date()));
 219:         }
 220:         else if (e.getActionCommand().equals("dateButtonClicked")) {
 221:             final JButton b = (JButton) e.getSource();
 222:             final int i = Integer.parseInt(b.getName());
 223:             final SerialDate first = getFirstVisibleDate();
 224:             final SerialDate selected = SerialDate.addDays(i, first);
 225:             setDate(selected);
 226:         }
 227: 
 228:     }
 229: 
 230:     /**
 231:      * Returns a panel of buttons, each button representing a day in the month.  This is a
 232:      * sub-component of the DatePanel.
 233:      *
 234:      * @return the panel.
 235:      */
 236:     private JPanel getCalendarPanel() {
 237: 
 238:         final JPanel panel = new JPanel(new GridLayout(7, 7));
 239:         panel.add(new JLabel("Sun", SwingConstants.CENTER));
 240:         panel.add(new JLabel("Mon", SwingConstants.CENTER));
 241:         panel.add(new JLabel("Tue", SwingConstants.CENTER));
 242:         panel.add(new JLabel("Wed", SwingConstants.CENTER));
 243:         panel.add(new JLabel("Thu", SwingConstants.CENTER));
 244:         panel.add(new JLabel("Fri", SwingConstants.CENTER));
 245:         panel.add(new JLabel("Sat", SwingConstants.CENTER));
 246: 
 247:         this.buttons = new JButton[42];
 248:         for (int i = 0; i < 42; i++) {
 249:             final JButton button = new JButton("");
 250:             button.setMargin(new Insets(1, 1, 1, 1));
 251:             button.setName(Integer.toString(i));
 252:             button.setFont(this.dateFont);
 253:             button.setFocusPainted(false);
 254:             button.setActionCommand("dateButtonClicked");
 255:             button.addActionListener(this);
 256:             this.buttons[i] = button;
 257:             panel.add(button);
 258:         }
 259:         return panel;
 260: 
 261:     }
 262: 
 263:     /**
 264:      * Returns the button color according to the specified date.
 265:      *
 266:      * @param targetDate  the target date.
 267:      *
 268:      * @return the button color.
 269:      */
 270:     protected Color getButtonColor(final SerialDate targetDate) {
 271: 
 272:         if (this.date.equals(this.date)) {
 273:             return this.dateButtonColor;
 274:         }
 275:         else if (targetDate.getMonth() == this.date.getMonth()) {
 276:             return this.monthButtonColor;
 277:         }
 278:         else {
 279:             return this.chosenOtherButtonColor;
 280:         }
 281: 
 282:     }
 283: 
 284:     /**
 285:      * Returns the first date that is visible in the grid.  This should always be in the month
 286:      * preceding the month of the selected date.
 287:      *
 288:      * @return the first visible date.
 289:      */
 290:     protected SerialDate getFirstVisibleDate() {
 291: 
 292:         SerialDate result = SerialDate.createInstance(1, this.date.getMonth(), this.date.getYYYY());
 293:         result = SerialDate.addDays(-1, result);
 294:         while (result.getDayOfWeek() != getFirstDayOfWeek()) {
 295:             result = SerialDate.addDays(-1, result);
 296:         }
 297:         return result;
 298: 
 299:     }
 300: 
 301:     /**
 302:      * Returns the first day of the week (controls the labels in the date panel).
 303:      *
 304:      * @return the first day of the week.
 305:      */
 306:     private int getFirstDayOfWeek() {
 307:         return this.firstDayOfWeek;
 308:     }
 309: 
 310:     /**
 311:      * Update the button labels and colors to reflect date selection.
 312:      */
 313:     protected void refreshButtons() {
 314: 
 315:         SerialDate current = getFirstVisibleDate();
 316:         for (int i = 0; i < 42; i++) {
 317:             final JButton button = this.buttons[i];
 318:             button.setText(String.valueOf(current.getDayOfWeek()));
 319:             button.setBackground(getButtonColor(current));
 320:             current = SerialDate.addDays(1, current);
 321:         }
 322: 
 323:     }
 324: 
 325:     /**
 326:      * Changes the contents of the year selection JComboBox to reflect the chosen date and the year
 327:      * range.
 328:      */
 329:     private void refreshYearSelector() {
 330:         if (!this.refreshing) {
 331:             this.refreshing = true;
 332:             this.yearSelector.removeAllItems();
 333:             final Vector v = getYears(this.date.getYYYY());
 334:             for (Enumeration e = v.elements(); e.hasMoreElements();) {
 335:                 this.yearSelector.addItem(e.nextElement());
 336:             }
 337:             this.yearSelector.setSelectedItem(new Integer(this.date.getYYYY()));
 338:             this.refreshing = false;
 339:         }
 340:     }
 341: 
 342:     /**
 343:      * Returns a vector of years preceding and following the specified year.  The number of years
 344:      * preceding and following is determined by the yearSelectionRange attribute.
 345:      *
 346:      * @param chosenYear  the current year.
 347:      *
 348:      * @return a vector of years.
 349:      */
 350:     private Vector getYears(final int chosenYear) {
 351:         final Vector v = new Vector();
 352:         for (int i = chosenYear - this.yearSelectionRange; 
 353:             i <= chosenYear + this.yearSelectionRange; i++) {
 354:             v.addElement(new Integer(i));
 355:         }
 356:         return v;
 357:     }
 358: 
 359:     /**
 360:      * Constructs a panel containing two JComboBoxes (for the month and year) and a button
 361:      * (to reset the date to TODAY).
 362:      *
 363:      * @return the panel.
 364:      */
 365:     private JPanel constructSelectionPanel() {
 366:         final JPanel p = new JPanel();
 367:         this.monthSelector = new JComboBox(SerialDate.getMonths());
 368:         this.monthSelector.addActionListener(this);
 369:         this.monthSelector.setActionCommand("monthSelectionChanged");
 370:         p.add(this.monthSelector);
 371: 
 372:         this.yearSelector = new JComboBox(getYears(0));
 373:         this.yearSelector.addActionListener(this);
 374:         this.yearSelector.setActionCommand("yearSelectionChanged");
 375:         p.add(this.yearSelector);
 376: 
 377:         return p;
 378:     }
 379: 
 380:     /**
 381:      * Returns a panel that appears at the bottom of the calendar panel - contains a button for
 382:      * selecting today's date.
 383:      *
 384:      * @return the panel.
 385:      */
 386:     private JPanel constructControlPanel() {
 387: 
 388:         final JPanel p = new JPanel();
 389:         p.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
 390:         this.todayButton = new JButton("Today");
 391:         this.todayButton.addActionListener(this);
 392:         this.todayButton.setActionCommand("todayButtonClicked");
 393:         p.add(this.todayButton);
 394:         return p;
 395: 
 396:     }
 397: 
 398: }