Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.widget;
     18 
     19 import android.content.Context;
     20 import android.graphics.Rect;
     21 import android.text.Editable;
     22 import android.text.InputFilter;
     23 import android.text.Selection;
     24 import android.text.Spannable;
     25 import android.text.Spanned;
     26 import android.text.TextWatcher;
     27 import android.text.method.DialerKeyListener;
     28 import android.text.method.KeyListener;
     29 import android.text.method.TextKeyListener;
     30 import android.util.AttributeSet;
     31 import android.view.KeyEvent;
     32 import android.view.View;
     33 
     34 /**
     35  * This widget is a layout that contains several specifically-named child views that
     36  * handle keyboard entry interpreted as standard phone dialpad digits.
     37  *
     38  * @deprecated Use a custom view or layout to handle this functionality instead
     39  */
     40 @Deprecated
     41 public class DialerFilter extends RelativeLayout
     42 {
     43     public DialerFilter(Context context) {
     44         super(context);
     45     }
     46 
     47     public DialerFilter(Context context, AttributeSet attrs) {
     48         super(context, attrs);
     49     }
     50 
     51     @Override
     52     protected void onFinishInflate() {
     53         super.onFinishInflate();
     54 
     55         // Setup the filter view
     56         mInputFilters = new InputFilter[] { new InputFilter.AllCaps() };
     57 
     58         mHint = (EditText) findViewById(com.android.internal.R.id.hint);
     59         if (mHint == null) {
     60             throw new IllegalStateException("DialerFilter must have a child EditText named hint");
     61         }
     62         mHint.setFilters(mInputFilters);
     63 
     64         mLetters = mHint;
     65         mLetters.setKeyListener(TextKeyListener.getInstance());
     66         mLetters.setMovementMethod(null);
     67         mLetters.setFocusable(false);
     68 
     69         // Setup the digits view
     70         mPrimary = (EditText) findViewById(com.android.internal.R.id.primary);
     71         if (mPrimary == null) {
     72             throw new IllegalStateException("DialerFilter must have a child EditText named primary");
     73         }
     74         mPrimary.setFilters(mInputFilters);
     75 
     76         mDigits = mPrimary;
     77         mDigits.setKeyListener(DialerKeyListener.getInstance());
     78         mDigits.setMovementMethod(null);
     79         mDigits.setFocusable(false);
     80 
     81         // Look for an icon
     82         mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
     83 
     84         // Setup focus & highlight for this view
     85         setFocusable(true);
     86 
     87         // XXX Force the mode to QWERTY for now, since 12-key isn't supported
     88         mIsQwerty = true;
     89         setMode(DIGITS_AND_LETTERS);
     90     }
     91 
     92     /**
     93      * Only show the icon view when focused, if there is one.
     94      */
     95     @Override
     96     protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
     97         super.onFocusChanged(focused, direction, previouslyFocusedRect);
     98 
     99         if (mIcon != null) {
    100             mIcon.setVisibility(focused ? View.VISIBLE : View.GONE);
    101         }
    102     }
    103 
    104 
    105     public boolean isQwertyKeyboard() {
    106         return mIsQwerty;
    107     }
    108 
    109     @Override
    110     public boolean onKeyDown(int keyCode, KeyEvent event) {
    111         boolean handled = false;
    112 
    113         switch (keyCode) {
    114             case KeyEvent.KEYCODE_DPAD_UP:
    115             case KeyEvent.KEYCODE_DPAD_DOWN:
    116             case KeyEvent.KEYCODE_DPAD_LEFT:
    117             case KeyEvent.KEYCODE_DPAD_RIGHT:
    118             case KeyEvent.KEYCODE_ENTER:
    119             case KeyEvent.KEYCODE_DPAD_CENTER:
    120                 break;
    121 
    122             case KeyEvent.KEYCODE_DEL:
    123                 switch (mMode) {
    124                     case DIGITS_AND_LETTERS:
    125                         handled = mDigits.onKeyDown(keyCode, event);
    126                         handled &= mLetters.onKeyDown(keyCode, event);
    127                         break;
    128 
    129                     case DIGITS_AND_LETTERS_NO_DIGITS:
    130                         handled = mLetters.onKeyDown(keyCode, event);
    131                         if (mLetters.getText().length() == mDigits.getText().length()) {
    132                             setMode(DIGITS_AND_LETTERS);
    133                         }
    134                         break;
    135 
    136                     case DIGITS_AND_LETTERS_NO_LETTERS:
    137                         if (mDigits.getText().length() == mLetters.getText().length()) {
    138                             mLetters.onKeyDown(keyCode, event);
    139                             setMode(DIGITS_AND_LETTERS);
    140                         }
    141                         handled = mDigits.onKeyDown(keyCode, event);
    142                         break;
    143 
    144                     case DIGITS_ONLY:
    145                         handled = mDigits.onKeyDown(keyCode, event);
    146                         break;
    147 
    148                     case LETTERS_ONLY:
    149                         handled = mLetters.onKeyDown(keyCode, event);
    150                         break;
    151                 }
    152                 break;
    153 
    154             default:
    155                 //mIsQwerty = msg.getKeyIsQwertyKeyboard();
    156 
    157                 switch (mMode) {
    158                     case DIGITS_AND_LETTERS:
    159                         handled = mLetters.onKeyDown(keyCode, event);
    160 
    161                         // pass this throw so the shift state is correct (for example,
    162                         // on a standard QWERTY keyboard, * and 8 are on the same key)
    163                         if (KeyEvent.isModifierKey(keyCode)) {
    164                             mDigits.onKeyDown(keyCode, event);
    165                             handled = true;
    166                             break;
    167                         }
    168 
    169                         // Only check to see if the digit is valid if the key is a printing key
    170                         // in the TextKeyListener. This prevents us from hiding the digits
    171                         // line when keys like UP and DOWN are hit.
    172                         // XXX note that KEYCODE_TAB is special-cased here for
    173                         // devices that share tab and 0 on a single key.
    174                         boolean isPrint = event.isPrintingKey();
    175                         if (isPrint || keyCode == KeyEvent.KEYCODE_SPACE
    176                                 || keyCode == KeyEvent.KEYCODE_TAB) {
    177                             char c = event.getMatch(DialerKeyListener.CHARACTERS);
    178                             if (c != 0) {
    179                                 handled &= mDigits.onKeyDown(keyCode, event);
    180                             } else {
    181                                 setMode(DIGITS_AND_LETTERS_NO_DIGITS);
    182                             }
    183                         }
    184                         break;
    185 
    186                     case DIGITS_AND_LETTERS_NO_LETTERS:
    187                     case DIGITS_ONLY:
    188                         handled = mDigits.onKeyDown(keyCode, event);
    189                         break;
    190 
    191                     case DIGITS_AND_LETTERS_NO_DIGITS:
    192                     case LETTERS_ONLY:
    193                         handled = mLetters.onKeyDown(keyCode, event);
    194                         break;
    195                 }
    196         }
    197 
    198         if (!handled) {
    199             return super.onKeyDown(keyCode, event);
    200         } else {
    201             return true;
    202         }
    203     }
    204 
    205     @Override
    206     public boolean onKeyUp(int keyCode, KeyEvent event) {
    207         boolean a = mLetters.onKeyUp(keyCode, event);
    208         boolean b = mDigits.onKeyUp(keyCode, event);
    209         return a || b;
    210     }
    211 
    212     public int getMode() {
    213         return mMode;
    214     }
    215 
    216     /**
    217      * Change the mode of the widget.
    218      *
    219      * @param newMode The mode to switch to.
    220      */
    221     public void setMode(int newMode) {
    222         switch (newMode) {
    223             case DIGITS_AND_LETTERS:
    224                 makeDigitsPrimary();
    225                 mLetters.setVisibility(View.VISIBLE);
    226                 mDigits.setVisibility(View.VISIBLE);
    227                 break;
    228 
    229             case DIGITS_ONLY:
    230                 makeDigitsPrimary();
    231                 mLetters.setVisibility(View.GONE);
    232                 mDigits.setVisibility(View.VISIBLE);
    233                 break;
    234 
    235             case LETTERS_ONLY:
    236                 makeLettersPrimary();
    237                 mLetters.setVisibility(View.VISIBLE);
    238                 mDigits.setVisibility(View.GONE);
    239                 break;
    240 
    241             case DIGITS_AND_LETTERS_NO_LETTERS:
    242                 makeDigitsPrimary();
    243                 mLetters.setVisibility(View.INVISIBLE);
    244                 mDigits.setVisibility(View.VISIBLE);
    245                 break;
    246 
    247             case DIGITS_AND_LETTERS_NO_DIGITS:
    248                 makeLettersPrimary();
    249                 mLetters.setVisibility(View.VISIBLE);
    250                 mDigits.setVisibility(View.INVISIBLE);
    251                 break;
    252 
    253         }
    254         int oldMode = mMode;
    255         mMode = newMode;
    256         onModeChange(oldMode, newMode);
    257     }
    258 
    259     private void makeLettersPrimary() {
    260         if (mPrimary == mDigits) {
    261             swapPrimaryAndHint(true);
    262         }
    263     }
    264 
    265     private void makeDigitsPrimary() {
    266         if (mPrimary == mLetters) {
    267             swapPrimaryAndHint(false);
    268         }
    269     }
    270 
    271     private void swapPrimaryAndHint(boolean makeLettersPrimary) {
    272         Editable lettersText = mLetters.getText();
    273         Editable digitsText = mDigits.getText();
    274         KeyListener lettersInput = mLetters.getKeyListener();
    275         KeyListener digitsInput = mDigits.getKeyListener();
    276 
    277         if (makeLettersPrimary) {
    278             mLetters = mPrimary;
    279             mDigits = mHint;
    280         } else {
    281             mLetters = mHint;
    282             mDigits = mPrimary;
    283         }
    284 
    285         mLetters.setKeyListener(lettersInput);
    286         mLetters.setText(lettersText);
    287         lettersText = mLetters.getText();
    288         Selection.setSelection(lettersText, lettersText.length());
    289 
    290         mDigits.setKeyListener(digitsInput);
    291         mDigits.setText(digitsText);
    292         digitsText = mDigits.getText();
    293         Selection.setSelection(digitsText, digitsText.length());
    294 
    295         // Reset the filters
    296         mPrimary.setFilters(mInputFilters);
    297         mHint.setFilters(mInputFilters);
    298     }
    299 
    300 
    301     public CharSequence getLetters() {
    302         if (mLetters.getVisibility() == View.VISIBLE) {
    303             return mLetters.getText();
    304         } else {
    305             return "";
    306         }
    307     }
    308 
    309     public CharSequence getDigits() {
    310         if (mDigits.getVisibility() == View.VISIBLE) {
    311             return mDigits.getText();
    312         } else {
    313             return "";
    314         }
    315     }
    316 
    317     public CharSequence getFilterText() {
    318         if (mMode != DIGITS_ONLY) {
    319             return getLetters();
    320         } else {
    321             return getDigits();
    322         }
    323     }
    324 
    325     public void append(String text) {
    326         switch (mMode) {
    327             case DIGITS_AND_LETTERS:
    328                 mDigits.getText().append(text);
    329                 mLetters.getText().append(text);
    330                 break;
    331 
    332             case DIGITS_AND_LETTERS_NO_LETTERS:
    333             case DIGITS_ONLY:
    334                 mDigits.getText().append(text);
    335                 break;
    336 
    337             case DIGITS_AND_LETTERS_NO_DIGITS:
    338             case LETTERS_ONLY:
    339                 mLetters.getText().append(text);
    340                 break;
    341         }
    342     }
    343 
    344     /**
    345      * Clears both the digits and the filter text.
    346      */
    347     public void clearText() {
    348         Editable text;
    349 
    350         text = mLetters.getText();
    351         text.clear();
    352 
    353         text = mDigits.getText();
    354         text.clear();
    355 
    356         // Reset the mode based on the hardware type
    357         if (mIsQwerty) {
    358             setMode(DIGITS_AND_LETTERS);
    359         } else {
    360             setMode(DIGITS_ONLY);
    361         }
    362     }
    363 
    364     public void setLettersWatcher(TextWatcher watcher) {
    365         CharSequence text = mLetters.getText();
    366         Spannable span = (Spannable)text;
    367         span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    368     }
    369 
    370     public void setDigitsWatcher(TextWatcher watcher) {
    371         CharSequence text = mDigits.getText();
    372         Spannable span = (Spannable)text;
    373         span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    374     }
    375 
    376     public void setFilterWatcher(TextWatcher watcher) {
    377         if (mMode != DIGITS_ONLY) {
    378             setLettersWatcher(watcher);
    379         } else {
    380             setDigitsWatcher(watcher);
    381         }
    382     }
    383 
    384     public void removeFilterWatcher(TextWatcher watcher) {
    385         Spannable text;
    386         if (mMode != DIGITS_ONLY) {
    387             text = mLetters.getText();
    388         } else {
    389             text = mDigits.getText();
    390         }
    391         text.removeSpan(watcher);
    392     }
    393 
    394     /**
    395      * Called right after the mode changes to give subclasses the option to
    396      * restyle, etc.
    397      */
    398     protected void onModeChange(int oldMode, int newMode) {
    399     }
    400 
    401     /** This mode has both lines */
    402     public static final int DIGITS_AND_LETTERS = 1;
    403     /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
    404      *  has removed all possibility of the digits matching, leaving only the letters line */
    405     public static final int DIGITS_AND_LETTERS_NO_DIGITS = 2;
    406     /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
    407      *  has removed all possibility of the letters matching, leaving only the digits line */
    408     public static final int DIGITS_AND_LETTERS_NO_LETTERS = 3;
    409     /** This mode has only the digits line */
    410     public static final int DIGITS_ONLY = 4;
    411     /** This mode has only the letters line */
    412     public static final int LETTERS_ONLY = 5;
    413 
    414     EditText mLetters;
    415     EditText mDigits;
    416     EditText mPrimary;
    417     EditText mHint;
    418     InputFilter mInputFilters[];
    419     ImageView mIcon;
    420     int mMode;
    421     private boolean mIsQwerty;
    422 }
    423