/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.gui.util;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
* This is Date mask control. Using this control we can pop up our date in the
* text field. And this control is developed basically for JDK1.3 and lower
* version support. This control is similar to JSpinner control this is
* available in JDK1.4 and above only.
* <p>
* This will set the date "yyyy/MM/dd HH:mm:ss" in this format only.
* </p>
*/
public class JDateField extends JTextField {
private static final long serialVersionUID = 240L;
// Datefields are not thread-safe
private final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); // $NON-NLS-1$
/*
* The following array must agree with dateFormat
*
* It is used to translate the positions in the buffer to the values used by
* the Calendar class for the field id.
*
* Current format: MM/DD/YYYY HH:MM:SS 01234567890123456789 ^buffer
* positions
*/
private static final int[] FIELD_POSITIONS = {
Calendar.YEAR, // Y
Calendar.YEAR, // Y
Calendar.YEAR, // Y
Calendar.YEAR, // Y
Calendar.YEAR, // sp
Calendar.MONTH, // M
Calendar.MONTH, // M
Calendar.MONTH, // /
Calendar.DAY_OF_MONTH, // D
Calendar.DAY_OF_MONTH, // D
Calendar.DAY_OF_MONTH, // /
Calendar.HOUR_OF_DAY, // H
Calendar.HOUR_OF_DAY, // H
Calendar.HOUR_OF_DAY, // :
Calendar.MINUTE, // M
Calendar.MINUTE, // M
Calendar.MINUTE, // :
Calendar.SECOND, // S
Calendar.SECOND, // S
Calendar.SECOND // end
};
/**
* Create a DateField with the specified date.
*
* @param date
* The {@link Date} to be used
*/
public JDateField(Date date) {
super(20);
this.addKeyListener(new KeyFocus());
this.addFocusListener(new FocusClass());
String myString = dateFormat.format(date);
setText(myString);
}
// Dummy constructor to allo JUnit tests to work
public JDateField() {
this(new Date());
}
/**
* Set the date to the Date mask control.
*
* @param date
* The {@link Date} to be set
*/
public void setDate(Date date) {
setText(dateFormat.format(date));
}
/**
* Get the date from the Date mask control.
*
* @return The currently set date
*/
public Date getDate() {
try {
return dateFormat.parse(getText());
} catch (ParseException e) {
return new Date();
}
}
/*
* Convert position in buffer to Calendar type Assumes that pos >=0 (which
* is true for getCaretPosition())
*/
private static int posToField(int pos) {
if (pos >= FIELD_POSITIONS.length) { // if beyond the end
pos = FIELD_POSITIONS.length - 1; // then set to the end
}
return FIELD_POSITIONS[pos];
}
/**
* Converts a date/time to a calendar using the defined format
*/
private Calendar parseDate(String datetime) {
Calendar c = Calendar.getInstance();
try {
Date dat = dateFormat.parse(datetime);
c.setTime(dat);
} catch (ParseException e) {
// Do nothing; the current time will be returned
}
return c;
}
/*
* Update the current field. The addend is only expected to be +1/-1, but
* other values will work. N.B. the roll() method only supports changes by a
* single unit - up or down
*/
private void update(int addend, boolean shifted) {
Calendar c = parseDate(getText());
int pos = getCaretPosition();
int field = posToField(pos);
if (shifted) {
c.roll(field, true);
} else {
c.add(field, addend);
}
String newDate = dateFormat.format(c.getTime());
setText(newDate);
if (pos > newDate.length()) {
pos = newDate.length();
}
final int newPosition = pos;
SwingUtilities.invokeLater(() -> setCaretPosition(newPosition));
}
class KeyFocus extends KeyAdapter {
KeyFocus() {}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
update(1, e.isShiftDown());
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
update(-1, e.isShiftDown());
}
}
}
class FocusClass implements FocusListener {
FocusClass() {}
@Override
public void focusGained(FocusEvent e) {}
@Override
public void focusLost(FocusEvent e) {
if(getText() == null || getText().isEmpty()) {
return;
}
try {
dateFormat.parse(getText());
} catch (ParseException e1) {
requestFocusInWindow();
}
}
}
}