Add basic support to handle hardware keyboard

Bug: 15710817
Change-Id: Icf50f4ddd6f7e3e8606074b533a34db66703da00
diff --git a/res/layout/display.xml b/res/layout/display.xml
index 0e1d978..066838a 100644
--- a/res/layout/display.xml
+++ b/res/layout/display.xml
@@ -38,6 +38,7 @@
         android:layout_height="wrap_content"
         android:layout_below="@id/formula"
         android:inputType="none"
+        android:focusable="false"
         android:textColor="@color/display_result_text_color" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index ac8c86a..d4f10f0 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -31,7 +31,9 @@
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.view.KeyEvent;
 import android.view.View;
+import android.view.View.OnKeyListener;
 import android.view.View.OnLongClickListener;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroupOverlay;
@@ -42,6 +44,8 @@
 import com.android.calculator2.CalculatorEditText.OnTextSizeChangeListener;
 import com.android.calculator2.CalculatorExpressionEvaluator.EvaluateCallback;
 
+import java.lang.Override;
+
 public class Calculator extends Activity
         implements OnTextSizeChangeListener, EvaluateCallback, OnLongClickListener {
 
@@ -76,6 +80,26 @@
         }
     };
 
+    private final OnKeyListener mFormulaOnKeyListener = new OnKeyListener() {
+        @Override
+        public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_NUMPAD_ENTER:
+                case KeyEvent.KEYCODE_ENTER:
+                    if (keyEvent.getAction() == KeyEvent.ACTION_UP) {
+                        mCurrentButton = mEqualButton;
+                        onEquals();
+                    }
+                    // ignore all other actions
+                    return true;
+                case KeyEvent.KEYCODE_DEL:
+                    onDelete();
+                    return true;
+            }
+            return false;
+        }
+    };
+
     private final Editable.Factory mFormulaEditableFactory = new Editable.Factory() {
         @Override
         public Editable newEditable(CharSequence source) {
@@ -93,6 +117,7 @@
     private CalculatorEditText mResultEditText;
     private ViewPager mPadViewPager;
     private View mDeleteButton;
+    private View mEqualButton;
     private View mClearButton;
 
     private View mCurrentButton;
@@ -109,6 +134,11 @@
         mDeleteButton = findViewById(R.id.del);
         mClearButton = findViewById(R.id.clr);
 
+        mEqualButton = findViewById(R.id.pad_numeric).findViewById(R.id.eq);
+        if (mEqualButton == null || mEqualButton.getVisibility() != View.VISIBLE) {
+            mEqualButton = findViewById(R.id.pad_operator).findViewById(R.id.eq);
+        }
+
         mTokenizer = new CalculatorExpressionTokenizer(this);
         mEvaluator = new CalculatorExpressionEvaluator(mTokenizer);
 
@@ -121,6 +151,7 @@
 
         mFormulaEditText.setEditableFactory(mFormulaEditableFactory);
         mFormulaEditText.addTextChangedListener(mFormulaTextWatcher);
+        mFormulaEditText.setOnKeyListener(mFormulaOnKeyListener);
         mFormulaEditText.setOnTextSizeChangeListener(this);
         mDeleteButton.setOnLongClickListener(this);
     }
@@ -189,18 +220,10 @@
 
         switch (view.getId()) {
             case R.id.eq:
-                if (mCurrentState == CalculatorState.INPUT) {
-                    setState(CalculatorState.EVALUATE);
-                    mEvaluator.evaluate(mFormulaEditText.getText(), this);
-                }
+                onEquals();
                 break;
             case R.id.del:
-                // Delete works like backspace; remove the last character from the expression.
-                final Editable formulaText = mFormulaEditText.getEditableText();
-                final int formulaLength = formulaText.length();
-                if (formulaLength > 0) {
-                    formulaText.delete(formulaLength - 1, formulaLength);
-                }
+                onDelete();
                 break;
             case R.id.clr:
                 onClear();
@@ -242,6 +265,8 @@
             // The current expression cannot be evaluated -> return to the input state.
             setState(CalculatorState.INPUT);
         }
+
+        mFormulaEditText.requestFocus();
     }
 
     @Override
@@ -270,6 +295,22 @@
         animatorSet.start();
     }
 
+    private void onEquals() {
+        if (mCurrentState == CalculatorState.INPUT) {
+            setState(CalculatorState.EVALUATE);
+            mEvaluator.evaluate(mFormulaEditText.getText(), this);
+        }
+    }
+
+    private void onDelete() {
+        // Delete works like backspace; remove the last character from the expression.
+        final Editable formulaText = mFormulaEditText.getEditableText();
+        final int formulaLength = formulaText.length();
+        if (formulaLength > 0) {
+            formulaText.delete(formulaLength - 1, formulaLength);
+        }
+    }
+
     private void reveal(View sourceView, int colorRes, AnimatorListener listener) {
         final View displayView = findViewById(R.id.display);
         final View decorView = getWindow().getDecorView();
diff --git a/src/com/android/calculator2/CalculatorEditText.java b/src/com/android/calculator2/CalculatorEditText.java
index b5ab026..746b6f5 100644
--- a/src/com/android/calculator2/CalculatorEditText.java
+++ b/src/com/android/calculator2/CalculatorEditText.java
@@ -90,7 +90,10 @@
         a.recycle();
 
         setCustomSelectionActionModeCallback(mNoSelectionActionModeCallback);
-        setMovementMethod(ScrollingMovementMethod.getInstance());
+
+        if (isFocusable()) {
+            setMovementMethod(ScrollingMovementMethod.getInstance());
+        }
         setTextSize(TypedValue.COMPLEX_UNIT_PX, mMaximumTextSize);
         setMinHeight(getLineHeight() + getCompoundPaddingBottom() + getCompoundPaddingTop());
     }