TimeChooser

/**
 * 
 * Copyright: Ares. All Rights Reserved. Company: Insigma HT
 * 
 * @author Ares <a href="mailto:icerainsoft@hotmail.com>send email</a>
 * @date 2013-11-17 16:53
 * 
 *       Revision History
 * 
 *       Date Programmer Notes --------- ---------------------
 *       -------------------------------------------- 2013-11-17 Ares initial
 * 
 *       1. you can change date format by parameter. 2. you can change week label content by
 *       showTEXT. 3. you can change dayOfWeek order by defaultStartDAY.
 */
package ref;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

/**
 * @author Ares
 * @Describe(Date Chooser class)
 */
public class Chooser
    extends JPanel
{

    private static final long serialVersionUID = -5384012731547358720L;

    private Calendar calendar;
    private Calendar now = Calendar.getInstance();
    private JPanel calendarPanel;
    private java.awt.Font font = new java.awt.Font( "Times", java.awt.Font.PLAIN, 12 );
    private java.text.SimpleDateFormat sdf;
    private final LabelManager lm = new LabelManager();
    private javax.swing.Popup pop;
    private TitlePanel titlePanel;
    private BodyPanel bodyPanel;
    private FooterPanel footerPanel;

    private JComponent showDate;
    private boolean isShow = false;
    private static final String DEFAULTFORMAT = "yyyy-MM-dd";
    private static final String[] showTEXT = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
    private static WeekLabel[] weekLabels = new WeekLabel[7];
    private static int defaultStartDAY = 0;//0 is from Sun, 1 is from Mon, 2 is from Tue

    private Chooser(java.util.Date date, String format, int startDAY)
    {
        if( startDAY > -1 && startDAY < 7 )
            defaultStartDAY = startDAY;
        int dayIndex = defaultStartDAY;
        for( int i = 0; i < 7; i++ )
        {
            if( dayIndex > 6 )
                dayIndex = 0;
            weekLabels[i] = new WeekLabel( dayIndex, showTEXT[dayIndex] );
            dayIndex++;
        }
        sdf = new java.text.SimpleDateFormat( format );
        calendar = Calendar.getInstance();
        calendar.setTime( date );
        initCalendarPanel();
    }

    public static Chooser getInstance( java.util.Date date, String format )
    {
        return new Chooser( date, format, defaultStartDAY );
    }

    public static Chooser getInstance( java.util.Date date )
    {
        return getInstance( date, DEFAULTFORMAT );
    }

    public static Chooser getInstance( String format )
    {
        return getInstance( new java.util.Date(), format );
    }

    public static Chooser getInstance()
    {
        return getInstance( new java.util.Date(), DEFAULTFORMAT );
    }

    private void initCalendarPanel()
    {
        calendarPanel = new JPanel( new java.awt.BorderLayout() );
        calendarPanel.setBorder( javax.swing.BorderFactory.createLineBorder( new java.awt.Color( 0xAA, 0xAA, 0xAA ) ) );
        calendarPanel.add( titlePanel = new TitlePanel(), java.awt.BorderLayout.NORTH );
        calendarPanel.add( bodyPanel = new BodyPanel(), java.awt.BorderLayout.CENTER );
        calendarPanel.add( footerPanel = new FooterPanel(), java.awt.BorderLayout.SOUTH );
        this.addAncestorListener( new AncestorListener()
        {
            public void ancestorAdded( AncestorEvent event )
            {
            }

            public void ancestorRemoved( AncestorEvent event )
            {
                hidePanel();
            }

            //hide pop when move component.  
            public void ancestorMoved( AncestorEvent event )
            {
                hidePanel();
            }
        } );
    }

    public void register( final JComponent showComponent )
    {
        this.showDate = showComponent;
        showComponent.setRequestFocusEnabled( true );
        showComponent.addMouseListener( new MouseAdapter()
        {
            public void mousePressed( MouseEvent me )
            {
                showComponent.requestFocusInWindow();
            }
        } );
        this.add( showComponent, BorderLayout.CENTER );
        this.setPreferredSize( new Dimension( 90, 25 ) );
        this.setBorder( BorderFactory.createLineBorder( Color.GRAY ) );
        showComponent.addMouseListener( new MouseAdapter()
        {
            public void mouseEntered( MouseEvent me )
            {
                if( showComponent.isEnabled() )
                {
                    showComponent.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
                }
            }

            public void mouseExited( MouseEvent me )
            {
                if( showComponent.isEnabled() )
                {
                    showComponent.setCursor( new Cursor( Cursor.DEFAULT_CURSOR ) );
                    showComponent.setForeground( Color.BLACK );
                }
            }

            public void mousePressed( MouseEvent me )
            {
                if( showComponent.isEnabled() )
                {
                    showComponent.setForeground( Color.BLUE );
                    if( isShow )
                    {
                        hidePanel();
                    }
                    else
                    {
                        showPanel( showComponent );
                    }
                }
            }

            public void mouseReleased( MouseEvent me )
            {
                if( showComponent.isEnabled() )
                {
                    showComponent.setForeground( Color.BLACK );
                }
            }
        } );
        showComponent.addFocusListener( new FocusListener()
        {
            public void focusLost( FocusEvent e )
            {
                hidePanel();
            }

            public void focusGained( FocusEvent e )
            {
            }
        } );
    }

    //hide the main panel.
    private void hidePanel()
    {
        if( pop != null )
        {
            isShow = false;
            pop.hide();
            pop = null;
        }
    }

    //show the main panel.
    private void showPanel( Component owner )
    {
        if( pop != null )
            pop.hide();
        Point show = new Point( 0, showDate.getHeight() );
        SwingUtilities.convertPointToScreen( show, showDate );
        Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
        int x = show.x;
        int y = show.y;
        if( x < 0 )
            x = 0;
        if( x > size.width - 212 )
            x = size.width - 212;
        if( y > size.height - 167 )
            y -= 165;
        pop = PopupFactory.getSharedInstance().getPopup( owner, calendarPanel, x, y );
        pop.show();
        isShow = true;
    }

    // change text or label's content.
    private void commit()
    {
        if( showDate instanceof JTextField )
        {
            ( (JTextField) showDate ).setText( sdf.format( calendar.getTime() ) );
        }
        else if( showDate instanceof JLabel )
        {
            ( (JLabel) showDate ).setText( sdf.format( calendar.getTime() ) );
        }
        hidePanel();
    }

    // control panel
    private class TitlePanel
        extends JPanel
    {

        private static final long serialVersionUID = -2865282186037420798L;
        private JLabel preYear, preMonth, center, nextMonth, nextYear, centercontainer;

        public TitlePanel()
        {
            super( new java.awt.BorderLayout() );
            this.setBackground( new java.awt.Color( 190, 200, 200 ) );
            initTitlePanel();
        }

        private void initTitlePanel()
        {
            preYear = new JLabel( "<<", JLabel.CENTER );
            preMonth = new JLabel( "<", JLabel.CENTER );
            center = new JLabel( "", JLabel.CENTER );
            centercontainer = new JLabel( "", JLabel.CENTER );
            nextMonth = new JLabel( ">", JLabel.CENTER );
            nextYear = new JLabel( ">>", JLabel.CENTER );

            preYear.setToolTipText( "Last Year" );
            preMonth.setToolTipText( "Last Month" );
            nextMonth.setToolTipText( "Next Month" );
            nextYear.setToolTipText( "Next Year" );

            preYear.setBorder( javax.swing.BorderFactory.createEmptyBorder( 2, 10, 0, 0 ) );
            preMonth.setBorder( javax.swing.BorderFactory.createEmptyBorder( 2, 15, 0, 0 ) );
            nextMonth.setBorder( javax.swing.BorderFactory.createEmptyBorder( 2, 0, 0, 15 ) );
            nextYear.setBorder( javax.swing.BorderFactory.createEmptyBorder( 2, 0, 0, 10 ) );

            centercontainer.setLayout( new java.awt.BorderLayout() );
            centercontainer.add( preMonth, java.awt.BorderLayout.WEST );
            centercontainer.add( center, java.awt.BorderLayout.CENTER );
            centercontainer.add( nextMonth, java.awt.BorderLayout.EAST );

            this.add( preYear, java.awt.BorderLayout.WEST );
            this.add( centercontainer, java.awt.BorderLayout.CENTER );
            this.add( nextYear, java.awt.BorderLayout.EAST );
            this.setPreferredSize( new java.awt.Dimension( 210, 25 ) );

            updateDate();

            preYear.addMouseListener( new MyMouseAdapter( preYear, Calendar.YEAR, -1 ) );
            preMonth.addMouseListener( new MyMouseAdapter( preMonth, Calendar.MONTH, -1 ) );
            nextMonth.addMouseListener( new MyMouseAdapter( nextMonth, Calendar.MONTH, 1 ) );
            nextYear.addMouseListener( new MyMouseAdapter( nextYear, Calendar.YEAR, 1 ) );
        }

        private void updateDate()
        {
            center.setText( calendar.get( Calendar.YEAR ) + "-" + ( calendar.get( Calendar.MONTH ) + 1 ) );
        }

        // listener for control label.
        class MyMouseAdapter
            extends java.awt.event.MouseAdapter
        {

            JLabel label;
            private int type, value;

            public MyMouseAdapter(final JLabel label, final int type, final int value)
            {
                this.label = label;
                this.type = type;
                this.value = value;
            }

            public void mouseEntered( java.awt.event.MouseEvent me )
            {
                label.setCursor( new java.awt.Cursor( java.awt.Cursor.HAND_CURSOR ) );
                label.setForeground( java.awt.Color.RED );
            }

            public void mouseExited( java.awt.event.MouseEvent me )
            {
                label.setCursor( new java.awt.Cursor( java.awt.Cursor.DEFAULT_CURSOR ) );
                label.setForeground( java.awt.Color.BLACK );
            }

            public void mousePressed( java.awt.event.MouseEvent me )
            {
                calendar.add( type, value );
                label.setForeground( java.awt.Color.WHITE );
                refresh();
            }

            public void mouseReleased( java.awt.event.MouseEvent me )
            {
                label.setForeground( java.awt.Color.BLACK );
            }
        }
    }

    // body panel, include week labels and day labels.
    private class BodyPanel
        extends JPanel
    {

        private static final long serialVersionUID = 5677718768457235447L;

        public BodyPanel()
        {
            super( new GridLayout( 7, 7 ) );
            this.setPreferredSize( new java.awt.Dimension( 210, 140 ) );
            initMonthPanel();
        }

        private void initMonthPanel()
        {
            updateDate();
        }

        public void updateDate()
        {
            this.removeAll();
            lm.clear();
            java.util.Date temp = calendar.getTime();
            Calendar cal = Calendar.getInstance();
            cal.setTime( temp );
            cal.set( Calendar.DAY_OF_MONTH, 1 );

            int index = cal.get( Calendar.DAY_OF_WEEK );
            cal.add( Calendar.DAY_OF_MONTH, defaultStartDAY - index );

            for( WeekLabel weekLabel : weekLabels )
            {
                this.add( weekLabel );
            }
            for( int i = 0; i < 42; i++ )
            {
                cal.add( Calendar.DAY_OF_MONTH, 1 );
                lm.addLabel( new DayLabel( cal ) );
            }
            for( DayLabel my : lm.getLabels() )
            {
                this.add( my );
            }
        }
    }

    private class FooterPanel
        extends JPanel
    {

        private static final long serialVersionUID = 8135037333899746736L;
        private JLabel dateLabel;

        public FooterPanel()
        {
            super( new BorderLayout() );
            initFooterPanel();
        }

        private void initFooterPanel()
        {
            dateLabel = new JLabel( "Today is : " + sdf.format( new java.util.Date() ) );
            dateLabel.addMouseListener( new MouseListener()
            {

                @Override
                public void mouseReleased( MouseEvent e )
                {
                }

                @Override
                public void mousePressed( MouseEvent e )
                {
                    calendar.setTime( new Date() );
                    refresh();
                    commit();
                }

                @Override
                public void mouseExited( MouseEvent e )
                {
                    dateLabel.setForeground( Color.BLACK );
                }

                @Override
                public void mouseEntered( MouseEvent e )
                {
                    dateLabel.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
                    dateLabel.setForeground( Color.CYAN );
                }

                @Override
                public void mouseClicked( MouseEvent e )
                {
                }
            } );
            this.add( dateLabel );
        }

        public void updateDate()
        {
        };
    }

    //refresh all panel
    private void refresh()
    {
        titlePanel.updateDate();
        bodyPanel.updateDate();
        footerPanel.updateDate();
        SwingUtilities.updateComponentTreeUI( this );
    }

    private class WeekLabel
        extends JLabel
    {

        private static final long serialVersionUID = -8053965084432740110L;
        private String name;

        public WeekLabel(int index, String name)
        {
            super( name, JLabel.CENTER );
            this.name = name;
        }

        public String toString()
        {
            return name;
        }
    }

    private class DayLabel
        extends JLabel
        implements java.util.Comparator<DayLabel>, java.awt.event.MouseListener, java.awt.event.MouseMotionListener
    {

        private static final long serialVersionUID = -6002103678554799020L;
        private boolean isSelected;
        private int year, month, day;

        public DayLabel(Calendar cal)
        {
            super( "" + cal.get( Calendar.DAY_OF_MONTH ), JLabel.CENTER );
            this.year = cal.get( Calendar.YEAR );
            this.month = cal.get( Calendar.MONTH );
            this.day = cal.get( Calendar.DAY_OF_MONTH );

            this.setFont( font );
            this.addMouseListener( this );
            this.addMouseMotionListener( this );
            if( month == calendar.get( Calendar.MONTH ) )
                this.setForeground( java.awt.Color.BLACK );
            else
                this.setForeground( java.awt.Color.LIGHT_GRAY );

        }

        public boolean getIsSelected()
        {
            return isSelected;
        }

        public void setSelected( boolean b, boolean isDrag )
        {
            isSelected = b;
            if( b && !isDrag )
            {
                int temp = calendar.get( Calendar.MONTH );
                calendar.set( year, month, day );
                if( temp == month )
                {
                    SwingUtilities.updateComponentTreeUI( bodyPanel );
                }
                else
                {
                    refresh();
                }
                this.repaint();
            }
        }

        @Override
        protected void paintComponent( Graphics g )
        {
            //set curr select day's background
            if( day == calendar.get( Calendar.DAY_OF_MONTH ) && month == calendar.get( Calendar.MONTH ) )
            {
                g.setColor( new java.awt.Color( 0xBB, 0xBF, 0xDA ) );
                g.fillRect( 0, 0, getWidth(), getHeight() );
            }
            //set current day's border
            if( year == now.get( Calendar.YEAR ) && month == now.get( Calendar.MONTH )
                && day == now.get( Calendar.DAY_OF_MONTH ) )
            {
                Graphics2D gd = (Graphics2D) g;
                gd.setColor( new java.awt.Color( 0x55, 0x55, 0x88 ) );
                Polygon p = new Polygon();
                p.addPoint( 0, 0 );
                p.addPoint( getWidth() - 1, 0 );
                p.addPoint( getWidth() - 1, getHeight() - 1 );
                p.addPoint( 0, getHeight() - 1 );
                gd.drawPolygon( p );
            }
            if( isSelected )
            {
                Stroke s = new BasicStroke( 1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 1.0f, new float[] {
                        2.0f, 2.0f }, 1.0f );
                Graphics2D gd = (Graphics2D) g;
                gd.setStroke( s );
                gd.setColor( Color.BLACK );
                Polygon p = new Polygon();
                p.addPoint( 0, 0 );
                p.addPoint( getWidth() - 1, 0 );
                p.addPoint( getWidth() - 1, getHeight() - 1 );
                p.addPoint( 0, getHeight() - 1 );
                gd.drawPolygon( p );
            }
            super.paintComponent( g );
        }

        public boolean contains( Point p )
        {
            return this.getBounds().contains( p );
        }

        private void update()
        {
            repaint();
        }

        @Override
        public void mouseDragged( MouseEvent e )
        {
        }

        @Override
        public void mouseMoved( MouseEvent e )
        {
        }

        @Override
        public void mouseClicked( MouseEvent e )
        {
        }

        @Override
        public void mousePressed( MouseEvent e )
        {
            isSelected = true;
            update();
        }

        @Override
        public void mouseReleased( MouseEvent e )
        {
            Point p = SwingUtilities.convertPoint( this, e.getPoint(), bodyPanel );
            this.setForeground( Color.BLACK );
            lm.setSelect( p, false );
            commit();
        }

        @Override
        // change color when mouse over.
        public void mouseEntered( MouseEvent e )
        {
            this.setForeground( Color.CYAN );
            this.repaint();
        }

        @Override
        // change color when mouse exit.
        public void mouseExited( MouseEvent e )
        {
            if( month == calendar.get( Calendar.MONTH ) )
                this.setForeground( java.awt.Color.BLACK );
            else
                this.setForeground( java.awt.Color.LIGHT_GRAY );
            this.repaint();
        }

        @Override
        public int compare( DayLabel o1, DayLabel o2 )
        {
            Calendar c1 = Calendar.getInstance();
            c1.set( o1.year, o1.month, o1.day );
            Calendar c2 = Calendar.getInstance();
            c2.set( o2.year, o2.month, o2.day );
            return c1.compareTo( c2 );
        }

    }

    private class LabelManager
    {
        private List<DayLabel> list;

        public LabelManager()
        {
            list = new ArrayList<Chooser.DayLabel>();
        }

        public List<DayLabel> getLabels()
        {
            return list;
        }

        public void addLabel( DayLabel label )
        {
            list.add( label );
        }

        public void clear()
        {
            list.clear();
        }

        public void setSelect( Point p, boolean b )
        {
            //如果是拖动,则要优化一下,以提高效率  
            if( b )
            {
                //表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和  
                //将要显示的标签找到了就可以了  
                boolean findPrevious = false, findNext = false;
                for( DayLabel lab : list )
                {
                    if( lab.contains( p ) )
                    {
                        findNext = true;
                        if( lab.getIsSelected() )
                            findPrevious = true;
                        else
                            lab.setSelected( true, b );
                    }
                    else if( lab.getIsSelected() )
                    {
                        findPrevious = true;
                        lab.setSelected( false, b );
                    }
                    if( findPrevious && findNext )
                        return;
                }
            }
            else
            {
                DayLabel temp = null;
                for( DayLabel m : list )
                {
                    if( m.contains( p ) )
                    {
                        temp = m;
                    }
                    else if( m.getIsSelected() )
                    {
                        m.setSelected( false, b );
                    }
                }
                if( temp != null )
                    temp.setSelected( true, b );
            }
        }
    }

    /**
     * @param args
     */
    public static void main( String[] args )
    {
        JFrame jf = new JFrame( "Date Picker Test" );
        jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        jf.setLayout( null );
        jf.setBounds( 400, 200, 600, 400 );

        Chooser ser = Chooser.getInstance();
        javax.swing.JTextField text = new JTextField();
        text.setBounds( 10, 10, 200, 30 );
        text.setText( "2013-10-11" );
        ser.register( text );

        Chooser ser2 = Chooser.getInstance( "yyyy年MM月dd日" );
        JLabel label = new JLabel( "please click me." );
        label.setBounds( 10, 50, 200, 30 );
        ser2.register( label );

        jf.add( text );
        jf.add( label );
        jf.setVisible( true );
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值