Package mygoodmoney

Source Code of mygoodmoney.JDateChooser

/**
* Copyright (c) 2005-2006 Adam Lane
*
* Licensed under the Academic Free License version 1.2
*/
package mygoodmoney;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.basic.BasicArrowButton;

/** This date chooser provides a combo box for selecting dates.  The date can be typed into
* the input field, or selected from a combo popup which provides a GUI calendar date
* picker.  The text date parsing is unique in that numerous date formats can be handled by the
* text date parser. */
public class JDateChooser extends JPanel {
    /** Stores the last date formatter that successfully parsed a date */
    //protected static DateFormat lastDateFormat = new SimpleDateFormat("MM/dd/yyyy");
    protected static DateFormat lastDateFormat = new SimpleDateFormat("dd/MM/yyyy");
   
    /** A set of date formatters that could be used for parsing dates */
    protected static final SimpleDateFormat[] DATE_FORMATS = new SimpleDateFormat[] {
        new SimpleDateFormat("dd MMM yyyy"),
        new SimpleDateFormat("dd/MM/yyyy"),
        new SimpleDateFormat("dd-MM-yyyy" ),
        new SimpleDateFormat("ddMMyyyy" ),
        new SimpleDateFormat("ddMMyy" )
    };

    /** Internal state varialble - date formatter for current local date format */
    protected DateFormat currentDateFormat = lastDateFormat;
   
    /** Internal state varialble - the original selected date */
    protected Date originalDate = null;
   
    /** Internal state varialble - the current selected date */
    protected Date date = null;
   
    /** Internal state varialble - flag indicating whether the popup is visible or not */
    protected boolean datePickerVisible = false;

    /** Date field for editing the date manually */
    protected JTextField dateField;
   
    /** The combo box toggle button */
    protected JButton comboBoxButton;
   
    /** The popup window date chooser window*/
    protected JWindow datePickerWindow;
   
    /** The date picker within the popup window */
    protected JDatePicker datePicker;
   
    private final Color colorBackground = Color.WHITE;
    private final Color colorBackgroundError = new Color(0xFFAAAA);
    private final Color colorBackgroundChange = Color.WHITE;
   
    /** Construct a JDateChooser initialized with selected date. */   
    public JDateChooser() {
        dateField = new JTextField();
        comboBoxButton = new BasicArrowButton(BasicArrowButton.SOUTH, UIManager.getColor("ComboBox.buttonBackground"), UIManager.getColor("ComboBox.buttonShadow"), UIManager.getColor("ComboBox.buttonDarkShadow"), UIManager.getColor("ComboBox.buttonHighlight"));
        comboBoxButton.setName("ComboBox.arrowButton");
        comboBoxButton.addActionListener(onComboButtonClick);
       
        dateField.addComponentListener(componentListener);
        dateField.getDocument().addDocumentListener(dateFieldDocumentListener);
        dateField.setBackground(colorBackground);
        dateField.setPreferredSize(new Dimension(125, dateField.getPreferredSize().height));
       
        this.setLayout(new ComboBoxLayout());
        this.add(dateField);
        this.add(comboBoxButton);
        this.addAncestorListener(ancestorListener);
        this.dateField.addFocusListener( new FocusAdapter() {
          @Override
          public void focusGained(FocusEvent e){
            dateField.selectAll();
          }
        });
    }
   
