1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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
17package com.android.stk;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.graphics.drawable.BitmapDrawable;
23import android.os.Bundle;
24import android.os.Handler;
25import android.os.Message;
26import android.text.Editable;
27import android.text.InputFilter;
28import android.text.TextWatcher;
29import android.text.method.PasswordTransformationMethod;
30import android.view.KeyEvent;
31import android.view.MenuItem;
32import android.view.View;
33import android.view.Window;
34import android.widget.Button;
35import android.widget.TextView;
36import android.widget.EditText;
37import android.widget.TextView.BufferType;
38
39import com.android.internal.telephony.cat.FontSize;
40import com.android.internal.telephony.cat.Input;
41
42/**
43 * Display a request for a text input a long with a text edit form.
44 */
45public class StkInputActivity extends Activity implements View.OnClickListener,
46        TextWatcher {
47
48    // Members
49    private int mState;
50    private Context mContext;
51    private EditText mTextIn = null;
52    private TextView mPromptView = null;
53    private View mYesNoLayout = null;
54    private View mNormalLayout = null;
55    private Input mStkInput = null;
56
57    // Constants
58    private static final int STATE_TEXT = 1;
59    private static final int STATE_YES_NO = 2;
60
61    static final String YES_STR_RESPONSE = "YES";
62    static final String NO_STR_RESPONSE = "NO";
63
64    // Font size factor values.
65    static final float NORMAL_FONT_FACTOR = 1;
66    static final float LARGE_FONT_FACTOR = 2;
67    static final float SMALL_FONT_FACTOR = (1 / 2);
68
69    // message id for time out
70    private static final int MSG_ID_TIMEOUT = 1;
71
72    Handler mTimeoutHandler = new Handler() {
73        @Override
74        public void handleMessage(Message msg) {
75            switch(msg.what) {
76            case MSG_ID_TIMEOUT:
77                //mAcceptUsersInput = false;
78                sendResponse(StkAppService.RES_ID_TIMEOUT);
79                finish();
80                break;
81            }
82        }
83    };
84
85    // Click listener to handle buttons press..
86    public void onClick(View v) {
87        String input = null;
88
89        switch (v.getId()) {
90        case R.id.button_ok:
91            // Check that text entered is valid .
92            if (!verfiyTypedText()) {
93                return;
94            }
95            input = mTextIn.getText().toString();
96            break;
97        // Yes/No layout buttons.
98        case R.id.button_yes:
99            input = YES_STR_RESPONSE;
100            break;
101        case R.id.button_no:
102            input = NO_STR_RESPONSE;
103            break;
104        }
105
106        sendResponse(StkAppService.RES_ID_INPUT, input, false);
107        finish();
108    }
109
110    @Override
111    public void onCreate(Bundle icicle) {
112        super.onCreate(icicle);
113
114        // Set the layout for this activity.
115        requestWindowFeature(Window.FEATURE_LEFT_ICON);
116        setContentView(R.layout.stk_input);
117
118        // Initialize members
119        mTextIn = (EditText) this.findViewById(R.id.in_text);
120        mPromptView = (TextView) this.findViewById(R.id.prompt);
121
122        // Set buttons listeners.
123        Button okButton = (Button) findViewById(R.id.button_ok);
124        Button yesButton = (Button) findViewById(R.id.button_yes);
125        Button noButton = (Button) findViewById(R.id.button_no);
126
127        okButton.setOnClickListener(this);
128        yesButton.setOnClickListener(this);
129        noButton.setOnClickListener(this);
130
131        mYesNoLayout = findViewById(R.id.yes_no_layout);
132        mNormalLayout = findViewById(R.id.normal_layout);
133
134        // Get the calling intent type: text/key, and setup the
135        // display parameters.
136        Intent intent = getIntent();
137        if (intent != null) {
138            mStkInput = intent.getParcelableExtra("INPUT");
139            if (mStkInput == null) {
140                finish();
141            } else {
142                mState = mStkInput.yesNo ? STATE_YES_NO : STATE_TEXT;
143                configInputDisplay();
144            }
145        } else {
146            finish();
147        }
148        mContext = getBaseContext();
149    }
150
151    @Override
152    protected void onPostCreate(Bundle savedInstanceState) {
153        super.onPostCreate(savedInstanceState);
154
155        mTextIn.addTextChangedListener(this);
156    }
157
158    @Override
159    public void onResume() {
160        super.onResume();
161
162        startTimeOut();
163    }
164
165    @Override
166    public void onPause() {
167        super.onPause();
168
169        cancelTimeOut();
170    }
171
172    @Override
173    public boolean onKeyDown(int keyCode, KeyEvent event) {
174        switch (keyCode) {
175        case KeyEvent.KEYCODE_BACK:
176            sendResponse(StkAppService.RES_ID_BACKWARD, null, false);
177            finish();
178            break;
179        }
180        return super.onKeyDown(keyCode, event);
181    }
182
183    private void sendResponse(int resId) {
184        sendResponse(resId, null, false);
185    }
186
187    private void sendResponse(int resId, String input, boolean help) {
188        Bundle args = new Bundle();
189        args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
190        args.putInt(StkAppService.RES_ID, resId);
191        if (input != null) {
192            args.putString(StkAppService.INPUT, input);
193        }
194        args.putBoolean(StkAppService.HELP, help);
195        mContext.startService(new Intent(mContext, StkAppService.class)
196                .putExtras(args));
197    }
198
199    @Override
200    public boolean onCreateOptionsMenu(android.view.Menu menu) {
201        super.onCreateOptionsMenu(menu);
202        menu.add(android.view.Menu.NONE, StkApp.MENU_ID_END_SESSION, 1,
203                R.string.menu_end_session);
204        menu.add(0, StkApp.MENU_ID_HELP, 2, R.string.help);
205
206        return true;
207    }
208
209    @Override
210    public boolean onPrepareOptionsMenu(android.view.Menu menu) {
211        super.onPrepareOptionsMenu(menu);
212        menu.findItem(StkApp.MENU_ID_END_SESSION).setVisible(true);
213        menu.findItem(StkApp.MENU_ID_HELP).setVisible(mStkInput.helpAvailable);
214
215        return true;
216    }
217
218    @Override
219    public boolean onOptionsItemSelected(MenuItem item) {
220        switch (item.getItemId()) {
221        case StkApp.MENU_ID_END_SESSION:
222            sendResponse(StkAppService.RES_ID_END_SESSION);
223            finish();
224            return true;
225        case StkApp.MENU_ID_HELP:
226            sendResponse(StkAppService.RES_ID_INPUT, "", true);
227            finish();
228            return true;
229        }
230        return super.onOptionsItemSelected(item);
231    }
232
233    public void beforeTextChanged(CharSequence s, int start, int count,
234            int after) {
235    }
236
237    public void onTextChanged(CharSequence s, int start, int before, int count) {
238        // Reset timeout.
239        startTimeOut();
240    }
241
242    public void afterTextChanged(Editable s) {
243    }
244
245    private boolean verfiyTypedText() {
246        // If not enough input was typed in stay on the edit screen.
247        if (mTextIn.getText().length() < mStkInput.minLen) {
248            return false;
249        }
250
251        return true;
252    }
253
254    private void cancelTimeOut() {
255        mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
256    }
257
258    private void startTimeOut() {
259        int duration = StkApp.calculateDurationInMilis(mStkInput.duration);
260
261        if (duration <= 0) {
262            duration = StkApp.UI_TIMEOUT;
263        }
264        cancelTimeOut();
265        mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
266                .obtainMessage(MSG_ID_TIMEOUT), duration);
267    }
268
269    private void configInputDisplay() {
270        TextView numOfCharsView = (TextView) findViewById(R.id.num_of_chars);
271        TextView inTypeView = (TextView) findViewById(R.id.input_type);
272
273        int inTypeId = R.string.alphabet;
274
275        // set the prompt.
276        mPromptView.setText(mStkInput.text);
277
278        // Set input type (alphabet/digit) info close to the InText form.
279        if (mStkInput.digitOnly) {
280            mTextIn.setKeyListener(StkDigitsKeyListener.getInstance());
281            inTypeId = R.string.digits;
282        }
283        inTypeView.setText(inTypeId);
284
285        if (mStkInput.icon != null) {
286            setFeatureDrawable(Window.FEATURE_LEFT_ICON, new BitmapDrawable(
287                    mStkInput.icon));
288        }
289
290        // Handle specific global and text attributes.
291        switch (mState) {
292        case STATE_TEXT:
293            int maxLen = mStkInput.maxLen;
294            int minLen = mStkInput.minLen;
295            mTextIn.setFilters(new InputFilter[] {new InputFilter.LengthFilter(
296                    maxLen)});
297
298            // Set number of chars info.
299            String lengthLimit = String.valueOf(minLen);
300            if (maxLen != minLen) {
301                lengthLimit = minLen + " - " + maxLen;
302            }
303            numOfCharsView.setText(lengthLimit);
304
305            if (!mStkInput.echo) {
306                mTextIn.setTransformationMethod(PasswordTransformationMethod
307                        .getInstance());
308            }
309            // Set default text if present.
310            if (mStkInput.defaultText != null) {
311                mTextIn.setText(mStkInput.defaultText);
312            } else {
313                // make sure the text is cleared
314                mTextIn.setText("", BufferType.EDITABLE);
315            }
316
317            break;
318        case STATE_YES_NO:
319            // Set display mode - normal / yes-no layout
320            mYesNoLayout.setVisibility(View.VISIBLE);
321            mNormalLayout.setVisibility(View.GONE);
322            break;
323        }
324    }
325
326    private float getFontSizeFactor(FontSize size) {
327        final float[] fontSizes =
328            {NORMAL_FONT_FACTOR, LARGE_FONT_FACTOR, SMALL_FONT_FACTOR};
329
330        return fontSizes[size.ordinal()];
331    }
332}
333