content: /*
   * 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;
  }
  