Browse Source

Adding inputDigitAndRememberPosition and getRememberedPosition methods to AsYouTypeFormatter.java to provide better cursor control.

pull/567/head
Shaopeng Jia 16 years ago
committed by Mihaela Rosca
parent
commit
b8e03db113
2 changed files with 137 additions and 17 deletions
  1. +74
    -6
      java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java
  2. +63
    -11
      java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java

+ 74
- 6
java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java View File

@ -54,11 +54,16 @@ public class AsYouTypeFormatter {
private String digitPlaceholder = "\u2008";
private Pattern digitPattern = Pattern.compile(digitPlaceholder);
private int lastMatchPosition = 0;
private boolean rememberPosition = false;
private int positionRemembered = 0;
private int originalPosition = 0;
private Pattern nationalPrefixForParsing;
private Pattern internationalPrefix;
private StringBuffer prefixBeforeNationalNumber;
private StringBuffer nationalNumber;
private final Pattern UNSUPPORTED_SYNTAX = Pattern.compile("[*#;,a-zA-Z]");
// No formatting will be applied when any of the character in the following character class is
// entered by users.
private final Pattern UNSUPPORTED_SYNTAX = Pattern.compile("[- *#;,.()/a-zA-Z]");
private final Pattern CHARACTER_CLASS_PATTERN = Pattern.compile("\\[([^\\[\\]])*\\]");
private final Pattern STANDALONE_DIGIT_PATTERN = Pattern.compile("\\d(?=[^,}][^,}])");
@ -169,6 +174,8 @@ public class AsYouTypeFormatter {
prefixBeforeNationalNumber.setLength(0);
nationalNumber.setLength(0);
ableToFormat = true;
positionRemembered = 0;
originalPosition = 0;
isInternationalFormatting = false;
if (!currentMetaData.equals(defaultMetaData)) {
initializeCountrySpecificInfo(defaultCountry);
@ -185,11 +192,18 @@ public class AsYouTypeFormatter {
*/
public String inputDigit(char nextChar) {
accruedInput.append(nextChar);
// * and # are normally used in mobile codes, which we do not format.
if (UNSUPPORTED_SYNTAX.matcher(Character.toString(nextChar)).matches()) {
ableToFormat = false;
}
if (!ableToFormat) {
if (positionRemembered > 0 && currentOutput.length() > 0) {
positionRemembered = originalPosition;
currentOutput.setLength(0);
}
if (rememberPosition) {
positionRemembered = accruedInput.length();
originalPosition = positionRemembered;
}
return accruedInput.toString();
}
@ -204,10 +218,18 @@ public class AsYouTypeFormatter {
case 3:
case 4:
case 5:
if (rememberPosition) {
positionRemembered = accruedInput.length();
originalPosition = positionRemembered;
}
return accruedInput.toString();
case 6:
if (!extractIddAndValidCountryCode()) {
ableToFormat = false;
if (rememberPosition) {
positionRemembered = accruedInput.length();
originalPosition = positionRemembered;
}
return accruedInput.toString();
}
removeNationalPrefixFromNationalNumber();
@ -221,6 +243,26 @@ public class AsYouTypeFormatter {
}
}
/**
* Same as inputDigit, but remember the position where nextChar is inserted, so that it could be
* retrieved later using getRememberedPosition(). The remembered position will be automatically
* adjusted if additional formatting characters are later inserted/removed in front of it.
*/
public String inputDigitAndRememberPosition(char nextChar) {
rememberPosition = true;
String result = inputDigit(nextChar);
rememberPosition = false;
return result;
}
/**
* Returns the current position in the partially formatted phone number of the character which was
* previously passed in as the parameter of inputDigitAndRememberPosition.
*/
public int getRememberedPosition() {
return positionRemembered;
}
// Attempts to set the formatting template and returns a string which contains the formatted
// version of the digits entered so far.
private String attemptToChooseFormattingPattern() {
@ -230,6 +272,9 @@ public class AsYouTypeFormatter {
chooseFormatAndCreateTemplate(nationalNumber.substring(0, 4));
return inputAccruedNationalNumber();
} else {
if (rememberPosition) {
positionRemembered = prefixBeforeNationalNumber.length() + nationalNumber.length();
}
return prefixBeforeNationalNumber + nationalNumber.toString();
}
}
@ -240,11 +285,17 @@ public class AsYouTypeFormatter {
int lengthOfNationalNumber = nationalNumber.length();
if (lengthOfNationalNumber > 0) {
for (int i = 0; i < lengthOfNationalNumber - 1; i++) {
inputDigitHelper(nationalNumber.charAt(i));
String temp = inputDigitHelper(nationalNumber.charAt(i));
if (positionRemembered == i + 1) {
positionRemembered = temp.length();
}
}
return prefixBeforeNationalNumber
+ inputDigitHelper(nationalNumber.charAt(lengthOfNationalNumber - 1));
return prefixBeforeNationalNumber +
inputDigitHelper(nationalNumber.charAt(lengthOfNationalNumber - 1));
} else {
if (rememberPosition) {
positionRemembered = prefixBeforeNationalNumber.length();
}
return prefixBeforeNationalNumber.toString();
}
}
@ -291,9 +342,20 @@ public class AsYouTypeFormatter {
prefixBeforeNationalNumber.append(
accruedInputWithoutFormatting.substring(0, startOfCountryCode));
if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN ) {
if (positionRemembered > prefixBeforeNationalNumber.length()) {
// Since a space will be inserted in front of the country code in this case, we increase
// the remembered position by 1.
positionRemembered++;
}
prefixBeforeNationalNumber.append(" ");
}
prefixBeforeNationalNumber.append(countryCode).append(" ");
String countryCodeString = Integer.toString(countryCode);
if (positionRemembered > prefixBeforeNationalNumber.length() + countryCodeString.length()) {
// Since a space will be inserted after the country code in this case, we increase the
// remembered position by 1.
positionRemembered++;
}
prefixBeforeNationalNumber.append(countryCodeString).append(" ");
}
} else {
nationalNumber.setLength(0);
@ -328,10 +390,16 @@ public class AsYouTypeFormatter {
if (digitMatcher.find(lastMatchPosition)) {
currentOutput = new StringBuffer(digitMatcher.replaceFirst(Character.toString(nextChar)));
lastMatchPosition = digitMatcher.start();
if (rememberPosition) {
positionRemembered = prefixBeforeNationalNumber.length() + lastMatchPosition + 1;
}
return currentOutput.substring(0, lastMatchPosition + 1);
} else { // More digits are entered than we could handle.
currentOutput.append(nextChar);
ableToFormat = false;
if (rememberPosition) {
positionRemembered = prefixBeforeNationalNumber.length() + currentOutput.length();
}
return currentOutput.toString();
}
}


+ 63
- 11
java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java View File

@ -66,44 +66,74 @@ public class AsYouTypeFormatterTest extends TestCase {
assertEquals("1 650 253 222", formatter.inputDigit('2'));
assertEquals("1 650 253 2222", formatter.inputDigit('2'));
formatter.clear();
assertEquals("1", formatter.inputDigitAndRememberPosition('1'));
assertEquals(1, formatter.getRememberedPosition());
assertEquals("16", formatter.inputDigit('6'));
assertEquals("165", formatter.inputDigit('5'));
assertEquals(1, formatter.getRememberedPosition());
assertEquals("1650", formatter.inputDigitAndRememberPosition('0'));
assertEquals(4, formatter.getRememberedPosition());
assertEquals("16502", formatter.inputDigit('2'));
assertEquals("1 650 25", formatter.inputDigit('5'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("1 650 253", formatter.inputDigit('3'));
assertEquals("1 650 253 2", formatter.inputDigit('2'));
assertEquals("1 650 253 22", formatter.inputDigit('2'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("1 650 253 222", formatter.inputDigitAndRememberPosition('2'));
assertEquals(13, formatter.getRememberedPosition());
assertEquals("1 650 253 2222", formatter.inputDigit('2'));
assertEquals(13, formatter.getRememberedPosition());
formatter.clear();
assertEquals("6", formatter.inputDigit('6'));
assertEquals("65", formatter.inputDigit('5'));
assertEquals("650", formatter.inputDigit('0'));
assertEquals("6502", formatter.inputDigit('2'));
assertEquals("65025", formatter.inputDigit('5'));
assertEquals("65025", formatter.inputDigitAndRememberPosition('5'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("650 253", formatter.inputDigit('3'));
assertEquals(6, formatter.getRememberedPosition());
assertEquals("650 253 2", formatter.inputDigit('2'));
assertEquals("650 253 22", formatter.inputDigit('2'));
assertEquals("650 253 222", formatter.inputDigit('2'));
// No more formatting when semicolon is entered.
assertEquals("650253222;", formatter.inputDigit(';'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("650253222;2", formatter.inputDigit('2'));
formatter.clear();
assertEquals("6", formatter.inputDigit('6'));
assertEquals("65", formatter.inputDigit('5'));
assertEquals("650", formatter.inputDigit('0'));
// No more formatting when users choose to do their own formatting.
assertEquals("650-", formatter.inputDigit('-'));
assertEquals("650-2", formatter.inputDigit('2'));
assertEquals("650-2", formatter.inputDigitAndRememberPosition('2'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("650-25", formatter.inputDigit('5'));
assertEquals("650 253", formatter.inputDigit('3'));
assertEquals("650 253", formatter.inputDigit('-'));
assertEquals("650 253 2", formatter.inputDigit('2'));
assertEquals("650 253 22", formatter.inputDigit('2'));
assertEquals("650 253 222", formatter.inputDigit('2'));
assertEquals("650 253 2222", formatter.inputDigit('2'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("650-253", formatter.inputDigit('3'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("650-253-", formatter.inputDigit('-'));
assertEquals("650-253-2", formatter.inputDigit('2'));
assertEquals("650-253-22", formatter.inputDigit('2'));
assertEquals("650-253-222", formatter.inputDigit('2'));
assertEquals("650-253-2222", formatter.inputDigit('2'));
formatter.clear();
assertEquals("0", formatter.inputDigit('0'));
assertEquals("01", formatter.inputDigit('1'));
assertEquals("011", formatter.inputDigit('1'));
assertEquals("0114", formatter.inputDigit('4'));
assertEquals("0114", formatter.inputDigitAndRememberPosition('4'));
assertEquals("01148", formatter.inputDigit('8'));
assertEquals(4, formatter.getRememberedPosition());
assertEquals("011 48 8", formatter.inputDigit('8'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("011 48 88", formatter.inputDigit('8'));
assertEquals("011 48 881", formatter.inputDigit('1'));
assertEquals("011 48 88 12", formatter.inputDigit('2'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("011 48 88 123", formatter.inputDigit('3'));
assertEquals("011 48 88 123 1", formatter.inputDigit('1'));
assertEquals("011 48 88 123 12", formatter.inputDigit('2'));
@ -148,15 +178,35 @@ public class AsYouTypeFormatterTest extends TestCase {
formatter.clear();
assertEquals("+", formatter.inputDigit('+'));
assertEquals("+1", formatter.inputDigit('1'));
assertEquals("+16", formatter.inputDigit('6'));
assertEquals("+16", formatter.inputDigitAndRememberPosition('6'));
assertEquals("+165", formatter.inputDigit('5'));
assertEquals("+1650", formatter.inputDigit('0'));
assertEquals(3, formatter.getRememberedPosition());
assertEquals("+1 650 2", formatter.inputDigit('2'));
assertEquals(4, formatter.getRememberedPosition());
assertEquals("+1 650 25", formatter.inputDigit('5'));
assertEquals("+1 650 253", formatter.inputDigitAndRememberPosition('3'));
assertEquals("+1 650 253 2", formatter.inputDigit('2'));
assertEquals("+1 650 253 22", formatter.inputDigit('2'));
assertEquals("+1 650 253 222", formatter.inputDigit('2'));
assertEquals(10, formatter.getRememberedPosition());
formatter.clear();
assertEquals("+", formatter.inputDigit('+'));
assertEquals("+1", formatter.inputDigit('1'));
assertEquals("+16", formatter.inputDigitAndRememberPosition('6'));
assertEquals("+165", formatter.inputDigit('5'));
assertEquals("+1650", formatter.inputDigit('0'));
assertEquals(3, formatter.getRememberedPosition());
assertEquals("+1 650 2", formatter.inputDigit('2'));
assertEquals(4, formatter.getRememberedPosition());
assertEquals("+1 650 25", formatter.inputDigit('5'));
assertEquals("+1 650 253", formatter.inputDigit('3'));
assertEquals("+1 650 253 2", formatter.inputDigit('2'));
assertEquals("+1 650 253 22", formatter.inputDigit('2'));
assertEquals("+1 650 253 222", formatter.inputDigit('2'));
assertEquals("+1650253222;", formatter.inputDigit(';'));
assertEquals(3, formatter.getRememberedPosition());
formatter.clear();
assertEquals("+", formatter.inputDigit('+'));
@ -214,9 +264,11 @@ public class AsYouTypeFormatterTest extends TestCase {
assertEquals("0", formatter.inputDigit('0'));
assertEquals("02", formatter.inputDigit('2'));
assertEquals("020", formatter.inputDigit('0'));
assertEquals("0207", formatter.inputDigit('7'));
assertEquals("0207", formatter.inputDigitAndRememberPosition('7'));
assertEquals(4, formatter.getRememberedPosition());
assertEquals("02070", formatter.inputDigit('0'));
assertEquals("020 703", formatter.inputDigit('3'));
assertEquals(5, formatter.getRememberedPosition());
assertEquals("020 7031", formatter.inputDigit('1'));
assertEquals("020 7031 3", formatter.inputDigit('3'));
assertEquals("020 7031 30", formatter.inputDigit('0'));


Loading…
Cancel
Save