/******************************************************************************* * Mission Control Technologies, Copyright (c) 2009-2012, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * The MCT platform is licensed 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. * * MCT includes source code licensed under additional open source licenses. See * the MCT Open Source Licenses file included with this distribution or the About * MCT Licenses dialog available at runtime from the MCT Help menu for additional * information. *******************************************************************************/ package gov.nasa.arc.mct.fastplot.view; import gov.nasa.arc.mct.fastplot.bridge.PlotConstants; import java.awt.event.ActionListener; import java.awt.event.FocusListener; import java.text.DecimalFormat; import java.text.ParseException; import java.util.GregorianCalendar; import javax.swing.InputVerifier; import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.text.MaskFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TimeSpanTextField extends JFormattedTextField { private static final long serialVersionUID = -4115671788373208673L; private final static Logger logger = LoggerFactory.getLogger(TimeSpanTextField.class); private static final String DEFAULT_VALUE = "000/00:00:00"; private static final int NUM_COLUMNS = DEFAULT_VALUE.length() - 3; // Don't need columns for colons static final private int DAYS_POSITION = 0; static final private int HOURS_POSITION = 4; static final private int MINUTES_POSITION = 7; static final private int SECONDS_POSITION = 10; private static final DecimalFormat dayFormat = new DecimalFormat("000"); private static final DecimalFormat hhmmssFormat = new DecimalFormat("00"); private MaskFormatter yearFormatter; private final YearSpanTextField yearSpanValue; public TimeSpanTextField(AbstractFormatter formatter) { super(formatter); setInputVerifier(new DurationVerifier()); setColumns(NUM_COLUMNS); setValue(DEFAULT_VALUE); setHorizontalAlignment(JFormattedTextField.RIGHT); yearSpanValue = createYearSpanTextField(); } @Override public void setEnabled(boolean state) { super.setEnabled(state); yearSpanValue.setEnabled(state); } public int getDayOfYear() { String work = (String) getValue(); return Integer.parseInt(work.substring(0, 3)); } public int getHourOfDay() { String work = (String) getValue(); return Integer.parseInt(work.substring(4, 6)); } public int getMinute() { String work = (String) getValue(); return Integer.parseInt(work.substring(7, 9)); } public int getSecond() { String work = (String) getValue(); return Integer.parseInt(work.substring(10, 12)); } public int getSubYearValue() { return getDayOfYear() + getHourOfDay() + getMinute() + getSecond(); } public long getDurationInMillis() { return (long) PlotConstants.MILLISECONDS_IN_SECOND * getSecond() + (long) PlotConstants.MILLISECONDS_IN_MIN * getMinute() + (long) PlotConstants.MILLISECONDS_IN_HOUR * getHourOfDay() + (long) PlotConstants.MILLISECONDS_IN_DAY * getDayOfYear() + (long) PlotConstants.MILLISECONDS_IN_YEAR * yearSpanValue.getYears(); } public void setTime(TimeDuration duration) { StringBuilder builder = new StringBuilder(); builder.append(dayFormat.format(duration.getDays()) + "/"); builder.append(hhmmssFormat.format(duration.getHours()) + ":"); builder.append(hhmmssFormat.format(duration.getMinutes()) + ":"); builder.append(hhmmssFormat.format(duration.getSeconds())); setValue(builder.toString()); yearSpanValue.setValue(duration.getYears()); } @Override public synchronized void addActionListener(ActionListener l) { super.addActionListener(l); if (yearSpanValue != null) yearSpanValue.addActionListener(l); } @Override public synchronized void removeActionListener(ActionListener l) { super.removeActionListener(l); if (yearSpanValue != null) yearSpanValue.removeActionListener(l); } @Override public synchronized void addFocusListener(FocusListener l) { super.addFocusListener(l); if (yearSpanValue != null) yearSpanValue.addFocusListener(l); } @Override public synchronized void removeFocusListener(FocusListener l) { super.removeFocusListener(l); if (yearSpanValue != null) yearSpanValue.removeFocusListener(l); } YearSpanTextField createYearSpanTextField() { try { yearFormatter = new MaskFormatter("#####") { /** * */ private static final long serialVersionUID = -6395586629439379363L; @Override public String valueToString(Object value) { if (value == null) return "00000"; return String.format("%05d", Integer.parseInt(value.toString())); } }; yearFormatter.setPlaceholderCharacter('0'); } catch (ParseException e) { logger.error("Error in creating a mask formatter", e); } return new YearSpanTextField(yearFormatter); } public YearSpanTextField getYearSpanValue() { return yearSpanValue; } /** * Used for a field with a Time Duration */ class DurationVerifier extends InputVerifier { private void setTimeValue(int dayOfYear, int hourOfDay, int minute, int second) { StringBuilder builder = new StringBuilder(); builder.append(dayFormat.format(dayOfYear) + "/"); builder.append(hhmmssFormat.format(hourOfDay) + ":"); builder.append(hhmmssFormat.format(minute) + ":"); builder.append(hhmmssFormat.format(second)); setValue(builder.toString()); } @Override public boolean verify(JComponent component) { TimeSpanTextField field = (TimeSpanTextField) component; String days = field.getText().substring(DAYS_POSITION, 3); String hours = field.getText().substring(HOURS_POSITION, 6); String minutes = field.getText().substring(MINUTES_POSITION, 9); String seconds = field.getText().substring(SECONDS_POSITION, 12); int yearsValue = Integer.parseInt(yearSpanValue.getValue().toString()); int daysValue = Integer.parseInt(days); int hoursValue = Integer.parseInt(hours); int minutesValue = Integer.parseInt(minutes); int secondsValue = Integer.parseInt(seconds); // Check seconds field. Carry over values > 59 if (secondsValue >= 60) { minutesValue += secondsValue/60; secondsValue = secondsValue % 60; } // Check minutes field. Carry over values > 59 if (minutesValue >= 60) { hoursValue += minutesValue/60; minutesValue = minutesValue % 60; } // Check hour of day field. Carry over values > 23 if (hoursValue >= 24) { daysValue += hoursValue/24; hoursValue = hoursValue % 24; } //Carry over values > 365 to year if (daysValue > 365) { yearSpanValue.setText(String.format("%05d", (Integer.parseInt(yearSpanValue.getValue().toString()) + (daysValue / 365)))); daysValue = daysValue % 365; } setTimeValue(daysValue, hoursValue, minutesValue, secondsValue); return field.isEditValid(); } } public static class YearSpanTextField extends JFormattedTextField { private static final long serialVersionUID = -2520968397371605584L; private static final String DEFAULT_VALUE = "00000"; private static final int NUM_COLUMNS = DEFAULT_VALUE.length(); public YearSpanTextField(AbstractFormatter formatter) { super(formatter); setColumns(NUM_COLUMNS); setValue(DEFAULT_VALUE); setHorizontalAlignment(JFormattedTextField.RIGHT); } public int getYears() { return Integer.parseInt(getText()); } } }