/*
* TimeFormat.java
* (FScape)
*
* Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de
*
*
* Changelog:
* 03-Mar-05 copied from Meloncillo
*/
package de.sciss.fscape.util;
import java.text.*;
import java.util.*;
/**
* A <code>MessageFormat</code> subclass for
* displaying time values in minutes
* and seconds.
*
* @author Hanns Holger Rutz
* @version 0.61, 09-Aug-04
*
* @see de.sciss.meloncillo.gui.NumberField#FLAG_MINSEC
*
* @todo this <strong>might</strong> be buggy (in apple's VM).
* the transport position label used to feed a time format
* which caused StackOverflow errors are a while. those errors
* disappeared when we programmed a custom label. however the
* bug might also come from JLabel. it should be checked if
* high frequency updates in the SimpleTransmitterEditor's setCursorInfo
* call -- which still use a TimeFormat -- provoke those StackOverflowErrors.
*/
public class TimeFormat
extends MessageFormat
{
private Object[] msgArgs = new Object[2];
private boolean isInteger;
/**
* Constructs a new <code>TimeFormat</code>
* with automatically created pattern.
*
* @param flags 0 at the moment
* @param prefix a string to prepend to the formatted string, or <code>null</code>
* @param suffix a string to append to the formatted string, or <code>null</code>
* @param numDecimals number of decimals, e.g. 3 for millisecs, 0 for secs
* @param locale <code>Locale</code> to choose for number formatting
*/
public TimeFormat( int flags, String prefix, String suffix, int numDecimals, Locale locale )
{
super( (prefix == null ? "" : prefix) + "{0}:{1}" + (suffix == null ? "" : suffix), locale );
isInteger = (numDecimals == 0);
NumberFormat formatSecs = NumberFormat.getInstance( locale );
formatSecs.setMinimumIntegerDigits( 2 );
formatSecs.setMaximumIntegerDigits( 2 );
formatSecs.setMinimumFractionDigits( numDecimals );
formatSecs.setMaximumFractionDigits( numDecimals );
this.setFormatByArgumentIndex( 0, NumberFormat.getIntegerInstance( locale ));
this.setFormatByArgumentIndex( 1, formatSecs );
}
/**
* Creates a formatted string
* using a parameter for seconds
*
* @param seconds the time in seconds which will
* be formatted using an MM:SS.millis pattern
* @return the formatted string ready for display
*/
public String formatTime( Number seconds )
{
double d = seconds.doubleValue();
msgArgs[0] = new Integer( (int) (d / 60) ); // XXX ?
msgArgs[1] = new Double( d % 60 );
return this.format( msgArgs );
}
/**
* Tries to parse a formatted time string
* (as produced by <code>formatTime</code>).
*
* @param str a formatted string such as "12:33.456"
* @return the number found by parsing the string. Either
* a Long, if the seconds are integer, otherwise
* a Double containing decimals for milliseconds.
* @throws ParseException if the string cannot be parsed
*/
public Number parseTime( String str )
throws ParseException
{
Object[] results = this.parse( str );
if( results.length != 2 || !(results[0] instanceof Number) || !(results[1] instanceof Number) ) {
throw new ParseException( str, 0 );
}
if( isInteger ) {
return new Long( ((Number) results[0]).longValue() * 60 + ((Number) results[1]).longValue() );
} else {
return new Double( ((Number) results[0]).longValue() * 60 + ((Number) results[1]).doubleValue() );
}
}
}