/*
|
* Copyright (C) 2006 The Android Open Source Project
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
package android.widget;
|
|
import android.content.Context;
|
import android.graphics.Rect;
|
import android.text.Editable;
|
import android.text.InputFilter;
|
import android.text.Selection;
|
import android.text.Spannable;
|
import android.text.Spanned;
|
import android.text.TextWatcher;
|
import android.text.method.DialerKeyListener;
|
import android.text.method.KeyListener;
|
import android.text.method.TextKeyListener;
|
import android.util.AttributeSet;
|
import android.view.KeyEvent;
|
import android.view.View;
|
|
/**
|
* This widget is a layout that contains several specifically-named child views that
|
* handle keyboard entry interpreted as standard phone dialpad digits.
|
*
|
* @deprecated Use a custom view or layout to handle this functionality instead
|
*/
|
@Deprecated
|
public class DialerFilter extends RelativeLayout
|
{
|
public DialerFilter(Context context) {
|
super(context);
|
}
|
|
public DialerFilter(Context context, AttributeSet attrs) {
|
super(context, attrs);
|
}
|
|
@Override
|
protected void onFinishInflate() {
|
super.onFinishInflate();
|
|
// Setup the filter view
|
mInputFilters = new InputFilter[] { new InputFilter.AllCaps() };
|
|
mHint = (EditText) findViewById(com.android.internal.R.id.hint);
|
if (mHint == null) {
|
throw new IllegalStateException("DialerFilter must have a child EditText named hint");
|
}
|
mHint.setFilters(mInputFilters);
|
|
mLetters = mHint;
|
mLetters.setKeyListener(TextKeyListener.getInstance());
|
mLetters.setMovementMethod(null);
|
mLetters.setFocusable(false);
|
|
// Setup the digits view
|
mPrimary = (EditText) findViewById(com.android.internal.R.id.primary);
|
if (mPrimary == null) {
|
throw new IllegalStateException("DialerFilter must have a child EditText named primary");
|
}
|
mPrimary.setFilters(mInputFilters);
|
|
mDigits = mPrimary;
|
mDigits.setKeyListener(DialerKeyListener.getInstance());
|
mDigits.setMovementMethod(null);
|
mDigits.setFocusable(false);
|
|
// Look for an icon
|
mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
|
|
// Setup focus & highlight for this view
|
setFocusable(true);
|
|
// XXX Force the mode to QWERTY for now, since 12-key isn't supported
|
mIsQwerty = true;
|
setMode(DIGITS_AND_LETTERS);
|
}
|
|
/**
|
* Only show the icon view when focused, if there is one.
|
*/
|
@Override
|
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
|
super.onFocusChanged(focused, direction, previouslyFocusedRect);
|
|
if (mIcon != null) {
|
mIcon.setVisibility(focused ? View.VISIBLE : View.GONE);
|
}
|
}
|
|
|
public boolean isQwertyKeyboard() {
|
return mIsQwerty;
|
}
|
|
@Override
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
boolean handled = false;
|
|
switch (keyCode) {
|
case KeyEvent.KEYCODE_DPAD_UP:
|
case KeyEvent.KEYCODE_DPAD_DOWN:
|
case KeyEvent.KEYCODE_DPAD_LEFT:
|
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
case KeyEvent.KEYCODE_ENTER:
|
case KeyEvent.KEYCODE_DPAD_CENTER:
|
break;
|
|
case KeyEvent.KEYCODE_DEL:
|
switch (mMode) {
|
case DIGITS_AND_LETTERS:
|
handled = mDigits.onKeyDown(keyCode, event);
|
handled &= mLetters.onKeyDown(keyCode, event);
|
break;
|
|
case DIGITS_AND_LETTERS_NO_DIGITS:
|
handled = mLetters.onKeyDown(keyCode, event);
|
if (mLetters.getText().length() == mDigits.getText().length()) {
|
setMode(DIGITS_AND_LETTERS);
|
}
|
break;
|
|
case DIGITS_AND_LETTERS_NO_LETTERS:
|
if (mDigits.getText().length() == mLetters.getText().length()) {
|
mLetters.onKeyDown(keyCode, event);
|
setMode(DIGITS_AND_LETTERS);
|
}
|
handled = mDigits.onKeyDown(keyCode, event);
|
break;
|
|
case DIGITS_ONLY:
|
handled = mDigits.onKeyDown(keyCode, event);
|
break;
|
|
case LETTERS_ONLY:
|
handled = mLetters.onKeyDown(keyCode, event);
|
break;
|
}
|
break;
|
|
default:
|
//mIsQwerty = msg.getKeyIsQwertyKeyboard();
|
|
switch (mMode) {
|
case DIGITS_AND_LETTERS:
|
handled = mLetters.onKeyDown(keyCode, event);
|
|
// pass this throw so the shift state is correct (for example,
|
// on a standard QWERTY keyboard, * and 8 are on the same key)
|
if (KeyEvent.isModifierKey(keyCode)) {
|
mDigits.onKeyDown(keyCode, event);
|
handled = true;
|
break;
|
}
|
|
// Only check to see if the digit is valid if the key is a printing key
|
// in the TextKeyListener. This prevents us from hiding the digits
|
// line when keys like UP and DOWN are hit.
|
// XXX note that KEYCODE_TAB is special-cased here for
|
// devices that share tab and 0 on a single key.
|
boolean isPrint = event.isPrintingKey();
|
if (isPrint || keyCode == KeyEvent.KEYCODE_SPACE
|
|| keyCode == KeyEvent.KEYCODE_TAB) {
|
char c = event.getMatch(DialerKeyListener.CHARACTERS);
|
if (c != 0) {
|
handled &= mDigits.onKeyDown(keyCode, event);
|
} else {
|
setMode(DIGITS_AND_LETTERS_NO_DIGITS);
|
}
|
}
|
break;
|
|
case DIGITS_AND_LETTERS_NO_LETTERS:
|
case DIGITS_ONLY:
|
handled = mDigits.onKeyDown(keyCode, event);
|
break;
|
|
case DIGITS_AND_LETTERS_NO_DIGITS:
|
case LETTERS_ONLY:
|
handled = mLetters.onKeyDown(keyCode, event);
|
break;
|
}
|
}
|
|
if (!handled) {
|
return super.onKeyDown(keyCode, event);
|
} else {
|
return true;
|
}
|
}
|
|
@Override
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
boolean a = mLetters.onKeyUp(keyCode, event);
|
boolean b = mDigits.onKeyUp(keyCode, event);
|
return a || b;
|
}
|
|
public int getMode() {
|
return mMode;
|
}
|
|
/**
|
* Change the mode of the widget.
|
*
|
* @param newMode The mode to switch to.
|
*/
|
public void setMode(int newMode) {
|
switch (newMode) {
|
case DIGITS_AND_LETTERS:
|
makeDigitsPrimary();
|
mLetters.setVisibility(View.VISIBLE);
|
mDigits.setVisibility(View.VISIBLE);
|
break;
|
|
case DIGITS_ONLY:
|
makeDigitsPrimary();
|
mLetters.setVisibility(View.GONE);
|
mDigits.setVisibility(View.VISIBLE);
|
break;
|
|
case LETTERS_ONLY:
|
makeLettersPrimary();
|
mLetters.setVisibility(View.VISIBLE);
|
mDigits.setVisibility(View.GONE);
|
break;
|
|
case DIGITS_AND_LETTERS_NO_LETTERS:
|
makeDigitsPrimary();
|
mLetters.setVisibility(View.INVISIBLE);
|
mDigits.setVisibility(View.VISIBLE);
|
break;
|
|
case DIGITS_AND_LETTERS_NO_DIGITS:
|
makeLettersPrimary();
|
mLetters.setVisibility(View.VISIBLE);
|
mDigits.setVisibility(View.INVISIBLE);
|
break;
|
|
}
|
int oldMode = mMode;
|
mMode = newMode;
|
onModeChange(oldMode, newMode);
|
}
|
|
private void makeLettersPrimary() {
|
if (mPrimary == mDigits) {
|
swapPrimaryAndHint(true);
|
}
|
}
|
|
private void makeDigitsPrimary() {
|
if (mPrimary == mLetters) {
|
swapPrimaryAndHint(false);
|
}
|
}
|
|
private void swapPrimaryAndHint(boolean makeLettersPrimary) {
|
Editable lettersText = mLetters.getText();
|
Editable digitsText = mDigits.getText();
|
KeyListener lettersInput = mLetters.getKeyListener();
|
KeyListener digitsInput = mDigits.getKeyListener();
|
|
if (makeLettersPrimary) {
|
mLetters = mPrimary;
|
mDigits = mHint;
|
} else {
|
mLetters = mHint;
|
mDigits = mPrimary;
|
}
|
|
mLetters.setKeyListener(lettersInput);
|
mLetters.setText(lettersText);
|
lettersText = mLetters.getText();
|
Selection.setSelection(lettersText, lettersText.length());
|
|
mDigits.setKeyListener(digitsInput);
|
mDigits.setText(digitsText);
|
digitsText = mDigits.getText();
|
Selection.setSelection(digitsText, digitsText.length());
|
|
// Reset the filters
|
mPrimary.setFilters(mInputFilters);
|
mHint.setFilters(mInputFilters);
|
}
|
|
|
public CharSequence getLetters() {
|
if (mLetters.getVisibility() == View.VISIBLE) {
|
return mLetters.getText();
|
} else {
|
return "";
|
}
|
}
|
|
public CharSequence getDigits() {
|
if (mDigits.getVisibility() == View.VISIBLE) {
|
return mDigits.getText();
|
} else {
|
return "";
|
}
|
}
|
|
public CharSequence getFilterText() {
|
if (mMode != DIGITS_ONLY) {
|
return getLetters();
|
} else {
|
return getDigits();
|
}
|
}
|
|
public void append(String text) {
|
switch (mMode) {
|
case DIGITS_AND_LETTERS:
|
mDigits.getText().append(text);
|
mLetters.getText().append(text);
|
break;
|
|
case DIGITS_AND_LETTERS_NO_LETTERS:
|
case DIGITS_ONLY:
|
mDigits.getText().append(text);
|
break;
|
|
case DIGITS_AND_LETTERS_NO_DIGITS:
|
case LETTERS_ONLY:
|
mLetters.getText().append(text);
|
break;
|
}
|
}
|
|
/**
|
* Clears both the digits and the filter text.
|
*/
|
public void clearText() {
|
Editable text;
|
|
text = mLetters.getText();
|
text.clear();
|
|
text = mDigits.getText();
|
text.clear();
|
|
// Reset the mode based on the hardware type
|
if (mIsQwerty) {
|
setMode(DIGITS_AND_LETTERS);
|
} else {
|
setMode(DIGITS_ONLY);
|
}
|
}
|
|
public void setLettersWatcher(TextWatcher watcher) {
|
CharSequence text = mLetters.getText();
|
Spannable span = (Spannable)text;
|
span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
}
|
|
public void setDigitsWatcher(TextWatcher watcher) {
|
CharSequence text = mDigits.getText();
|
Spannable span = (Spannable)text;
|
span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
}
|
|
public void setFilterWatcher(TextWatcher watcher) {
|
if (mMode != DIGITS_ONLY) {
|
setLettersWatcher(watcher);
|
} else {
|
setDigitsWatcher(watcher);
|
}
|
}
|
|
public void removeFilterWatcher(TextWatcher watcher) {
|
Spannable text;
|
if (mMode != DIGITS_ONLY) {
|
text = mLetters.getText();
|
} else {
|
text = mDigits.getText();
|
}
|
text.removeSpan(watcher);
|
}
|
|
/**
|
* Called right after the mode changes to give subclasses the option to
|
* restyle, etc.
|
*/
|
protected void onModeChange(int oldMode, int newMode) {
|
}
|
|
/** This mode has both lines */
|
public static final int DIGITS_AND_LETTERS = 1;
|
/** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
|
* has removed all possibility of the digits matching, leaving only the letters line */
|
public static final int DIGITS_AND_LETTERS_NO_DIGITS = 2;
|
/** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
|
* has removed all possibility of the letters matching, leaving only the digits line */
|
public static final int DIGITS_AND_LETTERS_NO_LETTERS = 3;
|
/** This mode has only the digits line */
|
public static final int DIGITS_ONLY = 4;
|
/** This mode has only the letters line */
|
public static final int LETTERS_ONLY = 5;
|
|
EditText mLetters;
|
EditText mDigits;
|
EditText mPrimary;
|
EditText mHint;
|
InputFilter mInputFilters[];
|
ImageView mIcon;
|
int mMode;
|
private boolean mIsQwerty;
|
}
|