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 
17 package com.android.systemui.qs;
18 
19 import android.content.Context;
20 import android.content.res.Configuration;
21 import android.graphics.drawable.Drawable;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.os.Message;
25 import android.text.TextUtils;
26 import android.util.AttributeSet;
27 import android.util.Log;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.BaseAdapter;
32 import android.widget.FrameLayout;
33 import android.widget.ImageView;
34 import android.widget.TextView;
35 import com.android.systemui.FontSizeUtils;
36 import com.android.systemui.R;
37 
38 /**
39  * Quick settings common detail view with line items.
40  */
41 public class QSDetailItems extends FrameLayout {
42     private static final String TAG = "QSDetailItems";
43     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
44 
45     private final Context mContext;
46     private final H mHandler = new H();
47     private final Adapter mAdapter = new Adapter();
48 
49     private String mTag;
50     private Callback mCallback;
51     private boolean mItemsVisible = true;
52     private AutoSizingList mItemList;
53     private View mEmpty;
54     private TextView mEmptyText;
55     private ImageView mEmptyIcon;
56 
57     private Item[] mItems;
58 
QSDetailItems(Context context, AttributeSet attrs)59     public QSDetailItems(Context context, AttributeSet attrs) {
60         super(context, attrs);
61         mContext = context;
62         mTag = TAG;
63     }
64 
convertOrInflate(Context context, View convert, ViewGroup parent)65     public static QSDetailItems convertOrInflate(Context context, View convert, ViewGroup parent) {
66         if (convert instanceof QSDetailItems) {
67             return (QSDetailItems) convert;
68         }
69         return (QSDetailItems) LayoutInflater.from(context).inflate(R.layout.qs_detail_items,
70                 parent, false);
71     }
72 
73     @Override
onFinishInflate()74     protected void onFinishInflate() {
75         super.onFinishInflate();
76         mItemList = (AutoSizingList) findViewById(android.R.id.list);
77         mItemList.setVisibility(GONE);
78         mItemList.setAdapter(mAdapter);
79         mEmpty = findViewById(android.R.id.empty);
80         mEmpty.setVisibility(GONE);
81         mEmptyText = (TextView) mEmpty.findViewById(android.R.id.title);
82         mEmptyIcon = (ImageView) mEmpty.findViewById(android.R.id.icon);
83     }
84 
85     @Override
onConfigurationChanged(Configuration newConfig)86     protected void onConfigurationChanged(Configuration newConfig) {
87         super.onConfigurationChanged(newConfig);
88         FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
89         int count = mItemList.getChildCount();
90         for (int i = 0; i < count; i++) {
91             View item = mItemList.getChildAt(i);
92             FontSizeUtils.updateFontSize(item, android.R.id.title,
93                     R.dimen.qs_detail_item_primary_text_size);
94             FontSizeUtils.updateFontSize(item, android.R.id.summary,
95                     R.dimen.qs_detail_item_secondary_text_size);
96         }
97     }
98 
setTagSuffix(String suffix)99     public void setTagSuffix(String suffix) {
100         mTag = TAG + "." + suffix;
101     }
102 
setEmptyState(int icon, int text)103     public void setEmptyState(int icon, int text) {
104         mEmptyIcon.setImageResource(icon);
105         mEmptyText.setText(text);
106     }
107 
108     @Override
onAttachedToWindow()109     protected void onAttachedToWindow() {
110         super.onAttachedToWindow();
111         if (DEBUG) Log.d(mTag, "onAttachedToWindow");
112     }
113 
114     @Override
onDetachedFromWindow()115     protected void onDetachedFromWindow() {
116         super.onDetachedFromWindow();
117         if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
118         mCallback = null;
119     }
120 
setCallback(Callback callback)121     public void setCallback(Callback callback) {
122         mHandler.removeMessages(H.SET_CALLBACK);
123         mHandler.obtainMessage(H.SET_CALLBACK, callback).sendToTarget();
124     }
125 
setItems(Item[] items)126     public void setItems(Item[] items) {
127         mHandler.removeMessages(H.SET_ITEMS);
128         mHandler.obtainMessage(H.SET_ITEMS, items).sendToTarget();
129     }
130 
setItemsVisible(boolean visible)131     public void setItemsVisible(boolean visible) {
132         mHandler.removeMessages(H.SET_ITEMS_VISIBLE);
133         mHandler.obtainMessage(H.SET_ITEMS_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
134     }
135 
handleSetCallback(Callback callback)136     private void handleSetCallback(Callback callback) {
137         mCallback = callback;
138     }
139 
handleSetItems(Item[] items)140     private void handleSetItems(Item[] items) {
141         final int itemCount = items != null ? items.length : 0;
142         mEmpty.setVisibility(itemCount == 0 ? VISIBLE : GONE);
143         mItemList.setVisibility(itemCount == 0 ? GONE : VISIBLE);
144         mItems = items;
145         mAdapter.notifyDataSetChanged();
146     }
147 
handleSetItemsVisible(boolean visible)148     private void handleSetItemsVisible(boolean visible) {
149         if (mItemsVisible == visible) return;
150         mItemsVisible = visible;
151         for (int i = 0; i < mItemList.getChildCount(); i++) {
152             mItemList.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
153         }
154     }
155 
156     private class Adapter extends BaseAdapter {
157 
158         @Override
getCount()159         public int getCount() {
160             return mItems != null ? mItems.length : 0;
161         }
162 
163         @Override
getItem(int position)164         public Object getItem(int position) {
165             return mItems[position];
166         }
167 
168         @Override
getItemId(int position)169         public long getItemId(int position) {
170             return 0;
171         }
172 
173         @Override
getView(int position, View view, ViewGroup parent)174         public View getView(int position, View view, ViewGroup parent) {
175             final Item item = mItems[position];
176             if (view == null) {
177                 view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, parent,
178                         false);
179             }
180             view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
181             final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
182             iv.setImageResource(item.icon);
183             iv.getOverlay().clear();
184             if (item.overlay != null) {
185                 item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
186                         item.overlay.getIntrinsicHeight());
187                 iv.getOverlay().add(item.overlay);
188             }
189             final TextView title = (TextView) view.findViewById(android.R.id.title);
190             title.setText(item.line1);
191             final TextView summary = (TextView) view.findViewById(android.R.id.summary);
192             final boolean twoLines = !TextUtils.isEmpty(item.line2);
193             title.setMaxLines(twoLines ? 1 : 2);
194             summary.setVisibility(twoLines ? VISIBLE : GONE);
195             summary.setText(twoLines ? item.line2 : null);
196             view.setOnClickListener(new OnClickListener() {
197                 @Override
198                 public void onClick(View v) {
199                     if (mCallback != null) {
200                         mCallback.onDetailItemClick(item);
201                     }
202                 }
203             });
204             final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
205             disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
206             disconnect.setOnClickListener(new OnClickListener() {
207                 @Override
208                 public void onClick(View v) {
209                     if (mCallback != null) {
210                         mCallback.onDetailItemDisconnect(item);
211                     }
212                 }
213             });
214             return view;
215         }
216     };
217 
218     private class H extends Handler {
219         private static final int SET_ITEMS = 1;
220         private static final int SET_CALLBACK = 2;
221         private static final int SET_ITEMS_VISIBLE = 3;
222 
H()223         public H() {
224             super(Looper.getMainLooper());
225         }
226 
227         @Override
handleMessage(Message msg)228         public void handleMessage(Message msg) {
229             if (msg.what == SET_ITEMS) {
230                 handleSetItems((Item[]) msg.obj);
231             } else if (msg.what == SET_CALLBACK) {
232                 handleSetCallback((QSDetailItems.Callback) msg.obj);
233             } else if (msg.what == SET_ITEMS_VISIBLE) {
234                 handleSetItemsVisible(msg.arg1 != 0);
235             }
236         }
237     }
238 
239     public static class Item {
240         public int icon;
241         public Drawable overlay;
242         public CharSequence line1;
243         public CharSequence line2;
244         public Object tag;
245         public boolean canDisconnect;
246     }
247 
248     public interface Callback {
onDetailItemClick(Item item)249         void onDetailItemClick(Item item);
onDetailItemDisconnect(Item item)250         void onDetailItemDisconnect(Item item);
251     }
252 }
253