All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jdesktop.swingx.calendar.JXMonthView Maven / Gradle / Ivy

/*
 * $Id: JXMonthView.java,v 1.47 2007/09/13 12:50:25 kleopatra Exp $
 *
 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.jdesktop.swingx.calendar;

import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.Date;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeSet;

import javax.swing.JComponent;
import javax.swing.Timer;
import javax.swing.UIManager;

import org.jdesktop.swingx.DateSelectionModel;
import org.jdesktop.swingx.DefaultDateSelectionModel;
import org.jdesktop.swingx.event.EventListenerMap;
import org.jdesktop.swingx.plaf.JXMonthViewAddon;
import org.jdesktop.swingx.plaf.LookAndFeelAddons;
import org.jdesktop.swingx.plaf.MonthViewUI;
import org.jdesktop.swingx.util.Contract;


/**
 * Component that displays a month calendar which can be used to select a day
 * or range of days.  By default the JXMonthView will display a
 * single calendar using the current month and year, using
 * Calendar.SUNDAY as the first day of the week.
 * 

* The JXMonthView can be configured to display more than one * calendar at a time by calling * setPreferredCalCols/setPreferredCalRows. These * methods will set the preferred number of calendars to use in each * column/row. As these values change, the Dimension returned * from getMinimumSize and getPreferredSize will * be updated. The following example shows how to create a 2x2 view which is * contained within a JFrame: *

 *     JXMonthView monthView = new JXMonthView();
 *     monthView.setPreferredCols(2);
 *     monthView.setPreferredRows(2);
 *
 *     JFrame frame = new JFrame();
 *     frame.getContentPane().add(monthView);
 *     frame.pack();
 *     frame.setVisible(true);
 * 
*

* JXMonthView can be further configured to allow any day of the * week to be considered the first day of the week. Character * representation of those days may also be set by providing an array of * strings. *

 *    monthView.setFirstDayOfWeek(Calendar.MONDAY);
 *    monthView.setDaysOfTheWeek(
 *            new String[]{"S", "M", "T", "W", "Th", "F", "S"});
 * 
*

* This component supports flagging days. These flagged days are displayed * in a bold font. This can be used to inform the user of such things as * scheduled appointment. *

 *    // Create some dates that we want to flag as being important.
 *    Calendar cal1 = Calendar.getInstance();
 *    cal1.set(2004, 1, 1);
 *    Calendar cal2 = Calendar.getInstance();
 *    cal2.set(2004, 1, 5);
 *
 *    long[] flaggedDates = new long[] {
 *        cal1.getTimeInMillis(),
 *        cal2.getTimeInMillis(),
 *        System.currentTimeMillis()
 *    };
 *
 *    monthView.setFlaggedDates(flaggedDates);
 * 
* Applications may have the need to allow users to select different ranges of * dates. There are four modes of selection that are supported, single, * multiple, week and no selection. Once a selection is made an action is * fired, with exception of the no selection mode, to inform listeners that * selection has changed. *
 *    // Change the selection mode to select full weeks.
 *    monthView.setSelectionMode(JXMonthView.WEEK_INTERVAL_SELECTION);
 *
 *    // Add an action listener that will be notified when the user
 *    // changes selection via the mouse.
 *    monthView.getSelectionModel().addDateSelectionListener(new DateSelectionListener {
 *        public void valueChanged(DateSelectionEvent e) {
 *            System.out.println(e.getSelection());
 *        }
 *    });
 * 
* * @author Joshua Outwater * @version $Revision: 1.47 $ */ public class JXMonthView extends JComponent { public static enum SelectionMode { /** * Mode that disallows selection of days from the calendar. */ NO_SELECTION, /** * Mode that allows for selection of a single day. */ SINGLE_SELECTION, /** * Mode that allows for selecting of multiple consecutive days. */ SINGLE_INTERVAL_SELECTION, /** * Mode that allows for selecting disjoint days. */ MULTIPLE_INTERVAL_SELECTION, /** * Mode where selections consisting of more than 7 days will * snap to a full week. */ WEEK_INTERVAL_SELECTION } /** action command used for commit actionEvent. */ public static final String COMMIT_KEY = "monthViewCommit"; /** action command used for cancel actionEvent. */ public static final String CANCEL_KEY = "monthViewCancel"; public static final String BOX_PADDING_X = "boxPaddingX"; public static final String BOX_PADDING_Y = "boxPaddingY"; public static final String DAYS_OF_THE_WEEK = "daysOfTheWeek"; public static final String ENSURE_DATE_VISIBILITY = "ensureDateVisibility"; public static final String FIRST_DISPLAYED_DATE = "firstDisplayedDate"; public static final String FIRST_DISPLAYED_MONTH = "firstDisplayedMonth"; public static final String FIRST_DISPLAYED_YEAR = "firstDisplayedYear"; public static final String SELECTION_MODEL = "selectionModel"; public static final String SHOW_LEADING_DATES = "showLeadingDates"; public static final String SHOW_TRAILING_DATES = "showTrailingDates"; public static final String TRAVERSABLE = "traversable"; public static final String WEEK_NUMBER = "weekNumber"; public static final String FLAGGED_DATES = "flaggedDates"; /** Return value used to identify when the month down button is pressed. */ public static final int MONTH_DOWN = 1; /** Return value used to identify when the month up button is pressed. */ public static final int MONTH_UP = 2; @SuppressWarnings({"unused"}) private static final int MONTH_TRAVERSABLE = 1; @SuppressWarnings({"unused"}) private static final int YEAR_TRAVERSABLE = 2; static { LookAndFeelAddons.contribute(new JXMonthViewAddon()); } /** * UI Class ID */ public static final String uiClassID = "MonthViewUI"; public static final int DAYS_IN_WEEK = 7; public static final int MONTHS_IN_YEAR = 12; /** * Insets used in determining the rectangle for the month string * background. */ protected Insets _monthStringInsets = new Insets(0, 0, 0, 0); /** * Keeps track of the first date we are displaying. We use this as a * restore point for the calendar. */ private long firstDisplayedDate; private int firstDisplayedMonth; private int firstDisplayedYear; private long lastDisplayedDate; private int boxPaddingX; private int boxPaddingY; private int minCalCols = 1; private int minCalRows = 1; private long today; private TreeSet flaggedDates; private int firstDayOfWeek; private boolean antiAlias; private boolean traversable; private boolean leadingDates; private boolean trailingDates; private Calendar cal; private String[] _daysOfTheWeek; private Color todayBackgroundColor; private Color monthStringBackground; private Color monthStringForeground; private Color daysOfTheWeekForeground; private Color selectedBackground; private String actionCommand = "selectionChanged"; private Timer todayTimer = null; private Hashtable dayToColorTable = new Hashtable(); private Color flaggedDayForeground; private boolean showWeekNumber; private DateSelectionModel model; private EventListenerMap listenerMap; private SelectionMode selectionMode; @SuppressWarnings({"FieldCanBeLocal"}) private Date modifyedStartDate; @SuppressWarnings({"FieldCanBeLocal"}) private Date modifyedEndDate; private boolean componentInputMapEnabled; /** * Create a new instance of the JXMonthView class using the * month and year of the current day as the first date to display. */ public JXMonthView() { this(System.currentTimeMillis(), null); } /** * Create a new instance of the JXMonthView class using the * month and year from initialTime as the first date to * display. * * @param firstDisplayedDate The first month to display. */ public JXMonthView(long firstDisplayedDate) { this(firstDisplayedDate, null); } public JXMonthView(long firstDisplayedDate, final DateSelectionModel model) { antiAlias = false; traversable = false; listenerMap = new EventListenerMap(); selectionMode = SelectionMode.SINGLE_SELECTION; this.model = model; if (this.model == null) { this.model = new DefaultDateSelectionModel(); } updateUI(); // Set up calendar instance cal = Calendar.getInstance(getLocale()); firstDayOfWeek = cal.getFirstDayOfWeek(); cal.setFirstDayOfWeek(firstDayOfWeek); cal.setMinimalDaysInFirstWeek(1); // Keep track of today setToday(cleanupDate(cal.getTimeInMillis())); // Set the first displayed date setFirstDisplayedDate(cleanupDate(firstDisplayedDate)); setFocusable(true); todayBackgroundColor = getForeground(); // Restore original time value cal.setTimeInMillis(this.firstDisplayedDate); } /** * @inheritDoc */ public MonthViewUI getUI() { return (MonthViewUI)ui; } /** * Sets the L&F object that renders this component. * * @param ui UI to use for this {@code JXMonthView} */ public void setUI(MonthViewUI ui) { super.setUI(ui); } /** * Resets the UI property with the value from the current look and feel. * * @see UIManager#getUI */ @Override public void updateUI() { setUI((MonthViewUI)LookAndFeelAddons.getUI(this, MonthViewUI.class)); invalidate(); } /** * @inheritDoc */ @Override public String getUIClassID() { return uiClassID; } /** * Returns the first displayed date. * * @return long The first displayed date. */ public long getFirstDisplayedDate() { return firstDisplayedDate; } /** * Set the first displayed date. We only use the month and year of * this date. The Calendar.DAY_OF_MONTH field is reset to * 1 and all other fields, with exception of the year and month, * are reset to 0. * * @param date The first displayed date. */ public void setFirstDisplayedDate(long date) { long oldFirstDisplayedDate = firstDisplayedDate; int oldFirstDisplayedMonth = firstDisplayedMonth; int oldFirstDisplayedYear = firstDisplayedYear; cal.setTimeInMillis(cleanupDate(date)); cal.set(Calendar.DAY_OF_MONTH, 1); firstDisplayedDate = cal.getTimeInMillis(); firstDisplayedMonth = cal.get(Calendar.MONTH); firstDisplayedYear = cal.get(Calendar.YEAR); firePropertyChange(FIRST_DISPLAYED_DATE, oldFirstDisplayedDate, firstDisplayedDate); firePropertyChange(FIRST_DISPLAYED_MONTH, oldFirstDisplayedMonth, firstDisplayedMonth); firePropertyChange(FIRST_DISPLAYED_YEAR, oldFirstDisplayedYear, firstDisplayedYear); calculateLastDisplayedDate(); repaint(); } /** * Returns the last date able to be displayed. For example, if the last * visible month was April the time returned would be April 30, 23:59:59. * * @return long The last displayed date. */ public long getLastDisplayedDate() { return lastDisplayedDate; } private void calculateLastDisplayedDate() { lastDisplayedDate = getUI().calculateLastDisplayedDate(); } /** * Moves the date into the visible region of the calendar. * If the date is greater than the last visible date it will become the * last visible date. While if it is less than the first visible date * it will become the first visible date. * * @param date Date to make visible. */ public void ensureDateVisible(long date) { if (date < firstDisplayedDate) { setFirstDisplayedDate(date); } else if (date > lastDisplayedDate) { cal.setTimeInMillis(date); int month = cal.get(Calendar.MONTH); int year = cal.get(Calendar.YEAR); cal.setTimeInMillis(lastDisplayedDate); int lastMonth = cal.get(Calendar.MONTH); int lastYear = cal.get(Calendar.YEAR); int diffMonths = month - lastMonth + ((year - lastYear) * MONTHS_IN_YEAR); cal.setTimeInMillis(firstDisplayedDate); cal.add(Calendar.MONTH, diffMonths); setFirstDisplayedDate(cal.getTimeInMillis()); } firePropertyChange(ENSURE_DATE_VISIBILITY, null, date); } /** * Returns a date span of the selected dates. The result will be null if * no dates are selected. * * @deprecated see #getSelection * @return Date span of the selected dates. */ @Deprecated public DateSpan getSelectedDateSpan() { DateSpan result = null; Iterator itr = getSelection().iterator(); if (itr.hasNext()) { Date date = itr.next(); result = new DateSpan(date, date); } return result; } /** * Selects the dates in the DateSpan. This method will not change the * initial date displayed so the caller must update this if necessary. * If we are in SINGLE_SELECTION mode only the start time from the DateSpan * will be used. If we are in WEEK_INTERVAL_SELECTION mode the span will be * modified to be valid if necessary. * * @param dateSpan DateSpan defining the selected dates. Passing * null will clear the selection. * * @deprecated see #setSelectionInterval */ @Deprecated public void setSelectedDateSpan(DateSpan dateSpan) { setSelectionInterval(dateSpan.getStartAsDate(), dateSpan.getEndAsDate()); } //---------------- DateSelectionModel /** * Returns the date selection model which drives this * JXMonthView. * * @return the date selection model */ public DateSelectionModel getSelectionModel() { return model; } /** * Sets the date selection model to drive this monthView. * * @param model the selection model to use, must not be null. * @throws NullPointerException if model is null */ public void setSelectionModel(DateSelectionModel model) { Contract.asNotNull(model, "date selection model must not be null"); DateSelectionModel oldModel = this.model; this.model = model; firePropertyChange(SELECTION_MODEL, oldModel, model); } //-------------------- delegates to model /** * Clear any selection from the selection model */ public void clearSelection() { getSelectionModel().clearSelection(); } /** * Return true if the selection is empty, false otherwise * * @return true if the selection is empty, false otherwise */ public boolean isSelectionEmpty() { return getSelectionModel().isSelectionEmpty(); } /** * Get the current selection * * @return sorted set of selected dates */ public SortedSet getSelection() { return getSelectionModel().getSelection(); } /** * Adds the selection interval to the selection model. All dates are * modified to remove their hour of day, minute, second, and millisecond * before being added to the selection model. * * @param startDate Start of date range to add to the selection * @param endDate End of date range to add to the selection */ public void addSelectionInterval(Date startDate, Date endDate) { if (selectionMode != SelectionMode.NO_SELECTION) { modifyedStartDate = startDate; modifyedEndDate = endDate; if (selectionMode == SelectionMode.WEEK_INTERVAL_SELECTION) { cleanupWeekSelectionDates(startDate, endDate); } getSelectionModel().addSelectionInterval( cleanupDate(modifyedStartDate), cleanupDate(modifyedEndDate)); } } /** * Sets the selection interval to the selection model. All dates are modified to remove their hour of * day, minute, second, and millisecond before being added to the selection model. * * @param startDate Start of date range to set the selection to * @param endDate End of date range to set the selection to */ public void setSelectionInterval(final Date startDate, final Date endDate) { if (selectionMode != SelectionMode.NO_SELECTION) { modifyedStartDate = startDate; modifyedEndDate = endDate; if (selectionMode == SelectionMode.WEEK_INTERVAL_SELECTION) { cleanupWeekSelectionDates(startDate, endDate); } getSelectionModel().setSelectionInterval(cleanupDate(modifyedStartDate), cleanupDate(modifyedEndDate)); } } /** * Removes the selection interval from the selection model. All dates are modified to remove their hour of * day, minute, second, and millisecond before being added to the selection model. * * @param startDate Start of the date range to remove from the selection * @param endDate End of the date range to remove from the selection */ public void removeSelectionInterval(final Date startDate, final Date endDate) { getSelectionModel().removeSelectionInterval(cleanupDate(startDate), cleanupDate(endDate)); } /** * Returns the current selection mode for this JXMonthView. * * @return int Selection mode. */ public SelectionMode getSelectionMode() { return selectionMode; } /** * Set the selection mode for this JXMonthView. * @param selectionMode The selection mode to use for this {@code JXMonthView} */ public void setSelectionMode(final SelectionMode selectionMode) { SelectionMode oldSelectionMode = this.selectionMode; this.selectionMode = selectionMode; if (selectionMode == SelectionMode.NO_SELECTION || selectionMode == SelectionMode.SINGLE_SELECTION) { getSelectionModel().setSelectionMode(DateSelectionModel.SelectionMode.SINGLE_SELECTION); } else if (selectionMode == SelectionMode.SINGLE_INTERVAL_SELECTION || selectionMode == SelectionMode.WEEK_INTERVAL_SELECTION) { getSelectionModel().setSelectionMode(DateSelectionModel.SelectionMode.SINGLE_INTERVAL_SELECTION); } else { getSelectionModel().setSelectionMode(DateSelectionModel.SelectionMode.MULTIPLE_INTERVAL_SELECTION); } firePropertyChange("selectionMode", oldSelectionMode, this.selectionMode); } /** * Returns the selected date. * * @return the first Date in the selection or null if empty. */ public Date getSelectedDate() { SortedSet selection = getSelection(); return selection.isEmpty() ? null : selection.first(); } /** * Sets the model's selection to the given date or clears the selection if * null. * * @param newDate the selection date to set */ public void setSelectedDate(Date newDate) { if (newDate == null) { clearSelection(); } else { setSelectionInterval(newDate, newDate); } } /** * Returns true if the specified date falls within the _startSelectedDate * and _endSelectedDate range. All dates are modified to remove their hour of * day, minute, second, and millisecond before being added to the selection model. * * @param date The date to check * @return true if the date is selected, false otherwise */ public boolean isSelectedDate(Date date) { return getSelectionModel().isSelected(cleanupDate(date)); } /** * Set the lower bound date that is allowed to be selected.

* * All dates are * modified to remove their hour of day, minute, second, and millisecond * before being added to the selection model. * * @param lowerBound the lower bound, null means none. */ public void setLowerBound(Date lowerBound) { Date lower = cleanupDate(lowerBound); getSelectionModel().setLowerBound(lower); } /** * Set the upper bound date that is allowed to be selected.

* * All dates are * modified to remove their hour of day, minute, second, and millisecond * before being added to the selection model. * * @param upperBound the upper bound, null means none. */ public void setUpperBound(Date upperBound) { Date upper = cleanupDate(upperBound); getSelectionModel().setUpperBound(upper); } /** * Return the lower bound date that is allowed to be selected for this * model * * @return lower bound date or null if not set */ public Date getLowerBound() { return getSelectionModel().getLowerBound(); } /** * Return the upper bound date that is allowed to be selected for this * model * * @return upper bound date or null if not set */ public Date getUpperBound() { return getSelectionModel().getUpperBound(); } /** * Identifies whether or not the date passed is an unselectable date. *

* * All dates are modified to remove their hour of day, minute, second, * and millisecond before being added to the selection model. * * @param date date which to test for unselectable status * @return true if the date is unselectable, false otherwise */ public boolean isUnselectableDate(Date date) { return getSelectionModel().isUnselectableDate(cleanupDate(date)); } /** * Sets the dates that should be unselectable. This will replace the model's * current set of unselectable dates. The implication is that calling with * zero dates will remove all unselectable dates. *

* * NOTE: neither the given array nor any of its elements must be null. *

* All dates are modified to remove their hour of day, minute, second, * and millisecond before being added to the selection model. * * @param unselectableDates zero or more not-null dates that should be * unselectable. * @throws NullPointerException if either the array or any of the elements * are null */ public void setUnselectableDates(Date... unselectableDates) { Contract.asNotNull(unselectableDates, "unselectable dates must not be null"); SortedSet unselectableSet = new TreeSet(); for (Date unselectableDate : unselectableDates) { unselectableSet.add(cleanupDate(unselectableDate)); } getSelectionModel().setUnselectableDates(unselectableSet); repaint(); } //---------------------- delegates to model: long param /** * Returns true if the specified date falls within the _startSelectedDate * and _endSelectedDate range. All dates are modified to remove their hour of * day, minute, second, and millisecond before being added to the selection model. * * @param date The date to check * @return true if the date is selected, false otherwise */ public boolean isSelectedDate(long date) { return getSelectionModel().isSelected(new Date(cleanupDate(date))); } /** * Identifies whether or not the date passed is an unselectable date. All dates are modified to remove their * hour of day, minute, second, and millisecond before being added to the selection model. * * @param date date which to test for unselectable status * @return true if the date is unselectable, false otherwise */ public boolean isUnselectableDate(long date) { return getSelectionModel().isUnselectableDate(new Date(cleanupDate(date))); } /** * An array of longs defining days that should be unselectable. All dates are modified to remove their hour of * day, minute, second, and millisecond before being added to the selection model. * * @param unselectableDates the dates that should be unselectable */ public void setUnselectableDates(long[] unselectableDates) { SortedSet unselectableSet = new TreeSet(); if (unselectableDates != null) { for (long unselectableDate : unselectableDates) { unselectableSet.add(new Date(cleanupDate(unselectableDate))); } } getSelectionModel().setUnselectableDates(unselectableSet); repaint(); } /** * Identifies whether or not the date passed is a flagged date. All dates are modified to remove their hour of * day, minute, second, and millisecond before being added to the selection model * * @param date date which to test for flagged status * @return true if the date is flagged, false otherwise */ public boolean isFlaggedDate(long date) { boolean result = false; if (flaggedDates != null) { result = flaggedDates.contains(cleanupDate(date)); } return result; } /** * An array of longs defining days that should be flagged. * * @param flaggedDates the dates to be flagged */ public void setFlaggedDates(long[] flaggedDates) { if (flaggedDates == null) { this.flaggedDates = null; } else { this.flaggedDates = new TreeSet(); // Loop through the flaggedDates and clean them up so // the hour, minute, seconds and milliseconds to 0 so // we can compare times later. for (long flaggedDate : flaggedDates) { this.flaggedDates.add(cleanupDate(flaggedDate)); } } firePropertyChange(FLAGGED_DATES, null, this.flaggedDates); repaint(); } /** * Whether or not to show leading dates for a months displayed by this component. * * @param value true if leading dates should be displayed, false otherwise. */ public void setShowLeadingDates(boolean value) { if (leadingDates == value) { return; } leadingDates = value; firePropertyChange(SHOW_LEADING_DATES, !leadingDates, leadingDates); } /** * Whether or not we're showing leading dates. * * @return true if leading dates are shown, false otherwise. */ public boolean isShowingLeadingDates() { return leadingDates; } /** * Whether or not to show trailing dates for the months displayed by this component. * * @param value true if trailing dates should be displayed, false otherwise. */ public void setShowTrailingDates(boolean value) { if (trailingDates == value) { return; } trailingDates = value; firePropertyChange(SHOW_TRAILING_DATES, !trailingDates, trailingDates); } /** * Whether or not we're showing trailing dates. * * @return true if trailing dates are shown, false otherwise. */ public boolean isShowingTrailingDates() { return trailingDates; } private void cleanupWeekSelectionDates(Date startDate, Date endDate) { int count = 1; cal.setTime(startDate); while (cal.getTimeInMillis() < endDate.getTime()) { cal.add(Calendar.DAY_OF_MONTH, 1); count++; } if (count > JXMonthView.DAYS_IN_WEEK) { // Move the start date to the first day of the week. cal.setTime(startDate); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); int firstDayOfWeek = getFirstDayOfWeek(); int daysFromStart = dayOfWeek - firstDayOfWeek; if (daysFromStart < 0) { daysFromStart += JXMonthView.DAYS_IN_WEEK; } cal.add(Calendar.DAY_OF_MONTH, -daysFromStart); modifyedStartDate = cal.getTime(); // Move the end date to the last day of the week. cal.setTime(endDate); dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); int lastDayOfWeek = firstDayOfWeek - 1; if (lastDayOfWeek == 0) { lastDayOfWeek = Calendar.SATURDAY; } int daysTillEnd = lastDayOfWeek - dayOfWeek; if (daysTillEnd < 0) { daysTillEnd += JXMonthView.DAYS_IN_WEEK; } cal.add(Calendar.DAY_OF_MONTH, daysTillEnd); modifyedEndDate = cal.getTime(); } } private Date cleanupDate(Date date) { // only modify defensive copies return new Date(cleanupDate(date.getTime())); } private long cleanupDate(long date) { cal.setTimeInMillis(date); // We only want to compare the day, month and year // so reset all other values to 0. cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTimeInMillis(); } /** * Returns the padding used between days in the calendar. * * @return Padding used between days in the calendar */ public int getBoxPaddingX() { return boxPaddingX; } /** * Sets the number of pixels used to pad the left and right side of a day. * The padding is applied to both sides of the days. Therefore, if you * used the padding value of 3, the number of pixels between any two days * would be 6. * * @param boxPaddingX Number of pixels applied to both sides of a day */ public void setBoxPaddingX(int boxPaddingX) { int oldBoxPadding = this.boxPaddingX; this.boxPaddingX = boxPaddingX; firePropertyChange(BOX_PADDING_X, oldBoxPadding, this.boxPaddingX); } /** * Returns the padding used above and below days in the calendar. * * @return Padding used between dats in the calendar */ public int getBoxPaddingY() { return boxPaddingY; } /** * Sets the number of pixels used to pad the top and bottom of a day. * The padding is applied to both the top and bottom of a day. Therefore, * if you used the padding value of 3, the number of pixels between any * two days would be 6. * * @param boxPaddingY Number of pixels applied to top and bottom of a day */ public void setBoxPaddingY(int boxPaddingY) { int oldBoxPadding = this.boxPaddingY; this.boxPaddingY = boxPaddingY; firePropertyChange(BOX_PADDING_Y, oldBoxPadding, this.boxPaddingY); } /** * Returns whether or not the month view supports traversing months. * * @return true if month traversing is enabled. */ public boolean isTraversable() { return traversable; } /** * Set whether or not the month view will display buttons to allow the * user to traverse to previous or next months. * * @param traversable set to true to enable month traversing, * false otherwise. */ public void setTraversable(boolean traversable) { if (traversable != this.traversable) { this.traversable = traversable; firePropertyChange(TRAVERSABLE, !this.traversable, this.traversable); repaint(); } } /** * Returns whether or not this JXMonthView should display * week number. * * @return true if week numbers should be displayed */ public boolean isShowingWeekNumber() { return showWeekNumber; } /** * Set whether or not this JXMonthView will display week * numbers or not. * * @param showWeekNumber true if week numbers should be displayed, * false otherwise */ public void setShowingWeekNumber(boolean showWeekNumber) { if (this.showWeekNumber != showWeekNumber) { this.showWeekNumber = showWeekNumber; firePropertyChange(WEEK_NUMBER, !this.showWeekNumber, showWeekNumber); repaint(); } } /** * Sets the single character representation for each day of the * week. For this method the first days of the week days[0] is assumed to * be Calendar.SUNDAY. * * @param days Array of characters that represents each day * @throws IllegalArgumentException if days.length != DAYS_IN_WEEK * @throws NullPointerException if days == null */ public void setDaysOfTheWeek(String[] days) throws IllegalArgumentException, NullPointerException { if (days == null) { throw new NullPointerException("Array of days is null."); } else if (days.length != DAYS_IN_WEEK) { throw new IllegalArgumentException( "Array of days is not of length " + DAYS_IN_WEEK + " as expected."); } String[] oldValue = _daysOfTheWeek; _daysOfTheWeek = days; firePropertyChange(DAYS_OF_THE_WEEK, oldValue, _daysOfTheWeek); repaint(); } /** * Returns the single character representation for each day of the * week. * * @return Single character representation for the days of the week */ public String[] getDaysOfTheWeek() { String[] days = new String[DAYS_IN_WEEK]; System.arraycopy(_daysOfTheWeek, 0, days, 0, DAYS_IN_WEEK); return days; } /** * Gets what the first day of the week is; e.g., * Calendar.SUNDAY in the U.S., Calendar.MONDAY * in France. * * @return int The first day of the week. */ public int getFirstDayOfWeek() { return firstDayOfWeek; } /** * Sets what the first day of the week is; e.g., * Calendar.SUNDAY in US, Calendar.MONDAY * in France. * * @param firstDayOfWeek The first day of the week. * @see java.util.Calendar */ public void setFirstDayOfWeek(int firstDayOfWeek) { if (firstDayOfWeek == this.firstDayOfWeek) { return; } int oldFirstDayOfWeek = this.firstDayOfWeek; this.firstDayOfWeek = firstDayOfWeek; cal.setFirstDayOfWeek(this.firstDayOfWeek); model.setFirstDayOfWeek(this.firstDayOfWeek); firePropertyChange("firstDayOfWeek", oldFirstDayOfWeek, this.firstDayOfWeek); repaint(); } /** * Gets the time zone. * * @return The TimeZone used by the JXMonthView. */ public TimeZone getTimeZone() { return cal.getTimeZone(); } /** * Sets the time zone with the given time zone value. * * This is a bound property. * * @param tz The TimeZone. */ public void setTimeZone(TimeZone tz) { TimeZone old =getTimeZone(); cal.setTimeZone(tz); firePropertyChange("timeZone", old, getTimeZone()); } /** * Returns true if anti-aliased text is enabled for this component, false * otherwise. * * @return boolean true if anti-aliased text is enabled, * false otherwise. */ public boolean isAntialiased() { return antiAlias; } /** * Turns on/off anti-aliased text for this component. * * @param antiAlias true for anti-aliased text, * false to turn it off. */ public void setAntialiased(boolean antiAlias) { if (this.antiAlias == antiAlias) { return; } this.antiAlias = antiAlias; firePropertyChange("antialiased", !this.antiAlias, this.antiAlias); repaint(); } /** * Returns the selected background color. * * @return the selected background color. */ public Color getSelectedBackground() { return selectedBackground; } /** * Sets the selected background color to c. The default color * is 138, 173, 209 (Blue-ish) * * @param c Selected background. */ public void setSelectedBackground(Color c) { selectedBackground = c; } /** * Returns the color used when painting the today background. * * @return Color Color */ public Color getTodayBackground() { return todayBackgroundColor; } /** * Sets the color used to draw the bounding box around today. The default * is the background of the JXMonthView component. * * @param c color to set */ public void setTodayBackground(Color c) { todayBackgroundColor = c; repaint(); } /** * Returns the color used to paint the month string background. * * @return Color Color. */ public Color getMonthStringBackground() { return monthStringBackground; } /** * Sets the color used to draw the background of the month string. The * default is 138, 173, 209 (Blue-ish). * * @param c color to set */ public void setMonthStringBackground(Color c) { monthStringBackground = c; repaint(); } /** * Returns the color used to paint the month string foreground. * * @return Color Color. */ public Color getMonthStringForeground() { return monthStringForeground; } /** * Sets the color used to draw the foreground of the month string. The * default is Color.WHITE. * * @param c color to set */ public void setMonthStringForeground(Color c) { monthStringForeground = c; repaint(); } /** * Sets the color used to draw the foreground of each day of the week. These * are the titles * * @param c color to set */ public void setDaysOfTheWeekForeground(Color c) { daysOfTheWeekForeground = c; repaint(); } /** * @return Color Color */ public Color getDaysOfTheWeekForeground() { return daysOfTheWeekForeground; } /** * Set the color to be used for painting the specified day of the week. * Acceptable values are Calendar.SUNDAY - Calendar.SATURDAY. * * @param dayOfWeek constant value defining the day of the week. * @param c The color to be used for painting the numeric day of the week. */ public void setDayForeground(int dayOfWeek, Color c) { dayToColorTable.put(dayOfWeek, c); } /** * Return the color that should be used for painting the numerical day of the week. * * @param dayOfWeek The day of week to get the color for. * @return The color to be used for painting the numeric day of the week. * If this was no color has yet been defined the component foreground color * will be returned. */ public Color getDayForeground(int dayOfWeek) { Color c; c = dayToColorTable.get(dayOfWeek); if (c == null) { c = getForeground(); } return c; } /** * Set the color to be used for painting the foreground of a flagged day. * * @param c The color to be used for painting. */ public void setFlaggedDayForeground(Color c) { flaggedDayForeground = c; } /** * Return the color that should be used for painting the foreground of the flagged day. * * @return The color to be used for painting */ public Color getFlaggedDayForeground() { return flaggedDayForeground; } /** * Returns a copy of the insets used to paint the month string background. * * @return Insets Month string insets. */ public Insets getMonthStringInsets() { return (Insets) _monthStringInsets.clone(); } /** * Insets used to modify the width/height when painting the background * of the month string area. * * @param insets Insets */ public void setMonthStringInsets(Insets insets) { if (insets == null) { _monthStringInsets.top = 0; _monthStringInsets.left = 0; _monthStringInsets.bottom = 0; _monthStringInsets.right = 0; } else { _monthStringInsets.top = insets.top; _monthStringInsets.left = insets.left; _monthStringInsets.bottom = insets.bottom; _monthStringInsets.right = insets.right; } repaint(); } /** * Returns the preferred number of columns to paint calendars in. * * @return int Columns of calendars. */ public int getPreferredCols() { return minCalCols; } /** * The preferred number of columns to paint calendars. * * @param cols The number of columns of calendars. */ public void setPreferredCols(int cols) { if (cols <= 0) { return; } minCalCols = cols; revalidate(); repaint(); } /** * Returns the preferred number of rows to paint calendars in. * * @return int Rows of calendars. */ public int getPreferredRows() { return minCalRows; } /** * Sets the preferred number of rows to paint calendars. * * @param rows The number of rows of calendars. */ public void setPreferredRows(int rows) { if (rows <= 0) { return; } minCalRows = rows; revalidate(); repaint(); } private void updateToday() { // Update today. cal.setTimeInMillis(today); cal.add(Calendar.DAY_OF_MONTH, 1); setToday(cal.getTimeInMillis()); // Restore calendar. cal.setTimeInMillis(firstDisplayedDate); repaint(); } private void setToday(long today) { long oldToday = this.today; this.today = today; firePropertyChange("today", oldToday, this.today); } /** * Moves and resizes this component to conform to the new bounding * rectangle r. This component's new position is specified by r.x and * r.y, and its new size is specified by r.width and r.height * * @param r The new bounding rectangle for this component */ @Override public void setBounds(Rectangle r) { setBounds(r.x, r.y, r.width, r.height); } /** * Sets the font of this component. * * @param font The font to become this component's font; if this parameter * is null then this component will inherit the font of its parent. */ @Override public void setFont(Font font) { Font old = getFont(); super.setFont(font); firePropertyChange("font", old, font); } /** * {@inheritDoc} */ @Override public void removeNotify() { todayTimer.stop(); super.removeNotify(); } /** * {@inheritDoc} */ @Override public void addNotify() { super.addNotify(); // Setup timer to update the value of today. int secondsTillTomorrow = 86400; if (todayTimer == null) { todayTimer = new Timer(secondsTillTomorrow * 1000, new ActionListener() { public void actionPerformed(ActionEvent e) { updateToday(); } }); } // Modify the initial delay by the current time. cal.setTimeInMillis(System.currentTimeMillis()); secondsTillTomorrow = secondsTillTomorrow - (cal.get(Calendar.HOUR_OF_DAY) * 3600) - (cal.get(Calendar.MINUTE) * 60) - cal.get(Calendar.SECOND); todayTimer.setInitialDelay(secondsTillTomorrow * 1000); todayTimer.start(); // Restore calendar cal.setTimeInMillis(firstDisplayedDate); } public Calendar getCalendar() { return cal; } /** * Return a long representing the date at the specified x/y position. * The date returned will have a valid day, month and year. Other fields * such as hour, minute, second and milli-second will be set to 0. * * @param x X position * @param y Y position * @return long The date, -1 if position does not contain a date. */ public long getDayAt(int x, int y) { return getUI().getDayAt(x, y); } /** * Returns the string currently used to identiy fired ActionEvents. * * @return String The string used for identifying ActionEvents. */ public String getActionCommand() { return actionCommand; } /** * Sets the string used to identify fired ActionEvents. * * @param actionCommand The string used for identifying ActionEvents. */ public void setActionCommand(String actionCommand) { this.actionCommand = actionCommand; } /** * Adds an ActionListener. *

* The ActionListener will receive an ActionEvent when a selection has * been made. * * @param l The ActionListener that is to be notified */ public void addActionListener(ActionListener l) { listenerMap.add(ActionListener.class, l); } /** * Removes an ActionListener. * * @param l The action listener to remove. */ public void removeActionListener(ActionListener l) { listenerMap.remove(ActionListener.class, l); } @Override @SuppressWarnings("unchecked") public T[] getListeners(Class listenerType) { java.util.List listeners = listenerMap.getListeners(listenerType); T[] result; if (!listeners.isEmpty()) { //noinspection unchecked result = (T[]) java.lang.reflect.Array.newInstance(listenerType, listeners.size()); result = listeners.toArray(result); } else { result = super.getListeners(listenerType); } return result; } /** * Creates and fires an ActionEvent with the given action * command to all listeners. * * @param actionCommand the command for the created. */ protected void fireActionPerformed(String actionCommand) { ActionListener[] listeners = getListeners(ActionListener.class); ActionEvent e = null; for (ActionListener listener : listeners) { if (e == null) { e = new ActionEvent(JXMonthView.this, ActionEvent.ACTION_PERFORMED, actionCommand); } listener.actionPerformed(e); } } /** * TODO: remove after commit/cancel are installed. * * @deprecated use {@link #commitSelection()} or {@link #cancelSelection()} */ public void postActionEvent() { // PENDING: remove fireActionPerformed(getActionCommand()); } /** * Commits the current selection.

* * Resets the model's adjusting property to false * and fires an ActionEvent * with the COMMIT_KEY action command. * *

PENDING: define what "commit selection" means ... currently * only fires (to keep the picker happy). * * @see #cancelSelection() * @see org.jdesktop.swingx.DateSelectionModel#setAdjusting(boolean) */ public void commitSelection() { getSelectionModel().setAdjusting(false); fireActionPerformed(COMMIT_KEY); } /** * Cancels the selection.

* * Resets the model's adjusting to * false and fires an ActionEvent with the CANCEL_KEY action command. * * @see #commitSelection * @see org.jdesktop.swingx.DateSelectionModel#setAdjusting(boolean) */ public void cancelSelection() { getSelectionModel().setAdjusting(false); fireActionPerformed(CANCEL_KEY); } /** * Sets the component input map enablement property.

* * If enabled, the keybinding for WHEN_IN_FOCUSED_WINDOW are * installed, otherwise not. Changing this property will * install/clear the corresponding key bindings. Typically, clients * which want to use the monthview in a popup, should enable these.

* * The default value is false. * * @param enabled boolean to indicate whether the component * input map should be enabled. * @see #isComponentInputMapEnabled() */ public void setComponentInputMapEnabled(boolean enabled) { if (isComponentInputMapEnabled() == enabled) return; this.componentInputMapEnabled = enabled; firePropertyChange("componentInputMapEnabled", !enabled, isComponentInputMapEnabled()); } /** * Returns the componentInputMapEnabled property. * * @return a boolean indicating whether the component input map is * enabled. * @see #setComponentInputMapEnabled(boolean) * */ public boolean isComponentInputMapEnabled() { return componentInputMapEnabled; } // public static void main(String args[]) { // SwingUtilities.invokeLater(new Runnable() { // public void run() { // JFrame frame = new JFrame(); // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // JXMonthView mv = new JXMonthView(); // mv.setShowingWeekNumber(true); // mv.setTraversable(true); // Calendar cal = Calendar.getInstance(); // cal.set(2006, 5, 20); // mv.setUnselectableDates(new long[] { cal.getTimeInMillis() }); // mv.setPreferredRows(2); // mv.setSelectionMode(SelectionMode.MULTIPLE_INTERVAL_SELECTION); // cal.setTimeInMillis(System.currentTimeMillis()); // mv.setSelectionInterval(cal.getTime(), cal.getTime()); // mv.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent e) { // System.out.println( // ((JXMonthView) e.getSource()).getSelection()); // } // }); // frame.getContentPane().add(mv); // frame.pack(); // frame.setVisible(true); // } // }); // } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy