001package arcommon.ui.window; 002 003// Code copied from https://examples.javacodegeeks.com/desktop-java/swing/java-swing-date-picker-example 004// and modified a lot 005 006import java.awt.BorderLayout; 007import java.awt.Color; 008import java.awt.Dimension; 009import java.awt.GridLayout; 010import java.awt.Point; 011import java.awt.event.ActionEvent; 012import java.awt.event.ActionListener; 013import java.text.ParseException; 014import java.text.SimpleDateFormat; 015import java.util.Calendar; 016import java.util.Date; 017 018import javax.swing.JButton; 019import javax.swing.JComponent; 020import javax.swing.JLabel; 021import javax.swing.JPanel; 022import javax.swing.SwingUtilities; 023 024import arcommon.DateUtil; 025import arcommon.Util; 026import arcommon.ui.other.GUIUtil; 027 028public class DatePickerJDialog extends AbstractJDialog { 029 private static final long serialVersionUID = 2861477430791190912L; 030 031 private static final SimpleDateFormat DEFAULT_DATE_FORMAT = DateUtil.DATE_FORMAT; 032 033 private static final String[] HEADER = {"Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"}; 034 private static final int ROWS = 7; 035 private static final int COLUMNS = 7; 036 037 private SimpleDateFormat simpleDateFormat; 038 039 private int month; 040 private int year; 041 042 private JLabel monthYearJLabel; 043 private String pickedDay; 044 private int pickedYear; 045 private boolean onlyYearWasSelected; 046 private JButton[] buttons; 047 048 private int nowYear; 049 private int nowMonth; 050 private int nowDay; 051 052 private int startYear; 053 private int startMonth; 054 private int startDay; 055 056 public DatePickerJDialog(String title, JComponent field, String dateString) { 057 this(title, field, dateString, null); 058 } 059 060 public DatePickerJDialog(String title, JComponent field, String dateString, boolean allowSelectYearOnly, JComponent extraComponent) { 061 this(title, field, dateString, null, allowSelectYearOnly, extraComponent); 062 } 063 064 public DatePickerJDialog(String title, JComponent field, String dateString, SimpleDateFormat psimpleDateFormat) { 065 this(title, field, dateString, null, false, null); 066 } 067 068 public DatePickerJDialog(String title, JComponent field, String dateString, SimpleDateFormat psimpleDateFormat, boolean allowSelectYearOnly, JComponent extraComponent) { 069 super(title != null ? title : "Select a date"); 070 071 if (psimpleDateFormat != null) { 072 simpleDateFormat = psimpleDateFormat; 073 } else { 074 simpleDateFormat = DEFAULT_DATE_FORMAT; 075 } 076 077 Calendar calendar = Calendar.getInstance(); 078 nowYear = calendar.get(Calendar.YEAR); 079 nowMonth = calendar.get(Calendar.MONTH); 080 nowDay = calendar.get(Calendar.DAY_OF_MONTH); 081 boolean yearOnly = false; 082 if (dateString != null && dateString.length() > 0) { 083 try { 084 Date date = DateUtil.stringToDate(simpleDateFormat, dateString, true); 085 calendar.setTime(date); 086 } catch (ParseException e) { 087 if (allowSelectYearOnly) { 088 try { 089 Date date = DateUtil.stringToDate(DateUtil.DATE_FORMAT_YEAR_ONLY, dateString, true); 090 calendar.setTime(date); 091 yearOnly = true; 092 } catch (ParseException e2) { 093 Util.printMessageWithSourceLine(e2.getMessage()); 094 } 095 } else { 096 Util.printMessageWithSourceLine(e.getMessage()); 097 } 098 } 099 } 100 year = calendar.get(Calendar.YEAR); 101 month = calendar.get(Calendar.MONTH); 102 103 startYear = calendar.get(Calendar.YEAR); 104 startMonth = calendar.get(Calendar.MONTH); 105 startDay = calendar.get(Calendar.DAY_OF_MONTH); 106 107 if (yearOnly) { 108 calendar = Calendar.getInstance(); 109 month = calendar.get(Calendar.MONTH); 110 startMonth = calendar.get(Calendar.MONTH); 111 startDay = -1; 112 } 113 114 JPanel northPanel = new JPanel(new GridLayout(1, 3)); 115 add(northPanel, BorderLayout.NORTH); 116 117 JPanel previousPanel = new JPanel(new GridLayout(1, 2)); 118 northPanel.add(previousPanel); 119 120 JButton previousYear = new JButton("<<"); 121 previousPanel.add(previousYear); 122 previousYear.addActionListener(new ActionListener() { 123 @Override 124 public void actionPerformed(ActionEvent event) { 125 year--; 126 updateDate(); 127 } 128 }); 129 130 JButton previousMonth = new JButton("<"); 131 previousPanel.add(previousMonth); 132 previousMonth.addActionListener(new ActionListener() { 133 @Override 134 public void actionPerformed(ActionEvent event) { 135 month--; 136 updateDate(); 137 } 138 }); 139 140 monthYearJLabel = new JLabel("", JLabel.CENTER); 141 northPanel.add(monthYearJLabel); 142 143 JPanel nextPanel = new JPanel(new GridLayout(1, 2)); 144 northPanel.add(nextPanel); 145 146 JButton nextMonth = new JButton(">"); 147 nextPanel.add(nextMonth); 148 nextMonth.addActionListener(new ActionListener() { 149 public void actionPerformed(ActionEvent ae) { 150 month++; 151 updateDate(); 152 } 153 }); 154 155 JButton nextYear = new JButton(">>"); 156 nextPanel.add(nextYear); 157 nextYear.addActionListener(new ActionListener() { 158 public void actionPerformed(ActionEvent ae) { 159 year++; 160 updateDate(); 161 } 162 }); 163 164 JPanel centerPanel = new JPanel(new GridLayout(ROWS, COLUMNS)); 165 add(centerPanel, BorderLayout.CENTER); 166 centerPanel.setPreferredSize(new Dimension(400, 120)); 167 168 for (int x = 0; x < COLUMNS; x++) { 169 JLabel label = new JLabel(HEADER[x], JLabel.CENTER); 170 centerPanel.add(label); 171 } 172 173 buttons = new JButton[(ROWS - 1) * COLUMNS]; 174 for (int i = 0; i < buttons.length; i++) { 175 buttons[i] = new JButton(); 176 centerPanel.add(buttons[i]); 177 final int finalI = i; 178 buttons[i].addActionListener(new ActionListener() { 179 public void actionPerformed(ActionEvent ae) { 180 String text = buttons[finalI].getActionCommand(); 181 if (text.length() == 0) { 182 return ; 183 } 184 185 pickedDay = text; 186 dispose(); 187 } 188 }); 189 } 190 191 JPanel southPanel = new JPanel(new GridLayout(1, 3)); 192 add(southPanel, BorderLayout.SOUTH); 193 194 if (extraComponent != null) { 195 southPanel.add(extraComponent); 196 } else { 197 southPanel.add(new JPanel()); 198 } 199 200 if (allowSelectYearOnly) { 201 JButton selectYearButton = new JButton("Select year"); 202 southPanel.add(selectYearButton); 203 selectYearButton.addActionListener(new ActionListener() { 204 public void actionPerformed(ActionEvent ae) { 205 pickedYear = year; 206 onlyYearWasSelected = true; 207 dispose(); 208 } 209 }); 210 } else { 211 southPanel.add(new JPanel()); 212 } 213 214 JButton cancelButton = new JButton("Cancel"); 215 southPanel.add(cancelButton); 216 cancelButton.addActionListener(new ActionListener() { 217 public void actionPerformed(ActionEvent ae) { 218 pickedDay = null; 219 dispose(); 220 } 221 }); 222 223 // This is done invoked later to make buttons[x].requestFocusInWindow() work. 224 SwingUtilities.invokeLater(new Runnable() { 225 @Override 226 public void run() { 227 updateDate(); 228 } 229 }); 230 231 pack(); 232 233 Point locationOnScreen = field.getLocationOnScreen(); 234 int x = locationOnScreen.x + field.getWidth() / 2 - getWidth() / 2; 235 int y = locationOnScreen.y + field.getHeight(); 236 237 Dimension screenSize = GUIUtil.getScreenSize(); 238 if (x + getWidth() > screenSize.width) { 239 System.out.println("x + width > screenSize.width " + this); 240 x = screenSize.width - getWidth() - 50; 241 } 242 if (y + getHeight() > screenSize.height) { 243 System.out.println("y + height > screenSize.height " + this); 244 y = screenSize.height - getHeight() - 50; 245 } 246 if (x < 0) { 247 x = 50; 248 } 249 if (y < 0) { 250 y = 50; 251 } 252 253 setLocation(x, y); 254 setModal(true); 255 setVisible(true); 256 } 257 258 public void updateDate() { 259 for (int x = 0; x < buttons.length; x++) { 260 buttons[x].setText(""); 261 buttons[x].setEnabled(false); 262 buttons[x].setBackground(new Color(215, 215, 215)); 263 buttons[x].setForeground(Color.BLACK); 264 } 265 266 Calendar calendar = Calendar.getInstance(); 267 calendar.set(year, month, 1); 268 int viewedYear = calendar.get(Calendar.YEAR); 269 int viewedMonth = calendar.get(Calendar.MONTH); 270 int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); 271 int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); 272 for (int x = (dayOfWeek + 5) % COLUMNS, day = 1; day <= daysInMonth; x++, day++) { 273 buttons[x].setText("" + day); 274 buttons[x].setEnabled(true); 275 if (viewedYear == nowYear && viewedMonth == nowMonth && day == nowDay) { 276 buttons[x].setForeground(Color.RED); 277 if (viewedYear != startYear || viewedMonth != startMonth) { 278 buttons[x].requestFocusInWindow(); 279 } 280 } 281 if (viewedYear == startYear && viewedMonth == startMonth && day == startDay) { 282 buttons[x].setBackground(new Color(150, 150, 255)); 283 buttons[x].requestFocusInWindow(); 284 } 285 } 286 287 SimpleDateFormat sdf = new SimpleDateFormat("MMMM yyyy"); 288 monthYearJLabel.setText(sdf.format(calendar.getTime())); 289 } 290 291 public boolean onlyYearWasSelected() { 292 return onlyYearWasSelected; 293 } 294 295 public int getPickedYear() { 296 return pickedYear; 297 } 298 299 public String getPickedDate() { 300 if (pickedDay == null || pickedDay.equals("")) { 301 return null; 302 } 303 304 if (onlyYearWasSelected) { 305 throw new RuntimeException("onlyYearWasSelected use getPickedYear() and onlyYearWasSelected()"); 306 } 307 308 Calendar calendar = Calendar.getInstance(); 309 calendar.set(year, month, Integer.parseInt(pickedDay)); 310 return simpleDateFormat.format(calendar.getTime()); 311 } 312}