gt:         if (!hasFocus) {
context: /*
   * Copyright (C) 2008 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 com.quietlycoding.android.picker;
  
  import android.content.Context;
  import android.os.Handler;
  import android.text.InputFilter;
  import android.text.InputType;
  import android.text.Spanned;
  import android.text.method.NumberKeyListener;
  import android.util.AttributeSet;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.view.View.OnFocusChangeListener;
  import android.view.View.OnLongClickListener;
  import android.widget.EditText;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  
  import com.mailboxplus.R;
  
  /**
   * This class has been pulled from the Android platform source code, its an internal widget that hasn't been
   * made public so its included in the project in this fashion for use with the preferences screen; I have made
   * a few slight modifications to the code here, I simply put a MAX and MIN default in the code but these values
   * can still be set publically by calling code.
   *
   * @author Google
   */
  public class NumberPicker extends LinearLayout implements OnClickListener,
          OnFocusChangeListener, OnLongClickListener {
  
      private static final String TAG = "NumberPicker";
      private static final int DEFAULT_MAX = 50;
      private static final int DEFAULT_MIN = 0;
  
      public interface OnChangedListener {
          void onChanged(NumberPicker picker, int oldVal, int newVal);
      }
  
      public interface Formatter {
          String toString(int value);
      }
  
      /*
       * Use a custom NumberPicker formatting callback to use two-digit
       * minutes strings like "01".  Keeping a static formatter etc. is the
       * most efficient way to do this; it avoids creating temporary objects
       * on every call to format().
       */
      public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER =
              new NumberPicker.Formatter() {
                  final StringBuilder mBuilder = new StringBuilder();
                  final java.util.Formatter mFmt = new java.util.Formatter(mBuilder);
                  final Object[] mArgs = new Object[1];
                  public String toString(int value) {
                      mArgs[0] = value;
                      mBuilder.delete(0, mBuilder.length());
                      mFmt.format("%02d", mArgs);
                      return mFmt.toString();
                  }
          };
  
      private final Handler mHandler;
      private final Runnable mRunnable = new Runnable() {
          public void run() {
              if (mIncrement) {
                  changeCurrent(mCurrent + 1);
                  mHandler.postDelayed(this, mSpeed);
              } else if (mDecrement) {
                  changeCurrent(mCurrent - 1);
                  mHandler.postDelayed(this, mSpeed);
              }
          }
      };
  
      private final EditText mText;
      private final InputFilter mNumberInputFilter;
  
      private String[] mDisplayedValues;
      protected int mStart;
      protected int mEnd;
      protected int mCurrent;
      protected int mPrevious;
      private OnChangedListener mListener;
      private Formatter mFormatter;
      private long mSpeed = 300;
  
      private boolean mIncrement;
      private boolean mDecrement;
  
      public NumberPicker(Context context) {
          this(context, null);
      }
  
      public NumberPicker(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      @SuppressWarnings({"UnusedDeclaration"})
      public NumberPicker(Context context, AttributeSet attrs, int defStyle) {
          super(context, attrs);
          setOrientation(VERTICAL);
          LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          inflater.inflate(R.layout.number_picker, this, true);
          mHandler = new Handler();
          InputFilter inputFilter = new NumberPickerInputFilter();
          mNumberInputFilter = new NumberRangeKeyListener();
          mIncrementButton = (NumberPickerButton) findViewById(R.id.increment);
          mIncrementButton.setOnClickListener(this);
          mIncrementButton.setOnLongClickListener(this);
          mIncrementButton.setNumberPicker(this);
          mDecrementButton = (NumberPickerButton) findViewById(R.id.decrement);
          mDecrementButton.setOnClickListener(this);
          mDecrementButton.setOnLongClickListener(this);
          mDecrementButton.setNumberPicker(this);
  
          mText = (EditText) findViewById(R.id.timepicker_input);
          mText.setOnFocusChangeListener(this);
          mText.setFilters(new InputFilter[] {inputFilter});
          mText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
  
          if (!isEnabled()) {
              setEnabled(false);
          }
  
          mStart = DEFAULT_MIN;
          mEnd = DEFAULT_MAX;
      }
  
      @Override
      public void setEnabled(boolean enabled) {
          super.setEnabled(enabled);
          mIncrementButton.setEnabled(enabled);
          mDecrementButton.setEnabled(enabled);
          mText.setEnabled(enabled);
      }
  
      public void setOnChangeListener(OnChangedListener listener) {
          mListener = listener;
      }
  
      public void setFormatter(Formatter formatter) {
          mFormatter = formatter;
      }
  
      /**
       * Set the range of numbers allowed for the number picker. The current
       * value will be automatically set to the start.
       *
       * @param start the start of the range (inclusive)
       * @param end the end of the range (inclusive)
       */
      public void setRange(int start, int end) {
          mStart = start;
          mEnd = end;
          mCurrent = start;
          updateView();
      }
  
      /**
       * Set the range of numbers allowed for the number picker. The current
       * value will be automatically set to the start. Also provide a mapping
       * for values used to display to the user.
       *
       * @param start the start of the range (inclusive)
       * @param end the end of the range (inclusive)
       * @param displayedValues the values displayed to the user.
       */
      public void setRange(int start, int end, String[] displayedValues) {
          mDisplayedValues = displayedValues;
          mStart = start;
          mEnd = end;
          mCurrent = start;
          updateView();
      }
  
      public void setCurrent(int current) {
          mCurrent = current;
          updateView();
      }
  
      /**
       * The speed (in milliseconds) at which the numbers will scroll
       * when the the +/- buttons are longpressed. Default is 300ms.
       */
      public void setSpeed(long speed) {
          mSpeed = speed;
      }
  
      public void onClick(View v) {
          validateInput(mText);
          if (!mText.hasFocus()) mText.requestFocus();
  
          // now perform the increment/decrement
          if (R.id.increment == v.getId()) {
              changeCurrent(mCurrent + 1);
          } else if (R.id.decrement == v.getId()) {
              changeCurrent(mCurrent - 1);
          }
      }
  
      private String formatNumber(int value) {
          return (mFormatter != null)
                  ? mFormatter.toString(value)
                  : String.valueOf(value);
      }
  
      protected void changeCurrent(int current) {
  
          // Wrap around the values if we go past the start or end
          if (current > mEnd) {
              current = mStart;
          } else if (current < mStart) {
              current = mEnd;
          }
          mPrevious = mCurrent;
          mCurrent = current;
  
          notifyChange();
          updateView();
      }
  
      protected void notifyChange() {
          if (mListener != null) {
              mListener.onChanged(this, mPrevious, mCurrent);
          }
      }
  
      protected void updateView() {
  
          /* If we don't have displayed values then use the
           * current number else find the correct value in the
           * displayed values for the current number.
           */
          if (mDisplayedValues == null) {
              mText.setText(formatNumber(mCurrent));
          } else {
              mText.setText(mDisplayedValues[mCurrent - mStart]);
          }
          mText.setSelection(mText.getText().length());
      }
  
      private void validateCurrentView(CharSequence str) {
          int val = getSelectedPos(str.toString());
          if ((val >= mStart) && (val <= mEnd)) {
              if (mCurrent != val) {
                  mPrevious = mCurrent;
                  mCurrent = val;
                  notifyChange();
              }
          }
          updateView();
      }
  
      public void onFocusChange(View v, boolean hasFocus) {
  
          /* When focus is lost check that the text field
           * has valid values.
           */
  