OSDN Git Service

Change light status bar tint color to spec
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / statusbar / SignalClusterView.java
1 /*
2  * Copyright (C) 2011 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.statusbar;
18
19 import android.content.Context;
20 import android.content.res.ColorStateList;
21 import android.graphics.Color;
22 import android.graphics.PorterDuff;
23 import android.telephony.SubscriptionInfo;
24 import android.util.AttributeSet;
25 import android.util.Log;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.view.accessibility.AccessibilityEvent;
30 import android.widget.ImageView;
31 import android.widget.LinearLayout;
32
33 import com.android.systemui.R;
34 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
35 import com.android.systemui.statusbar.policy.SecurityController;
36
37 import java.util.ArrayList;
38 import java.util.List;
39
40 // Intimately tied to the design of res/layout/signal_cluster_view.xml
41 public class SignalClusterView
42         extends LinearLayout
43         implements NetworkControllerImpl.SignalCluster,
44         SecurityController.SecurityControllerCallback {
45
46     static final String TAG = "SignalClusterView";
47     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
48
49     NetworkControllerImpl mNC;
50     SecurityController mSC;
51
52     private boolean mNoSimsVisible = false;
53     private boolean mVpnVisible = false;
54     private boolean mWifiVisible = false;
55     private int mWifiStrengthId = 0;
56     private boolean mIsAirplaneMode = false;
57     private int mAirplaneIconId = 0;
58     private int mAirplaneContentDescription;
59     private String mWifiDescription;
60     private ArrayList<PhoneState> mPhoneStates = new ArrayList<PhoneState>();
61     private int mIconTint = Color.WHITE;
62     private float mDarkIntensity;
63
64     ViewGroup mWifiGroup;
65     ImageView mVpn, mWifi, mAirplane, mNoSims, mWifiDark, mNoSimsDark;
66     View mWifiAirplaneSpacer;
67     View mWifiSignalSpacer;
68     LinearLayout mMobileSignalGroup;
69
70     private int mWideTypeIconStartPadding;
71     private int mSecondaryTelephonyPadding;
72     private int mEndPadding;
73     private int mEndPaddingNothingVisible;
74
75     public SignalClusterView(Context context) {
76         this(context, null);
77     }
78
79     public SignalClusterView(Context context, AttributeSet attrs) {
80         this(context, attrs, 0);
81     }
82
83     public SignalClusterView(Context context, AttributeSet attrs, int defStyle) {
84         super(context, attrs, defStyle);
85     }
86
87     public void setNetworkController(NetworkControllerImpl nc) {
88         if (DEBUG) Log.d(TAG, "NetworkController=" + nc);
89         mNC = nc;
90     }
91
92     public void setSecurityController(SecurityController sc) {
93         if (DEBUG) Log.d(TAG, "SecurityController=" + sc);
94         mSC = sc;
95         mSC.addCallback(this);
96         mVpnVisible = mSC.isVpnEnabled();
97     }
98
99     @Override
100     protected void onFinishInflate() {
101         super.onFinishInflate();
102         mWideTypeIconStartPadding = getContext().getResources().getDimensionPixelSize(
103                 R.dimen.wide_type_icon_start_padding);
104         mSecondaryTelephonyPadding = getContext().getResources().getDimensionPixelSize(
105                 R.dimen.secondary_telephony_padding);
106         mEndPadding = getContext().getResources().getDimensionPixelSize(
107                 R.dimen.signal_cluster_battery_padding);
108         mEndPaddingNothingVisible = getContext().getResources().getDimensionPixelSize(
109                 R.dimen.no_signal_cluster_battery_padding);
110     }
111
112     @Override
113     protected void onAttachedToWindow() {
114         super.onAttachedToWindow();
115
116         mVpn            = (ImageView) findViewById(R.id.vpn);
117         mWifiGroup      = (ViewGroup) findViewById(R.id.wifi_combo);
118         mWifi           = (ImageView) findViewById(R.id.wifi_signal);
119         mWifiDark       = (ImageView) findViewById(R.id.wifi_signal_dark);
120         mAirplane       = (ImageView) findViewById(R.id.airplane);
121         mNoSims         = (ImageView) findViewById(R.id.no_sims);
122         mNoSimsDark     = (ImageView) findViewById(R.id.no_sims_dark);
123         mWifiAirplaneSpacer =         findViewById(R.id.wifi_airplane_spacer);
124         mWifiSignalSpacer =           findViewById(R.id.wifi_signal_spacer);
125         mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group);
126         for (PhoneState state : mPhoneStates) {
127             mMobileSignalGroup.addView(state.mMobileGroup);
128         }
129
130         apply();
131         applyIconTint();
132     }
133
134     @Override
135     protected void onDetachedFromWindow() {
136         mVpn            = null;
137         mWifiGroup      = null;
138         mWifi           = null;
139         mAirplane       = null;
140         mMobileSignalGroup.removeAllViews();
141         mMobileSignalGroup = null;
142
143         super.onDetachedFromWindow();
144     }
145
146     // From SecurityController.
147     @Override
148     public void onStateChanged() {
149         post(new Runnable() {
150             @Override
151             public void run() {
152                 mVpnVisible = mSC.isVpnEnabled();
153                 apply();
154             }
155         });
156     }
157
158     @Override
159     public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) {
160         mWifiVisible = visible;
161         mWifiStrengthId = strengthIcon;
162         mWifiDescription = contentDescription;
163
164         apply();
165     }
166
167     @Override
168     public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
169             String contentDescription, String typeContentDescription, boolean isTypeIconWide,
170             int subId) {
171         PhoneState state = getOrInflateState(subId);
172         state.mMobileVisible = visible;
173         state.mMobileStrengthId = strengthIcon;
174         state.mMobileTypeId = typeIcon;
175         state.mMobileDescription = contentDescription;
176         state.mMobileTypeDescription = typeContentDescription;
177         state.mIsMobileTypeIconWide = isTypeIconWide;
178
179         apply();
180     }
181
182     @Override
183     public void setNoSims(boolean show) {
184         mNoSimsVisible = show;
185     }
186
187     @Override
188     public void setSubs(List<SubscriptionInfo> subs) {
189         // Clear out all old subIds.
190         mPhoneStates.clear();
191         if (mMobileSignalGroup != null) {
192             mMobileSignalGroup.removeAllViews();
193         }
194         final int n = subs.size();
195         for (int i = 0; i < n; i++) {
196             inflatePhoneState(subs.get(i).getSubscriptionId());
197         }
198         if (isAttachedToWindow()) {
199             applyIconTint();
200         }
201     }
202
203     private PhoneState getOrInflateState(int subId) {
204         for (PhoneState state : mPhoneStates) {
205             if (state.mSubId == subId) {
206                 return state;
207             }
208         }
209         return inflatePhoneState(subId);
210     }
211
212     private PhoneState inflatePhoneState(int subId) {
213         PhoneState state = new PhoneState(subId, mContext);
214         if (mMobileSignalGroup != null) {
215             mMobileSignalGroup.addView(state.mMobileGroup);
216         }
217         mPhoneStates.add(state);
218         return state;
219     }
220
221     @Override
222     public void setIsAirplaneMode(boolean is, int airplaneIconId, int contentDescription) {
223         mIsAirplaneMode = is;
224         mAirplaneIconId = airplaneIconId;
225         mAirplaneContentDescription = contentDescription;
226
227         apply();
228     }
229
230     @Override
231     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
232         // Standard group layout onPopulateAccessibilityEvent() implementations
233         // ignore content description, so populate manually
234         if (mWifiVisible && mWifiGroup != null && mWifiGroup.getContentDescription() != null)
235             event.getText().add(mWifiGroup.getContentDescription());
236         for (PhoneState state : mPhoneStates) {
237             state.populateAccessibilityEvent(event);
238         }
239         return super.dispatchPopulateAccessibilityEventInternal(event);
240     }
241
242     @Override
243     public void onRtlPropertiesChanged(int layoutDirection) {
244         super.onRtlPropertiesChanged(layoutDirection);
245
246         if (mWifi != null) {
247             mWifi.setImageDrawable(null);
248         }
249
250         for (PhoneState state : mPhoneStates) {
251             if (state.mMobile != null) {
252                 state.mMobile.setImageDrawable(null);
253             }
254             if (state.mMobileType != null) {
255                 state.mMobileType.setImageDrawable(null);
256             }
257         }
258
259         if(mAirplane != null) {
260             mAirplane.setImageDrawable(null);
261         }
262
263         apply();
264     }
265
266     @Override
267     public boolean hasOverlappingRendering() {
268         return false;
269     }
270
271     // Run after each indicator change.
272     private void apply() {
273         if (mWifiGroup == null) return;
274
275         mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE);
276         if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
277         if (mWifiVisible) {
278             mWifi.setImageResource(mWifiStrengthId);
279             mWifiDark.setImageResource(mWifiStrengthId);
280             mWifiGroup.setContentDescription(mWifiDescription);
281             mWifiGroup.setVisibility(View.VISIBLE);
282         } else {
283             mWifiGroup.setVisibility(View.GONE);
284         }
285
286         if (DEBUG) Log.d(TAG,
287                 String.format("wifi: %s sig=%d",
288                     (mWifiVisible ? "VISIBLE" : "GONE"),
289                     mWifiStrengthId));
290
291         boolean anyMobileVisible = false;
292         int firstMobileTypeId = 0;
293         for (PhoneState state : mPhoneStates) {
294             if (state.apply(anyMobileVisible)) {
295                 if (!anyMobileVisible) {
296                     firstMobileTypeId = state.mMobileTypeId;
297                     anyMobileVisible = true;
298                 }
299             }
300         }
301
302         if (mIsAirplaneMode) {
303             mAirplane.setImageResource(mAirplaneIconId);
304             mAirplane.setContentDescription(mAirplaneContentDescription != 0 ?
305                     mContext.getString(mAirplaneContentDescription) : null);
306             mAirplane.setVisibility(View.VISIBLE);
307         } else {
308             mAirplane.setVisibility(View.GONE);
309         }
310
311         if (mIsAirplaneMode && mWifiVisible) {
312             mWifiAirplaneSpacer.setVisibility(View.VISIBLE);
313         } else {
314             mWifiAirplaneSpacer.setVisibility(View.GONE);
315         }
316
317         if (((anyMobileVisible && firstMobileTypeId != 0) || mNoSimsVisible) && mWifiVisible) {
318             mWifiSignalSpacer.setVisibility(View.VISIBLE);
319         } else {
320             mWifiSignalSpacer.setVisibility(View.GONE);
321         }
322
323         mNoSims.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
324         mNoSimsDark.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
325
326         boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
327                 || anyMobileVisible || mVpnVisible;
328         setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
329     }
330
331     public void setIconTint(int tint, float darkIntensity) {
332         boolean changed = tint != mIconTint || darkIntensity != mDarkIntensity;
333         mIconTint = tint;
334         mDarkIntensity = darkIntensity;
335         if (changed && isAttachedToWindow()) {
336             applyIconTint();
337         }
338     }
339
340     private void applyIconTint() {
341         setTint(mVpn, mIconTint);
342         setTint(mAirplane, mIconTint);
343         applyDarkIntensity(mDarkIntensity, mNoSims, mNoSimsDark);
344         applyDarkIntensity(mDarkIntensity, mWifi, mWifiDark);
345         for (int i = 0; i < mPhoneStates.size(); i++) {
346             mPhoneStates.get(i).setIconTint(mIconTint, mDarkIntensity);
347         }
348     }
349
350     private void applyDarkIntensity(float darkIntensity, View lightIcon, View darkIcon) {
351         lightIcon.setAlpha(1 - darkIntensity);
352         darkIcon.setAlpha(darkIntensity);
353     }
354
355     private void setTint(ImageView v, int tint) {
356         v.setImageTintMode(PorterDuff.Mode.SRC_ATOP);
357         v.setImageTintList(ColorStateList.valueOf(tint));
358     }
359
360     private class PhoneState {
361         private final int mSubId;
362         private boolean mMobileVisible = false;
363         private int mMobileStrengthId = 0, mMobileTypeId = 0;
364         private boolean mIsMobileTypeIconWide;
365         private String mMobileDescription, mMobileTypeDescription;
366
367         private ViewGroup mMobileGroup;
368         private ImageView mMobile, mMobileDark, mMobileType;
369
370         public PhoneState(int subId, Context context) {
371             ViewGroup root = (ViewGroup) LayoutInflater.from(context)
372                     .inflate(R.layout.mobile_signal_group, null);
373             setViews(root);
374             mSubId = subId;
375         }
376
377         public void setViews(ViewGroup root) {
378             mMobileGroup    = root;
379             mMobile         = (ImageView) root.findViewById(R.id.mobile_signal);
380             mMobileDark     = (ImageView) root.findViewById(R.id.mobile_signal_dark);
381             mMobileType     = (ImageView) root.findViewById(R.id.mobile_type);
382         }
383
384         public boolean apply(boolean isSecondaryIcon) {
385             if (mMobileVisible && !mIsAirplaneMode) {
386                 mMobile.setImageResource(mMobileStrengthId);
387                 mMobileDark.setImageResource(mMobileStrengthId);
388                 mMobileType.setImageResource(mMobileTypeId);
389                 mMobileGroup.setContentDescription(mMobileTypeDescription
390                         + " " + mMobileDescription);
391                 mMobileGroup.setVisibility(View.VISIBLE);
392             } else {
393                 mMobileGroup.setVisibility(View.GONE);
394             }
395
396             // When this isn't next to wifi, give it some extra padding between the signals.
397             mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0,
398                     0, 0, 0);
399             mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0,
400                     0, 0, 0);
401             mMobileDark.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0,
402                     0, 0, 0);
403
404             if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
405                         (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId));
406
407             mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE);
408
409             return mMobileVisible;
410         }
411
412         public void populateAccessibilityEvent(AccessibilityEvent event) {
413             if (mMobileVisible && mMobileGroup != null
414                     && mMobileGroup.getContentDescription() != null) {
415                 event.getText().add(mMobileGroup.getContentDescription());
416             }
417         }
418
419         public void setIconTint(int tint, float darkIntensity) {
420             applyDarkIntensity(darkIntensity, mMobile, mMobileDark);
421             setTint(mMobileType, tint);
422         }
423     }
424 }
425