DateChooser.java :  » Content-Management-System » contelligent » de » finix » contelligent » client » util » Java Open Source

Java Open Source » Content Management System » contelligent 
contelligent » de » finix » contelligent » client » util » DateChooser.java
/*
 * Copyright 2001-2006 C:1 Financial Services GmbH
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License Version 2.1, as published by the Free Software Foundation.
 *
 * This software 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
 */

package de.finix.contelligent.client.util;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;

import de.finix.contelligent.client.i18n.Resources;

/**
 * Custom dialog box to enter dates. The <code>DateChooser</code> class
 * presents a calendar and allows the user to visually select a day, month and
 * year so that it is impossible to enter an invalid date.
 */
public class DateChooser extends JPanel implements ItemListener, MouseListener, FocusListener, KeyListener,
        ActionListener {
    /** Names of the months. */
    private static final String[] MONTHS = new String[] { "January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December" };

    /** Names of the days of the week. */
    private static final String[] DAYS = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

    /**
     * Text color of the days of the weeks, used as column headers in the
     * calendar.
     */
    private static final Color WEEK_DAYS_FOREGROUND = Color.black;

    /** Text color of the days' numbers in the calendar. */
    private static final Color DAYS_FOREGROUND = Color.blue;

    /** Background color of the selected day in the calendar. */
    private static final Color SELECTED_DAY_FOREGROUND = Color.white;

    /** Text color of the selected day in the calendar. */
    private static final Color SELECTED_DAY_BACKGROUND = Color.blue;

    /** Empty border, used when the calendar does not have the focus. */
    private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(1, 1, 1, 1);

    /**
     * Border used to highlight the selected day when the calendar has the
     * focus.
     */
    private static final Border FOCUSED_BORDER = BorderFactory.createLineBorder(Color.yellow, 1);

    /** First year that can be selected. */
    private static final int FIRST_YEAR = 1900;

    /** Last year that can be selected. */
    private static final int LAST_YEAR = 2100;

    /** Auxiliary variable to compute dates. */
    private GregorianCalendar calendar;

    /**
     * Calendar, as a matrix of labels. The first row represents the first week
     * of the month, the second row, the second week, and so on. Each column
     * represents a day of the week, the first is Sunday, and the last is
     * Saturday. The label's text is the number of the corresponding day.
     */
    private JLabel[][] days;

    /**
     * Day selection control. It is just a panel that can receive the focus. The
     * actual user interaction is driven by the <code>DateChooser</code>
     * class.
     */
    private FocusablePanel daysGrid;

    /** Month selection control. */
    private JComboBox month;

    /** Year selection control. */
    private JComboBox year;

    private JComboBox hour;

    private JComboBox minute;

    private JButton today;

    /**
     * Day of the week (0=Sunday) corresponding to the first day of the selected
     * month. Used to calculate the position, in the calendar ({@link #days}),
     * corresponding to a given day.
     */
    private int offset;

    /** Last day of the selected month. */
    private int lastDay;

    /** Selected day. */
    private JLabel day;

    /**
     * <code>true</code> if the "Ok" button was clicked to close the dialog
     * box, <code>false</code> otherwise.
     */
    private boolean okClicked;

    /**
     * Custom panel that can receive the focus. Used to implement the calendar
     * control.
     */
    private static class FocusablePanel extends JPanel {
        /**
         * Constructs a new <code>FocusablePanel</code> with the given layout
         * manager.
         * 
         * @param layout
         *            layout manager
         */
        public FocusablePanel(LayoutManager layout) {
            super(layout);
        }

        /**
         * Always returns <code>true</code>, since
         * <code>FocusablePanel</code> can receive the focus.
         * 
         * @return <code>true</code>
         */
        public boolean isFocusTraversable() {
            return true;
        }
    }

    /**
     * Initializes this <code>DateChooser</code> object. Creates the controls,
     * registers listeners and initializes the dialog box.
     */
    private void construct() {
        calendar = new GregorianCalendar();

        month = new JComboBox(MONTHS);
        month.addItemListener(this);

        year = new JComboBox();
        for (int i = FIRST_YEAR; i <= LAST_YEAR; i++)
            year.addItem(Integer.toString(i));
        year.addItemListener(this);

        hour = new JComboBox();
        for (int i = 0; i < 24; i++) {
            hour.addItem(Integer.toString(i));
        }

        minute = new JComboBox();
        for (int i = 0; i < 60; i++) {
            minute.addItem(i < 10 ? "0" + Integer.toString(i) : Integer.toString(i));
        }

        days = new JLabel[7][7];
        for (int i = 0; i < 7; i++) {
            days[0][i] = new JLabel(DAYS[i], JLabel.RIGHT);
            days[0][i].setForeground(WEEK_DAYS_FOREGROUND);
        }
        for (int i = 1; i < 7; i++)
            for (int j = 0; j < 7; j++) {
                days[i][j] = new JLabel(" ", JLabel.RIGHT);
                days[i][j].setForeground(DAYS_FOREGROUND);
                days[i][j].setBackground(SELECTED_DAY_BACKGROUND);
                days[i][j].setBorder(EMPTY_BORDER);
                days[i][j].addMouseListener(this);
            }

        today = new JButton(Resources.getLocalString("today"));
        today.addActionListener(this);

        JPanel monthYear = new JPanel();
        monthYear.setLayout(new FlowLayout(FlowLayout.LEFT));
        monthYear.add(month);
        monthYear.add(year);
        monthYear.add(today);

        JPanel hourMinute = new JPanel();
        hourMinute.setLayout(new FlowLayout(FlowLayout.LEFT));
        hourMinute.add(new JLabel(Resources.getLocalString("time_of_day") + ": "));
        hourMinute.add(hour);
        hourMinute.add(new JLabel(":"));
        hourMinute.add(minute);

        daysGrid = new FocusablePanel(new GridLayout(7, 7, 5, 0));
        daysGrid.addFocusListener(this);
        daysGrid.addKeyListener(this);
        for (int i = 0; i < 7; i++)
            for (int j = 0; j < 7; j++)
                daysGrid.add(days[i][j]);
        daysGrid.setBackground(Color.white);
        daysGrid.setBorder(BorderFactory.createLoweredBevelBorder());
        JPanel daysPanel = new JPanel();
        daysPanel.add(daysGrid);

        // Container dialog = getContentPane();
        add(monthYear, BorderLayout.NORTH);
        add(daysPanel, BorderLayout.WEST);
        add(hourMinute, BorderLayout.SOUTH);

        // pack();
        // setResizable( false );
    }

    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        month.setEnabled(enabled);
        year.setEnabled(enabled);
        today.setEnabled(enabled);
        daysGrid.setEnabled(enabled);
        hour.setEnabled(enabled);
        minute.setEnabled(enabled);
        for (int i = 1; i < 7; i++)
            for (int j = 0; j < 7; j++) {
                days[i][j].setEnabled(enabled);
            }
        if (!enabled) {
            setSelected(null); // Unselect date
        }
    }

    /**
     * Gets the selected day, as an <code>int</code>. Parses the text of the
     * selected label in the calendar to get the day.
     * 
     * @return the selected day or -1 if there is no day selected
     */
    private int getSelectedDay() {
        if (day == null)
            return -1;
        try {
            return Integer.parseInt(day.getText());
        } catch (NumberFormatException e) {
        }
        return -1;
    }

    /**
     * Sets the selected day. The day is specified as the label control, in the
     * calendar, corresponding to the day to select.
     * 
     * @param newDay
     *            day to select
     */
    private void setSelected(JLabel newDay) {
        if (day != null) {
            day.setForeground(DAYS_FOREGROUND);
            day.setOpaque(false);
            day.setBorder(EMPTY_BORDER);
        }
        day = newDay;
        if (day != null) {
            day.setForeground(SELECTED_DAY_FOREGROUND);
            day.setOpaque(true);
            if (daysGrid.hasFocus())
                day.setBorder(FOCUSED_BORDER);
        }
    }

    /**
     * Sets the selected day. The day is specified as the number of the day, in
     * the month, to selected. The function compute the corresponding control to
     * select.
     * 
     * @param newDay
     *            day to select
     */
    private void setSelected(int newDay) {
        setSelected(days[(newDay + offset - 1) / 7 + 1][(newDay + offset - 1) % 7]);
    }

    /**
     * Updates the calendar. This function updates the calendar panel to reflect
     * the month and year selected. It keeps the same day of the month that was
     * selected, except if it is beyond the last day of the month. In this case,
     * the last day of the month is selected.
     */
    private void update() {
        int iday = getSelectedDay();
        for (int i = 0; i < 7; i++) {
            days[1][i].setText(" ");
            days[5][i].setText(" ");
            days[6][i].setText(" ");
        }
        calendar.set(Calendar.DATE, 1);
        calendar.set(Calendar.MONTH, month.getSelectedIndex() + Calendar.JANUARY);
        calendar.set(Calendar.YEAR, year.getSelectedIndex() + FIRST_YEAR);

        offset = calendar.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
        lastDay = calendar.getActualMaximum(Calendar.DATE);
        for (int i = 0; i < lastDay; i++)
            days[(i + offset) / 7 + 1][(i + offset) % 7].setText(String.valueOf(i + 1));
        if (iday != -1) {
            if (iday > lastDay)
                iday = lastDay;
            setSelected(iday);
        }
    }

    /**
     * Called when the calendar gains the focus. Just re-sets the selected day
     * so that it is redrawn with the border that indicate focus.
     */
    public void focusGained(FocusEvent e) {
        setSelected(day);
    }

    /**
     * Called when the calendar loses the focus. Just re-sets the selected day
     * so that it is redrawn without the border that indicate focus.
     */
    public void focusLost(FocusEvent e) {
        setSelected(day);
    }

    /**
     * Called when a new month or year is selected. Updates the calendar to
     * reflect the selection.
     */
    public void itemStateChanged(ItemEvent e) {
        update();
    }

    /**
     * Called when a key is pressed and the calendar has the focus. Handles the
     * arrow keys so that the user can select a day using the keyboard.
     */
    public void keyPressed(KeyEvent e) {
        int iday = getSelectedDay();
        switch (e.getKeyCode()) {
        case KeyEvent.VK_LEFT:
            if (iday > 1)
                setSelected(iday - 1);
            break;
        case KeyEvent.VK_RIGHT:
            if (iday < lastDay)
                setSelected(iday + 1);
            break;
        case KeyEvent.VK_UP:
            if (iday > 7)
                setSelected(iday - 7);
            break;
        case KeyEvent.VK_DOWN:
            if (iday <= lastDay - 7)
                setSelected(iday + 7);
            break;
        }
    }

    /**
     * Called when the mouse is clicked on a day in the calendar. Selects the
     * clicked day.
     */
    public void mouseClicked(MouseEvent e) {
        if (isEnabled()) {
            JLabel day = (JLabel) e.getSource();
            if (!day.getText().equals(" "))
                setSelected(day);
            daysGrid.requestFocus();
        }
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyTyped(KeyEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    public DateChooser() {
        super();
        setLayout(new BorderLayout());
        construct();
    }

    /**
     * Selects a date. Displays the dialog box, with a given date as the
     * selected date, and allows the user select a new date.
     * 
     * @param date
     *            initial date
     * 
     * @return the new date selected or <code>null</code> if the user press
     *         "Cancel" or closes the dialog box
     */
    public void select(Date date) {
        calendar.setTime(date);
        int _day = calendar.get(Calendar.DATE);
        int _month = calendar.get(Calendar.MONTH);
        int _year = calendar.get(Calendar.YEAR);
        int _hour = calendar.get(Calendar.HOUR_OF_DAY);
        int _minute = calendar.get(Calendar.MINUTE);

        year.setSelectedIndex(_year - FIRST_YEAR);
        month.setSelectedIndex(_month - Calendar.JANUARY);
        setSelected(_day);
        hour.setSelectedIndex(_hour);
        minute.setSelectedIndex(_minute);
    }

    public Date getDate() {
        calendar.set(Calendar.DATE, getSelectedDay());
        calendar.set(Calendar.MONTH, month.getSelectedIndex() + Calendar.JANUARY);
        calendar.set(Calendar.YEAR, year.getSelectedIndex() + FIRST_YEAR);
        calendar.set(Calendar.HOUR_OF_DAY, hour.getSelectedIndex());
        calendar.set(Calendar.MINUTE, minute.getSelectedIndex());
        return calendar.getTime();
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == today) {
            select(new Date());
        }
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.