001: /* ========================================================================
002: * JCommon : a free general purpose class library for the Java(tm) platform
003: * ========================================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jcommon/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * ---------------------------
028: * SerialDateChooserPanel.java
029: * ---------------------------
030: * (C) Copyright 2001-2005, by Object Refinery Limited.
031: *
032: * Original Author: David Gilbert (for Object Refinery Limited);
033: * Contributor(s): -;
034: *
035: * $Id: SerialDateChooserPanel.java,v 1.6 2005/11/16 15:58:41 taqua Exp $
036: *
037: * Changes
038: * -------
039: * 08-Dec-2001 : Version 1 (DG);
040: * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG);
041: *
042: */
043:
044: package org.jfree.ui;
045:
046: import java.awt.BorderLayout;
047: import java.awt.Color;
048: import java.awt.Font;
049: import java.awt.GridLayout;
050: import java.awt.Insets;
051: import java.awt.event.ActionEvent;
052: import java.awt.event.ActionListener;
053: import java.util.Calendar;
054: import java.util.Date;
055: import java.util.Enumeration;
056: import java.util.Vector;
057:
058: import javax.swing.BorderFactory;
059: import javax.swing.JButton;
060: import javax.swing.JComboBox;
061: import javax.swing.JLabel;
062: import javax.swing.JPanel;
063: import javax.swing.SwingConstants;
064:
065: import org.jfree.date.SerialDate;
066:
067: /**
068: * A panel that allows the user to select a date.
069: * <P>
070: * This class is incomplete and untested. You should not use it yet...
071: *
072: * @author David Gilbert
073: */
074: public class SerialDateChooserPanel extends JPanel implements
075: ActionListener {
076:
077: /** The default background color for the selected date. */
078: public static final Color DEFAULT_DATE_BUTTON_COLOR = Color.red;
079:
080: /** The default background color for the current month. */
081: public static final Color DEFAULT_MONTH_BUTTON_COLOR = Color.lightGray;
082:
083: /** The date selected in the panel. */
084: private SerialDate date;
085:
086: /** The color for the selected date. */
087: private Color dateButtonColor;
088:
089: /** The color for dates in the current month. */
090: private Color monthButtonColor;
091:
092: /** The color for dates that are visible, but not in the current month. */
093: private Color chosenOtherButtonColor = Color.darkGray;
094:
095: /** The first day-of-the-week. */
096: private int firstDayOfWeek = Calendar.SUNDAY;
097:
098: /** The range used for selecting years. */
099: private int yearSelectionRange = 20;
100:
101: /** The font used to display the date. */
102: private Font dateFont = new Font("SansSerif", Font.PLAIN, 10);
103:
104: /** A combo for selecting the month. */
105: private JComboBox monthSelector = null;
106:
107: /** A combo for selecting the year. */
108: private JComboBox yearSelector = null;
109:
110: /** A button for selecting today's date. */
111: private JButton todayButton = null;
112:
113: /** An array of buttons used to display the days-of-the-month. */
114: private JButton[] buttons = null;
115:
116: /** A flag that indicates whether or not we are currently refreshing the buttons. */
117: private boolean refreshing = false;
118:
119: /**
120: * Constructs a new date chooser panel, using today's date as the initial selection.
121: */
122: public SerialDateChooserPanel() {
123:
124: this (SerialDate.createInstance(new Date()), false,
125: DEFAULT_DATE_BUTTON_COLOR, 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,
137: final boolean controlPanel) {
138:
139: this (date, controlPanel, 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,
153: final boolean controlPanel, final Color dateButtonColor,
154: final Color monthButtonColor) {
155:
156: super (new BorderLayout());
157:
158: this .date = date;
159: this .dateButtonColor = dateButtonColor;
160: this .monthButtonColor = monthButtonColor;
161:
162: add(constructSelectionPanel(), BorderLayout.NORTH);
163: add(getCalendarPanel(), BorderLayout.CENTER);
164: if (controlPanel) {
165: add(constructControlPanel(), BorderLayout.SOUTH);
166: }
167:
168: }
169:
170: /**
171: * Sets the date chosen in the panel.
172: *
173: * @param date the new date.
174: */
175: public void setDate(final SerialDate date) {
176:
177: this .date = date;
178: this .monthSelector.setSelectedIndex(date.getMonth() - 1);
179: refreshYearSelector();
180: refreshButtons();
181:
182: }
183:
184: /**
185: * Returns the date selected in the panel.
186: *
187: * @return the selected date.
188: */
189: public SerialDate getDate() {
190: return this .date;
191: }
192:
193: /**
194: * Handles action-events from the date panel.
195: *
196: * @param e information about the event that occurred.
197: */
198: public void actionPerformed(final ActionEvent e) {
199:
200: if (e.getActionCommand().equals("monthSelectionChanged")) {
201: final JComboBox c = (JComboBox) e.getSource();
202: this .date = SerialDate.createInstance(this .date
203: .getDayOfMonth(), c.getSelectedIndex() + 1,
204: this .date.getYYYY());
205: refreshButtons();
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(this .date
211: .getDayOfMonth(), this .date.getMonth(), y
212: .intValue());
213: refreshYearSelector();
214: refreshButtons();
215: }
216: } else if (e.getActionCommand().equals("todayButtonClicked")) {
217: setDate(SerialDate.createInstance(new Date()));
218: } else if (e.getActionCommand().equals("dateButtonClicked")) {
219: final JButton b = (JButton) e.getSource();
220: final int i = Integer.parseInt(b.getName());
221: final SerialDate first = getFirstVisibleDate();
222: final SerialDate selected = SerialDate.addDays(i, first);
223: setDate(selected);
224: }
225:
226: }
227:
228: /**
229: * Returns a panel of buttons, each button representing a day in the month. This is a
230: * sub-component of the DatePanel.
231: *
232: * @return the panel.
233: */
234: private JPanel getCalendarPanel() {
235:
236: final JPanel panel = new JPanel(new GridLayout(7, 7));
237: panel.add(new JLabel("Sun", SwingConstants.CENTER));
238: panel.add(new JLabel("Mon", SwingConstants.CENTER));
239: panel.add(new JLabel("Tue", SwingConstants.CENTER));
240: panel.add(new JLabel("Wed", SwingConstants.CENTER));
241: panel.add(new JLabel("Thu", SwingConstants.CENTER));
242: panel.add(new JLabel("Fri", SwingConstants.CENTER));
243: panel.add(new JLabel("Sat", SwingConstants.CENTER));
244:
245: this .buttons = new JButton[42];
246: for (int i = 0; i < 42; i++) {
247: final JButton button = new JButton("");
248: button.setMargin(new Insets(1, 1, 1, 1));
249: button.setName(Integer.toString(i));
250: button.setFont(this .dateFont);
251: button.setFocusPainted(false);
252: button.setActionCommand("dateButtonClicked");
253: button.addActionListener(this );
254: this .buttons[i] = button;
255: panel.add(button);
256: }
257: return panel;
258:
259: }
260:
261: /**
262: * Returns the button color according to the specified date.
263: *
264: * @param targetDate the target date.
265: *
266: * @return the button color.
267: */
268: protected Color getButtonColor(final SerialDate targetDate) {
269:
270: if (this .date.equals(this .date)) {
271: return this .dateButtonColor;
272: } else if (targetDate.getMonth() == this .date.getMonth()) {
273: return this .monthButtonColor;
274: } else {
275: return this .chosenOtherButtonColor;
276: }
277:
278: }
279:
280: /**
281: * Returns the first date that is visible in the grid. This should always be in the month
282: * preceding the month of the selected date.
283: *
284: * @return the first visible date.
285: */
286: protected SerialDate getFirstVisibleDate() {
287:
288: SerialDate result = SerialDate.createInstance(1, this .date
289: .getMonth(), this .date.getYYYY());
290: result = SerialDate.addDays(-1, result);
291: while (result.getDayOfWeek() != getFirstDayOfWeek()) {
292: result = SerialDate.addDays(-1, result);
293: }
294: return result;
295:
296: }
297:
298: /**
299: * Returns the first day of the week (controls the labels in the date panel).
300: *
301: * @return the first day of the week.
302: */
303: private int getFirstDayOfWeek() {
304: return this .firstDayOfWeek;
305: }
306:
307: /**
308: * Update the button labels and colors to reflect date selection.
309: */
310: protected void refreshButtons() {
311:
312: SerialDate current = getFirstVisibleDate();
313: for (int i = 0; i < 42; i++) {
314: final JButton button = this .buttons[i];
315: button.setText(String.valueOf(current.getDayOfWeek()));
316: button.setBackground(getButtonColor(current));
317: current = SerialDate.addDays(1, current);
318: }
319:
320: }
321:
322: /**
323: * Changes the contents of the year selection JComboBox to reflect the chosen date and the year
324: * range.
325: */
326: private void refreshYearSelector() {
327: if (!this .refreshing) {
328: this .refreshing = true;
329: this .yearSelector.removeAllItems();
330: final Vector v = getYears(this .date.getYYYY());
331: for (Enumeration e = v.elements(); e.hasMoreElements();) {
332: this .yearSelector.addItem(e.nextElement());
333: }
334: this .yearSelector.setSelectedItem(new Integer(this .date
335: .getYYYY()));
336: this .refreshing = false;
337: }
338: }
339:
340: /**
341: * Returns a vector of years preceding and following the specified year. The number of years
342: * preceding and following is determined by the yearSelectionRange attribute.
343: *
344: * @param chosenYear the current year.
345: *
346: * @return a vector of years.
347: */
348: private Vector getYears(final int chosenYear) {
349: final Vector v = new Vector();
350: for (int i = chosenYear - this .yearSelectionRange; i <= chosenYear
351: + this .yearSelectionRange; i++) {
352: v.addElement(new Integer(i));
353: }
354: return v;
355: }
356:
357: /**
358: * Constructs a panel containing two JComboBoxes (for the month and year) and a button
359: * (to reset the date to TODAY).
360: *
361: * @return the panel.
362: */
363: private JPanel constructSelectionPanel() {
364: final JPanel p = new JPanel();
365: this .monthSelector = new JComboBox(SerialDate.getMonths());
366: this .monthSelector.addActionListener(this );
367: this .monthSelector.setActionCommand("monthSelectionChanged");
368: p.add(this .monthSelector);
369:
370: this .yearSelector = new JComboBox(getYears(0));
371: this .yearSelector.addActionListener(this );
372: this .yearSelector.setActionCommand("yearSelectionChanged");
373: p.add(this .yearSelector);
374:
375: return p;
376: }
377:
378: /**
379: * Returns a panel that appears at the bottom of the calendar panel - contains a button for
380: * selecting today's date.
381: *
382: * @return the panel.
383: */
384: private JPanel constructControlPanel() {
385:
386: final JPanel p = new JPanel();
387: p.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
388: this .todayButton = new JButton("Today");
389: this .todayButton.addActionListener(this );
390: this .todayButton.setActionCommand("todayButtonClicked");
391: p.add(this.todayButton);
392: return p;
393:
394: }
395:
396: }
|