001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.comp;
015:
016: import java.beans.PropertyVetoException;
017: import java.text.Format;
018: import java.text.ParseException;
019:
020: /**
021: * Is the base interface of text based components which text is rendered/edited
022: * as a single line and following a format.
023: *
024: * <p>This component type is inspired in <code>javax.swing.JFormattedTextField</code>.
025: * Some documentation is borrowed from Swing.</p>
026: *
027: * <p>This component maintains two values, the value returned by {@link #getText()}
028: * is the value in the visual control rendering the component, and the value returned by {@link #getValue()}.
029: * The last one is restricted to the scope defined by {@link #getItsNatFormatter()}.</p>
030: *
031: * <p>When a new value on the visual control is set as the component value calling {@link #commitEdit()} first
032: * is validated/converted calling {@link ItsNatFormatter#stringToValue(String,ItsNatFormattedTextField)}.</p>
033: *
034: * <p>Any change to the internal value is notified with a "value" property change event
035: * and may be vetoed (see {@link #setValue(Object)}).</p>
036: *
037: * @author Jose Maria Arranz Santamaria
038: */
039: public interface ItsNatFormattedTextField extends ItsNatTextField {
040: /**
041: * Constant identifying that when focus is lost,
042: * <code>commitEdit</code> should be invoked. If in committing the
043: * new value a <code>ParseException</code> or
044: * <code>PropertyVetoException</code> is thrown, the invalid
045: * value will remain.
046: *
047: * @see #setFocusLostBehavior(int)
048: */
049: public static final int COMMIT = 0;
050:
051: /**
052: * Constant identifying that when focus is lost,
053: * <code>commitEdit</code> should be invoked. If in commiting the new
054: * value a <code>ParseException</code> or
055: * <code>PropertyVetoException</code> is thrown, the value will be
056: * reverted.
057: *
058: * @see #setFocusLostBehavior(int)
059: */
060: public static final int COMMIT_OR_REVERT = 1;
061:
062: /**
063: * Constant identifying that when focus is lost, editing value should
064: * be reverted to current value set on the component.
065: *
066: * @see #setFocusLostBehavior(int)
067: */
068: public static final int REVERT = 2;
069:
070: /**
071: * Constant identifying that when focus is lost, the edited value
072: * should be left.
073: *
074: * @see #setFocusLostBehavior(int)
075: */
076: public static final int PERSIST = 3;
077:
078: /**
079: * Returns the behavior when focus is lost. This will be one of
080: * {@link #COMMIT_OR_REVERT},
081: * {@link #COMMIT},
082: * {@link #REVERT} or
083: * {@link #PERSIST}
084: *
085: * Note that some {@link ItsNatFormatter}s may push changes to the
086: * control value.
087: *
088: * @return returns behavior when focus is lost. {@link #COMMIT_OR_REVERT} by default
089: * @see #setFocusLostBehavior(int)
090: */
091: public int getFocusLostBehavior();
092:
093: /**
094: * Sets the behavior when focus is lost. This will be one of
095: * {@link #COMMIT_OR_REVERT},
096: * {@link #COMMIT},
097: * {@link #REVERT} or
098: * {@link #PERSIST}
099: *
100: * @param behavior identifies behavior when focus is lost
101: * @see #getFocusLostBehavior()
102: */
103: public void setFocusLostBehavior(int behavior);
104:
105: /**
106: * Returns the last valid value. Based on the editing policy of
107: * the {@link ItsNatFormatter} this may not return the current
108: * edited value. The currently edited value can be obtained by invoking
109: * {@link #commitEdit()} followed by {@link #getValue()}.
110: *
111: * @return last valid value. The default value is null.
112: */
113: public Object getValue();
114:
115: /**
116: * Sets the value that will be formatted to the control by an
117: * {@link ItsNatFormatter} obtained from the current
118: * {@link ItsNatFormatterFactory}. If no
119: * {@link ItsNatFormatterFactory} has been specified, this will
120: * attempt to create one based on the type of <code>value</code>.
121: *
122: * <p>This new value is "voted" before is set firing a <code>java.beans.PropertyChangeEvent</code>
123: * event, with name "value", sent to the listeners registered with {@link ItsNatComponent#addVetoableChangeListener(VetoableChangeListener)}
124: * if some listener does a "veto" (throws a <code>java.beans.PropertyVetoException</code>)
125: * the new value is not set. If finally set the <code>PropertyChangeEvent</code> event
126: * is sent to the listeners registered with
127: * {@link ItsNatComponent#addPropertyChangeListener(java.beans.PropertyChangeListener)}
128: * or {@link ItsNatComponent#addPropertyChangeListener(String,java.beans.PropertyChangeListener)}
129: * with property name "value".
130: * </p>
131: *
132: * @param value value to display (and may be edit).
133: * @throws PropertyVetoException if the new value was vetoed.
134: */
135: public void setValue(Object value) throws PropertyVetoException;
136:
137: /**
138: * Forces the current value to be taken from the
139: * control and set as the current value converted first using the current
140: * {@link ItsNatFormatter}.
141: *
142: * @throws ParseException if the {@link ItsNatFormatter} is not able
143: * to format the current control value
144: * @throws PropertyVetoException if the new value was vetoed.
145: */
146: public void commitEdit() throws ParseException,
147: PropertyVetoException;
148:
149: /**
150: * Informs whether visual control content has changed and component value is
151: * still not modified.
152: *
153: * @return if visual value has changed and component value not.
154: */
155: public boolean isEdited();
156:
157: /**
158: * Returns true if the current value being edited is valid.
159: *
160: * @return true if the current value being edited is valid.
161: */
162: public boolean isEditValid();
163:
164: /**
165: * Creates a new default ItsNat formatter factory.
166: *
167: * <p>Current implementation is an {@link ItsNatFormatterFactoryDefault}.</p>
168: *
169: * @return a default formatter factory instance.
170: */
171: public ItsNatFormatterFactory createDefaultItsNatFormatterFactory();
172:
173: /**
174: * Returns the current ItsNat formatter factory.
175: *
176: * <p>By default ItsNat provides a default factory created with
177: * {@link #createDefaultItsNatFormatterFactory()}.</p>
178: *
179: * @return the current factory. May be null.
180: * @see #setItsNatFormatterFactory(ItsNatFormatterFactory)
181: */
182: public ItsNatFormatterFactory getItsNatFormatterFactory();
183:
184: /**
185: * Sets the current ItsNat formatter factory.
186: *
187: * @param tf the new formatter factory. May be null.
188: */
189: public void setItsNatFormatterFactory(ItsNatFormatterFactory tf);
190:
191: /**
192: * This method is called when the component needs to convert an Object value
193: * from/to String.
194: *
195: * <p>If a formatter was defined explicitly with a call to {@link #setItsNatFormatter(ItsNatFormatter)}
196: * this method returns this formatter, else returns the formatter of
197: * the default formatter factory ({@link #getItsNatFormatterFactory()} calling
198: * {@link ItsNatFormatterFactory#getItsNatFormatter(ItsNatFormattedTextField)},
199: * if no factory is defined or the factory has not an appropriated formatter,
200: * then the component tries to build an appropriated formatter to the current
201: * value ({@link #getValue()}).</p>
202: *
203: * @return the selected formatter.
204: */
205: public ItsNatFormatter getItsNatFormatter();
206:
207: /**
208: * Sets the default ItsNat formatter.
209: *
210: * @param formatter the default formatter. May be null (the factory will be used).
211: */
212: public void setItsNatFormatter(ItsNatFormatter formatter);
213:
214: /**
215: * Defines a default ItsNat formatter based on the specified <code>java.text.Format</code>.
216: *
217: * <p>The method {@link #createItsNatFormatter(java.text.Format)} is called to create
218: * an ItsNat formatter wrapping this format. The new ItsNat formatter is
219: * set calling {@link #setItsNatFormatter(ItsNatFormatter)}.</p>
220: *
221: * @param format the <code>java.text.Format</code> object to set as the default formatter.
222: */
223: public void setFormat(Format format);
224:
225: /**
226: * Creates an ItsNat formatter wrapping the specified <code>java.text.Format</code>.
227: *
228: * <p>Current implementation uses <code>Format.parseObject(String)</code> and
229: * <code>Format.format(Object)</code> to convert string and values.</p>
230: *
231: * @param format the <code>java.text.Format</code> to wrap.
232: * @return a new ItsNat formatter wrapping the specified format.
233: */
234: public ItsNatFormatter createItsNatFormatter(Format format);
235:
236: /**
237: * Defines an ItsNat formatter. A formatter is used to convert a String from/to
238: * an Object.
239: */
240: public interface ItsNatFormatter {
241: /**
242: * Converts the specified <code>String</code> to an <code>Object</code> using some kind of conversion rules.
243: *
244: * @param text the string to convert.
245: * @param comp the component using this formatter.
246: * @return the converted Object value.
247: * @throws java.text.ParseException the text can not be converted.
248: */
249: public Object stringToValue(String text,
250: ItsNatFormattedTextField comp) throws ParseException;
251:
252: /**
253: * Converts the specified <code>Object</code> to <code>String</code> using some kind of conversion rules.
254: *
255: * @param value the value to convert.
256: * @param comp the component using this formatter.
257: * @return the converted string.
258: * @throws java.text.ParseException the object value can not be converted.
259: */
260: public String valueToString(Object value,
261: ItsNatFormattedTextField comp) throws ParseException;
262: }
263:
264: /**
265: * Defines an ItsNat formatter factory. A formatter factory is used to create
266: * ItsNat formatters.
267: *
268: */
269: public interface ItsNatFormatterFactory {
270: /**
271: * Returns an appropiated formatter to the specified formatted text field.
272: *
273: * <p>The target formatted text field is used to build the appropriated formatter,
274: * for instance using the current component value ({@link #getValue()}) to determine
275: * what kind of conversion is needed.</p>
276: *
277: * @param comp the formatted text field used to build the formatter.
278: * @return the formatter.
279: */
280: public ItsNatFormatter getItsNatFormatter(
281: ItsNatFormattedTextField comp);
282: }
283:
284: }
|