    // UI FUNCTIONALITY   
    private final Action onComboButtonClick = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (datePickerVisible == false) {
                showDatePicker();
            } else {
                hideDatePicker();
            }
        }
    };

    private final Action onSelectDate = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            Date date = datePicker.getDate();
            dateField.setText(currentDateFormat.format(date));
            if (e.getActionCommand().equalsIgnoreCase("Clicked")) {
                hideDatePicker();
                ActionEvent event = new ActionEvent(JDateChooser.this, ActionEvent.ACTION_PERFORMED, "changed", System.currentTimeMillis(), 0);
                fireActionPerformed(event);
            }
        }
    };

    private final DocumentListener dateFieldDocumentListener = new DocumentListener() {
        @Override
        public void insertUpdate(DocumentEvent e) {
          onTextChange();
          format();
        }
        @Override
        public void removeUpdate(DocumentEvent e) {
          onTextChange();
        }
        @Override
        public void changedUpdate(DocumentEvent e) {
          onTextChange();
        }
    };
   
    public void format() {
      String data = dateField.getText();
     
      if( data.length() == 8 ) {
        try {
          final DateFormat dfAtual = new SimpleDateFormat( "ddMMyyyy" );
          final DateFormat dfCorreto = new SimpleDateFormat( "dd/MM/yyyy" );
          final Date d = dfAtual.parse(data);
          SwingUtilities.invokeLater( new Runnable() {
            @Override
            public void run(){
              dateField.setText( dfCorreto.format( d ) );
            }
          });
        }
        catch( ParseException p ){}
      }
    }
   
    private final ComponentListener componentListener = new ComponentListener() {
        @Override
        public void componentResized(ComponentEvent e) { hideDatePicker(); }
        @Override
        public void componentMoved(ComponentEvent e) { hideDatePicker(); }
        @Override
        public void componentShown(ComponentEvent e) { hideDatePicker(); }
        @Override
        public void componentHidden(ComponentEvent e) { hideDatePicker(); }
    };
   
    private final WindowFocusListener windowFocusListener = new WindowFocusListener() {
        @Override
        public void windowGainedFocus(WindowEvent e) { }
        @Override
        public void windowLostFocus(WindowEvent e) { hideDatePicker(); }
    };
   
    private final AncestorListener ancestorListener = new AncestorListener() {
        @Override
        public void ancestorAdded(AncestorEvent event){ hideDatePicker(); }
        @Override
        public void ancestorRemoved(AncestorEvent event){ hideDatePicker(); }
        @Override
        public void ancestorMoved(AncestorEvent event){
            if (event.getSource() != datePickerWindow) {
                hideDatePicker();
            }
        }
    };

    /** Find the frame parent of the component.
     * @param component the component whose frame is needed */
    private Frame getFrame(Component component) {
        if (component == null) component = this;
        if (component.getParent() instanceof Frame) {
            return (Frame) component.getParent();
        }
        return getFrame(component.getParent());
    }
   
    /** Toggle the visiblity of the date picker selection popup.  This is used as a response to the
     * combo box toggle button, but it can be manually toggled as well if there is some need. */
    public void showDatePicker() {
        if (datePickerWindow == null) {
            datePickerWindow = new JWindow(getFrame(null));
            datePickerWindow.setAlwaysOnTop(true);
            datePicker = new JDatePicker();
            datePickerWindow.getContentPane().add(datePicker);
            datePickerWindow.addWindowFocusListener(windowFocusListener);
            datePicker.setBorder(BorderFactory.createLineBorder(Color.BLACK));
            datePicker.addActionListener(onSelectDate);
            datePicker.setFocusable(true);
        }
        if (datePickerVisible == false) {
            Date date = getDate();
            if (date != null || datePicker.getDate() != null) datePicker.setDate(date);
            Dimension max = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
            int x = JDateChooser.this.getWidth()-250+JDateChooser.this.getLocationOnScreen().x;
            int y = JDateChooser.this.getLocationOnScreen().y+JDateChooser.this.getHeight();
            int w = 250;
            int h = 220;
            if (x + w > max.width) x = max.width - w;
            if (x < 0) x = 0;
            if (y + h > max.height) y = JDateChooser.this.getLocationOnScreen().y - h;
            if (y < 0) y = 0;
            datePickerWindow.setLocation(x, y);
            datePickerWindow.setSize(w, h);
            datePickerWindow.setVisible(true);
            datePickerWindow.requestFocus();
            datePickerVisible = true;
        }
    }

    /** Hide the date picker popup if it is currently visible. */
    public void hideDatePicker() {
        if (datePickerVisible == true) {
            datePickerWindow.setVisible(false);
            datePickerVisible = false;
        }
    }
   
    /** Handle parsing the text field date and updating the rest of the UI accorindingly. */
    private void onTextChange() {
        String text = dateField.getText();
        date = null;
        for (SimpleDateFormat dateFormat : DATE_FORMATS) {
            try {
                Date parsedDate = dateFormat.parse(text);
                if (text.equals(dateFormat.format(parsedDate))) {
                    date = parsedDate;
                    currentDateFormat = dateFormat;
                    lastDateFormat = dateFormat;
                    break;
                }
            } catch (ParseException ex) {
                // continue
            }
        }
        if (date == null && text.length() > 0) {
            dateField.setBackground(colorBackgroundError);
        } else {
            if (isDateChanged()) {
                dateField.setBackground(colorBackgroundChange);
            } else {
                dateField.setBackground(colorBackground);
            }
        }
       
        ActionEvent event = new ActionEvent(JDateChooser.this, ActionEvent.ACTION_PERFORMED, "changed", System.currentTimeMillis(), 0);
        fireActionPerformed(event);
    }

    // ACTION LISTENER FUNCTIONALITY
    /** Add an action listener.  The JCalendar provides ActionEvents for clicks
     * as well as for moving the mouse between date cells.
     * @param listener the listener object */
    public final void addActionListener(ActionListener listener) {
        listenerList.add(ActionListener.class, listener);
    }

    /** Remove an action listener.
     * @param listener the listener object */
    public final void removeActionListener(ActionListener listener) {
        listenerList.remove(ActionListener.class, listener);
    }

    private void fireActionPerformed(ActionEvent event) {
        Object[] listeners = listenerList.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == ActionListener.class) {
                ((ActionListener) listeners[i + 1]).actionPerformed(event);
            }
        }
    }
   
    // DATE ACCESSORS
    /** Set the current selected date of the date chooser.  The date may be null.
     * This will update the text field and the rest of the UI to reflect the change.
     * @param date the newly current selected date */
    public void setDate(Date date) {
        if (date != null) {
            dateField.setText(currentDateFormat.format(date));
        } else {
            dateField.setText("");
        }
        onTextChange();
    }
   
    /** Set the originally selected date.  Used in detecting changes in the date
     * selection of the component.
     * @param date the originally selected date */
    public void setOriginalDate(Date date) {
        this.originalDate = date;
        onTextChange();
    }
   
    /** Get the currently chosen date.
     * @return the date currently selected, or null if no date is selected (or if text date is invalid) */
    public Date getDate() {
        return (Date) date;
    }
   
    /** Check to see if the currently selected date differs from the original date holder
     * variable.
     * @return true if the date selection has changed, false otherwise */
    public boolean isDateChanged() {
        if (date == null && originalDate == null) return false;
        if (originalDate == null) return true;
        return (date != null && !date.equals(originalDate));
    }
   
    // COMBO BOX UI
    /** This class performs the ComboBox style layout of the component elements. */
    private class ComboBoxLayout implements LayoutManager {
        @Override
        public void addLayoutComponent(String name, Component component) {}
        @Override
        public void removeLayoutComponent(Component component) {}

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            Dimension dimension = new Dimension(comboBoxButton.getPreferredSize().width + dateField.getPreferredSize().width, combineDimensions(new Dimension[] { comboBoxButton.getPreferredSize(), dateField.getPreferredSize() }, true).height);
            return dimension;
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return comboBoxButton.getMinimumSize();
        }

        protected Rectangle rectangleForCurrentValue() {
            int width = JDateChooser.this.getWidth();
            int height = JDateChooser.this.getHeight();
            Insets insets = getInsets();
            int buttonSize = height - (insets.top + insets.bottom);
            if (comboBoxButton != null) {
                buttonSize = comboBoxButton.getWidth();
            }
            return new Rectangle(insets.left, insets.top, width - (insets.left + insets.right + buttonSize), height - (insets.top + insets.bottom));
        }

        @Override
        public void layoutContainer(Container parent) {
            int width = JDateChooser.this.getWidth();
            int height = JDateChooser.this.getHeight();

            Insets insets = getInsets();
            int buttonSize = height - (insets.top + insets.bottom);
            Rectangle cvb;

            if (comboBoxButton != null) {
                comboBoxButton.setBounds(width - (insets.right + buttonSize), insets.top, buttonSize, buttonSize);
            }
            if (dateField != null) {
                cvb = rectangleForCurrentValue();
                dateField.setBounds(cvb);
            }
        }
    }

    /** Takes a set of dimensions and derives a maximum dimension that can be applied to other components. */
    private static Dimension combineDimensions(Dimension[] dimensions, boolean maximum) {
        if (maximum) {
            int w = 0;
            int h = 0;
            int size = dimensions.length;
            for (int i = 0; i < size; i++) {
                if (dimensions[i].width > w) w = dimensions[i].width;
                if (dimensions[i].height > h) h = dimensions[i].height;
            }
            return new Dimension(w, h);
        } else {
            int w = 100000;
            int h = 100000;
            int size = dimensions.length;
            for (int i = 0; i < size; i++) {
                if (dimensions[i].width < w) w = dimensions[i].width;
                if (dimensions[i].height < h) h = dimensions[i].height;
            }
            return new Dimension(w, h);
        }
    }
   
    /** Try to determine if an event is within the popup window so that it
     * can be automatically closed if an event occurs outside of it.
     * @param source source component
     * @return true is source component is a descendent of the JDateChooser */
    private static boolean isInPopup(Component source) {
        for (Component component = source; component != null; component = component.getParent()) {
            if (component instanceof Applet || component instanceof Window) {
                break;
            } else if (component instanceof JDateChooser) {
                return true;
            }
        }
        return false;
    }
   
    public void setText( String texto ) {
      this.dateField.setText( texto );
    }
   
    public void setEditable( boolean ed ) {
      this.dateField.setEditable(ed);
      this.dateField.setEnabled(ed);
      this.comboBoxButton.setEnabled(ed);
    }
   
    @Override
    public void requestFocus() {
      this.dateField.requestFocus();
      this.dateField.selectAll();
    }
   
    public JTextField getField() {
      return( this.dateField );
    }
}
TOP

Related Classes of mygoodmoney.JDateChooser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.