1/*
2 * Copyright (C) 2014 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
17package com.android.tv.settings.connectivity.setup;
18
19import android.app.Activity;
20import android.app.Fragment;
21import android.content.Context;
22import android.os.Bundle;
23import android.os.Handler;
24import android.text.InputType;
25import android.view.KeyEvent;
26import android.view.LayoutInflater;
27import android.view.View;
28import android.view.View.OnClickListener;
29import android.view.ViewGroup;
30import android.view.inputmethod.InputMethodManager;
31import android.widget.CheckBox;
32import android.widget.EditText;
33import android.widget.TextView;
34
35import com.android.tv.settings.R;
36
37/**
38 * Displays a UI for text input in the "wizard" style.
39 * TODO: Merge with EditTextFragment
40 */
41public class PasswordInputWizardFragment extends Fragment {
42
43    public interface Listener {
44        /**
45         * Called when text input is complete.
46         *
47         * @param text the text that was input.
48         * @param obfuscate whether the input was obfuscated or not.
49         * @return true if the text is acceptable; false if not.
50         */
51        boolean onPasswordInputComplete(String text, boolean obfuscate);
52    }
53
54    private static final String EXTRA_TITLE = "title";
55    private static final String EXTRA_DESCRIPTION = "description";
56    private static final String EXTRA_PREFILL = "prefill";
57    private static final String EXTRA_OBFUSCATE = "obfuscate";
58
59    public static final String OPTION_OBFUSCATE = "option_obfuscate";
60
61    public static PasswordInputWizardFragment newInstance(
62            String title, String description, String prefill, boolean obfuscate) {
63        PasswordInputWizardFragment fragment = new PasswordInputWizardFragment();
64        Bundle args = new Bundle();
65        args.putString(EXTRA_TITLE, title);
66        args.putString(EXTRA_DESCRIPTION, description);
67        args.putString(EXTRA_PREFILL, prefill);
68        args.putBoolean(EXTRA_OBFUSCATE, obfuscate);
69        fragment.setArguments(args);
70        return fragment;
71    }
72
73    private Handler mHandler;
74    private EditText mTextInput;
75    private CheckBox mTextObfuscationToggle;
76
77    @Override
78    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) {
79        mHandler = new Handler();
80        final View view = inflater.inflate(R.layout.account_content_area, container, false);
81
82        final ViewGroup descriptionArea = (ViewGroup) view.findViewById(R.id.description);
83        final View content = inflater.inflate(R.layout.wifi_content, descriptionArea, false);
84        descriptionArea.addView(content);
85
86        final ViewGroup actionArea = (ViewGroup) view.findViewById(R.id.action);
87        final View action = inflater.inflate(R.layout.password_text_input, actionArea, false);
88        actionArea.addView(action);
89
90        TextView titleText = (TextView) content.findViewById(R.id.guidance_title);
91        TextView descriptionText = (TextView) content.findViewById(R.id.guidance_description);
92        mTextInput = (EditText) action.findViewById(R.id.text_input);
93        mTextObfuscationToggle = (CheckBox) action.findViewById(R.id.text_obfuscation_toggle);
94
95        final Bundle args = getArguments();
96        final String title = args.getString(EXTRA_TITLE);
97        final String description = args.getString(EXTRA_DESCRIPTION);
98        final String prefill = args.getString(EXTRA_PREFILL);
99        final boolean obfuscate = args.getBoolean(EXTRA_OBFUSCATE);
100
101        if (title != null) {
102            titleText.setText(title);
103            titleText.setVisibility(View.VISIBLE);
104        } else {
105            titleText.setVisibility(View.GONE);
106        }
107
108        if (description != null) {
109            descriptionText.setText(description);
110            descriptionText.setVisibility(View.VISIBLE);
111        } else {
112            descriptionText.setVisibility(View.GONE);
113        }
114
115        mTextObfuscationToggle.setOnClickListener(new OnClickListener() {
116            @Override
117            public void onClick(View v) {
118                updatePasswordInputObfuscation();
119                showSoftInput();
120            }
121        });
122        mTextObfuscationToggle.setChecked(obfuscate);
123        updatePasswordInputObfuscation();
124
125        if (prefill != null) {
126            mTextInput.setText(prefill);
127            mTextInput.setSelection(mTextInput.getText().length(), mTextInput.getText().length());
128        }
129
130        mTextInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
131            @Override
132            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
133                if (event == null || event.getAction() == KeyEvent.ACTION_UP) {
134                    Activity a = getActivity();
135                    if (a instanceof Listener) {
136                        boolean inputValid =
137                                ((Listener) a)
138                                        .onPasswordInputComplete(v.getText().toString(),
139                                                mTextObfuscationToggle.isChecked());
140                        if (inputValid) {
141                            hideSoftInput();
142                        }
143                    }
144                }
145                return true;  // If we don't return true on ACTION_DOWN, we don't get the ACTION_UP.
146            }
147        });
148
149        return view;
150    }
151
152    @Override
153    public void onResume() {
154        super.onResume();
155        if (mTextInput == null) return;
156        showSoftInput();
157    }
158
159    private void showSoftInput() {
160        mHandler.post(new Runnable() {
161            @Override
162            public void run() {
163                Activity a = getActivity();
164                if (a != null) {
165                    InputMethodManager inputMethodManager =
166                            (InputMethodManager) a.getSystemService(Context.INPUT_METHOD_SERVICE);
167                    mTextInput.requestFocus();
168                    mTextInput.setSelection(mTextInput.getText().length());
169                    inputMethodManager.viewClicked(mTextInput);
170                    inputMethodManager.showSoftInput(mTextInput, 0);
171                }
172            }
173        });
174    }
175
176    @Override
177    public void onPause() {
178        if (mTextInput == null) return;
179        hideSoftInput();
180        super.onPause();
181    }
182
183    private void hideSoftInput() {
184        InputMethodManager imm =
185                (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
186        imm.hideSoftInputFromWindow(mTextInput.getWindowToken(), 0);
187    }
188
189    public void updatePasswordInputObfuscation() {
190        mTextInput.setInputType(InputType.TYPE_CLASS_TEXT |
191                (mTextObfuscationToggle.isChecked() ?
192                        InputType.TYPE_TEXT_VARIATION_PASSWORD :
193                        InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD));
194    }
195
196}
197