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.7 2007/11/02 17:50:36 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: import javax.swing.BorderFactory;
  58: import javax.swing.JButton;
  59: import javax.swing.JComboBox;
  60: import javax.swing.JLabel;
  61: import javax.swing.JPanel;
  62: import javax.swing.SwingConstants;
  63: 
  64: import org.jfree.date.SerialDate;
  65: 
  66: /**
  67:  * A panel that allows the user to select a date.
  68:  * <P>
  69:  * This class is incomplete and untested.  You should not use it yet...
  70:  *
  71:  * @author David Gilbert
  72:  */
  73: public class SerialDateChooserPanel extends JPanel implements ActionListener {
  74: 
  75:     /** The default background color for the selected date. */
  76:     public static final Color DEFAULT_DATE_BUTTON_COLOR = Color.red;
  77: 
  78:     /** The default background color for the current month. */
  79:     public static final Color DEFAULT_MONTH_BUTTON_COLOR = Color.lightGray;
  80: 
  81:     /** The date selected in the panel. */
  82:     private SerialDate date;
  83: 
  84:     /** The color for the selected date. */
  85:     private Color dateButtonColor;
  86: 
  87:     /** The color for dates in the current month. */
  88:     private Color monthButtonColor;
  89: 
  90:     /** The color for dates that are visible, but not in the current month. */
  91:     private Color chosenOtherButtonColor = Color.darkGray;
  92: 
  93:     /** The first day-of-the-week. */
  94:     private int firstDayOfWeek = Calendar.SUNDAY;
  95: 
  96:     /** The range used for selecting years. */
  97:     private int yearSelectionRange = 20;
  98: 
  99:     /** The font used to display the date. */
 100:     private Font dateFont = new Font("SansSerif", Font.PLAIN, 10);
 101: 
 102:     /** A combo for selecting the month. */
 103:     private JComboBox monthSelector = null;
 104: 
 105:     /** A combo for selecting the year. */
 106:     private JComboBox yearSelector = null;
 107: 
 108:     /** A button for selecting today's date. */
 109:     private JButton todayButton = null;
 110: 
 111:     /** An array of buttons used to display the days-of-the-month. */
 112:     private JButton[] buttons = null;
 113: 
 114:     /** A flag that indicates whether or not we are currently refreshing the buttons. */
 115:     private boolean refreshing = false;
 116: 
 117:     /**
 118:      * Constructs a new date chooser panel, using today's date as the initial selection.
 119:      */
 120:     public SerialDateChooserPanel() {
 121: 
 122:         this(SerialDate.createInstance(new Date()), false,
 123:              DEFAULT_DATE_BUTTON_COLOR,
 124:              DEFAULT_MONTH_BUTTON_COLOR);
 125: 
 126:     }
 127: 
 128:     /**
 129:      * Constructs a new date chooser panel.
 130:      *
 131:      * @param date  the date.
 132:      * @param controlPanel  a flag that indicates whether or not the 'today' button should
 133:      *                      appear on the panel.
 134:      */
 135:     public SerialDateChooserPanel(final SerialDate date, final boolean controlPanel) {
 136: 
 137:         this(date, controlPanel,
 138:              DEFAULT_DATE_BUTTON_COLOR,
 139:              DEFAULT_MONTH_BUTTON_COLOR);
 140: 
 141:     }
 142: 
 143:     /**
 144:      * Constructs a new date chooser panel.
 145:      *
 146:      * @param date  the date.
 147:      * @param controlPanel  the control panel.
 148:      * @param dateButtonColor  the date button color.
 149:      * @param monthButtonColor  the month button color.
 150:      */
 151:     public SerialDateChooserPanel(final SerialDate date, final boolean controlPanel,
 152:                                   final Color dateButtonColor, final Color monthButtonColor) {
 153: 
 154:         super(new BorderLayout());
 155: 
 156:         this.date = date;
 157:         this.dateButtonColor = dateButtonColor;
 158:         this.monthButtonColor = monthButtonColor;
 159: 
 160:         add(constructSelectionPanel(), BorderLayout.NORTH);
 161:         add(getCalendarPanel(), BorderLayout.CENTER);
 162:         if (controlPanel) {
 163:             add(constructControlPanel(), BorderLayout.SOUTH);
 164:         }
 165: 
 166:     }
 167: 
 168:     /**
 169:      * Sets the date chosen in the panel.
 170:      *
 171:      * @param date  the new date.
 172:      */
 173:     public void setDate(final SerialDate date) {
 174: 
 175:         this.date = date;
 176:         this.monthSelector.setSelectedIndex(date.getMonth() - 1);
 177:         refreshYearSelector();
 178:         refreshButtons();
 179: 
 180:     }
 181: 
 182:     /**
 183:      * Returns the date selected in the panel.
 184:      *
 185:      * @return the selected date.
 186:      */
 187:     public SerialDate getDate() {
 188:         return this.date;
 189:     }
 190: 
 191:     /**
 192:      * Handles action-events from the date panel.
 193:      *
 194:      * @param e information about the event that occurred.
 195:      */
 196:     public void actionPerformed(final ActionEvent e) {
 197: 
 198:         if (e.getActionCommand().equals("monthSelectionChanged")) {
 199:             final JComboBox c = (JComboBox) e.getSource();
 200:             this.date = SerialDate.createInstance(
 201:                 this.date.getDayOfMonth(), c.getSelectedIndex() + 1, this.date.getYYYY()
 202:             );
 203:             refreshButtons();
 204:         }
 205:         else if (e.getActionCommand().equals("yearSelectionChanged")) {
 206:             if (!this.refreshing) {
 207:                 final JComboBox c = (JComboBox) e.getSource();
 208:                 final Integer y = (Integer) c.getSelectedItem();
 209:                 this.date = SerialDate.createInstance(
 210:                     this.date.getDayOfMonth(), this.date.getMonth(), y.intValue()
 211:                 );
 212:                 refreshYearSelector();
 213:                 refreshButtons();
 214:             }
 215:         }
 216:         else if (e.getActionCommand().equals("todayButtonClicked")) {
 217:             setDate(SerialDate.createInstance(new Date()));
 218:         }
 219:         else if (e.getActionCommand().equals("dateButtonClicked")) {
 220:             final JButton b = (JButton) e.getSource();
 221:             final int i = Integer.parseInt(b.getName());
 222:             final SerialDate first = getFirstVisibleDate();
 223:             final SerialDate selected = SerialDate.addDays(i, first);
 224:             setDate(selected);
 225:         }
 226: 
 227:     }
 228: 
 229:     /**
 230:      * Returns a panel of buttons, each button representing a day in the month.  This is a
 231:      * sub-component of the DatePanel.
 232:      *
 233:      * @return the panel.
 234:      */
 235:     private JPanel getCalendarPanel() {
 236: 
 237:         final JPanel panel = new JPanel(new GridLayout(7, 7));
 238:         panel.add(new JLabel("Sun", SwingConstants.CENTER));
 239:         panel.add(new JLabel("Mon", SwingConstants.CENTER));
 240:         panel.add(new JLabel("Tue", SwingConstants.CENTER));
 241:         panel.add(new JLabel("Wed", SwingConstants.CENTER));
 242:         panel.add(new JLabel("Thu", SwingConstants.CENTER));
 243:         panel.add(new JLabel("Fri", SwingConstants.CENTER));
 244:         panel.add(new JLabel("Sat", SwingConstants.CENTER));
 245: 
 246:         this.buttons = new JButton[42];
 247:         for (int i = 0; i < 42; i++) {
 248:             final JButton button = new JButton("");
 249:             button.setMargin(new Insets(1, 1, 1, 1));
 250:             button.setName(Integer.toString(i));
 251:             button.setFont(this.dateFont);
 252:             button.setFocusPainted(false);
 253:             button.setActionCommand("dateButtonClicked");
 254:             button.addActionListener(this);
 255:             this.buttons[i] = button;
 256:             panel.add(button);
 257:         }
 258:         return panel;
 259: 
 260:     }
 261: 
 262:     /**
 263:      * Returns the button color according to the specified date.
 264:      *
 265:      * @param targetDate  the target date.
 266:      *
 267:      * @return the button color.
 268:      */
 269:     protected Color getButtonColor(final SerialDate targetDate) {
 270: 
 271:         if (this.date.equals(this.date)) {
 272:             return this.dateButtonColor;
 273:         }
 274:         else if (targetDate.getMonth() == this.date.getMonth()) {
 275:             return this.monthButtonColor;
 276:         }
 277:         else {
 278:             return this.chosenOtherButtonColor;
 279:         }
 280: 
 281:     }
 282: 
 283:     /**
 284:      * Returns the first date that is visible in the grid.  This should always be in the month
 285:      * preceding the month of the selected date.
 286:      *
 287:      * @return the first visible date.
 288:      */
 289:     protected SerialDate getFirstVisibleDate() {
 290: 
 291:         SerialDate result = SerialDate.createInstance(1, this.date.getMonth(), this.date.getYYYY());
 292:         result = SerialDate.addDays(-1, result);
 293:         while (result.getDayOfWeek() != getFirstDayOfWeek()) {
 294:             result = SerialDate.addDays(-1, result);
 295:         }
 296:         return result;
 297: 
 298:     }
 299: 
 300:     /**
 301:      * Returns the first day of the week (controls the labels in the date panel).
 302:      *
 303:      * @return the first day of the week.
 304:      */
 305:     private int getFirstDayOfWeek() {
 306:         return this.firstDayOfWeek;
 307:     }
 308: 
 309:     /**
 310:      * Update the button labels and colors to reflect date selection.
 311:      */
 312:     protected void refreshButtons() {
 313: 
 314:         SerialDate current = getFirstVisibleDate();
 315:         for (int i = 0; i < 42; i++) {
 316:             final JButton button = this.buttons[i];
 317:             button.setText(String.valueOf(current.getDayOfWeek()));
 318:             button.setBackground(getButtonColor(current));
 319:             current = SerialDate.addDays(1, current);
 320:         }
 321: 
 322:     }
 323: 
 324:     /**
 325:      * Changes the contents of the year selection JComboBox to reflect the chosen date and the year
 326:      * range.
 327:      */
 328:     private void refreshYearSelector() {
 329:         if (!this.refreshing) {
 330:             this.refreshing = true;
 331:             this.yearSelector.removeAllItems();
 332:             final Vector v = getYears(this.date.getYYYY());
 333:             for (Enumeration e = v.elements(); e.hasMoreElements();) {
 334:                 this.yearSelector.addItem(e.nextElement());
 335:             }
 336:             this.yearSelector.setSelectedItem(new Integer(this.date.getYYYY()));
 337:             this.refreshing = false;
 338:         }
 339:     }
 340: 
 341:     /**
 342:      * Returns a vector of years preceding and following the specified year.  The number of years
 343:      * preceding and following is determined by the yearSelectionRange attribute.
 344:      *
 345:      * @param chosenYear  the current year.
 346:      *
 347:      * @return a vector of years.
 348:      */
 349:     private Vector getYears(final int chosenYear) {
 350:         final Vector v = new Vector();
 351:         for (int i = chosenYear - this.yearSelectionRange; 
 352:             i <= chosenYear + this.yearSelectionRange; i++) {
 353:             v.addElement(new Integer(i));
 354:         }
 355:         return v;
 356:     }
 357: 
 358:     /**
 359:      * Constructs a panel containing two JComboBoxes (for the month and year) and a button
 360:      * (to reset the date to TODAY).
 361:      *
 362:      * @return the panel.
 363:      */
 364:     private JPanel constructSelectionPanel() {
 365:         final JPanel p = new JPanel();
 366:         this.monthSelector = new JComboBox(SerialDate.getMonths());
 367:         this.monthSelector.addActionListener(this);
 368:         this.monthSelector.setActionCommand("monthSelectionChanged");
 369:         p.add(this.monthSelector);
 370: 
 371:         this.yearSelector = new JComboBox(getYears(0));
 372:         this.yearSelector.addActionListener(this);
 373:         this.yearSelector.setActionCommand("yearSelectionChanged");
 374:         p.add(this.yearSelector);
 375: 
 376:         return p;
 377:     }
 378: 
 379:     /**
 380:      * Returns a panel that appears at the bottom of the calendar panel - contains a button for
 381:      * selecting today's date.
 382:      *
 383:      * @return the panel.
 384:      */
 385:     private JPanel constructControlPanel() {
 386: 
 387:         final JPanel p = new JPanel();
 388:         p.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
 389:         this.todayButton = new JButton("Today");
 390:         this.todayButton.addActionListener(this);
 391:         this.todayButton.setActionCommand("todayButtonClicked");
 392:         p.add(this.todayButton);
 393:         return p;
 394: 
 395:     }
 396: 
 397: }