1 /* 2 * Copyright (C) 2008 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 com.android.calculator2; 18 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.text.Editable; 22 import android.text.Spanned; 23 import android.text.method.NumberKeyListener; 24 import android.util.AttributeSet; 25 import android.view.animation.TranslateAnimation; 26 import android.view.inputmethod.EditorInfo; 27 import android.widget.EditText; 28 import android.widget.ViewSwitcher; 29 30 /** 31 * Provides vertical scrolling for the input/result EditText. 32 */ 33 class CalculatorDisplay extends ViewSwitcher { 34 35 private static final String ATTR_MAX_DIGITS = "maxDigits"; 36 private static final int DEFAULT_MAX_DIGITS = 10; 37 38 // only these chars are accepted from keyboard 39 private static final char[] ACCEPTED_CHARS = 40 "0123456789.+-*/\u2212\u00d7\u00f7()!%^".toCharArray(); 41 42 private static final int ANIM_DURATION = 500; 43 44 enum Scroll { UP, DOWN, NONE } 45 46 TranslateAnimation inAnimUp; 47 TranslateAnimation outAnimUp; 48 TranslateAnimation inAnimDown; 49 TranslateAnimation outAnimDown; 50 51 private Logic mLogic; 52 private int mMaxDigits = DEFAULT_MAX_DIGITS; 53 54 public CalculatorDisplay(Context context, AttributeSet attrs) { 55 super(context, attrs); 56 mMaxDigits = attrs.getAttributeIntValue(null, ATTR_MAX_DIGITS, DEFAULT_MAX_DIGITS); 57 } 58 59 public int getMaxDigits() { 60 return mMaxDigits; 61 } 62 63 protected void setLogic(Logic logic) { 64 mLogic = logic; 65 NumberKeyListener calculatorKeyListener = 66 new NumberKeyListener() { 67 public int getInputType() { 68 return EditorInfo.TYPE_CLASS_TEXT; 69 } 70 71 @Override 72 protected char[] getAcceptedChars() { 73 return ACCEPTED_CHARS; 74 } 75 76 @Override 77 public CharSequence filter(CharSequence source, int start, int end, 78 Spanned dest, int dstart, int dend) { 79 /* the EditText should still accept letters (eg. 'sin') 80 coming from the on-screen touch buttons, so don't filter anything. 81 */ 82 return null; 83 } 84 }; 85 86 Editable.Factory factory = new CalculatorEditable.Factory(logic); 87 for (int i = 0; i < 2; ++i) { 88 EditText text = (EditText) getChildAt(i); 89 text.setBackgroundDrawable(null); 90 text.setEditableFactory(factory); 91 text.setKeyListener(calculatorKeyListener); 92 text.setSingleLine(); 93 } 94 } 95 96 @Override 97 public void setOnKeyListener(OnKeyListener l) { 98 getChildAt(0).setOnKeyListener(l); 99 getChildAt(1).setOnKeyListener(l); 100 } 101 102 @Override 103 protected void onSizeChanged(int w, int h, int oldW, int oldH) { 104 inAnimUp = new TranslateAnimation(0, 0, h, 0); 105 inAnimUp.setDuration(ANIM_DURATION); 106 outAnimUp = new TranslateAnimation(0, 0, 0, -h); 107 outAnimUp.setDuration(ANIM_DURATION); 108 109 inAnimDown = new TranslateAnimation(0, 0, -h, 0); 110 inAnimDown.setDuration(ANIM_DURATION); 111 outAnimDown = new TranslateAnimation(0, 0, 0, h); 112 outAnimDown.setDuration(ANIM_DURATION); 113 } 114 115 void insert(String delta) { 116 EditText editor = (EditText) getCurrentView(); 117 int cursor = editor.getSelectionStart(); 118 editor.getText().insert(cursor, delta); 119 } 120 121 EditText getEditText() { 122 return (EditText) getCurrentView(); 123 } 124 125 Editable getText() { 126 EditText text = (EditText) getCurrentView(); 127 return text.getText(); 128 } 129 130 void setText(CharSequence text, Scroll dir) { 131 if (getText().length() == 0) { 132 dir = Scroll.NONE; 133 } 134 135 if (dir == Scroll.UP) { 136 setInAnimation(inAnimUp); 137 setOutAnimation(outAnimUp); 138 } else if (dir == Scroll.DOWN) { 139 setInAnimation(inAnimDown); 140 setOutAnimation(outAnimDown); 141 } else { // Scroll.NONE 142 setInAnimation(null); 143 setOutAnimation(null); 144 } 145 146 EditText editText = (EditText) getNextView(); 147 editText.setText(text); 148 //Calculator.log("selection to " + text.length() + "; " + text); 149 editText.setSelection(text.length()); 150 showNext(); 151 } 152 153 int getSelectionStart() { 154 EditText text = (EditText) getCurrentView(); 155 return text.getSelectionStart(); 156 } 157 158 @Override 159 protected void onFocusChanged(boolean gain, int direction, Rect prev) { 160 //Calculator.log("focus " + gain + "; " + direction + "; " + prev); 161 if (!gain) { 162 requestFocus(); 163 } 164 } 165 } 166