/*
 * Created on Mar 23, 2005
Michael Permana
mpermana@hotmail.com
Siebel Systems

 */
package hibergui.swt;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Vector;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

/**
 * @author mpermana
 */
public class DateField {

    Text text;

    GregorianCalendar calendar = new GregorianCalendar();

    DateFormat dateFormat;

    private FieldPosition[] fieldPositions;

    private int[] gregorianFields;

   
    public DateField(DateFormat dateFormat) {
        this.dateFormat = dateFormat;
        fieldPositions = new FieldPosition[] {
                new FieldPosition(DateFormat.YEAR_FIELD),
                new FieldPosition(DateFormat.MONTH_FIELD),
                new FieldPosition(DateFormat.DATE_FIELD),
                new FieldPosition(DateFormat.HOUR_OF_DAY0_FIELD),
                new FieldPosition(DateFormat.HOUR_OF_DAY1_FIELD),
                new FieldPosition(DateFormat.HOUR0_FIELD),
                new FieldPosition(DateFormat.HOUR1_FIELD),
                new FieldPosition(DateFormat.MINUTE_FIELD),
                new FieldPosition(DateFormat.SECOND_FIELD),
                new FieldPosition(DateFormat.AM_PM_FIELD) };

        gregorianFields = new int[] { GregorianCalendar.YEAR,
                GregorianCalendar.MONTH, GregorianCalendar.DAY_OF_MONTH,
                GregorianCalendar.HOUR_OF_DAY, GregorianCalendar.HOUR_OF_DAY,
                GregorianCalendar.HOUR, GregorianCalendar.HOUR,
                GregorianCalendar.MINUTE, GregorianCalendar.SECOND,
                GregorianCalendar.AM_PM, };
    }

