blob: 4a7d67f9fe3857bec562198badd157c810253d01 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.qs.customize;
import android.animation.Animator;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toolbar;
import android.widget.Toolbar.OnMenuItemClickListener;
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTile.Host.Callback;
import com.android.systemui.qs.customize.DropButton.OnDropListener;
import com.android.systemui.qs.customize.TileAdapter.TileSelectedListener;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.tuner.QSPagingSwitch;
import java.util.ArrayList;
/**
* Allows full-screen customization of QS, through show() and hide().
*
* This adds itself to the status bar window, so it can appear on top of quick settings and
* *someday* do fancy animations to get into/out of it.
*/
public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener, Callback,
OnDropListener, OnClickListener, Animator.AnimatorListener, TileSelectedListener,
OnCancelListener, OnDismissListener {
private static final int MENU_SAVE = Menu.FIRST;
private static final int MENU_RESET = Menu.FIRST + 1;
private final QSDetailClipper mClipper;
private PhoneStatusBar mPhoneStatusBar;
private Toolbar mToolbar;
private ViewGroup mDragButtons;
private CustomQSPanel mQsPanel;
private boolean isShown;
private DropButton mInfoButton;
private DropButton mRemoveButton;
private FloatingActionButton mFab;
private SystemUIDialog mDialog;
private QSTileHost mHost;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
mClipper = new QSDetailClipper(this);
}
public void setHost(QSTileHost host) {
mHost = host;
mHost.addCallback(this);
mPhoneStatusBar = host.getPhoneStatusBar();
mQsPanel.setTiles(mHost.getTiles());
mQsPanel.setHost(mHost);
mQsPanel.setSavedTiles();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
TypedValue value = new TypedValue();
mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
mToolbar.setNavigationIcon(
getResources().getDrawable(R.drawable.ic_close_white, mContext.getTheme()));
mToolbar.setNavigationOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hide(0, 0);
}
});
mToolbar.setOnMenuItemClickListener(this);
mToolbar.getMenu().add(Menu.NONE, MENU_SAVE, 0, mContext.getString(R.string.save))
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
mContext.getString(com.android.internal.R.string.reset));
mQsPanel = (CustomQSPanel) findViewById(R.id.quick_settings_panel);
mDragButtons = (ViewGroup) findViewById(R.id.drag_buttons);
setDragging(false);
mInfoButton = (DropButton) findViewById(R.id.info_button);
mInfoButton.setOnDropListener(this);
mRemoveButton = (DropButton) findViewById(R.id.remove_button);
mRemoveButton.setOnDropListener(this);
mFab = (FloatingActionButton) findViewById(R.id.fab);
mFab.setImageResource(R.drawable.ic_add);
mFab.setOnClickListener(this);
}
public void show(int x, int y) {
isShown = true;
mQsPanel.setSavedTiles();
mPhoneStatusBar.getStatusBarWindow().addView(this);
mQsPanel.setListening(true);
mClipper.animateCircularClip(x, y, true, this);
}
public void hide(int x, int y) {
isShown = false;
mQsPanel.setListening(false);
mClipper.animateCircularClip(x, y, false, this);
}
public boolean isCustomizing() {
return isShown;
}
private void reset() {
ArrayList<String> tiles = new ArrayList<>();
for (String tile : QSPagingSwitch.QS_PAGE_TILES.split(",")) {
tiles.add(tile);
}
mQsPanel.setTiles(tiles);
}
private void setDragging(boolean dragging) {
mToolbar.setVisibility(!dragging ? View.VISIBLE : View.INVISIBLE);
}
private void save() {
Log.d("CustomQSPanel", "Save!");
mQsPanel.saveCurrentTiles();
// TODO: At save button.
hide(0, 0);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case MENU_SAVE:
Log.d("CustomQSPanel", "Save...");
save();
break;
case MENU_RESET:
reset();
break;
}
return true;
}
@Override
public void onTileSelected(String spec) {
if (mDialog != null) {
mQsPanel.addTile(spec);
mDialog.dismiss();
}
}
@Override
public void onTilesChanged() {
mQsPanel.setTiles(mHost.getTiles());
}
public boolean onDragEvent(DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
setDragging(true);
break;
case DragEvent.ACTION_DRAG_ENDED:
setDragging(false);
break;
}
return true;
}
public void onDrop(View v, ClipData data) {
if (v == mRemoveButton) {
mQsPanel.remove(mQsPanel.getSpec(data));
} else if (v == mInfoButton) {
mQsPanel.unstashTiles();
SystemUIDialog dialog = new SystemUIDialog(mContext);
dialog.setTitle(mQsPanel.getSpec(data));
dialog.setPositiveButton(R.string.ok, null);
dialog.show();
}
}
@Override
public void onClick(View v) {
if (mFab == v) {
mDialog = new SystemUIDialog(mContext,
android.R.style.Theme_Material_Dialog);
View view = LayoutInflater.from(mContext).inflate(R.layout.qs_add_tiles_list, null);
ListView listView = (ListView) view.findViewById(android.R.id.list);
TileAdapter adapter = new TileAdapter(mContext, mQsPanel.getTiles(), mHost);
adapter.setListener(this);
listView.setDivider(null);
listView.setDividerHeight(0);
listView.setAdapter(adapter);
listView.setEmptyView(view.findViewById(R.id.empty_text));
mDialog.setView(view);
mDialog.setOnDismissListener(this);
mDialog.setOnCancelListener(this);
mDialog.show();
// Too lazy to figure out what this will be now, but it should probably be something
// besides just a dialog.
// For now, just make it big.
WindowManager.LayoutParams params = mDialog.getWindow().getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
mDialog.getWindow().setAttributes(params);
}
}
@Override
public void onDismiss(DialogInterface dialog) {
mDialog = null;
}
@Override
public void onCancel(DialogInterface dialog) {
mDialog = null;
}
@Override
public void onAnimationEnd(Animator animation) {
if (!isShown) {
mPhoneStatusBar.getStatusBarWindow().removeView(this);
}
}
@Override
public void onAnimationCancel(Animator animation) {
if (!isShown) {
mPhoneStatusBar.getStatusBarWindow().removeView(this);
}
}
@Override
public void onAnimationStart(Animator animation) {
// Don't care.
}
@Override
public void onAnimationRepeat(Animator animation) {
// Don't care.
}
}