/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2007, by :
* Corporate:
* EADS Astrium SAS
* EADS CRC
* Individual:
* Ronan Ogor
*
* $Id: DateTimePanel.java,v 1.4 2008/04/29 09:55:08 ogor Exp $
*
* Changes
* -------
* 11 mai 2007 : Initial public release (RO);
*
*/
package jsynoptic.builtin.ui;
import java.awt.FlowLayout;
import java.awt.Label;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import jsynoptic.ui.Run;
import simtools.ui.NumberField;
import simtools.ui.UserProperties;
public class DateTimePanel extends JPanel{
protected static String defaultDisplayTimeZone = "GMT";
static{
UserProperties prop = Run.getProperties();
if (prop!=null) {
if (prop.getString("jsynoptic.ui.JSynoptic.displayTimeZone",null)!=null){
defaultDisplayTimeZone = prop.getString("jsynoptic.ui.JSynoptic.displayTimeZone",null);
}else{
prop.setString("jsynoptic.ui.JSynoptic.displayTimeZone", defaultDisplayTimeZone);
}
}
}
public static final String[] dateFormats = {
"dd",
"MMM",
"yyyy",
"HH",
"mm",
"ss",
"SSS"
};
public static final String[] dateSeparators = {
"-",
"-",
" ",
":",
":",
".",
"",
};
public static final int DAY_POS = 0;
public static final int MONTH_POS = 1;
public static final int YEAR_POS = 2;
public static final int HOUR_POS = 3;
public static final int MINUTE_POS = 4;
public static final int SECOND_POS = 5;
public static final int MILLISECOND_POS = 6;
protected static final String defaultDateFormat = dateFormats[DAY_POS]+dateSeparators[DAY_POS]+dateFormats[MONTH_POS]+dateSeparators[MONTH_POS]+
dateFormats[YEAR_POS]+dateSeparators[YEAR_POS]+dateFormats[HOUR_POS]+dateSeparators[HOUR_POS]+
dateFormats[MINUTE_POS]+dateSeparators[MINUTE_POS]+dateFormats[SECOND_POS]+dateSeparators[SECOND_POS]+
dateFormats[MILLISECOND_POS];
public static SimpleDateFormat getDateRefFormat(Date tsMin, Date tsMax, int posEndRef[]) {
String dateRef = null;
if(!compareDatePart(tsMin, tsMax, dateFormats[YEAR_POS])) {
dateRef = "";
posEndRef[0] = -1;
} else if(!compareDatePart(tsMin, tsMax, dateFormats[MONTH_POS])) {
dateRef = dateFormats[YEAR_POS];
posEndRef[0] = YEAR_POS;
} else if(!compareDatePart(tsMin, tsMax, dateFormats[DAY_POS])) {
dateRef = dateFormats[MONTH_POS]+dateSeparators[MONTH_POS]+
dateFormats[YEAR_POS];
posEndRef[0] = MONTH_POS;
} else if(!compareDatePart(tsMin, tsMax, dateFormats[HOUR_POS])) {
dateRef = dateFormats[DAY_POS]+dateSeparators[DAY_POS]+dateFormats[MONTH_POS]+dateSeparators[MONTH_POS]+
dateFormats[YEAR_POS];
posEndRef[0] = DAY_POS;
} else if(!compareDatePart(tsMin, tsMax, dateFormats[MINUTE_POS])) {
dateRef = dateFormats[DAY_POS]+dateSeparators[DAY_POS]+dateFormats[MONTH_POS]+dateSeparators[MONTH_POS]+
dateFormats[YEAR_POS]+dateSeparators[YEAR_POS]+dateFormats[HOUR_POS];
posEndRef[0] = HOUR_POS;
} else if(!compareDatePart(tsMin, tsMax, dateFormats[SECOND_POS])) {
dateRef = dateFormats[DAY_POS]+dateSeparators[DAY_POS]+dateFormats[MONTH_POS]+dateSeparators[MONTH_POS]+
dateFormats[YEAR_POS]+dateSeparators[YEAR_POS]+dateFormats[HOUR_POS]+dateSeparators[HOUR_POS]+
dateFormats[MINUTE_POS];
posEndRef[0] = MINUTE_POS;
} else {
dateRef = dateFormats[DAY_POS]
+ dateSeparators[DAY_POS]
+ dateFormats[MONTH_POS]
+ dateSeparators[MONTH_POS]
+ dateFormats[YEAR_POS]
+ dateSeparators[YEAR_POS]
+ dateFormats[HOUR_POS]
+ dateSeparators[HOUR_POS]
+ dateFormats[MINUTE_POS]+dateSeparators[MINUTE_POS]+dateFormats[SECOND_POS];
posEndRef[0] = SECOND_POS;
}
SimpleDateFormat fmt = new SimpleDateFormat(dateRef);
fmt.setTimeZone(TimeZone.getTimeZone(defaultDisplayTimeZone));
return fmt;
}
public static SimpleDateFormat getDatePartFormat(Date tsMin, Date tsMax,
double pxstep, int posEndRef) {
int posEnd = MILLISECOND_POS;
if(pxstep >= 31536000000./*msInYear*/) posEnd = YEAR_POS;
else if(pxstep >= 2628000000./*msInMonth*/)posEnd = MONTH_POS;
else if(pxstep >= 86400000./*msInDay*/) posEnd = DAY_POS;
else if(pxstep >= 3600000./*msInHour*/) posEnd = HOUR_POS;
else if(pxstep >= 60000./*msInMinute*/) posEnd = MINUTE_POS;
else if(pxstep >= 1000./*msInSecond*/) posEnd = SECOND_POS;
String datePart = new String();
String sep;
if(posEndRef <0 || posEndRef == YEAR_POS || posEndRef == MONTH_POS || (posEnd<=MONTH_POS && posEndRef != DAY_POS)){
datePart += dateFormats[DAY_POS];
sep=dateSeparators[DAY_POS];
}
else{
sep=null;
}
if(posEndRef <0 || posEndRef == YEAR_POS || (posEnd<=YEAR_POS && posEndRef != MONTH_POS)){
if(sep!=null){
datePart+=sep;
}
datePart += dateFormats[MONTH_POS];
sep=dateSeparators[MONTH_POS];
}
else{
sep=null;
}
if(posEndRef <0 || posEnd==YEAR_POS){
if(sep!=null){
datePart+=sep;
}
datePart += dateFormats[YEAR_POS];
sep=dateSeparators[YEAR_POS];
}
else{
sep=null;
}
if(posEndRef == DAY_POS || ((posEnd==DAY_POS ||posEnd >= HOUR_POS) && posEnd < SECOND_POS && posEndRef != HOUR_POS)){
if(sep!=null){
datePart+=sep;
}
else{
if(datePart.length()!=0){
datePart+=dateSeparators[YEAR_POS];
}
}
datePart += dateFormats[HOUR_POS];
sep=dateSeparators[HOUR_POS];
}
else{
sep=null;
}
if(posEndRef == HOUR_POS || (posEnd >= HOUR_POS && posEnd < MILLISECOND_POS && posEndRef != MINUTE_POS)){
if(sep!=null){
datePart+=sep;
}
datePart += dateFormats[MINUTE_POS];
sep=dateSeparators[MINUTE_POS];
}
else{
sep=null;
}
if(posEndRef == MINUTE_POS || (posEnd >= MINUTE_POS && posEndRef != SECOND_POS)){
if(sep!=null){
datePart+=sep;
}
datePart += dateFormats[SECOND_POS];
sep=dateSeparators[SECOND_POS];
}
else{
sep=null;
}
if(posEndRef == SECOND_POS || posEnd >= MILLISECOND_POS){
if(sep!=null){
datePart+=sep;
}
datePart += dateFormats[MILLISECOND_POS];
}
SimpleDateFormat fmt = new SimpleDateFormat(datePart);
fmt.setTimeZone(TimeZone.getTimeZone(defaultDisplayTimeZone));
return fmt;
}
/**
* @param tsMin
* @param tsMax
* @param dateFmt
*/
public static boolean compareDatePart(Date tsMin, Date tsMax, String dateFmt) {
SimpleDateFormat dateFormat = new SimpleDateFormat(dateFmt);
dateFormat.setTimeZone(TimeZone.getTimeZone(defaultDisplayTimeZone));
String minValue = dateFormat.format(tsMin);
String maxValue = dateFormat.format(tsMax);
return minValue.equals(maxValue);
}
// Panel components
protected DatePartField _dayField;
protected JComboBox _monthField;
protected NumberField _yearField;
protected DatePartField _hourField, _minuteField, _secondField, _millisecondField;
protected TimeZone displayTimeZone;
public DateTimePanel(double value,TimeZone timeZone) {
if (timeZone==null)
displayTimeZone = TimeZone.getTimeZone(defaultDisplayTimeZone);
else
displayTimeZone= timeZone;
setLayout(new FlowLayout(FlowLayout.LEADING, 0, 5));
GregorianCalendar date = new GregorianCalendar();
date.setTimeZone(displayTimeZone);
date.setTimeInMillis(new Double(value).longValue());
add(_dayField = new DatePartField(date.get(Calendar.DAY_OF_MONTH), date.getActualMinimum(Calendar.DAY_OF_MONTH), date.getActualMaximum(Calendar.DAY_OF_MONTH), 2));
String[] months = new String[12];
SimpleDateFormat dateFmt = new SimpleDateFormat("MMM");
boolean isComplete = false;
for(GregorianCalendar iDate = new GregorianCalendar(1970, Calendar.JANUARY, 1);
!isComplete ;
iDate.roll(Calendar.MONTH, true)) {
months[iDate.get(Calendar.MONTH)] = dateFmt.format(new Date(iDate.getTimeInMillis()));
isComplete = iDate.get(Calendar.MONTH) == Calendar.DECEMBER;
}
_monthField = new JComboBox(months);
add(_monthField);
_monthField.setSelectedIndex(date.get(Calendar.MONTH));
add(_yearField = new NumberField(date.get(Calendar.YEAR), 4));
add(new Label(""));
add(_hourField = new DatePartField(date.get(Calendar.HOUR_OF_DAY), 0, 23, 2));
add(_minuteField = new DatePartField(date.get(Calendar.MINUTE), 0, 59, 2));
add(_secondField = new DatePartField(date.get(Calendar.SECOND), 0, 59, 2));
add(_millisecondField = new DatePartField(date.get(Calendar.MILLISECOND), 0, 999, 3));
}
public DateTimePanel(double value) {
this(value, null);
}
public long getValue() {
Date dateTmp = getDate();
return dateTmp.getTime();
}
public void setValue(double value) {
GregorianCalendar date = new GregorianCalendar();
date.setTimeZone(displayTimeZone);
date.setTimeInMillis(new Double(value).longValue());
_dayField.setValue(date.get(Calendar.DAY_OF_MONTH));
_monthField.setSelectedIndex(date.get(Calendar.MONTH));
_yearField.setValue(date.get(Calendar.YEAR));
_hourField.setValue(date.get(Calendar.HOUR_OF_DAY));
_minuteField.setValue(date.get(Calendar.MINUTE));
_secondField.setValue(date.get(Calendar.SECOND));
_millisecondField.setValue(date.get(Calendar.MILLISECOND));
}
public void setEnabled(boolean isEnabled) {
for(int iComponent = 0 ; iComponent < getComponentCount() ; iComponent++) {
getComponent(iComponent).setEnabled(isEnabled);
}
}
public void setText(String s) {
Date dateTmp = getDate();
GregorianCalendar date = new GregorianCalendar();
date.setTimeZone(displayTimeZone);
date.setTimeInMillis(dateTmp.getTime());
_dayField.setValue(date.get(Calendar.DAY_OF_MONTH));
_monthField.setSelectedIndex(date.get(Calendar.MONTH));
_yearField.setValue(date.get(Calendar.YEAR));
_hourField.setValue(date.get(Calendar.HOUR_OF_DAY));
_minuteField.setValue(date.get(Calendar.MINUTE));
_secondField.setValue(date.get(Calendar.SECOND));
_millisecondField.setValue(date.get(Calendar.MILLISECOND));
}
public Date getDate() {
SimpleDateFormat fmt = new SimpleDateFormat(defaultDateFormat);
fmt.setTimeZone(displayTimeZone);
Date dateTmp;
String sDay = _dayField.getText()+dateSeparators[DAY_POS];
String sMonth = _monthField.getSelectedItem()+dateSeparators[MONTH_POS];
String sYear = _yearField.getText()+dateSeparators[YEAR_POS];
String sDate = sDay+sMonth+sYear;
String sHour = _hourField.getText()+dateSeparators[HOUR_POS];
String sMinute = _minuteField.getText()+dateSeparators[MINUTE_POS];
String sSecond = _secondField.getText()+dateSeparators[SECOND_POS];
String sMillisecond = _millisecondField.getText();
String sTime = sHour+sMinute+sSecond+sMillisecond;
ParsePosition pos = new ParsePosition(0);
dateTmp = fmt.parse(sDate+sTime, pos);
if( pos.getIndex() == 0 )
throw new NumberFormatException("Invalid date.");
return dateTmp;
}
public String getText() {
SimpleDateFormat fmt = new SimpleDateFormat(defaultDateFormat);
fmt.setTimeZone(displayTimeZone);
String textDate = _dayField+dateSeparators[DAY_POS]+_monthField+dateSeparators[MONTH_POS]+
_yearField+dateSeparators[YEAR_POS]+_hourField+dateSeparators[HOUR_POS]+
_minuteField+dateSeparators[MINUTE_POS]+_secondField+dateSeparators[SECOND_POS]+
_millisecondField;
try {
fmt.parse(textDate);
} catch (ParseException e) {
throw new NumberFormatException("Invalid date.");
}
return textDate;
}
// Inner classes
public class DatePartField extends NumberField {
private double _min, _max;
DatePartField(double value, double min, double max, int columns) {
super(columns);
_min = min;
_max = max;
if(value < _min || value > _max)
throw new NumberFormatException("Invalid date part.");
setValue(value);
}
public double getDoubleValue() throws NumberFormatException {
double value = super.getDoubleValue();
if(value < _min || value > _max)
throw new NumberFormatException("Invalid date part.");
return value;
}
public long getLongValue() throws NumberFormatException {
long value = super.getLongValue();
if(value < new Double(_min).longValue() || value > new Double(_max).longValue())
throw new NumberFormatException("Invalid date part.");
return value;
}
public void setValue(double value) {
setValue(new Double(value).longValue());
}
public void setValue(long value) {
if(value < new Double(_min).longValue() || value > new Double(_max).longValue())
throw new NumberFormatException("Invalid date part.");
super.setValue(value);
}
}
}