// (c) 2003 Allen I Holub. All rights reserved.
package com.holub.ui;
import javax.swing.*;
import java.util.Date;
import java.text.*;
import java.awt.event.*; // for testing
import javax.swing.*; // for testing
import com.holub.ui.Input;
import com.holub.tools.DateUtil;
/***
* This convenience class customizes {@link Input} to handle date input.
* It provides a {@link Input.Customizer} and also appropriate constructors
* and accessors.
* <p>
* Note that you can use both the {@link #toString} overload and base-class
* {@link #getText} methods to get the contents of the control. They behave
* slightly differently, though. <code>getText()</code> returns exactly what
* the user typed. This string is garanteed to be valid input to
* {@link DateUtil#parseDate}, but may not be correctly recognized by
* {@link DateFormat#parse DateFormat.parse()}. The string returned from
* <code>toString()</code> is in a cannonical form that's guaranteed to
* be recognizable by both of the foregoing methods. This string is not
* usually what the user typed; rather, it's a string representation of
* the date specified by the user.
*
* <!-- ====================== distribution terms ===================== -->
* <p><blockquote
* style="border-style: solid; border-width:thin; padding: 1em 1em 1em 1em;">
* <center>
* Copyright © 2003, Allen I. Holub. All rights reserved.
* </center>
* <br>
* <br>
* This code is distributed under the terms of the
* <a href="http://www.gnu.org/licenses/gpl.html"
* >GNU Public License</a> (GPL)
* with the following ammendment to section 2.c:
* <p>
* As a requirement for distributing this code, your splash screen,
* about box, or equivalent must include an my name, copyright,
* <em>and URL</em>. An acceptable message would be:
* <center>
* This program contains Allen Holub's <em>XXX</em> utility.<br>
* (c) 2003 Allen I. Holub. All Rights Reserved.<br>
* http://www.holub.com<br>
* </center>
* If your progam does not run interactively, then the foregoing
* notice must appear in your documentation.
* </blockquote>
* <!-- =============================================================== -->
* @author Allen I. Holub
*
* @see com.holub.ui.DateSelectorPanel
* @see com.holub.ui.DateSelectorDialog
* @see com.holub.ui.InteractiveDate
*/
public class DateInput extends Input
{
private static final DateFormat formatter = DateFormat.getDateInstance( DateFormat.MEDIUM );
/** Create a DateInput object for the given Date.
*/
public DateInput( Date source, final BorderStyle border, final boolean isHighlighted )
{ super( formatter.format(source), new Behavior(), border, isHighlighted);
}
/** Create a DateInput object for the Date represented in the given string.
* @param value String specifying the date. Extended formats described
* in {@link com.holub.tools.DateUtil#parseDate} are
* recognized. Use <code>null</code> or <code>""</code>
* for today's date.
*/
public DateInput( String value, final BorderStyle border, final boolean isHighlighted )
{ super( (value==null || value.length()== 0)
? formatter.format(new Date())
: value, new Behavior(), border, isHighlighted);
}
/** Creates a DateInput input field initialized to today, boxed and not
* highlighted.
*/
public DateInput()
{ this( new Date(), Input.BOXED, false );
}
/** Creates a DateInput input field initialized to the date specified
* in the argument, boxed and not highlighted.
*/
public DateInput( Date d )
{ this( d, Input.BOXED, false );
}
/** Creates a DateInput field initialized to the date specified
* in the argument, boxed and not highlighted.
*/
public DateInput( String str )
{ this( str, Input.BOXED, false );
}
/** Return the value of the current Input object as a Date.
* @return the value
*/
public Date value()
{ return DateUtil.parseDate( getText() );
}
/** Return the value of the current Input object. This is
* the string that the user typed, but is guaranteed to
* be recognisable by the {@link DateFormat#parse}. This
* method returns the same value as {@link #getText}.
*
* Return the string the user typed translated into a
* "canonical" form that the DateFormat class will
* recognize. I do this because the internal processor
* recognizes a few comon input formats that aren't handled
* properly by {@link DateFormat}. The {@link #getText} method
* returns the string the user <em>actually</em>typed.
*
* @return A string representing a date the user typed.
*/
public String toString()
{
return formatter.format( DateUtil.parseDate(getText()) );
}
/** Replace the current value with <code>source</code>
* @return the old value or null if the old
* value was empty or otherwise invalid.
*/
public Date assign( Date source )
{ String old = getText();
setText( formatter.format(source) );
Date value = DateUtil.parseDate(old);
return value;
}
/** An implemenation of {@link Input.Customizer} for dates.
*/
public static class Behavior implements Customizer
{
/** Check if input is valid. */
public boolean isValid(String inputString)
{ return DateUtil.parseDate(inputString) != null;
}
public String help( String badInput )
{ return "You must enter a date in one of the following formats:<br>\n"
+ DateUtil.supportedDateFormats(true);
}
public void prepare( JTextField current )
{ current.setToolTipText("Enter a Date");
}
public boolean validatesOnExit(){ return true; }
}
//----------------------------------------------------------------------
public static class Test
{ public static void main( String[] args )
{ JFrame frame = new JFrame("DateInput Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BoxLayout layout = new BoxLayout(
frame.getContentPane(), BoxLayout.Y_AXIS);
frame.getContentPane().setLayout(layout);
final DateInput in1 = new DateInput();
frame.getContentPane().add( in1 );
final DateInput in2 = new DateInput((String)null);
frame.getContentPane().add( in2 );
final DateInput in3 = new DateInput("");
frame.getContentPane().add( in3 );
final DateInput in4 = new DateInput("1/2/34");
frame.getContentPane().add( in4 );
ActionListener reporter = new ActionListener()
{ public void actionPerformed(ActionEvent e)
{ System.out.println("----------------------------");
System.out.println( "value: in1=" + in1.value() );
System.out.println( "value: in2=" + in2.value() );
System.out.println( "value: in3=" + in3.value() );
System.out.println( "value: in4=" + in4.value() );
}
};
in1.addActionListener(reporter);
in2.addActionListener(reporter);
in3.addActionListener(reporter);
in4.addActionListener(reporter);
frame.addWindowListener
( new WindowAdapter()
{ public void windowClosing( WindowEvent e )
{ System.out.println( "value: in1=" + in1.value() );
System.out.println( "value: in2=" + in2.value() );
System.out.println( "value: in3=" + in3.value() );
System.out.println( "value: in4=" + in4.value() );
System.out.println( "");
System.out.println( "text: in1=" + in1.getText() );
System.out.println( "text: in2=" + in2.getText() );
System.out.println( "text: in3=" + in3.getText() );
System.out.println( "text: in4=" + in4.getText() );
System.out.println( "");
System.out.println( "string: in1=" + in1.toString() );
System.out.println( "string: in2=" + in2.toString() );
System.out.println( "string: in3=" + in3.toString() );
System.out.println( "string: in4=" + in4.toString() );
System.exit(0);
}
}
);
frame.pack();
frame.show();
}
}
}