blob: 69978378d140d7bbb9de5c1bd7db6583379e5103 [file] [log] [blame]
Joe Onorato0cbda992010-05-02 16:28:15 -07001/*
2 * Copyright (C) 2008 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
Joe Onorato79de0c52010-05-26 17:03:26 -040017package com.android.systemui.statusbar;
Joe Onorato0cbda992010-05-02 16:28:15 -070018
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070019import android.app.Notification;
Joe Onorato0cbda992010-05-02 16:28:15 -070020import android.content.Context;
21import android.content.pm.PackageManager;
22import android.content.res.Resources;
23import android.graphics.drawable.Drawable;
24import android.graphics.Canvas;
Joe Onorato6c01a112010-10-04 17:38:47 -040025import android.graphics.Paint;
26import android.graphics.Rect;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070027import android.text.TextUtils;
Joe Onorato0cbda992010-05-02 16:28:15 -070028import android.util.Slog;
Joe Onoratof9ec03c2010-09-23 15:09:18 -070029import android.util.Log;
Joe Onorato0cbda992010-05-02 16:28:15 -070030import android.view.ViewDebug;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070031import android.view.accessibility.AccessibilityEvent;
Daniel Sandlerabff0322011-09-27 11:19:34 -040032import android.widget.ImageView;
Joe Onorato0cbda992010-05-02 16:28:15 -070033
Daniel Sandlerebce0112011-06-16 16:44:51 -040034import java.text.NumberFormat;
35
Joe Onorato0cbda992010-05-02 16:28:15 -070036import com.android.internal.statusbar.StatusBarIcon;
37
Joe Onorato6c01a112010-10-04 17:38:47 -040038import com.android.systemui.R;
39
Joe Onorato0cbda992010-05-02 16:28:15 -070040public class StatusBarIconView extends AnimatedImageView {
41 private static final String TAG = "StatusBarIconView";
42
43 private StatusBarIcon mIcon;
44 @ViewDebug.ExportedProperty private String mSlot;
Joe Onorato6c01a112010-10-04 17:38:47 -040045 private Drawable mNumberBackground;
46 private Paint mNumberPain;
47 private int mNumberX;
48 private int mNumberY;
49 private String mNumberText;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070050 private Notification mNotification;
Joe Onorato0cbda992010-05-02 16:28:15 -070051
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070052 public StatusBarIconView(Context context, String slot, Notification notification) {
Joe Onorato0cbda992010-05-02 16:28:15 -070053 super(context);
Joe Onorato6c01a112010-10-04 17:38:47 -040054 final Resources res = context.getResources();
Joe Onorato0cbda992010-05-02 16:28:15 -070055 mSlot = slot;
Joe Onorato6c01a112010-10-04 17:38:47 -040056 mNumberPain = new Paint();
57 mNumberPain.setTextAlign(Paint.Align.CENTER);
58 mNumberPain.setColor(res.getColor(R.drawable.notification_number_text_color));
59 mNumberPain.setAntiAlias(true);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070060 mNotification = notification;
61 setContentDescription(notification);
Daniel Sandler26c84b12011-07-27 00:09:40 -040062
Daniel Sandler7579bca2011-08-18 15:47:26 -040063 // We do not resize and scale system icons (on the right), only notification icons (on the
64 // left).
65 if (notification != null) {
66 final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
67 final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
68 final float scale = (float)imageBounds / (float)outerBounds;
69 setScaleX(scale);
70 setScaleY(scale);
71 final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
72 setAlpha(alpha);
73 }
Daniel Sandlerabff0322011-09-27 11:19:34 -040074
75 setScaleType(ImageView.ScaleType.CENTER);
Joe Onorato0cbda992010-05-02 16:28:15 -070076 }
77
78 private static boolean streq(String a, String b) {
Joe Onorato66d7d012010-05-14 10:05:10 -070079 if (a == b) {
80 return true;
81 }
Joe Onorato0cbda992010-05-02 16:28:15 -070082 if (a == null && b != null) {
83 return false;
84 }
85 if (a != null && b == null) {
86 return false;
87 }
88 return a.equals(b);
89 }
90
Joe Onorato005847b2010-06-04 16:08:02 -040091 /**
92 * Returns whether the set succeeded.
93 */
94 public boolean set(StatusBarIcon icon) {
95 final boolean iconEquals = mIcon != null
96 && streq(mIcon.iconPackage, icon.iconPackage)
97 && mIcon.iconId == icon.iconId;
98 final boolean levelEquals = iconEquals
99 && mIcon.iconLevel == icon.iconLevel;
100 final boolean visibilityEquals = mIcon != null
101 && mIcon.visible == icon.visible;
Joe Onorato6c01a112010-10-04 17:38:47 -0400102 final boolean numberEquals = mIcon != null
103 && mIcon.number == icon.number;
104 mIcon = icon.clone();
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700105 setContentDescription(icon.contentDescription);
Joe Onorato005847b2010-06-04 16:08:02 -0400106 if (!iconEquals) {
107 Drawable drawable = getIcon(icon);
108 if (drawable == null) {
Joe Onoratofd52b182010-11-10 18:00:52 -0800109 Slog.w(StatusBar.TAG, "No icon for slot " + mSlot);
Joe Onorato005847b2010-06-04 16:08:02 -0400110 return false;
Joe Onorato871bdb92010-05-24 18:36:53 -0400111 }
Joe Onorato005847b2010-06-04 16:08:02 -0400112 setImageDrawable(drawable);
Joe Onorato0cbda992010-05-02 16:28:15 -0700113 }
Joe Onorato005847b2010-06-04 16:08:02 -0400114 if (!levelEquals) {
115 setImageLevel(icon.iconLevel);
Joe Onorato0cbda992010-05-02 16:28:15 -0700116 }
Daniel Sandler26c84b12011-07-27 00:09:40 -0400117
Joe Onorato6c01a112010-10-04 17:38:47 -0400118 if (!numberEquals) {
Joe Onorato8595a3d2010-11-19 18:12:07 -0800119 if (icon.number > 0 && mContext.getResources().getBoolean(
120 R.bool.config_statusBarShowNumber)) {
Joe Onorato6c01a112010-10-04 17:38:47 -0400121 if (mNumberBackground == null) {
122 mNumberBackground = getContext().getResources().getDrawable(
123 R.drawable.ic_notification_overlay);
124 }
125 placeNumber();
126 } else {
127 mNumberBackground = null;
128 mNumberText = null;
129 }
130 invalidate();
131 }
Joe Onorato005847b2010-06-04 16:08:02 -0400132 if (!visibilityEquals) {
133 setVisibility(icon.visible ? VISIBLE : GONE);
134 }
Joe Onorato005847b2010-06-04 16:08:02 -0400135 return true;
Joe Onorato0cbda992010-05-02 16:28:15 -0700136 }
137
Joe Onoratof5510542010-06-01 07:46:41 -0700138 private Drawable getIcon(StatusBarIcon icon) {
139 return getIcon(getContext(), icon);
140 }
141
Joe Onorato0cbda992010-05-02 16:28:15 -0700142 /**
143 * Returns the right icon to use for this item, respecting the iconId and
144 * iconPackage (if set)
145 *
146 * @param context Context to use to get resources if iconPackage is not set
147 * @return Drawable for this item, or null if the package or item could not
148 * be found
149 */
Joe Onoratof5510542010-06-01 07:46:41 -0700150 public static Drawable getIcon(Context context, StatusBarIcon icon) {
Joe Onorato0cbda992010-05-02 16:28:15 -0700151 Resources r = null;
152
153 if (icon.iconPackage != null) {
154 try {
155 r = context.getPackageManager().getResourcesForApplication(icon.iconPackage);
156 } catch (PackageManager.NameNotFoundException ex) {
Joe Onoratofd52b182010-11-10 18:00:52 -0800157 Slog.e(StatusBar.TAG, "Icon package not found: " + icon.iconPackage);
Joe Onorato0cbda992010-05-02 16:28:15 -0700158 return null;
159 }
160 } else {
161 r = context.getResources();
162 }
163
164 if (icon.iconId == 0) {
Joe Onorato0cbda992010-05-02 16:28:15 -0700165 return null;
166 }
167
168 try {
169 return r.getDrawable(icon.iconId);
170 } catch (RuntimeException e) {
Joe Onoratofd52b182010-11-10 18:00:52 -0800171 Slog.w(StatusBar.TAG, "Icon not found in "
Joe Onorato0cbda992010-05-02 16:28:15 -0700172 + (icon.iconPackage != null ? icon.iconId : "<system>")
173 + ": " + Integer.toHexString(icon.iconId));
174 }
175
176 return null;
177 }
Joe Onoratob77f53b2010-05-28 19:59:51 -0400178
179 public StatusBarIcon getStatusBarIcon() {
180 return mIcon;
181 }
Joe Onoratof9ec03c2010-09-23 15:09:18 -0700182
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700183 @Override
184 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
185 super.onInitializeAccessibilityEvent(event);
186 if (mNotification != null) {
187 event.setParcelableData(mNotification);
188 }
189 }
190
191 @Override
Joe Onorato6c01a112010-10-04 17:38:47 -0400192 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
193 super.onSizeChanged(w, h, oldw, oldh);
194 if (mNumberBackground != null) {
195 placeNumber();
196 }
197 }
198
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700199 @Override
Joe Onorato6c01a112010-10-04 17:38:47 -0400200 protected void onDraw(Canvas canvas) {
201 super.onDraw(canvas);
202
203 if (mNumberBackground != null) {
204 mNumberBackground.draw(canvas);
205 canvas.drawText(mNumberText, mNumberX, mNumberY, mNumberPain);
206 }
207 }
208
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700209 @Override
Joe Onoratof9ec03c2010-09-23 15:09:18 -0700210 protected void debug(int depth) {
211 super.debug(depth);
212 Log.d("View", debugIndent(depth) + "slot=" + mSlot);
213 Log.d("View", debugIndent(depth) + "icon=" + mIcon);
214 }
Joe Onorato6c01a112010-10-04 17:38:47 -0400215
216 void placeNumber() {
Daniel Sandlerebce0112011-06-16 16:44:51 -0400217 final String str;
218 final int tooBig = mContext.getResources().getInteger(
219 android.R.integer.status_bar_notification_info_maxnum);
220 if (mIcon.number > tooBig) {
221 str = mContext.getResources().getString(
222 android.R.string.status_bar_notification_info_overflow);
223 } else {
224 NumberFormat f = NumberFormat.getIntegerInstance();
225 str = f.format(mIcon.number);
226 }
227 mNumberText = str;
228
Joe Onorato6c01a112010-10-04 17:38:47 -0400229 final int w = getWidth();
230 final int h = getHeight();
231 final Rect r = new Rect();
232 mNumberPain.getTextBounds(str, 0, str.length(), r);
233 final int tw = r.right - r.left;
234 final int th = r.bottom - r.top;
235 mNumberBackground.getPadding(r);
236 int dw = r.left + tw + r.right;
237 if (dw < mNumberBackground.getMinimumWidth()) {
238 dw = mNumberBackground.getMinimumWidth();
239 }
240 mNumberX = w-r.right-((dw-r.right-r.left)/2);
241 int dh = r.top + th + r.bottom;
242 if (dh < mNumberBackground.getMinimumWidth()) {
243 dh = mNumberBackground.getMinimumWidth();
244 }
245 mNumberY = h-r.bottom-((dh-r.top-th-r.bottom)/2);
246 mNumberBackground.setBounds(w-dw, h-dh, w, h);
247 }
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700248
249 private void setContentDescription(Notification notification) {
250 if (notification != null) {
251 CharSequence tickerText = notification.tickerText;
252 if (!TextUtils.isEmpty(tickerText)) {
253 setContentDescription(tickerText);
254 }
255 }
256 }
Daniel Sandler7579bca2011-08-18 15:47:26 -0400257
258 public String toString() {
259 return "StatusBarIconView(slot=" + mSlot + " icon=" + mIcon
260 + " notification=" + mNotification + ")";
261 }
Joe Onorato0cbda992010-05-02 16:28:15 -0700262}