1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package com.android.tv.quicksettings;
15
16import android.app.Activity;
17import android.app.AlertDialog;
18import android.content.DialogInterface;
19import android.content.Intent;
20import android.os.Bundle;
21import android.os.Parcelable;
22import android.support.v17.leanback.widget.OnChildSelectedListener;
23import android.support.v17.leanback.widget.VerticalGridView;
24import android.support.v7.widget.RecyclerView;
25import android.util.Log;
26import android.view.animation.AlphaAnimation;
27import android.view.animation.Animation;
28import android.view.animation.AnimationSet;
29import android.view.animation.ScaleAnimation;
30import android.view.Gravity;
31import android.view.KeyEvent;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.view.ViewGroup;
35import android.view.WindowManager;
36import android.widget.SeekBar;
37import android.widget.TextView;
38
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.List;
42
43public class SettingsDialog extends Activity {
44
45    private static final String TAG = "SettingsDialog";
46    private static final boolean DEBUG = true;
47
48    static final String EXTRA_START_POS = "com.android.tv.quicksettings.START_POS";
49    static final String EXTRA_SETTINGS = "com.android.tv.quicksettings.SETTINGS";
50    static final String
51            RESULT_EXTRA_NEW_SETTINGS_VALUES = "com.android.tv.quicksettings.NEW_SETTINGS_VALUES";
52    private static final int SETTING_INT_VALUE_MIN = 0;
53    private static final int SETTING_INT_VALUE_STEP = 10;
54
55    private VerticalGridView mPanelList;
56    private SeekBar mSeekBar;
57    private TextView mSettingValue;
58    private DialogAdapter mAdapter;
59    private SettingSelectedListener mSettingSelectedListener = new SettingSelectedListener();
60    private Setting mFocusedSetting;
61    private ArrayList<Setting> mSettings;
62
63    @Override
64    public void onCreate(Bundle savedInstanceState) {
65        super.onCreate(savedInstanceState);
66
67        WindowManager.LayoutParams lp = getWindow().getAttributes();
68        lp.height = WindowManager.LayoutParams.MATCH_PARENT;
69        lp.gravity = Gravity.BOTTOM | Gravity.CENTER;
70        lp.y = getResources().getDimensionPixelSize(R.dimen.panel_y_offset);
71        getWindow().setAttributes(lp);
72
73        setContentView(R.layout.main_quicksettings);
74
75        Intent intent = getIntent();
76        int startPos = intent.getIntExtra(EXTRA_START_POS, -1);
77        if (DEBUG)
78            Log.d(TAG, "startPos=" + startPos);
79
80        mPanelList = (VerticalGridView) findViewById(R.id.main_panel_list);
81        mPanelList.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE);
82        mPanelList.setOnChildSelectedListener(mSettingSelectedListener);
83
84        mSettings = getIntent().getParcelableArrayListExtra(EXTRA_SETTINGS);
85        int pivotX = getResources().getDimensionPixelSize(
86                R.dimen.main_panel_text_width_minus_padding);
87        int pivotY = getResources().getDimensionPixelSize(R.dimen.main_panel_text_height_half);
88
89        mAdapter = new DialogAdapter(mSettings, pivotX, pivotY, new SettingClickedListener() {
90            @Override
91            public void onSettingClicked(Setting s) {
92                if (s.getType() != Setting.TYPE_UNKNOWN) {
93                    setResult(RESULT_OK, new Intent().putExtra(RESULT_EXTRA_NEW_SETTINGS_VALUES,
94                            mSettings));
95                    finish();
96                } else {
97                    new AlertDialog.Builder(SettingsDialog.this).setPositiveButton(
98                            android.R.string.ok, new DialogInterface.OnClickListener() {
99                                @Override
100                                public void onClick(DialogInterface dialog, int id) {
101                                    // User clicked OK button
102                                    String[] presetSettingChoices = getResources().getStringArray(
103                                            R.array.setting_preset_choices);
104                                    mSettings.get(QuickSettings.PRESET_SETTING_INDEX).setValue(
105                                            presetSettingChoices[getResources().getInteger(
106                                                    R.integer.standard_setting_index)]);
107                                    int[] newSettingValues = getResources().getIntArray(
108                                            R.array.standard_setting_values);
109                                    for (int i = 0; i < newSettingValues.length; i++) {
110                                        mSettings.get(i + QuickSettings.INTEGER_SETTING_START_INDEX)
111                                                .setValue(
112                                                        newSettingValues[i]);
113                                    }
114                                }
115                            }).setNegativeButton(android.R.string.cancel,
116                            new DialogInterface.OnClickListener() {
117                                @Override
118                                public void onClick(DialogInterface dialog, int id) {
119                                    // User cancelled the dialog - do nothing
120                                }
121                            }).setTitle(R.string.reset_dialog_message).create().show();
122                }
123            }
124        });
125
126        mPanelList.setAdapter(mAdapter);
127        mPanelList.setSelectedPosition(startPos);
128        mPanelList.requestFocus();
129
130        mSeekBar = (SeekBar) findViewById(R.id.main_slider);
131
132        mSettingValue = (TextView) findViewById(R.id.setting_value);
133    }
134
135    private class SettingSelectedListener implements OnChildSelectedListener {
136        private static final float ALPHA_UNSELECTED = 0.3f;
137        private static final float ALPHA_SELECTED = 1.0f;
138        private static final float SCALE_UNSELECTED = 1.0f;
139        private static final float SCALE_SELECTED = 1.3f;
140
141        @Override
142        public void onChildSelected(ViewGroup parent, View view, int position, long id) {
143            mFocusedSetting = mSettings.get(position);
144            switch (mFocusedSetting.getType()) {
145                case Setting.TYPE_STRING:
146                    mSettingValue.setVisibility(View.VISIBLE);
147                    mSettingValue.setText(mFocusedSetting.getStringValue());
148                    mSeekBar.setVisibility(View.GONE);
149                    break;
150                case Setting.TYPE_INT:
151                    mSettingValue.setVisibility(View.VISIBLE);
152                    mSettingValue.setText(Integer.toString(mFocusedSetting.getIntValue()));
153                    mSeekBar.setMax(mFocusedSetting.getMaxValue());
154                    mSeekBar.setProgress(mFocusedSetting.getIntValue());
155                    mSeekBar.setVisibility(View.VISIBLE);
156                    break;
157                default:
158                    mSettingValue.setVisibility(View.GONE);
159                    mSeekBar.setVisibility(View.GONE);
160                    break;
161            }
162        }
163    }
164
165    @Override
166    public boolean onKeyUp(int keyCode, KeyEvent event) {
167        if (mFocusedSetting == null) {
168            return super.onKeyUp(keyCode, event);
169        }
170        switch (mFocusedSetting.getType()) {
171            case Setting.TYPE_INT:
172                return integerSettingHandleKeyCode(keyCode, event);
173            case Setting.TYPE_STRING:
174                return stringSettingHandleKeyCode(keyCode, event);
175            default:
176                return super.onKeyUp(keyCode, event);
177        }
178    }
179
180    private boolean integerSettingHandleKeyCode(int keyCode, KeyEvent event) {
181        switch (keyCode) {
182            case KeyEvent.KEYCODE_DPAD_RIGHT:
183                setFocusedSettingToValue(Math.min(
184                        mFocusedSetting.getIntValue() + SETTING_INT_VALUE_STEP,
185                        mFocusedSetting.getMaxValue()));
186                return true;
187            case KeyEvent.KEYCODE_DPAD_LEFT:
188                setFocusedSettingToValue(Math.max(
189                        mFocusedSetting.getIntValue() - SETTING_INT_VALUE_STEP,
190                        SETTING_INT_VALUE_MIN));
191                return true;
192            default:
193                return super.onKeyUp(keyCode, event);
194        }
195    }
196
197    private void setFocusedSettingToValue(int value) {
198        mFocusedSetting.setValue(value);
199        mSeekBar.setProgress(mFocusedSetting.getIntValue());
200        mSettingValue.setText(Integer.toString(mFocusedSetting.getIntValue()));
201        String[] presetSettingChoices = getResources().getStringArray(
202                R.array.setting_preset_choices);
203        mSettings.get(QuickSettings.PRESET_SETTING_INDEX).setValue(
204                presetSettingChoices[getResources().getInteger(R.integer.custom_setting_index)]);
205    }
206
207    private boolean stringSettingHandleKeyCode(int keyCode, KeyEvent event) {
208        if (!mFocusedSetting.getTitle().equals(getString(R.string.setting_preset_name))) {
209            return super.onKeyUp(keyCode, event);
210        }
211
212        String[] presetSettingChoices = getResources().getStringArray(
213                R.array.setting_preset_choices);
214
215        int currentIndex = Arrays.asList(presetSettingChoices).indexOf(
216                mFocusedSetting.getStringValue());
217        switch (keyCode) {
218            case KeyEvent.KEYCODE_DPAD_RIGHT:
219                currentIndex++;
220                break;
221            case KeyEvent.KEYCODE_DPAD_LEFT:
222                currentIndex--;
223                break;
224            default:
225                return super.onKeyUp(keyCode, event);
226        }
227        int newIndex = (currentIndex + presetSettingChoices.length) % presetSettingChoices.length;
228        mFocusedSetting.setValue(presetSettingChoices[newIndex]);
229        mSettingValue.setText(mFocusedSetting.getStringValue());
230        int[] newSettingValues = null;
231        if (newIndex == getResources().getInteger(R.integer.standard_setting_index)) {
232            newSettingValues = getResources().getIntArray(R.array.standard_setting_values);
233        } else if (newIndex == getResources().getInteger(R.integer.cinema_setting_index)) {
234            newSettingValues = getResources().getIntArray(R.array.cinema_setting_values);
235        } else if (newIndex == getResources().getInteger(R.integer.vivid_setting_index)) {
236            newSettingValues = getResources().getIntArray(R.array.vivid_setting_values);
237        } else if (newIndex == getResources().getInteger(R.integer.game_setting_index)) {
238            newSettingValues = getResources().getIntArray(R.array.game_setting_values);
239        }
240        if (newSettingValues != null) {
241            for (int i = 0; i < newSettingValues.length; i++) {
242                mSettings.get(i + QuickSettings.INTEGER_SETTING_START_INDEX).setValue(
243                        newSettingValues[i]);
244            }
245        }
246        return true;
247    }
248}
249