📄 jxmonthview.java
字号:
/* * $Id: JXMonthView.java,v 1.12 2005/10/10 18:02:45 rbair 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.*;import java.awt.event.*;import java.text.SimpleDateFormat;import java.text.DateFormatSymbols;import java.util.Calendar;import java.util.Date;import java.util.Hashtable;import java.util.TimeZone;import javax.swing.*;import javax.swing.border.Border;/** * Component that displays a month calendar which can be used to select a day * or range of days. By default the <code>JXMonthView</code> will display a * single calendar using the current month and year, using * <code>Calendar.SUNDAY</code> as the first day of the week. * <p> * The <code>JXMonthView</code> can be configured to display more than one * calendar at a time by calling * <code>setPreferredCalCols</code>/<code>setPreferredCalRows</code>. These * methods will set the preferred number of calendars to use in each * column/row. As these values change, the <code>Dimension</code> returned * from <code>getMinimumSize</code> and <code>getPreferredSize</code> will * be updated. The following example shows how to create a 2x2 view which is * contained within a <code>JFrame</code>: * <pre> * JXMonthView monthView = new JXMonthView(); * monthView.setPreferredCols(2); * monthView.setPreferredRows(2); * * JFrame frame = new JFrame(); * frame.getContentPane().add(monthView); * frame.pack(); * frame.setVisible(true); * </pre> * <p> * <code>JXMonthView</code> 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. * <pre> * monthView.setFirstDayOfWeek(Calendar.MONDAY); * monthView.setDaysOfTheWeek( * new String[]{"S", "M", "T", "W", "Th", "F", "S"}); * </pre> * <p> * This component supports flagging days. These flagged days, which must be * provided in sorted order, are displayed in a bold font. This can be used to * inform the user of such things as scheduled appointment. * <pre> * // 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() * }; * * // Sort them in ascending order. * java.util.Arrays.sort(flaggedDates); * monthView.setFlaggedDates(flaggedDates); * </pre> * 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. * <pre> * // Change the selection mode to select full weeks. * monthView.setSelectionMode(JXMonthView.WEEK_SELECTION); * * // Add an action listener that will be notified when the user * // changes selection via the mouse. * monthView.addActionListener(new ActionListener() { * public void actionPerformed(ActionEvent e) { * System.out.println( * ((JXMonthView)e.getSource()).getSelectedDateSpan()); * } * }); * </pre> * * @author Joshua Outwater * @version $Revision: 1.12 $ */public class JXMonthView extends JComponent { /** Mode that disallows selection of days from the calendar. */ public static final int NO_SELECTION = 0; /** Mode that allows for selection of a single day. */ public static final int SINGLE_SELECTION = 1; /** Mode that allows for selecting of multiple consecutive days. */ public static final int MULTIPLE_SELECTION = 2; /** * Mode where selections consisting of more than 7 days will * snap to a full week. */ public static final int WEEK_SELECTION = 3; /** 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; /** * Insets used in determining the rectangle for the month string * background. */ protected Insets _monthStringInsets = new Insets(0,0,0,0); private static final int MONTH_DROP_SHADOW = 1; private static final int MONTH_LINE_DROP_SHADOW = 2; private static final int WEEK_DROP_SHADOW = 4; private int _boxPaddingX = 3; private int _boxPaddingY = 3; private int _arrowPaddingX = 3; private int _arrowPaddingY = 3; private static final int CALENDAR_SPACING = 10; private static final int DAYS_IN_WEEK = 7; private static final int MONTHS_IN_YEAR = 12; /** * 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 Font _derivedFont; /** Beginning date of selection. -1 if no date is selected. */ private long _startSelectedDate = -1; /** End date of selection. -1 if no date is selected. */ private long _endSelectedDate = -1; /** For multiple selection we need to record the date we pivot around. */ private long _pivotDate = -1; /** The number of calendars able to be displayed horizontally. */ private int _numCalCols = 1; /** The number of calendars able to be displayed vertically. */ private int _numCalRows = 1; private int _minCalCols = 1; private int _minCalRows = 1; private long _today; private long[] _flaggedDates; private int _selectionMode = SINGLE_SELECTION; private int _boxHeight; private int _boxWidth; private int _monthBoxHeight; private int _calendarWidth; private int _calendarHeight; private int _firstDayOfWeek = Calendar.SUNDAY; private int _startX; private int _startY; private int _dropShadowMask = 0; private boolean _dirty = false; private boolean _antiAlias = false; private boolean _ltr; private boolean _traversable = false; private boolean _usingKeyboard = false; private boolean _asKirkWouldSay_FIRE = false; private Calendar _cal; private String[] _daysOfTheWeek; private static String[] _monthsOfTheYear; private Dimension _dim = new Dimension(); private Rectangle _bounds = new Rectangle(); private Rectangle _dirtyRect = new Rectangle(); private Color _todayBackgroundColor; private Color _monthStringBackground; private Color _monthStringForeground; private Color _daysOfTheWeekForeground; private Color _selectedBackground; private SimpleDateFormat _dayOfMonthFormatter = new SimpleDateFormat("d"); private String _actionCommand = "selectionChanged"; private Timer _todayTimer = null; private ImageIcon _monthDownImage; private ImageIcon _monthUpImage; private Hashtable<Integer, Color> _dayToColorTable = new Hashtable<Integer, Color>(); /** * Date span used by the keyboard actions to track the original selection. */ private DateSpan _originalDateSpan = null; /** * Create a new instance of the <code>JXMonthView</code> class using the * month and year of the current day as the first date to display. */ public JXMonthView() { this(new Date().getTime()); } /** * Create a new instance of the <code>JXMonthView</code> class using the * month and year from <code>initialTime</code> as the first date to * display. * * @param initialTime The first month to display. */ public JXMonthView(long initialTime) { super(); _ltr = getComponentOrientation().isLeftToRight(); // Set up calendar instance. _cal = Calendar.getInstance(getLocale()); _cal.setFirstDayOfWeek(_firstDayOfWeek); _cal.setMinimalDaysInFirstWeek(1); // Keep track of today. _cal.set(Calendar.HOUR_OF_DAY, 0); _cal.set(Calendar.MINUTE, 0); _cal.set(Calendar.SECOND, 0); _cal.set(Calendar.MILLISECOND, 0); _today = _cal.getTimeInMillis(); _cal.setTimeInMillis(initialTime); setFirstDisplayedDate(_cal.getTimeInMillis()); // Get string representation of the months of the year. _monthsOfTheYear = new DateFormatSymbols().getMonths(); setOpaque(true); setBackground(Color.WHITE); setFocusable(true); _todayBackgroundColor = getForeground(); // Restore original time value. _cal.setTimeInMillis(_firstDisplayedDate); enableEvents(AWTEvent.MOUSE_EVENT_MASK); enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK); // Setup the keyboard handler. InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "acceptSelection"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "cancelSelection"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "selectPreviousDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "selectNextDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "selectDayInPreviousWeek"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "selectDayInNextWeek"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.SHIFT_MASK, false), "addPreviousDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.SHIFT_MASK, false), "addNextDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.SHIFT_MASK, false), "addToPreviousWeek"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.SHIFT_MASK, false), "addToNextWeek"); // Needed to allow for keyboard control in popups. inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "acceptSelection"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "cancelSelection"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "selectPreviousDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "selectNextDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "selectDayInPreviousWeek"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "selectDayInNextWeek"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.SHIFT_MASK, false), "addPreviousDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.SHIFT_MASK, false), "addNextDay"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.SHIFT_MASK, false), "addToPreviousWeek"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.SHIFT_MASK, false), "addToNextWeek"); ActionMap actionMap = getActionMap(); actionMap.put("acceptSelection", new KeyboardAction(KeyboardAction.ACCEPT_SELECTION)); actionMap.put("cancelSelection", new KeyboardAction(KeyboardAction.CANCEL_SELECTION)); actionMap.put("selectPreviousDay", new KeyboardAction(KeyboardAction.SELECT_PREVIOUS_DAY)); actionMap.put("selectNextDay", new KeyboardAction(KeyboardAction.SELECT_NEXT_DAY)); actionMap.put("selectDayInPreviousWeek", new KeyboardAction(KeyboardAction.SELECT_DAY_PREVIOUS_WEEK)); actionMap.put("selectDayInNextWeek", new KeyboardAction(KeyboardAction.SELECT_DAY_NEXT_WEEK)); actionMap.put("addPreviousDay", new KeyboardAction(KeyboardAction.ADD_PREVIOUS_DAY)); actionMap.put("addNextDay", new KeyboardAction(KeyboardAction.ADD_NEXT_DAY)); actionMap.put("addToPreviousWeek", new KeyboardAction(KeyboardAction.ADD_TO_PREVIOUS_WEEK)); actionMap.put("addToNextWeek", new KeyboardAction(KeyboardAction.ADD_TO_NEXT_WEEK)); updateUI(); } /** * Resets the UI property to a value from the current look and feel. */ public void updateUI() { super.updateUI(); String[] daysOfTheWeek = (String[])UIManager.get("JXMonthView.daysOfTheWeek"); if (daysOfTheWeek == null) { String[] dateFormatSymbols = new DateFormatSymbols().getShortWeekdays(); daysOfTheWeek = new String[DAYS_IN_WEEK]; for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { daysOfTheWeek[i - 1] = dateFormatSymbols[i]; } } setDaysOfTheWeek(daysOfTheWeek); Color color = UIManager.getColor("JXMonthView.monthStringBackground"); if (color == null) { color = new Color(138, 173, 209); } setMonthStringBackground(color); color = UIManager.getColor("JXMonthView.monthStringForeground"); if (color == null) { color = new Color(68, 68, 68); } setMonthStringForeground(color); color = UIManager.getColor("JXMonthView.daysOfTheWeekForeground"); if (color == null) { color = new Color(68, 68, 68); } setDaysOfTheWeekForeground(color); color = UIManager.getColor("JXMonthView.selectedBackground"); if (color == null) { color = new Color(197, 220, 240); } setSelectedBackground(color); Font font = UIManager.getFont("JXMonthView.font"); if (font == null) { font = UIManager.getFont("Button.font");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -