/*
ALMA - Atacama Large Millimiter Array
* Copyright (c) European Southern Observatory, 2013
*
* This library 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 library 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alma.acs.gui.widgets;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import alma.acs.gui.util.threadsupport.EDTExecutor;
/**
* A widget to select date and time replacing
* <CODE>com.cosylab.gui.components.r2.DateTimeChooser</CODE>.
* <P>
* The widget allows the user to select the date and time.
*
* @author acaproni
* @since ACS 12.1
*/
public class DateTimeSelector extends JComponent implements ActionListener {
/**
* The combo box to select the year.
*/
private final JComboBox yearCB=new JComboBox();
/**
* The combo box to select the month.
*/
private final JComboBox monthCB=new JComboBox();
/**
* The combo box to select the day of the month.
*/
private final JComboBox dayCB=new JComboBox();
/**
* The combo box to select the hours.
*/
private final JComboBox hoursCB=new JComboBox();
/**
* The combo box to select the minutes.
*/
private final JComboBox minsCB=new JComboBox();
/**
* The combo box to select the seconds.
*/
private final JComboBox secsCB=new JComboBox();
/**
* A helper object
*/
private final JComboBox[] comboBoxes = {yearCB, monthCB, dayCB, hoursCB, minsCB, secsCB };
/**
* Constructor
*/
public DateTimeSelector() {
EDTExecutor.instance().execute(new Runnable() {
@Override
public void run() {
initGUI();
}
});
}
/**
* Init the GUI
*/
private void initGUI() {
// YearCB is initialized from 2000 to the year next to this on
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
for (int t=2000; t<=cal.get(Calendar.YEAR)+1; t++) {
yearCB.addItem(Integer.valueOf(t));
}
// Month
for (int t=1; t<=12; t++) {
monthCB.addItem(Integer.valueOf(t));
}
// The day has its dedicated model
//dayCB.setModel(new DayComboBoxModel());
for (int t=1; t<=31; t++) {
dayCB.addItem(Integer.valueOf(t));
}
// hour
for (int t=0; t<24; t++) {
hoursCB.addItem(Integer.valueOf(t));
}
// Minutes and seconds
for (int t=0; t<60; t++) {
secsCB.addItem(Integer.valueOf(t));
minsCB.addItem(Integer.valueOf(t));
}
// Add the date panel
JPanel datePnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
datePnl.setBorder(BorderFactory.createTitledBorder("Date"));
datePnl.add(new JLabel("Day: "));
datePnl.add(dayCB);
datePnl.add(new JLabel("Month: "));
datePnl.add(monthCB);
datePnl.add(new JLabel("Year: "));
datePnl.add(yearCB);
// Add the time panel
JPanel timePnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
timePnl.setBorder(BorderFactory.createTitledBorder("Time"));
timePnl.add(new JLabel("Hour: "));
timePnl.add(hoursCB);
timePnl.add(new JLabel("Minute: "));
timePnl.add(minsCB);
timePnl.add(new JLabel("Second: "));
timePnl.add(secsCB);
// Add the widgets to the component
setLayout(new BorderLayout());
add(datePnl,BorderLayout.NORTH);
add(timePnl,BorderLayout.SOUTH);
for (JComboBox box: comboBoxes) {
box.setEditable(false);
// Initial selection that will be updated by the next setDate
//
// Do not add the action listener before selecting a item because actionPerformed calls #ratioDayCB
// that needs to get a selected item.
box.setSelectedIndex(0);
box.addActionListener(this);
}
setDate(cal);
}
/**
* The days displayed by {@link #dayCB} depends on the month
*/
private void ratioDayCB() {
int selectedMonth=(Integer)monthCB.getSelectedItem();
int selectedYear=(Integer)yearCB.getSelectedItem();
int maxDays;
switch (selectedMonth) {
case 2: {
// Feb
maxDays=(selectedYear%4==0) ? 29 :28;
break;
}
case 3: // Mar
case 4: // Apr
case 6: //Jun
case 9: // Sep
case 11: { //Nov
maxDays=30;
break;
}
default: {
maxDays=31;
}
}
DefaultComboBoxModel cbModel = (DefaultComboBoxModel)dayCB.getModel();
for (int d=29; d<=31; d++) {
if (d<=maxDays) {
// This day must be present for the selected month
if (cbModel.getIndexOf(Integer.valueOf(d))==-1) {
dayCB.addItem(Integer.valueOf(d));
}
} else {
// This day must be removed for the selected month
if (cbModel.getIndexOf(Integer.valueOf(d))!=-1) {
dayCB.removeItem(Integer.valueOf(d));
}
}
}
}
/**
* Set the date of the widgets to that represented by the passed calendar
*
* @param cal The date to set in the widgets
*/
public void setDate(Calendar cal) {
if (cal==null) {
throw new IllegalArgumentException("Can't set a date from a nul calendar obejct");
}
int year=cal.get(Calendar.YEAR);
int month=cal.get(Calendar.MONTH);
int day=cal.get(Calendar.DAY_OF_MONTH);
int hour=cal.get(Calendar.HOUR_OF_DAY);
int min=cal.get(Calendar.MINUTE);
int sec=cal.get(Calendar.SECOND);
// Select the current date in the widget
yearCB.setSelectedItem(Integer.valueOf(year));
monthCB.setSelectedItem(Integer.valueOf(month)+1);
dayCB.setSelectedItem(Integer.valueOf(day));
hoursCB.setSelectedItem(Integer.valueOf(hour));
minsCB.setSelectedItem(Integer.valueOf(min));
secsCB.setSelectedItem(Integer.valueOf(sec));
ratioDayCB();
}
/**
*
* @return The date selected by the user
*/
public Calendar getDate() {
Calendar ret = Calendar.getInstance();
int year=(Integer)yearCB.getSelectedItem();
int month=(Integer)monthCB.getSelectedItem()-1;
int day=(Integer)dayCB.getSelectedItem();
int hr=(Integer)hoursCB.getSelectedItem();
int min=(Integer)minsCB.getSelectedItem();
int sec=(Integer)secsCB.getSelectedItem();
ret.set(year, month, day, hr, min, sec);
return ret;
}
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource()==monthCB || e.getSource()==yearCB) {
ratioDayCB();
}
}
}