    public DateField() {
        this(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT,

                Locale.US));
    }

    public Text create(Composite composite) {

        text = new Text(composite, SWT.BORDER | SWT.READ_ONLY);
        text.setBackground(new Color(null, 255,255,255));
        text.setToolTipText("Use arrow key to ");
        onDateChange();

        KeyListener keyListener = new KeyListener() {

            public void keyPressed(KeyEvent e) {
                int multiply = 1;
                switch (e.keyCode) {
                case SWT.ARROW_DOWN:
                    multiply = -1;
                case SWT.ARROW_UP:
                    addCalendar(multiply, 0 < (e.stateMask & SWT.CONTROL));
                    e.doit = false;
                    break;

                case SWT.ARROW_LEFT:
                    selectDateFormatField(nextDateFormatField(
                            getDateFormatField(text.getSelection().x), -1));
                    e.doit = false;
                    break;
                case SWT.ARROW_RIGHT:
                    selectDateFormatField(nextDateFormatField(
                            getDateFormatField(text.getSelection().x), 1));
                    e.doit = false;
                    break;
                }
            }

            public void keyReleased(KeyEvent e) {
            }

        };
        text.addKeyListener(keyListener);

        return text;
    }

    protected void addCalendar(int amount, boolean big) {
        int x = text.getSelection().x;
        int dateFormatField = getDateFormatField(x);
        int gregorianField = dateFormatFieldToGregorianField(dateFormatField);
        if (GregorianCalendar.AM_PM == gregorianField) {
            calendar.set(gregorianField, 1 - calendar.get(gregorianField));
        } else if (-1 != gregorianField) {
            int value = calendar.get(gregorianField);
            calendar.set(gregorianField, value + amount);
        }
        onDateChange();
        selectDateFormatField(dateFormatField);
    }

    private int dateFormatFieldToGregorianField(int dateFormatField) {
        for (int i = 0; i < fieldPositions.length; i++) {
            if (fieldPositions[i].getField() == dateFormatField)
                return gregorianFields[i];
        }
        return -1;
    }

    private void selectDateFormatField(int dateFormatField) {
        int correctPosition = 0;
        for (int i = 0; i < fieldPositions.length; i++) {
            if (fieldPositions[i].getField() == dateFormatField)
                correctPosition = fieldPositions[i].getBeginIndex();
        }
        text.setSelection(correctPosition);
    }

    /**
     * @return DateFormat.HOUR0_FIELD etc..
     */
    protected int getDateFormatField(int position) {
        for (int i = 0; i < fieldOrder.size(); i++) {
            int[] fieldPosition = (int[]) fieldOrder.get(i);
            int beginIndex = fieldPosition[1];
            int endIndex = fieldPosition[2];
            if (beginIndex <= position && position < endIndex)
                return fieldPosition[3];
        }
        return -1;
    }

    Vector<int[]> fieldOrder = new Vector<int[]>();

    public void onDateChange() {
        fieldOrder.removeAllElements();

        Date date = calendar.getTime();

        for (int i = 0; i < fieldPositions.length; i++) {
            FieldPosition fieldPosition = fieldPositions[i];
            dateFormat.format(date, new StringBuffer(), fieldPosition);
            if (fieldPosition.getBeginIndex() < fieldPosition.getEndIndex())
                addFieldOrder(gregorianFields[i], fieldPosition);
        }

        text.setText(dateFormat.format(calendar.getTime()));
    }

    private void addFieldOrder(int field, FieldPosition fieldPosition) {
        int[] entry = new int[] { field, fieldPosition.getBeginIndex(),
                fieldPosition.getEndIndex(), fieldPosition.getField() };
        for (int i = 0; i < fieldOrder.size(); i++) {
            int[] fieldPositions = (int[]) fieldOrder.get(i);
            if (fieldPosition.getBeginIndex() < fieldPositions[1]) {
                fieldOrder.add(i, entry);
                return;
            }
        }
        fieldOrder.add(entry);
    }

    private int nextDateFormatField(int dateFormatField, int step) {
        for (int i = 0; i < fieldOrder.size(); i++) {
            int[] fieldPosition = (int[]) fieldOrder.get(i);
            if (fieldPosition[3] == dateFormatField) {
                return ((int[]) fieldOrder.get((i + fieldOrder.size() + step)
                        % fieldOrder.size()))[3];
            }
        }
        return -1;
    }

    /**
     * @return Returns the dateFormat.
     */
    public DateFormat getDateFormat() {
        return dateFormat;
    }

    /**
     * @param dateFormat
     *            The dateFormat to set.
     */
    public void setDateFormat(DateFormat dateFormat) {
        this.dateFormat = dateFormat;
    }

    /**
     * @return Returns the calendar.
     */
    public GregorianCalendar getCalendar() {
        return calendar;
    }

    /**
     * @param calendar
     *            The calendar to set.
     */
    public void setCalendar(GregorianCalendar calendar) {
        this.calendar = calendar;
    }

    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 3;
        shell.setLayout(gridLayout);

        try {

            Locale[] locales = { Locale.CHINA, Locale.US, Locale.KOREA,
                    Locale.JAPAN };
            DateField dateField;
            GridData gridData;
            int width = 150;
            for (int i = 0; i < locales.length; i++) {

                dateField = new DateField(DateFormat.getDateInstance(
                        DateFormat.SHORT, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);
                dateField = new DateField(DateFormat.getDateInstance(
                        DateFormat.MEDIUM, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);
                dateField = new DateField(DateFormat.getDateInstance(
                        DateFormat.LONG, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);

                dateField = new DateField(DateFormat.getTimeInstance(
                        DateFormat.SHORT, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);
                dateField = new DateField(DateFormat.getTimeInstance(
                        DateFormat.MEDIUM, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);
                dateField = new DateField(DateFormat.getTimeInstance(
                        DateFormat.LONG, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);

                dateField = new DateField(DateFormat.getDateTimeInstance(
                        DateFormat.SHORT, DateFormat.SHORT, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);
                dateField = new DateField(DateFormat.getDateTimeInstance(
                        DateFormat.MEDIUM, DateFormat.MEDIUM, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);
                dateField = new DateField(DateFormat.getDateTimeInstance(
                        DateFormat.LONG, DateFormat.LONG, locales[i]));
                gridData = new GridData();
                gridData.widthHint = width;
                dateField.create(shell).setLayoutData(gridData);

            }

            // createScheduleSection(shell);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();

    }
}
 