Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da8b340f authored by Todor Kalaydjiev's avatar Todor Kalaydjiev Committed by Android (Google) Code Review
Browse files

Merge "Support auto-complete in PhoneNumberFormattingTextWatcher. Also,...

Merge "Support auto-complete in PhoneNumberFormattingTextWatcher. Also, simplify logic. Previously, the assumption was that only a deletion or an insertion can happen at a time; but with auto-complete, a deletion and insertion happen at the same time."
parents f19d5f02 26a92257
Loading
Loading
Loading
Loading
+8 −48
Original line number Diff line number Diff line
@@ -39,30 +39,6 @@ import java.util.Locale;
 * The formatting will be restarted once the text is cleared.
 */
public class PhoneNumberFormattingTextWatcher implements TextWatcher {
    /**
     * One or more characters were removed from the end.
     */
    private final static int STATE_REMOVE_LAST = 0;

    /**
     * One or more characters were appended.
     */
    private final static int STATE_APPEND = 1;

    /**
     * One or more digits were changed in the beginning or the middle of text.
     */
    private final static int STATE_MODIFY_DIGITS = 2;

    /**
     * The changes other than the above.
     */
    private final static int STATE_OTHER = 3;

    /**
     * The state of this change could be one value of the above
     */
    private int mState;

    /**
     * Indicates the change was caused by ourselves.
@@ -97,46 +73,30 @@ public class PhoneNumberFormattingTextWatcher implements TextWatcher {
        mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
        if (mSelfChange || mStopFormatting) {
            return;
        }
        if (count == 0 && s.length() == start) {
            // Append one or more new chars
            mState = STATE_APPEND;
        } else if (after == 0 && start + count == s.length() && count > 0) {
            // Remove one or more chars from the end of string.
            mState = STATE_REMOVE_LAST;
        } else if (count > 0 && !hasSeparator(s, start, count)) {
            // Remove the dialable chars in the begin or middle of text.
            mState = STATE_MODIFY_DIGITS;
        } else {
            mState = STATE_OTHER;
        // If the user manually deleted any non-dialable characters, stop formatting
        if (count > 0 && hasSeparator(s, start, count)) {
            stopFormatting();
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if (mSelfChange || mStopFormatting) {
            return;
        }
        if (mState == STATE_OTHER) {
            if (count > 0 && !hasSeparator(s, start, count)) {
                // User inserted the dialable characters in the middle of text.
                mState = STATE_MODIFY_DIGITS;
            }
        }
        // Check whether we should stop formatting.
        if (mState == STATE_APPEND && count > 0 && hasSeparator(s, start, count)) {
            // User appended the non-dialable character, stop formatting.
            stopFormatting();
        } else if (mState == STATE_OTHER) {
            // User must insert or remove the non-dialable characters in the begin or middle of
            // number, stop formatting.
        // If the user inserted any non-dialable characters, stop formatting
        if (count > 0 && hasSeparator(s, start, count)) {
            stopFormatting();
        }
    }

    @Override
    public synchronized void afterTextChanged(Editable s) {
        if (mStopFormatting) {
            // Restart the formatting when all texts were clear.
+78 −0
Original line number Diff line number Diff line
@@ -182,14 +182,17 @@ public class PhoneNumberWatcherTest extends AndroidTestCase {

    public void testTextChangedByOtherTextWatcher() {
        final TextWatcher cleanupTextWatcher = new TextWatcher() {
            @Override
            public void afterTextChanged(Editable s) {
                s.clear();
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {
            }
@@ -208,6 +211,81 @@ public class PhoneNumberWatcherTest extends AndroidTestCase {
        assertEquals(expected1, number.toString());
    }

    /**
     * Test the case where some other component is auto-completing what the user is typing
     */
    public void testAutoCompleteWithFormattedNumber() {
        String init = "650-1";
        String expected = "+1-650-123-4567"; // Different formatting than ours
        testReplacement(init, expected, expected);
    }

    /**
     * Test the case where some other component is auto-completing what the user is typing
     */
    public void testAutoCompleteWithFormattedNameAndNumber() {
        String init = "650-1";
        String expected = "Test User <650-123-4567>";
        testReplacement(init, expected, expected);
    }

    /**
     * Test the case where some other component is auto-completing what the user is typing
     */
    public void testAutoCompleteWithNumericNameAndNumber() {
        String init = "650";
        String expected = "2nd Test User <650-123-4567>";
        testReplacement(init, expected, expected);
    }

    /**
     * Test the case where some other component is auto-completing what the user is typing
     */
    public void testAutoCompleteWithUnformattedNumber() {
        String init = "650-1";
        String expected = "6501234567";
        testReplacement(init, expected, expected);
    }

    /**
     * Test the case where some other component is auto-completing what the user is typing, where
     * the deleted text doesn't have any formatting and neither does the replacement text: in this
     * case the replacement text should be formatted by the PhoneNumberFormattingTextWatcher.
     */
    public void testAutoCompleteUnformattedWithUnformattedNumber() {
        String init = "650";
        String replacement = "6501234567";
        String expected = "(650) 123-4567";
        testReplacement(init, replacement, expected);

        String init2 = "650";
        String replacement2 = "16501234567";
        String expected2 = "1 650-123-4567";
        testReplacement(init2, replacement2, expected2);
    }

    /**
     * Helper method for testing replacing the entire string with another string
     * @param init The initial string
     * @param expected
     */
    private void testReplacement(String init, String replacement, String expected) {
        TextWatcher textWatcher = getTextWatcher();

        SpannableStringBuilder number = new SpannableStringBuilder(init);

        // Replace entire text with the given values
        textWatcher.beforeTextChanged(number, 0, init.length(), replacement.length());
        number.replace(0, init.length(), replacement, 0, replacement.length());
        Selection.setSelection(number, replacement.length()); // move the cursor to the end
        textWatcher.onTextChanged(number, 0, init.length(), replacement.length());
        textWatcher.afterTextChanged(number);

        assertEquals(expected, number.toString());
        // the cursor should be still at the end
        assertEquals(expected.length(), Selection.getSelectionEnd(number));
    }

    private TextWatcher getTextWatcher() {
        return new PhoneNumberFormattingTextWatcher("US");
    }