to handle the
conversion to a String, and the conversion from a String.
may return.
Method from javax.swing.text.InternationalFormatter Detail: |
Object adjustValue(Object value,
Map attributes,
Object field,
int direction) throws BadLocationException, ParseException {
return null;
}
Subclasses supporting incrementing must override this to handle
the actual incrementing. value is the current value,
attributes gives the field the cursor is in (may be
null depending upon canIncrement ) and
direction is the amount to increment by. |
boolean canIncrement(Object field,
int cursorPosition) {
return (field != null);
}
Returns true if field is non-null.
Subclasses that wish to allow incrementing to happen outside of
the known fields will need to override this. |
boolean canReplace(ReplaceHolder rh) {
if (!getAllowsInvalid()) {
String text = rh.text;
int tl = (text != null) ? text.length() : 0;
JTextComponent c = getFormattedTextField();
if (tl == 0 && rh.length == 1 && c.getSelectionStart() != rh.offset) {
// Backspace, adjust to actually delete next non-literal.
rh.offset = getNextNonliteralIndex(rh.offset, -1);
} else if (getOverwriteMode()) {
int pos = rh.offset;
int textPos = pos;
boolean overflown = false;
for (int i = 0; i < rh.length; i++) {
while (isLiteral(pos)) pos++;
if (pos >= string.length()) {
pos = textPos;
overflown = true;
break;
}
textPos = ++pos;
}
if (overflown || c.getSelectedText() == null) {
rh.length = pos - rh.offset;
}
}
else if (tl > 0) {
// insert (or insert and remove)
rh.offset = getNextNonliteralIndex(rh.offset, 1);
}
else {
// remove only
rh.offset = getNextNonliteralIndex(rh.offset, -1);
}
((ExtendedReplaceHolder)rh).endOffset = rh.offset;
((ExtendedReplaceHolder)rh).endTextLength = (rh.text != null) ?
rh.text.length() : 0;
}
else {
((ExtendedReplaceHolder)rh).endOffset = rh.offset;
((ExtendedReplaceHolder)rh).endTextLength = (rh.text != null) ?
rh.text.length() : 0;
}
boolean can = super.canReplace(rh);
if (can && !getAllowsInvalid()) {
((ExtendedReplaceHolder)rh).resetFromValue(this);
}
return can;
}
Overriden in an attempt to honor the literals.
If we do not allow invalid values and are in overwrite mode, this
{@code rh.length} is corrected as to preserve trailing literals.
If not in overwrite mode, and there is text to insert it is
inserted at the next non literal index going forward. If there
is only text to remove, it is removed from the next non literal
index going backward. |
public Object clone() throws CloneNotSupportedException {
InternationalFormatter formatter = (InternationalFormatter)super.
clone();
formatter.literalMask = null;
formatter.iterator = null;
formatter.validMask = false;
formatter.string = null;
return formatter;
}
Creates a copy of the DefaultFormatter. |
protected Action[] getActions() {
if (getSupportsIncrement()) {
return new Action[] { new IncrementAction("increment", 1),
new IncrementAction("decrement", -1) };
}
return null;
}
If getSupportsIncrement returns true, this returns
two Actions suitable for incrementing/decrementing the value. |
Object getAdjustField(int start,
Map attributes) {
return null;
}
Returns the field that will be adjusted by adjustValue. |
int getAttributeStart(Attribute id) {
if (isValidMask()) {
AttributedCharacterIterator iterator = getIterator();
iterator.first();
while (iterator.current() != CharacterIterator.DONE) {
if (iterator.getAttribute(id) != null) {
return iterator.getIndex();
}
iterator.next();
}
}
return -1;
}
Returns the start of the first run that contains the attribute
id . This will return -1 if the attribute
can not be found. |
Map<Attribute, Object> getAttributes(int index) {
if (isValidMask()) {
AttributedCharacterIterator iterator = getIterator();
if (index >= 0 && index < = iterator.getEndIndex()) {
iterator.setIndex(index);
return iterator.getAttributes();
}
}
return null;
}
Returns a Set of the attribute identifiers at index . |
char getBufferedChar(int index) {
if (isValidMask()) {
if (string != null && index < string.length()) {
return string.charAt(index);
}
}
return (char)0;
}
Returns the character from the mask that has been buffered
at index . |
public Field[] getFields(int offset) {
if (getAllowsInvalid()) {
// This will work if the currently edited value is valid.
updateMask();
}
Map< Attribute, Object > attrs = getAttributes(offset);
if (attrs != null && attrs.size() > 0) {
ArrayList< Attribute > al = new ArrayList< Attribute >();
al.addAll(attrs.keySet());
return al.toArray(EMPTY_FIELD_ARRAY);
}
return EMPTY_FIELD_ARRAY;
}
Returns the Format.Field constants associated with
the text at offset . If offset is not
a valid location into the current text, this will return an
empty array. |
public Format getFormat() {
return format;
}
Returns the format that dictates the legal values that can be edited
and displayed. |
AttributedCharacterIterator getIterator() {
return iterator;
}
Returns the AttributedCharacterIterator used to
format the last value. |
char getLiteral(int index) {
if (isValidMask() && string != null && index < string.length()) {
return string.charAt(index);
}
return (char)0;
}
Returns the literal character at index. |
int getLiteralCountTo(int index) {
int lCount = 0;
for (int counter = 0; counter < index; counter++) {
if (isLiteral(counter)) {
lCount++;
}
}
return lCount;
}
Returns the number of literal characters before index . |
public Comparable getMaximum() {
return max;
}
Returns the maximum permissible value. |
public Comparable getMinimum() {
return min;
}
Returns the minimum permissible value. |
ReplaceHolder getReplaceHolder(FilterBypass fb,
int offset,
int length,
String text,
AttributeSet attrs) {
if (replaceHolder == null) {
replaceHolder = new ExtendedReplaceHolder();
}
return super.getReplaceHolder(fb, offset, length, text, attrs);
}
Overriden to return an instance of ExtendedReplaceHolder . |
boolean getSupportsIncrement() {
return false;
}
Returns false, indicating InternationalFormatter does not allow
incrementing of the value. Subclasses that wish to support
incrementing/decrementing the value should override this and
return true. Subclasses should also override
adjustValue . |
public void install(JFormattedTextField ftf) {
super.install(ftf);
updateMaskIfNecessary();
// invoked again as the mask should now be valid.
positionCursorAtInitialLocation();
}
Installs the DefaultFormatter onto a particular
JFormattedTextField .
This will invoke valueToString to convert the
current value from the JFormattedTextField to
a String. This will then install the Action s from
getActions , the DocumentFilter
returned from getDocumentFilter and the
NavigationFilter returned from
getNavigationFilter onto the
JFormattedTextField .
Subclasses will typically only need to override this if they
wish to install additional listeners on the
JFormattedTextField .
If there is a ParseException in converting the
current value to a String, this will set the text to an empty
String, and mark the JFormattedTextField as being
in an invalid state.
While this is a public method, this is typically only useful
for subclassers of JFormattedTextField .
JFormattedTextField will invoke this method at
the appropriate times when the value changes, or its internal
state changes. |
boolean isLiteral(int index) {
if (isValidMask() && index < string.length()) {
return literalMask.get(index);
}
return false;
}
Returns true if the character at index is a literal, that is
not editable. |
boolean isLiteral(Map attributes) {
return ((attributes == null) || attributes.size() == 0);
}
Returns true if attributes is null or empty. |
boolean isNavigatable(int offset) {
return !isLiteral(offset);
}
Returns true if the character at offset is navigatable too. This
is implemented in terms of isLiteral , subclasses
may wish to provide different behavior. |
boolean isValidMask() {
return validMask;
}
Returns true if the current mask is valid. |
boolean isValidValue(Object value,
boolean wantsCCE) {
Comparable min = getMinimum();
try {
if (min != null && min.compareTo(value) > 0) {
return false;
}
} catch (ClassCastException cce) {
if (wantsCCE) {
throw cce;
}
return false;
}
Comparable max = getMaximum();
try {
if (max != null && max.compareTo(value) < 0) {
return false;
}
} catch (ClassCastException cce) {
if (wantsCCE) {
throw cce;
}
return false;
}
return true;
}
Returns true if value is between the min/max. |
boolean replace(ReplaceHolder rh) throws BadLocationException {
int start = -1;
int direction = 1;
int literalCount = -1;
if (rh.length > 0 && (rh.text == null || rh.text.length() == 0) &&
(getFormattedTextField().getSelectionStart() != rh.offset ||
rh.length > 1)) {
direction = -1;
}
if (!getAllowsInvalid()) {
if ((rh.text == null || rh.text.length() == 0) && rh.length > 0) {
// remove
start = getFormattedTextField().getSelectionStart();
}
else {
start = rh.offset;
}
literalCount = getLiteralCountTo(start);
}
if (super.replace(rh)) {
if (start != -1) {
int end = ((ExtendedReplaceHolder)rh).endOffset;
end += ((ExtendedReplaceHolder)rh).endTextLength;
repositionCursor(literalCount, end, direction);
}
else {
start = ((ExtendedReplaceHolder)rh).endOffset;
if (direction == 1) {
start += ((ExtendedReplaceHolder)rh).endTextLength;
}
repositionCursor(start, direction);
}
return true;
}
return false;
}
When in !allowsInvalid mode the text is reset on every edit, thus
supers implementation will position the cursor at the wrong position.
As such, this invokes supers implementation and then invokes
repositionCursor to correctly reset the cursor. |
void replace(FilterBypass fb,
int offset,
int length,
String text,
AttributeSet attrs) throws BadLocationException {
if (ignoreDocumentMutate) {
fb.replace(offset, length, text, attrs);
return;
}
super.replace(fb, offset, length, text, attrs);
}
Overriden to unconditionally allow the replace if
ignoreDocumentMutate is true. |
void resetValue(Object value) throws BadLocationException, ParseException {
Document doc = getFormattedTextField().getDocument();
String string = valueToString(value);
try {
ignoreDocumentMutate = true;
doc.remove(0, doc.getLength());
doc.insertString(0, string, null);
} finally {
ignoreDocumentMutate = false;
}
updateValue(value);
}
Resets the value of the JFormattedTextField to be
value . |
void selectField(Object f,
int count) {
AttributedCharacterIterator iterator = getIterator();
if (iterator != null &&
(f instanceof AttributedCharacterIterator.Attribute)) {
AttributedCharacterIterator.Attribute field =
(AttributedCharacterIterator.Attribute)f;
iterator.first();
while (iterator.current() != CharacterIterator.DONE) {
while (iterator.getAttribute(field) == null &&
iterator.next() != CharacterIterator.DONE);
if (iterator.current() != CharacterIterator.DONE) {
int limit = iterator.getRunLimit(field);
if (--count < = 0) {
getFormattedTextField().select(iterator.getIndex(),
limit);
break;
}
iterator.setIndex(limit);
iterator.next();
}
}
}
}
Selects the fields identified by attributes . |
public void setFormat(Format format) {
this.format = format;
}
Sets the format that dictates the legal values that can be edited
and displayed. |
public void setMaximum(Comparable max) {
if (getValueClass() == null && max != null) {
setValueClass(max.getClass());
}
this.max = max;
}
Sets the maximum permissible value. If the valueClass has
not been specified, and max is non null, the
valueClass will be set to that of the class of
max . |
public void setMinimum(Comparable minimum) {
if (getValueClass() == null && minimum != null) {
setValueClass(minimum.getClass());
}
min = minimum;
}
Sets the minimum permissible value. If the valueClass has
not been specified, and minimum is non null, the
valueClass will be set to that of the class of
minimum . |
public Object stringToValue(String text) throws ParseException {
Object value = stringToValue(text, getFormat());
// Convert to the value class if the Value returned from the
// Format does not match.
if (value != null && getValueClass() != null &&
!getValueClass().isInstance(value)) {
value = super.stringToValue(value.toString());
}
try {
if (!isValidValue(value, true)) {
throw new ParseException("Value not within min/max range", 0);
}
} catch (ClassCastException cce) {
throw new ParseException("Class cast exception comparing values: "
+ cce, 0);
}
return value;
}
Returns the Object representation of the
String text . |
Object stringToValue(String text,
Format f) throws ParseException {
if (f == null) {
return text;
}
return f.parseObject(text);
}
Invokes parseObject on f , returning
its value. |
void updateMask() {
if (getFormat() != null) {
Document doc = getFormattedTextField().getDocument();
validMask = false;
if (doc != null) {
try {
string = doc.getText(0, doc.getLength());
} catch (BadLocationException ble) {
string = null;
}
if (string != null) {
try {
Object value = stringToValue(string);
AttributedCharacterIterator iterator = getFormat().
formatToCharacterIterator(value);
updateMask(iterator);
}
catch (ParseException pe) {}
catch (IllegalArgumentException iae) {}
catch (NullPointerException npe) {}
}
}
}
}
Updates the AttributedCharacterIterator by invoking
formatToCharacterIterator on the Format .
If this is successful,
updateMask(AttributedCharacterIterator)
is then invoked to update the internal bitmask. |
void updateMaskIfNecessary() {
if (!getAllowsInvalid() && (getFormat() != null)) {
if (!isValidMask()) {
updateMask();
}
else {
String newString = getFormattedTextField().getText();
if (!newString.equals(string)) {
updateMask();
}
}
}
}
Updates the AttributedCharacterIterator and bitset, if necessary. |
void updateValue(Object value) {
super.updateValue(value);
updateMaskIfNecessary();
}
Overriden to update the mask after invoking supers implementation. |
public String valueToString(Object value) throws ParseException {
if (value == null) {
return "";
}
Format f = getFormat();
if (f == null) {
return value.toString();
}
return f.format(value);
}
Returns a String representation of the Object value .
This invokes format on the current Format . |