QSCustomizer.java revision 94a1bf6a18132e83a424cd41354094c3780f2868
1/*
2 * Copyright (C) 2015 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 */
16package com.android.systemui.qs.customize;
17
18import android.animation.Animator;
19import android.content.ClipData;
20import android.content.Context;
21import android.util.AttributeSet;
22import android.util.TypedValue;
23import android.view.*;
24import android.view.View.OnClickListener;
25import android.widget.LinearLayout;
26import android.widget.Toolbar;
27import android.widget.Toolbar.OnMenuItemClickListener;
28import com.android.systemui.R;
29import com.android.systemui.SystemUIApplication;
30import com.android.systemui.qs.QSDetailClipper;
31import com.android.systemui.qs.QSTile.Host.Callback;
32import com.android.systemui.qs.customize.DropButton.OnDropListener;
33import com.android.systemui.statusbar.phone.PhoneStatusBar;
34import com.android.systemui.statusbar.phone.QSTileHost;
35import com.android.systemui.statusbar.phone.SystemUIDialog;
36import com.android.systemui.tuner.QSPagingSwitch;
37
38import java.util.ArrayList;
39
40/**
41 * Allows full-screen customization of QS, through show() and hide().
42 *
43 * This adds itself to the status bar window, so it can appear on top of quick settings and
44 * *someday* do fancy animations to get into/out of it.
45 */
46public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener, Callback,
47        OnDropListener, OnClickListener, Animator.AnimatorListener {
48
49    private static final int MENU_SAVE = Menu.FIRST;
50    private static final int MENU_RESET = Menu.FIRST + 1;
51    private final QSDetailClipper mClipper;
52
53    private PhoneStatusBar mPhoneStatusBar;
54
55    private Toolbar mToolbar;
56    private ViewGroup mDragButtons;
57    private CustomQSPanel mQsPanel;
58
59    private boolean isShown;
60    private CustomQSTileHost mHost;
61    private DropButton mInfoButton;
62    private DropButton mRemoveButton;
63    private FloatingActionButton mFab;
64
65    public QSCustomizer(Context context, AttributeSet attrs) {
66        super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
67        mPhoneStatusBar = ((SystemUIApplication) mContext.getApplicationContext())
68                .getComponent(PhoneStatusBar.class);
69        mClipper = new QSDetailClipper(this);
70    }
71
72    public void setHost(QSTileHost host) {
73        mHost = new CustomQSTileHost(mContext, host);
74        mHost.setCallback(this);
75        mQsPanel.setTiles(mHost.getTiles());
76        mQsPanel.setHost(mHost);
77        mHost.setSavedTiles();
78    }
79
80    @Override
81    protected void onFinishInflate() {
82        super.onFinishInflate();
83        mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
84        TypedValue value = new TypedValue();
85        mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
86        mToolbar.setNavigationIcon(
87                getResources().getDrawable(R.drawable.ic_close_white, mContext.getTheme()));
88        mToolbar.setNavigationOnClickListener(new OnClickListener() {
89            @Override
90            public void onClick(View v) {
91                hide(0, 0);
92            }
93        });
94        mToolbar.setOnMenuItemClickListener(this);
95        mToolbar.getMenu().add(Menu.NONE, MENU_SAVE, 0, mContext.getString(R.string.save))
96                .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
97        mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
98                mContext.getString(com.android.internal.R.string.reset));
99
100        mQsPanel = (CustomQSPanel) findViewById(R.id.quick_settings_panel);
101
102        mDragButtons = (ViewGroup) findViewById(R.id.drag_buttons);
103        setDragging(false);
104
105        mInfoButton = (DropButton) findViewById(R.id.info_button);
106        mInfoButton.setOnDropListener(this);
107        mRemoveButton = (DropButton) findViewById(R.id.remove_button);
108        mRemoveButton.setOnDropListener(this);
109
110        mFab = (FloatingActionButton) findViewById(R.id.fab);
111        mFab.setImageResource(R.drawable.ic_add);
112        mFab.setOnClickListener(this);
113    }
114
115    public void show(int x, int y) {
116        isShown = true;
117        mHost.setSavedTiles();
118        mPhoneStatusBar.getStatusBarWindow().addView(this);
119        mQsPanel.setListening(true);
120        mClipper.animateCircularClip(x, y, true, this);
121    }
122
123    public void hide(int x, int y) {
124        isShown = false;
125        mQsPanel.setListening(false);
126        mClipper.animateCircularClip(x, y, false, this);
127    }
128
129    public boolean isCustomizing() {
130        return isShown;
131    }
132
133    private void reset() {
134        ArrayList<String> tiles = new ArrayList<>();
135        for (String tile : QSPagingSwitch.QS_PAGE_TILES.split(",")) {
136            tiles.add(tile);
137        }
138        mHost.setTiles(tiles);
139    }
140
141    private void setDragging(boolean dragging) {
142        mToolbar.setVisibility(!dragging ? View.VISIBLE : View.INVISIBLE);
143    }
144
145    private void save() {
146        mHost.saveCurrentTiles();
147        // TODO: At save button.
148        hide(0, 0);
149    }
150
151    @Override
152    public boolean onMenuItemClick(MenuItem item) {
153        switch (item.getItemId()) {
154            case MENU_SAVE:
155                save();
156                break;
157            case MENU_RESET:
158                reset();
159                break;
160        }
161        return true;
162    }
163
164    @Override
165    public void onTilesChanged() {
166        mQsPanel.setTiles(mHost.getTiles());
167    }
168
169    public boolean onDragEvent(DragEvent event) {
170        switch (event.getAction()) {
171            case DragEvent.ACTION_DRAG_STARTED:
172                setDragging(true);
173                break;
174            case DragEvent.ACTION_DRAG_ENDED:
175                setDragging(false);
176                break;
177        }
178        return true;
179    }
180
181    public void onDrop(View v, ClipData data) {
182        if (v == mRemoveButton) {
183            mHost.remove(mQsPanel.getSpec(data));
184        } else if (v == mInfoButton) {
185            mHost.unstashTiles();
186            SystemUIDialog dialog = new SystemUIDialog(mContext);
187            dialog.setTitle(mQsPanel.getSpec(data));
188            dialog.setPositiveButton(R.string.ok, null);
189            dialog.show();
190        }
191    }
192
193    @Override
194    public void onClick(View v) {
195        if (mFab == v) {
196            SystemUIDialog dialog = new SystemUIDialog(mContext);
197            dialog.show();
198        }
199    }
200
201    @Override
202    public void onAnimationEnd(Animator animation) {
203        if (!isShown) {
204            mPhoneStatusBar.getStatusBarWindow().removeView(this);
205        }
206    }
207
208    @Override
209    public void onAnimationCancel(Animator animation) {
210        if (!isShown) {
211            mPhoneStatusBar.getStatusBarWindow().removeView(this);
212        }
213    }
214
215    @Override
216    public void onAnimationStart(Animator animation) {
217        // Don't care.
218    }
219
220    @Override
221    public void onAnimationRepeat(Animator animation) {
222        // Don't care.
223    }
224}