001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2025 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas/ 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see https://www.gnu.org/licenses/. 027 */ 028 029package edu.wisc.ssec.mcidasv.ui; 030 031import java.awt.BorderLayout; 032import java.util.Calendar; 033import java.util.Date; 034import java.util.GregorianCalendar; 035import java.util.TimeZone; 036 037import javax.swing.Box; 038import javax.swing.JComponent; 039import javax.swing.JLabel; 040import javax.swing.JPanel; 041import javax.swing.JSpinner; 042import javax.swing.SpinnerDateModel; 043 044import com.toedter.calendar.JCalendar; 045import com.toedter.calendar.JDateChooser; 046 047import ucar.unidata.idv.IdvConstants; 048import ucar.unidata.util.GuiUtils; 049 050/** 051 * This class is just a backport of the IDV's old {@code DateTimePicker}. 052 */ 053public class JCalendarPicker extends JPanel { 054 055 /** Date chooser */ 056 private JDateChooser dateChooser; 057 058 /** SpinnerDateModel */ 059 private SpinnerDateModel timeModel; 060 061 /** JCalendar */ 062 private JCalendar jc; 063 064 /** 065 * Default constructor. Builds a {@code JCalendarPicker} with a {@code null} 066 * initial date and includes the {@literal "hour picker"}. 067 */ 068 public JCalendarPicker() { 069 this(null, null, true); 070 } 071 072 /** 073 * Creates a {@code JCalendarPicker} with a {@code null} initial date. 074 * 075 * @param includeHours Whether or not to include an hour picker. 076 */ 077 public JCalendarPicker(boolean includeHours) { 078 this(null, null, includeHours); 079 } 080 081 /** 082 * Create a {@code JCalendarPicker} with the initial date. 083 * 084 * @param date Initial date. {@code null} is allowed. 085 */ 086 public JCalendarPicker(Date date) { 087 this(date, null, true); 088 } 089 090 /** 091 * Create a {@code JCalendarPicker} with the initial date. 092 * 093 * @param date Initial date. {@code null} is allowed. 094 * @param timeZoneId Time zone identifier. If {@code null}, 095 * {@link IdvConstants#DEFAULT_TIMEZONE} is used. 096 * @param includeHours {@code true} to have an hour picker. 097 * 098 * @see TimeZone#getTimeZone(String) 099 */ 100 public JCalendarPicker(Date date, String timeZoneId, boolean includeHours) { 101 jc = new JCalendar(); 102 Calendar calendar = getCalendar(null); 103 jc.getDayChooser().setCalendar(calendar); 104 jc.setCalendar(calendar); 105 106 dateChooser = new JDateChooser(jc, new Date(), null, new JCalendarDateEditor()); 107 setLayout(new BorderLayout()); 108 109 // Create a date spinner that controls the hours 110 timeModel = new SpinnerDateModel(calendar.getTime(), null, null, 111 Calendar.HOUR_OF_DAY); 112 JSpinner spinner = new JSpinner(timeModel); 113 JSpinner.DateEditor editor = 114 new JSpinner.DateEditor(spinner, "HH:mm"); 115 spinner.setEditor(editor); 116 JComponent timeComp; 117 if (timeZoneId == null) { 118 timeZoneId = IdvConstants.DEFAULT_TIMEZONE; 119 } 120 String timeZoneLabel = ' ' + TimeZone.getTimeZone(timeZoneId).getID(); 121 if (includeHours) { 122 timeComp = GuiUtils.hbox(spinner, new JLabel(timeZoneLabel), 5); 123 } else { 124 timeComp = new JLabel(timeZoneLabel); 125 } 126 add(BorderLayout.CENTER, GuiUtils.hbox(dateChooser, 127 GuiUtils.hbox(timeComp, Box.createHorizontalStrut(8)))); 128 if (date != null) { 129 setDate(date); 130 } 131 } 132 133 public JDateChooser getDateChooser() { 134 return dateChooser; 135 } 136 137 /** 138 * Get the {@link Date} that has been set. 139 * 140 * @return {@code Date} that represents the user's selection. 141 */ 142 public Date getDate() { 143 Date d = dateChooser.getDate(); 144 Calendar c0 = getCalendar(d); 145 Calendar c1 = new GregorianCalendar(c0.get(Calendar.YEAR), 146 c0.get(Calendar.MONTH), 147 c0.get(Calendar.DAY_OF_MONTH)); 148 149 if (timeModel != null) { 150 Date time = timeModel.getDate(); 151 Calendar timeCal = getCalendar(time); 152 c1.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY)); 153 c1.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE)); 154 c1.set(Calendar.SECOND, timeCal.get(Calendar.SECOND)); 155 } 156 return c1.getTime(); 157 } 158 159 /** 160 * Get the calendar for this instance. 161 * 162 * @param date The date. If {@code null}, the current time in the system's 163 * default time zone will be used instead. 164 * 165 * @return {@link GregorianCalendar} associated with {@code date}. 166 */ 167 private Calendar getCalendar(Date date) { 168 Calendar calendar = new GregorianCalendar(); 169 if (date != null) { 170 calendar.setTime(date); 171 } 172 return calendar; 173 } 174 175 /** 176 * Set the {@link Date} that will be used to populate the GUI components. 177 * 178 * @param date {@code Date}. 179 */ 180 public void setDate(Date date) { 181 Calendar c = getCalendar(date); 182 dateChooser.setDate(c.getTime()); 183 timeModel.setValue(date); 184 } 185 186 /** 187 * Get the user's selection as a {@literal "YYYY-MM-DD"} string. 188 * <b>This method ignores time zones.</b> 189 * 190 * @return Selected date as a {@literal "YYYY-MM-DD"} string. 191 */ 192 public String getUserSelectedDay() { 193 Calendar selectedDay = getCalendar(dateChooser.getDate()); 194 int year = selectedDay.get(Calendar.YEAR); 195 int month = selectedDay.get(Calendar.MONTH) + 1; // zero-based 196 int day = selectedDay.get(Calendar.DAY_OF_MONTH); 197 return String.format("%d-%02d-%02d", year, month, day); 198 } 199}