1/*
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
17package com.android.systemui.statusbar;
18
19import android.app.Notification;
20import android.os.IBinder;
21import android.view.View;
22import android.widget.ImageView;
23
24import com.android.internal.statusbar.StatusBarNotification;
25import com.android.systemui.R;
26
27import java.util.Comparator;
28import java.util.ArrayList;
29
30/**
31 * The list of currently displaying notifications.
32 */
33public class NotificationData {
34    public static final class Entry {
35        public IBinder key;
36        public StatusBarNotification notification;
37        public StatusBarIconView icon;
38        public View row; // the outer expanded view
39        public View content; // takes the click events and sends the PendingIntent
40        public View expanded; // the inflated RemoteViews
41        public ImageView largeIcon;
42        protected View expandedLarge;
43        public Entry() {}
44        public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic) {
45            this.key = key;
46            this.notification = n;
47            this.icon = ic;
48        }
49        public void setLargeView(View expandedLarge) {
50            this.expandedLarge = expandedLarge;
51            writeBooleanTag(row, R.id.expandable_tag, expandedLarge != null);
52        }
53        public View getLargeView() {
54            return expandedLarge;
55        }
56        /**
57         * Return whether the entry can be expanded.
58         */
59        public boolean expandable() {
60            return NotificationData.getIsExpandable(row);
61        }
62        /**
63         * Return whether the entry has been manually expanded by the user.
64         */
65        public boolean userExpanded() {
66            return NotificationData.getUserExpanded(row);
67        }
68        /**
69         * Set the flag indicating that this was manually expanded by the user.
70         */
71        public boolean setUserExpanded(boolean userExpanded) {
72            return NotificationData.setUserExpanded(row, userExpanded);
73        }
74        /**
75         * Return whether the entry is being touched by the user.
76         */
77        public boolean userLocked() {
78            return NotificationData.getUserLocked(row);
79        }
80        /**
81         * Set the flag indicating that this is being touched by the user.
82         */
83        public boolean setUserLocked(boolean userLocked) {
84            return NotificationData.setUserLocked(row, userLocked);
85        }
86    }
87    private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
88    private final Comparator<Entry> mEntryCmp = new Comparator<Entry>() {
89        // sort first by score, then by when
90        public int compare(Entry a, Entry b) {
91            final StatusBarNotification na = a.notification;
92            final StatusBarNotification nb = b.notification;
93            int d = na.score - nb.score;
94            return (d != 0)
95                ? d
96                : (int)(na.notification.when - nb.notification.when);
97        }
98    };
99
100    public int size() {
101        return mEntries.size();
102    }
103
104    public Entry get(int i) {
105        return mEntries.get(i);
106    }
107
108    public Entry findByKey(IBinder key) {
109        for (Entry e : mEntries) {
110            if (e.key == key) {
111                return e;
112            }
113        }
114        return null;
115    }
116
117    public int add(Entry entry) {
118        int i;
119        int N = mEntries.size();
120        for (i=0; i<N; i++) {
121            if (mEntryCmp.compare(mEntries.get(i), entry) > 0) {
122                break;
123            }
124        }
125        mEntries.add(i, entry);
126        return i;
127    }
128
129    public int add(IBinder key, StatusBarNotification notification, View row, View content,
130            View expanded, StatusBarIconView icon) {
131        Entry entry = new Entry();
132        entry.key = key;
133        entry.notification = notification;
134        entry.row = row;
135        entry.content = content;
136        entry.expanded = expanded;
137        entry.icon = icon;
138        entry.largeIcon = null; // TODO add support for large icons
139        return add(entry);
140    }
141
142    public Entry remove(IBinder key) {
143        Entry e = findByKey(key);
144        if (e != null) {
145            mEntries.remove(e);
146        }
147        return e;
148    }
149
150    /**
151     * Return whether there are any visible items (i.e. items without an error).
152     */
153    public boolean hasVisibleItems() {
154        for (Entry e : mEntries) {
155            if (e.expanded != null) { // the view successfully inflated
156                return true;
157            }
158        }
159        return false;
160    }
161
162    /**
163     * Return whether there are any clearable items (that aren't errors).
164     */
165    public boolean hasClearableItems() {
166        for (Entry e : mEntries) {
167            if (e.expanded != null) { // the view successfully inflated
168                if (e.notification.isClearable()) {
169                    return true;
170                }
171            }
172        }
173        return false;
174    }
175
176    protected static boolean readBooleanTag(View view, int id)  {
177        if (view != null) {
178            Object value = view.getTag(id);
179            return value != null && value instanceof Boolean && ((Boolean) value).booleanValue();
180        }
181        return false;
182    }
183
184    protected static boolean writeBooleanTag(View view, int id, boolean value)  {
185        if (view != null) {
186            view.setTag(id, Boolean.valueOf(value));
187            return value;
188        }
189        return false;
190    }
191
192    /**
193     * Return whether the entry can be expanded.
194     */
195    public static boolean getIsExpandable(View row) {
196        return readBooleanTag(row, R.id.expandable_tag);
197    }
198
199    /**
200     * Return whether the entry has been manually expanded by the user.
201     */
202    public static boolean getUserExpanded(View row) {
203        return readBooleanTag(row, R.id.user_expanded_tag);
204    }
205
206    /**
207     * Set whether the entry has been manually expanded by the user.
208     */
209    public static boolean setUserExpanded(View row, boolean userExpanded) {
210        return writeBooleanTag(row, R.id.user_expanded_tag, userExpanded);
211    }
212
213    /**
214     * Return whether the entry is being touched by the user.
215     */
216    public static boolean getUserLocked(View row) {
217        return readBooleanTag(row, R.id.user_lock_tag);
218    }
219
220    /**
221     * Set whether the entry is being touched by the user.
222     */
223    public static boolean setUserLocked(View row, boolean userLocked) {
224        return writeBooleanTag(row, R.id.user_lock_tag, userLocked);
225    }
226}
227