Methods Summary |
---|
private void | append(java.lang.StringBuffer result, java.lang.String value, int[] index, java.lang.String placeholder, javax.swing.text.MaskFormatter$MaskCharacter[] mask)Invokes append on the mask characters in
mask .
for (int counter = 0, maxCounter = mask.length;
counter < maxCounter; counter++) {
mask[counter].append(result, value, index, placeholder);
}
|
boolean | canReplace(ReplaceHolder rh)This method does the following (assuming !getAllowsInvalid()):
iterate over the max of the deleted region or the text length, for
each character:
- If it is valid (matches the mask at the particular position, or
matches the literal character at the position), allow it
- Else if the position identifies a literal character, add it. This
allows for the user to paste in text that may/may not contain
the literals. For example, in pasing in 5551212 into ###-####
when the 1 is evaluated it is illegal (by the first test), but there
is a literal at this position (-), so it is used. NOTE: This has
a problem that you can't tell (without looking ahead) if you should
eat literals in the text. For example, if you paste '555' into
#5##, should it result in '5555' or '555 '? The current code will
result in the latter, which feels a little better as selecting
text than pasting will always result in the same thing.
- Else if at the end of the inserted text, the replace the item with
the placeholder
- Otherwise the insert is bogus and false is returned.
// This method is rather long, but much of the burden is in
// maintaining a String and swapping to a StringBuffer only if
// absolutely necessary.
if (!getAllowsInvalid()) {
StringBuffer replace = null;
String text = rh.text;
int tl = (text != null) ? text.length() : 0;
if (tl == 0 && rh.length == 1 && getFormattedTextField().
getSelectionStart() != rh.offset) {
// Backspace, adjust to actually delete next non-literal.
while (rh.offset > 0 && isLiteral(rh.offset)) {
rh.offset--;
}
}
int max = Math.min(getMaxLength() - rh.offset,
Math.max(tl, rh.length));
for (int counter = 0, textIndex = 0; counter < max; counter++) {
if (textIndex < tl && isValidCharacter(rh.offset + counter,
text.charAt(textIndex))) {
char aChar = text.charAt(textIndex);
if (aChar != getCharacter(rh.offset + counter, aChar)) {
if (replace == null) {
replace = new StringBuffer();
if (textIndex > 0) {
replace.append(text.substring(0, textIndex));
}
}
}
if (replace != null) {
replace.append(getCharacter(rh.offset + counter,
aChar));
}
textIndex++;
}
else if (isLiteral(rh.offset + counter)) {
if (replace != null) {
replace.append(getLiteral(rh.offset + counter));
if (textIndex < tl) {
max = Math.min(max + 1, getMaxLength() -
rh.offset);
}
}
else if (textIndex > 0) {
replace = new StringBuffer(max);
replace.append(text.substring(0, textIndex));
replace.append(getLiteral(rh.offset + counter));
if (textIndex < tl) {
// Evaluate the character in text again.
max = Math.min(max + 1, getMaxLength() -
rh.offset);
}
else if (rh.cursorPosition == -1) {
rh.cursorPosition = rh.offset + counter;
}
}
else {
rh.offset++;
rh.length--;
counter--;
max--;
}
}
else if (textIndex >= tl) {
// placeholder
if (replace == null) {
replace = new StringBuffer();
if (text != null) {
replace.append(text);
}
}
replace.append(getPlaceholderCharacter());
if (tl > 0 && rh.cursorPosition == -1) {
rh.cursorPosition = rh.offset + counter;
}
}
else {
// Bogus character.
return false;
}
}
if (replace != null) {
rh.text = replace.toString();
}
else if (text != null && rh.offset + tl > getMaxLength()) {
rh.text = text.substring(0, getMaxLength() - rh.offset);
}
if (getOverwriteMode() && rh.text != null) {
rh.length = rh.text.length();
}
}
return super.canReplace(rh);
|
private char | getCharacter(int index, char aChar)Returns the character to insert at the specified location based on
the passed in character. This provides a way to map certain sets
of characters to alternative values (lowercase to
uppercase...).
return getMaskCharacter(index).getChar(aChar);
|
public java.lang.String | getInvalidCharacters()Returns the characters that are not valid for input.
return invalidCharacters;
|
private int | getInvalidOffset(java.lang.String string, boolean completeMatch)Returns -1 if the passed in string is valid, otherwise the index of
the first bogus character is returned.
int iLength = string.length();
if (iLength != getMaxLength()) {
// trivially false
return iLength;
}
for (int counter = 0, max = string.length(); counter < max; counter++){
char aChar = string.charAt(counter);
if (!isValidCharacter(counter, aChar) &&
(completeMatch || !isPlaceholder(counter, aChar))) {
return counter;
}
}
return -1;
|
private char | getLiteral(int index)Returns the literal character at the specified location.
return getMaskCharacter(index).getChar((char)0);
|
public java.lang.String | getMask()Returns the formatting mask.
return mask;
|
private javax.swing.text.MaskFormatter$MaskCharacter | getMaskCharacter(int index)Returns the MaskCharacter at the specified location.
if (index >= maskChars.length) {
return null;
}
return maskChars[index];
|
private int | getMaxLength()Returns the maximum length the text can be.
return maskChars.length;
|
public java.lang.String | getPlaceholder()Returns the String to use if the value does not completely fill
in the mask.
return placeholderString;
|
public char | getPlaceholderCharacter()Returns the character to use in place of characters that are not present
in the value, ie the user must fill them in.
return placeholder;
|
public java.lang.String | getValidCharacters()Returns the valid characters that can be input.
return validCharacters;
|
public boolean | getValueContainsLiteralCharacters()Returns true if stringToValue should return literal
characters in the mask.
return containsLiteralChars;
|
public void | install(javax.swing.JFormattedTextField ftf)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.
super.install(ftf);
// valueToString doesn't throw, but stringToValue does, need to
// update the editValid state appropriately
if (ftf != null) {
Object value = ftf.getValue();
try {
stringToValue(valueToString(value));
} catch (ParseException pe) {
setEditValid(false);
}
}
|
private boolean | isLiteral(int index)Returns true if the character at the specified location is a literal,
that is it can not be edited.
return getMaskCharacter(index).isLiteral();
|
boolean | isNavigatable(int offset)Returns true if the MaskFormatter allows invalid, or
the offset is less than the max length and the character at
offset is a literal.
if (!getAllowsInvalid()) {
return (offset < getMaxLength() && !isLiteral(offset));
}
return true;
|
private boolean | isPlaceholder(int index, char aChar)Returns true if the placeholder character matches aChar.
return (getPlaceholderCharacter() == aChar);
|
private boolean | isValidCharacter(int index, char aChar)Returns true if the passed in character matches the mask at the
specified location.
return getMaskCharacter(index).isValidCharacter(aChar);
|
boolean | isValidEdit(ReplaceHolder rh)
if (!getAllowsInvalid()) {
String newString = getReplaceString(rh.offset, rh.length, rh.text);
try {
rh.value = stringToValue(newString, false);
return true;
} catch (ParseException pe) {
return false;
}
}
return true;
|
private void | readObject(java.io.ObjectInputStream s)Subclassed to update the internal representation of the mask after
the default read operation has completed.
s.defaultReadObject();
try {
updateInternalMask();
} catch (ParseException pe) {
// assert();
}
|
public void | setInvalidCharacters(java.lang.String invalidCharacters)Allows for further restricting of the characters that can be input.
Only characters specified in the mask, not in the
invalidCharacters , and in
validCharacters will be allowed to be input. Passing
in null (the default) implies the valid characters are only bound
by the mask and the valid characters.
this.invalidCharacters = invalidCharacters;
|
public void | setMask(java.lang.String mask)Sets the mask dictating the legal characters.
This will throw a ParseException if mask is
not valid.
this.mask = mask;
updateInternalMask();
|
public void | setPlaceholder(java.lang.String placeholder)Sets the string to use if the value does not completely fill in
the mask. A null value implies the placeholder char should be used.
this.placeholderString = placeholder;
|
public void | setPlaceholderCharacter(char placeholder)Sets the character to use in place of characters that are not present
in the value, ie the user must fill them in. The default value is
a space.
This is only applicable if the placeholder string has not been
specified, or does not completely fill in the mask.
this.placeholder = placeholder;
|
public void | setValidCharacters(java.lang.String validCharacters)Allows for further restricting of the characters that can be input.
Only characters specified in the mask, not in the
invalidCharacters , and in
validCharacters will be allowed to be input. Passing
in null (the default) implies the valid characters are only bound
by the mask and the invalid characters.
this.validCharacters = validCharacters;
|
public void | setValueContainsLiteralCharacters(boolean containsLiteralChars)If true, the returned value and set value will also contain the literal
characters in mask.
For example, if the mask is '(###) ###-####' , the
current value is '(415) 555-1212' , and
valueContainsLiteralCharacters is
true stringToValue will return
'(415) 555-1212' . On the other hand, if
valueContainsLiteralCharacters is false,
stringToValue will return '4155551212' .
this.containsLiteralChars = containsLiteralChars;
|
public java.lang.Object | stringToValue(java.lang.String value)Parses the text, returning the appropriate Object representation of
the String value . This strips the literal characters as
necessary and invokes supers stringToValue , so that if
you have specified a value class (setValueClass ) an
instance of it will be created. This will throw a
ParseException if the value does not match the current
mask. Refer to {@link #setValueContainsLiteralCharacters} for details
on how literals are treated.
return stringToValue(value, true);
|
private java.lang.Object | stringToValue(java.lang.String value, boolean completeMatch)Actual stringToValue implementation.
If completeMatch is true, the value must exactly match
the mask, on the other hand if completeMatch is false
the string must match the mask or the placeholder string.
int errorOffset = -1;
if ((errorOffset = getInvalidOffset(value, completeMatch)) == -1) {
if (!getValueContainsLiteralCharacters()) {
value = stripLiteralChars(value);
}
return super.stringToValue(value);
}
throw new ParseException("stringToValue passed invalid value",
errorOffset);
|
private java.lang.String | stripLiteralChars(java.lang.String string)Removes the literal characters from the passed in string.
StringBuffer sb = null;
int last = 0;
for (int counter = 0, max = string.length(); counter < max; counter++){
if (isLiteral(counter)) {
if (sb == null) {
sb = new StringBuffer();
if (counter > 0) {
sb.append(string.substring(0, counter));
}
last = counter + 1;
}
else if (last != counter) {
sb.append(string.substring(last, counter));
}
last = counter + 1;
}
}
if (sb == null) {
// Assume the mask isn't all literals.
return string;
}
else if (last != string.length()) {
if (sb == null) {
return string.substring(last);
}
sb.append(string.substring(last));
}
return sb.toString();
|
private void | updateInternalMask()Updates the internal representation of the mask.
String mask = getMask();
ArrayList fixed = new ArrayList();
ArrayList temp = fixed;
if (mask != null) {
for (int counter = 0, maxCounter = mask.length();
counter < maxCounter; counter++) {
char maskChar = mask.charAt(counter);
switch (maskChar) {
case DIGIT_KEY:
temp.add(new DigitMaskCharacter());
break;
case LITERAL_KEY:
if (++counter < maxCounter) {
maskChar = mask.charAt(counter);
temp.add(new LiteralCharacter(maskChar));
}
// else: Could actually throw if else
break;
case UPPERCASE_KEY:
temp.add(new UpperCaseCharacter());
break;
case LOWERCASE_KEY:
temp.add(new LowerCaseCharacter());
break;
case ALPHA_NUMERIC_KEY:
temp.add(new AlphaNumericCharacter());
break;
case CHARACTER_KEY:
temp.add(new CharCharacter());
break;
case ANYTHING_KEY:
temp.add(new MaskCharacter());
break;
case HEX_KEY:
temp.add(new HexCharacter());
break;
default:
temp.add(new LiteralCharacter(maskChar));
break;
}
}
}
if (fixed.size() == 0) {
maskChars = EmptyMaskChars;
}
else {
maskChars = new MaskCharacter[fixed.size()];
fixed.toArray(maskChars);
}
|
public java.lang.String | valueToString(java.lang.Object value)Returns a String representation of the Object value
based on the mask. Refer to
{@link #setValueContainsLiteralCharacters} for details
on how literals are treated.
String sValue = (value == null) ? "" : value.toString();
StringBuffer result = new StringBuffer();
String placeholder = getPlaceholder();
int[] valueCounter = { 0 };
append(result, sValue, valueCounter, placeholder, maskChars);
return result.toString();
|