
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import java.text.*;
import javax.swing.*;
import javax.swing.border.*;

public class JDayChooser extends JPanel implements ActionListener {

	public JDayChooser() {
		locale = Locale.getDefault();
		days = new JButton[49];
		selectedDay = null;
		Calendar calendar = Calendar.getInstance( locale );
		today = (Calendar) calendar.clone();

		setLayout( new GridLayout( 7, 7 ) );

		for( int y=0; y<7; y++ ) {
			for( int x=0; x<7; x++ ) {
				int index = x + 7 * y;
				if( y == 0 ) {
					// Create a button that does'nt react on clicks
					days[index] = new JButton() {
						public void addMouseListener(MouseListener l) {}
					};
					days[index].setBackground( new Color( 200, 200, 255 ) );
				}
				else {
					days[index] = new JButton( "x" );
					days[index].addActionListener( this );
				}

				days[index].setMargin( new Insets( 0, 0, 0, 0 ) );
				days[index].setFocusPainted( false );
				add( days[ index ] );
			}
		}
		init();
		setDay( Calendar.getInstance().get( Calendar.DAY_OF_MONTH ) );
	}

	protected void init() {
		calendar = Calendar.getInstance( locale );
		int firstDayOfWeek = calendar.getFirstDayOfWeek();
		DateFormatSymbols dateFormatSymbols = new DateFormatSymbols( locale );
		dayNames = dateFormatSymbols.getShortWeekdays();
		int day = firstDayOfWeek;

		for( int i = 0 ; i<7; i++ ) {
			days[i].setText( dayNames[day] );
			if( day == 1 )
				days[i].setForeground( Color.red );
			else
				days[i].setForeground( Color.blue );

			if( day < 7 )
				day++;
			else
				day -= 6;

		}
		oldDayBackground = (new JButton()).getBackground();
		drawDays();
	}

	protected void drawDays() {
		Calendar tmpCalendar = (Calendar) calendar.clone();
		int firstDayOfWeek = tmpCalendar.getFirstDayOfWeek();
		tmpCalendar.set( Calendar.DAY_OF_MONTH, 1 );

		int firstDay = tmpCalendar.get( Calendar.DAY_OF_WEEK ) - firstDayOfWeek;
		if( firstDay < 0 )
			firstDay += 7;

		int i;

		for( i=0; i< firstDay; i++ ) {
			days[ i+7 ].setVisible( false );
			days[ i+7 ].setText( "" );
		}

		tmpCalendar.add( Calendar.MONTH, 1 );
		Date firstDayInNextMonth = tmpCalendar.getTime();
		tmpCalendar.add( Calendar.MONTH, -1 );

		Date day = tmpCalendar.getTime();
		int n = 0;
		Color foreground = getForeground();

		while( day.before( firstDayInNextMonth ) ) {
			days[i+n+7].setText( Integer.toString( n+1 ) );
			days[i+n+7].setVisible( true );
			if( tmpCalendar.get( Calendar.DAY_OF_YEAR ) == today.get( Calendar.DAY_OF_YEAR ) &&
				tmpCalendar.get( Calendar.YEAR ) == today.get( Calendar.YEAR ) ) {
					days[i+n+7].setForeground( Color.red );
			}
			else
				days[i+n+7].setForeground( foreground );

			if( n+1 == this.day ) {
				days[i+n+7].setBackground( Color.gray );
				selectedDay = days[i+n+7];
			}
			else
				days[i+n+7].setBackground( oldDayBackground );

			n++;
			tmpCalendar.add( Calendar.DATE, 1 );
			day = tmpCalendar.getTime();
		}

		for( int k=n+i+7; k<49; k++ ) {
			days[k].setVisible( false );
			days[k].setText( "" );
		}
	}

	public Locale getLocale() {
		return locale;
	}

	public void setLocale( Locale l ) {
		locale = l;
		init();
	}

	public void setDay( int d ) {
		if( d < 1 )
		d = 1;

		Calendar tmpCalendar = (Calendar) calendar.clone();
		tmpCalendar.set( Calendar.DAY_OF_MONTH, 1 );
		tmpCalendar.add( Calendar.MONTH, 1 );
		tmpCalendar.add( Calendar.DATE, -1 );
		int maxDaysInMonth = tmpCalendar.get( Calendar.DATE );

		if( d > maxDaysInMonth )
			d = maxDaysInMonth;

		int oldDay = day;
		day = d;

		if( selectedDay != null ) {
			selectedDay.setBackground( oldDayBackground );
			selectedDay.repaint(); // Bug: needed for Swing 1.0.3
		}

		for( int i=7; i<42; i++ ) {
			if( days[i].getText().equals( Integer.toString( day ) ) ) {
				selectedDay = days[i];
				selectedDay.setBackground( Color.gray );
				break;
			}
		}
		firePropertyChange( "day", oldDay, day );
	}

	public int getDay() {
		return day;
	}

	public void setMonth( int month ) {
		calendar.set( Calendar.MONTH, month );
		setDay( day );
		drawDays();
	}

	public void setYear( int year ) {
		calendar.set( Calendar.YEAR, year );
		drawDays();
	}

	public void setCalendar( Calendar c ) {
		calendar = c;
		drawDays();
	}

	public void setFont( Font font ) {
		if( days != null ) {
			for( int i=0; i<49; i++ )
				days[i].setFont( font );
		}
	}

	public void setForeground( Color fg) {
		super.setForeground( fg);
		if( days != null ) {
			for( int i=7; i<49; i++ )
				days[i].setForeground( fg);
				drawDays();
		}
	}

	public String getName() {
		return "JDayChooser";
	}

	public void actionPerformed( ActionEvent e ) {
		JButton button = (JButton) e.getSource();
		int day = ( new Integer( button.getText() ) ).intValue();
		setDay( day );
	}

	private JButton  days[];
	private JButton  selectedDay;
	private int      day;
	private Color    oldDayBackground;
	private String   dayNames[];
	private Calendar calendar;
	private Calendar today;
	private Locale   locale;
}


