/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.bpel.ui.properties; import java.text.DateFormat; import java.text.FieldPosition; import java.util.Date; import org.eclipse.bpel.common.ui.details.IDetailsAreaConstants; import org.eclipse.bpel.common.ui.flatui.FlatFormAttachment; import org.eclipse.bpel.common.ui.flatui.FlatFormData; import org.eclipse.bpel.common.ui.flatui.FlatFormLayout; import org.eclipse.bpel.ui.Messages; import org.eclipse.bpel.ui.Policy; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.TypedListener; import org.eclipse.ui.forms.widgets.FormToolkit; /** * Collection of widgets for choosing a specific date and time. * * TODO: rewrite this to be independent of serialization format. Move that code elsewhere. */ public class DateTimeSelector extends Composite { static final String ID = "id"; //$NON-NLS-1$ public static String[] DateTimeSelector_Months = new String[] { Messages.DateTimeSelector_Month_1, Messages.DateTimeSelector_Month_2, Messages.DateTimeSelector_Month_3, Messages.DateTimeSelector_Month_4, Messages.DateTimeSelector_Month_5, Messages.DateTimeSelector_Month_6, Messages.DateTimeSelector_Month_7, Messages.DateTimeSelector_Month_8, Messages.DateTimeSelector_Month_9, Messages.DateTimeSelector_Month_10, Messages.DateTimeSelector_Month_11, Messages.DateTimeSelector_Month_12 }; static final int YEAR = 0; static final int MONTH = YEAR+1; static final int DAY = YEAR+2; static final int HOUR = YEAR+3; static final int MINUTE = YEAR+4; static final int SECOND = YEAR+5; static final int LAST_IDX = YEAR+6; protected Object lastChangeContext ; private Combo[] combo; private Label timeSep, timeSep2, dateSep, dateSep2; private int yearMin; private int yearMax; protected String dateSepText = "/"; //$NON-NLS-1$ protected String timeSepText = ":"; //$NON-NLS-1$ protected static final int[] rawDaysInMonth = { 31,28,31,30,31,30,31,31,30,31,30,31 }; public static int daysInMonth(int monthMinusOne, int year) { // february has a leap day every 4 years, except not every 100 years (except every 400..) if (monthMinusOne==1 && (year&3)==0 && ((year%100)!=0 || (year%400)==0)) return 29; return rawDaysInMonth[monthMinusOne]; } private static String[] MONTH_NAMES; private FormToolkit wf; public DateTimeSelector(FormToolkit toolkit, Composite parent, int style, int yearMin, int yearMax) { super(parent, style); combo = new Combo[6]; this.wf = toolkit; this.yearMin = yearMin; this.yearMax = yearMax; if (MONTH_NAMES == null) { MONTH_NAMES = new String[12]; for (int i = 0; i<MONTH_NAMES.length; i++) { MONTH_NAMES[i] = DateTimeSelector_Months[i]; } } setLayout(new FillLayout()); createControls(this); } private void createControls(Composite parent){ FlatFormData data; Composite composite = wf.createComposite(parent); FlatFormLayout layout = new FlatFormLayout(); layout.marginWidth = layout.marginHeight = 0; composite.setLayout(layout); FlatFormAttachment monthLeft = new FlatFormAttachment(0,0); FlatFormAttachment monthRight = new FlatFormAttachment(30,0); FlatFormAttachment dayLeft = new FlatFormAttachment(35,0); FlatFormAttachment dayRight = new FlatFormAttachment(65,0); FlatFormAttachment yearLeft = new FlatFormAttachment(70,0); FlatFormAttachment yearRight = new FlatFormAttachment(100,0); FlatFormAttachment hourLeft = new FlatFormAttachment(0,0); FlatFormAttachment hourRight = new FlatFormAttachment(30,0); FlatFormAttachment minuteLeft = new FlatFormAttachment(35,0); FlatFormAttachment minuteRight = new FlatFormAttachment(65,0); FlatFormAttachment secondLeft = new FlatFormAttachment(70,0); FlatFormAttachment secondRight = new FlatFormAttachment(100,0); for(int i=0; i < combo.length; i++) { combo[i] = new Combo(composite,SWT.READ_ONLY); combo[i].setData(ID, Integer.valueOf( i )); } dateSep = wf.createLabel(composite, dateSepText, SWT.CENTER); dateSep2 = wf.createLabel(composite, dateSepText, SWT.CENTER); timeSep = wf.createLabel(composite, timeSepText, SWT.CENTER); timeSep2 = wf.createLabel(composite, timeSepText, SWT.CENTER); data = new FlatFormData(); data.left = monthLeft; data.right = monthRight; data.top = new FlatFormAttachment(0, 0); combo[MONTH].setLayoutData(data); data = new FlatFormData(); data.left = dayLeft; data.right = dayRight; data.top = new FlatFormAttachment(0, 0); combo[DAY].setLayoutData(data); data = new FlatFormData(); data.left = yearLeft; data.right = yearRight; data.top = new FlatFormAttachment(0, 0); combo[YEAR].setLayoutData(data); data = new FlatFormData(); data.left = hourLeft; data.right = hourRight; data.top = new FlatFormAttachment(combo[YEAR], IDetailsAreaConstants.VSPACE); combo[HOUR].setLayoutData(data); data = new FlatFormData(); data.left = minuteLeft; data.right = minuteRight; data.top = new FlatFormAttachment(combo[YEAR], IDetailsAreaConstants.VSPACE); combo[MINUTE].setLayoutData(data); data = new FlatFormData(); data.left = secondLeft; data.right = secondRight; data.top = new FlatFormAttachment(combo[YEAR], IDetailsAreaConstants.VSPACE); combo[SECOND].setLayoutData(data); data = new FlatFormData(); data.left = new FlatFormAttachment(combo[MONTH], 0); data.right = new FlatFormAttachment(combo[DAY], 0); data.top = new FlatFormAttachment(combo[MONTH], 0, SWT.CENTER); dateSep.setLayoutData(data); data = new FlatFormData(); data.left = new FlatFormAttachment(combo[DAY], 0); data.right = new FlatFormAttachment(combo[YEAR], 0); data.top = new FlatFormAttachment(combo[MONTH], 0, SWT.CENTER); dateSep2.setLayoutData(data); data = new FlatFormData(); data.left = new FlatFormAttachment(combo[HOUR], 0); data.right = new FlatFormAttachment(combo[MINUTE], 0); data.top = new FlatFormAttachment(combo[HOUR], 0, SWT.CENTER); timeSep.setLayoutData(data); data = new FlatFormData(); data.left = new FlatFormAttachment(combo[MINUTE], 0); data.right = new FlatFormAttachment(combo[SECOND], 0); data.top = new FlatFormAttachment(combo[HOUR], 0, SWT.CENTER); timeSep2.setLayoutData(data); reorderDateWidgetsForLocale(); init(); layout(true); } private void reorderDateWidgetsForLocale() { // swap widgets around if our default layout doesn't match locale-specific order! int dayPos; int monthPos; int yearPos; DateFormat dateFlatFormat = DateFormat.getDateInstance();//DateFlatFormat.DEFAULT, Locale.JAPAN); Date date = new Date(); StringBuffer junkBuffer = new StringBuffer(); FieldPosition pos = new FieldPosition(DateFormat.DATE_FIELD); dateFlatFormat.format(date, junkBuffer, pos); dayPos = pos.getBeginIndex(); if (Policy.DEBUG) System.out.println(junkBuffer); junkBuffer.setLength(0); pos = new FieldPosition(DateFormat.MONTH_FIELD); dateFlatFormat.format(date, junkBuffer, pos); monthPos = pos.getBeginIndex(); junkBuffer.setLength(0); pos = new FieldPosition(DateFormat.YEAR_FIELD); dateFlatFormat.format(date, junkBuffer, pos); yearPos = pos.getBeginIndex(); Combo left = combo[MONTH]; Combo middle = combo[DAY]; Combo right = combo[YEAR]; // The current widget arrangement assumes MDY. if (dayPos < monthPos) { // it should be DMY or YDM or DYM. if (monthPos < yearPos) { // D<M<Y combo[DAY]=left; combo[MONTH]=middle; combo[YEAR]=right; // DMY } else if (dayPos < yearPos) { // D<M Y<M D<Y combo[DAY]=left; combo[YEAR]=middle; combo[MONTH]=right; // DYM } else { // Y<D<M Y<M combo[YEAR]=left; combo[DAY]=middle; combo[MONTH]=right; // YDM } } else { if (dayPos < yearPos) { // M<D<Y combo[MONTH]=left; combo[DAY]=middle; combo[YEAR]=right; // MDY } else if (monthPos < yearPos) { // M<D Y<D M<Y combo[MONTH]=left; combo[YEAR]=middle; combo[DAY]=right; // MYD } else { // Y<D Y<M<D combo[YEAR]=left; combo[MONTH]=middle; combo[DAY]=right; // YMD } } } private void init(){ populateCombos(); setInitialSelections(); addListeners(); } private void populateComboWithInts(Combo combo, int start, int length) { combo.removeAll(); for (int i = start; i<start+length; i++) { combo.add(((i<10)?"0":"")+String.valueOf(i)); //$NON-NLS-1$ //$NON-NLS-2$ } } private void updateDaysCombo(){ int sel = combo[DAY].getSelectionIndex(); int days = daysInMonth(combo[MONTH].getSelectionIndex(), Integer.parseInt(combo[YEAR].getText())); populateComboWithInts(combo[DAY], 1, days); combo[DAY].select(Math.min(sel, days-1)); } private void populateCombos() { populateComboWithInts(combo[YEAR], yearMin, Math.max(0, yearMax-yearMin)); combo[MONTH].setItems(MONTH_NAMES); populateComboWithInts(combo[DAY], 1, 31); populateComboWithInts(combo[HOUR], 0, 24); populateComboWithInts(combo[MINUTE], 0, 60); populateComboWithInts(combo[SECOND], 0, 60); } private void setInitialSelections(){ combo[YEAR].select(0); combo[MONTH].select(0); updateDaysCombo(); combo[DAY].select(0); combo[HOUR].select(12); combo[MINUTE].select(0); combo[SECOND].select(0); } private void addListeners() { SelectionListener commonListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { Combo cw = (Combo) e.widget; lastChangeContext = cw.getData(ID); if (cw == combo[YEAR] || cw == combo[MONTH]) { updateDaysCombo(); } selectionChanged(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; for (int i = 0; i<6; i++) { combo[i].addSelectionListener(commonListener); } } /** * Returns an array of six values for year,month,day,hour,minute,second. */ public int[] getValues() { int[] v = new int[6]; v[YEAR] = combo[YEAR].getSelectionIndex()+yearMin; v[MONTH] = combo[MONTH].getSelectionIndex()+1; v[DAY] = combo[DAY].getSelectionIndex()+1; v[HOUR] = combo[HOUR].getSelectionIndex(); v[MINUTE] = combo[MINUTE].getSelectionIndex(); v[SECOND] = combo[SECOND].getSelectionIndex(); return v; } /** * Expects an array of six values for year,month,day,hour,minute,second. */ public boolean setValues(int[] v) { if (!checkValues(v)) return false; // these values are within the valid ranges for the combos. combo[YEAR].select(v[YEAR]-yearMin); combo[MONTH].select(v[MONTH]-1); updateDaysCombo(); combo[DAY].select(v[DAY]-1); combo[HOUR].select(v[HOUR]); combo[MINUTE].select(v[MINUTE]); combo[SECOND].select(v[SECOND]); return true; } protected boolean checkValues(int[] v) { if (v == null) return false; if (v[YEAR] < yearMin || v[YEAR] > yearMax) return false; if (v[MONTH] < 1 || v[MONTH] > 12) return false; if (v[DAY] < 1 || v[DAY] > daysInMonth(v[MONTH]-1, v[YEAR])) return false; if (v[HOUR] < 0 || v[HOUR] > 23) return false; if (v[MINUTE] < 0 || v[MINUTE] > 59) return false; if (v[SECOND] < 0 || v[SECOND] > 59) return false; return true; } void selectionChanged() { Event e = new Event(); e.type = SWT.Selection; e.widget = this; e.widget.notifyListeners(e.type, e); } public void addSelectionListener(SelectionListener listener){ TypedListener typedListener = new TypedListener (listener); addListener (SWT.Selection,typedListener); // addListener (SWT.DefaultSelection,typedListener); } public Object getUserContext() { return lastChangeContext; } public void restoreUserContext(Object userContext) { int i = ((Integer)userContext).intValue(); switch (i) { case YEAR: case MONTH: case DAY: case HOUR: case MINUTE: case SECOND: combo[i].setFocus(); return; } } @Override public void setEnabled (boolean enabled) { super.setEnabled(enabled); for (int i = 0; i < combo.length; i++) { combo[i].setEnabled(enabled); } } }