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.text.Editable; 21 import android.text.Spanned; 22 import android.text.method.NumberKeyListener; 23 import android.util.AttributeSet; 24 import android.view.animation.TranslateAnimation; 25 import android.text.InputType; 26 import android.widget.EditText; 27 import android.widget.TextView; 28 import android.widget.ViewSwitcher; 29 import android.graphics.Rect; 30 import android.graphics.Paint; 31 32 /** 33 * Provides vertical scrolling for the input/result EditText. 34 */ 35 class CalculatorDisplay extends ViewSwitcher { 36 // only these chars are accepted from keyboard 37 private static final char[] ACCEPTED_CHARS = 38 "0123456789.+-*/\u2212\u00d7\u00f7()!%^".toCharArray(); 39 40 private static final int ANIM_DURATION = 500; 41 enum Scroll { UP, DOWN, NONE } 42 43 TranslateAnimation inAnimUp; 44 TranslateAnimation outAnimUp; 45 TranslateAnimation inAnimDown; 46 TranslateAnimation outAnimDown; 47 48 private Logic mLogic; 49 private boolean mComputedLineLength = false; 50 CalculatorDisplay(Context context, AttributeSet attrs)51 public CalculatorDisplay(Context context, AttributeSet attrs) { 52 super(context, attrs); 53 } 54 55 @Override onFinishInflate()56 protected void onFinishInflate() { 57 super.onFinishInflate(); 58 Calculator calc = (Calculator) getContext(); 59 calc.adjustFontSize((TextView)getChildAt(0)); 60 calc.adjustFontSize((TextView)getChildAt(1)); 61 } 62 63 @Override onLayout(boolean changed, int left, int top, int right, int bottom)64 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 65 super.onLayout(changed, left, top, right, bottom); 66 if (!mComputedLineLength) { 67 mLogic.setLineLength(getNumberFittingDigits((TextView) getCurrentView())); 68 mComputedLineLength = true; 69 } 70 } 71 72 // compute the maximum number of digits that fit in the 73 // calculator display without scrolling. getNumberFittingDigits(TextView display)74 private int getNumberFittingDigits(TextView display) { 75 int available = display.getWidth() 76 - display.getTotalPaddingLeft() - display.getTotalPaddingRight(); 77 Paint paint = display.getPaint(); 78 float digitWidth = paint.measureText("2222222222") / 10f; 79 return (int) (available / digitWidth); 80 } 81 setLogic(Logic logic)82 protected void setLogic(Logic logic) { 83 mLogic = logic; 84 NumberKeyListener calculatorKeyListener = 85 new NumberKeyListener() { 86 public int getInputType() { 87 // Don't display soft keyboard. 88 return InputType.TYPE_NULL; 89 } 90 91 protected char[] getAcceptedChars() { 92 return ACCEPTED_CHARS; 93 } 94 95 public CharSequence filter(CharSequence source, int start, int end, 96 Spanned dest, int dstart, int dend) { 97 /* the EditText should still accept letters (eg. 'sin') 98 coming from the on-screen touch buttons, so don't filter anything. 99 */ 100 return null; 101 } 102 }; 103 104 Editable.Factory factory = new CalculatorEditable.Factory(logic); 105 for (int i = 0; i < 2; ++i) { 106 EditText text = (EditText) getChildAt(i); 107 text.setBackgroundDrawable(null); 108 text.setEditableFactory(factory); 109 text.setKeyListener(calculatorKeyListener); 110 } 111 } 112 113 @Override setOnKeyListener(OnKeyListener l)114 public void setOnKeyListener(OnKeyListener l) { 115 getChildAt(0).setOnKeyListener(l); 116 getChildAt(1).setOnKeyListener(l); 117 } 118 119 @Override onSizeChanged(int w, int h, int oldW, int oldH)120 protected void onSizeChanged(int w, int h, int oldW, int oldH) { 121 inAnimUp = new TranslateAnimation(0, 0, h, 0); 122 inAnimUp.setDuration(ANIM_DURATION); 123 outAnimUp = new TranslateAnimation(0, 0, 0, -h); 124 outAnimUp.setDuration(ANIM_DURATION); 125 126 inAnimDown = new TranslateAnimation(0, 0, -h, 0); 127 inAnimDown.setDuration(ANIM_DURATION); 128 outAnimDown = new TranslateAnimation(0, 0, 0, h); 129 outAnimDown.setDuration(ANIM_DURATION); 130 } 131 insert(String delta)132 void insert(String delta) { 133 EditText editor = (EditText) getCurrentView(); 134 int cursor = editor.getSelectionStart(); 135 editor.getText().insert(cursor, delta); 136 } 137 getEditText()138 EditText getEditText() { 139 return (EditText) getCurrentView(); 140 } 141 getText()142 Editable getText() { 143 EditText text = (EditText) getCurrentView(); 144 return text.getText(); 145 } 146 setText(CharSequence text, Scroll dir)147 void setText(CharSequence text, Scroll dir) { 148 if (getText().length() == 0) { 149 dir = Scroll.NONE; 150 } 151 152 if (dir == Scroll.UP) { 153 setInAnimation(inAnimUp); 154 setOutAnimation(outAnimUp); 155 } else if (dir == Scroll.DOWN) { 156 setInAnimation(inAnimDown); 157 setOutAnimation(outAnimDown); 158 } else { // Scroll.NONE 159 setInAnimation(null); 160 setOutAnimation(null); 161 } 162 163 EditText editText = (EditText) getNextView(); 164 editText.setText(text); 165 //Calculator.log("selection to " + text.length() + "; " + text); 166 editText.setSelection(text.length()); 167 showNext(); 168 } 169 setSelection(int i)170 void setSelection(int i) { 171 EditText text = (EditText) getCurrentView(); 172 text.setSelection(i); 173 } 174 getSelectionStart()175 int getSelectionStart() { 176 EditText text = (EditText) getCurrentView(); 177 return text.getSelectionStart(); 178 } 179 180 @Override onFocusChanged(boolean gain, int direction, Rect prev)181 protected void onFocusChanged(boolean gain, int direction, Rect prev) { 182 //Calculator.log("focus " + gain + "; " + direction + "; " + prev); 183 if (!gain) { 184 requestFocus(); 185 } 186 } 187 } 188