|
1 package org.mozilla.gecko.db; |
|
2 |
|
3 import android.database.Cursor; |
|
4 import android.database.CursorWrapper; |
|
5 import android.util.SparseArray; |
|
6 |
|
7 import org.mozilla.gecko.db.BrowserContract.Bookmarks; |
|
8 import org.mozilla.gecko.db.BrowserDB.URLColumns; |
|
9 |
|
10 /** |
|
11 * {@TopSitesCursorWrapper} is a cursor wrapper that merges |
|
12 * the top and pinned sites cursors into one. It ensures the |
|
13 * cursor will contain at least a given minimum number of |
|
14 * entries. |
|
15 */ |
|
16 public class TopSitesCursorWrapper extends CursorWrapper { |
|
17 |
|
18 private static class PinnedSite { |
|
19 public final String title; |
|
20 public final String url; |
|
21 |
|
22 public PinnedSite(String title, String url) { |
|
23 this.title = (title == null ? "" : title); |
|
24 this.url = (url == null ? "" : url); |
|
25 } |
|
26 } |
|
27 |
|
28 // The cursor for the top sites query |
|
29 private final Cursor topCursor; |
|
30 |
|
31 // Associates pinned sites and their respective positions |
|
32 private SparseArray<PinnedSite> pinnedSites; |
|
33 |
|
34 // Current position of the cursor |
|
35 private int currentPosition = -1; |
|
36 |
|
37 // The size of the cursor wrapper |
|
38 private final int count; |
|
39 |
|
40 public TopSitesCursorWrapper(Cursor pinnedCursor, Cursor topCursor, int minSize) { |
|
41 super(topCursor); |
|
42 |
|
43 setPinnedSites(pinnedCursor); |
|
44 this.topCursor = topCursor; |
|
45 |
|
46 count = Math.max(minSize, pinnedSites.size() + topCursor.getCount()); |
|
47 } |
|
48 |
|
49 public void setPinnedSites(Cursor c) { |
|
50 pinnedSites = new SparseArray<PinnedSite>(); |
|
51 |
|
52 if (c == null) { |
|
53 return; |
|
54 } |
|
55 |
|
56 try { |
|
57 if (c.getCount() <= 0) { |
|
58 return; |
|
59 } |
|
60 |
|
61 c.moveToPosition(0); |
|
62 do { |
|
63 final int pos = c.getInt(c.getColumnIndex(Bookmarks.POSITION)); |
|
64 final String url = c.getString(c.getColumnIndex(URLColumns.URL)); |
|
65 final String title = c.getString(c.getColumnIndex(URLColumns.TITLE)); |
|
66 pinnedSites.put(pos, new PinnedSite(title, url)); |
|
67 } while (c.moveToNext()); |
|
68 } finally { |
|
69 c.close(); |
|
70 } |
|
71 } |
|
72 |
|
73 public boolean hasPinnedSites() { |
|
74 return (pinnedSites != null && pinnedSites.size() > 0); |
|
75 } |
|
76 |
|
77 public PinnedSite getPinnedSite(int position) { |
|
78 if (!hasPinnedSites()) { |
|
79 return null; |
|
80 } |
|
81 |
|
82 return pinnedSites.get(position); |
|
83 } |
|
84 |
|
85 public boolean isPinned() { |
|
86 return (pinnedSites.get(currentPosition) != null); |
|
87 } |
|
88 |
|
89 private int getPinnedBefore(int position) { |
|
90 int numFound = 0; |
|
91 if (!hasPinnedSites()) { |
|
92 return numFound; |
|
93 } |
|
94 |
|
95 for (int i = 0; i < position; i++) { |
|
96 if (pinnedSites.get(i) != null) { |
|
97 numFound++; |
|
98 } |
|
99 } |
|
100 |
|
101 return numFound; |
|
102 } |
|
103 |
|
104 @Override |
|
105 public int getPosition() { |
|
106 return currentPosition; |
|
107 } |
|
108 |
|
109 @Override |
|
110 public int getCount() { |
|
111 return count; |
|
112 } |
|
113 |
|
114 @Override |
|
115 public boolean isAfterLast() { |
|
116 return (currentPosition >= count); |
|
117 } |
|
118 |
|
119 @Override |
|
120 public boolean isBeforeFirst() { |
|
121 return (currentPosition < 0); |
|
122 } |
|
123 |
|
124 @Override |
|
125 public boolean isLast() { |
|
126 return (currentPosition == count - 1); |
|
127 } |
|
128 |
|
129 @Override |
|
130 public boolean moveToNext() { |
|
131 return moveToPosition(currentPosition + 1); |
|
132 } |
|
133 |
|
134 @Override |
|
135 public boolean moveToPrevious() { |
|
136 return moveToPosition(currentPosition - 1); |
|
137 } |
|
138 |
|
139 @Override |
|
140 public boolean move(int offset) { |
|
141 return moveToPosition(currentPosition + offset); |
|
142 } |
|
143 |
|
144 @Override |
|
145 public boolean moveToFirst() { |
|
146 return moveToPosition(0); |
|
147 } |
|
148 |
|
149 @Override |
|
150 public boolean moveToLast() { |
|
151 return moveToPosition(count - 1); |
|
152 } |
|
153 |
|
154 @Override |
|
155 public boolean moveToPosition(int position) { |
|
156 currentPosition = position; |
|
157 |
|
158 // Move the real cursor as if we were stepping through it to this position. |
|
159 // Account for pinned sites, and be careful to update its position to the |
|
160 // minimum or maximum position, even if we're moving beyond its bounds. |
|
161 final int before = getPinnedBefore(position); |
|
162 final int p2 = position - before; |
|
163 |
|
164 if (p2 <= -1) { |
|
165 super.moveToPosition(-1); |
|
166 } else if (p2 >= topCursor.getCount()) { |
|
167 super.moveToPosition(topCursor.getCount()); |
|
168 } else { |
|
169 super.moveToPosition(p2); |
|
170 } |
|
171 |
|
172 return (!isBeforeFirst() && !isAfterLast()); |
|
173 } |
|
174 |
|
175 @Override |
|
176 public long getLong(int columnIndex) { |
|
177 if (hasPinnedSites()) { |
|
178 final PinnedSite site = getPinnedSite(currentPosition); |
|
179 |
|
180 if (site != null) { |
|
181 return 0; |
|
182 } |
|
183 } |
|
184 |
|
185 if (!super.isBeforeFirst() && !super.isAfterLast()) { |
|
186 return super.getLong(columnIndex); |
|
187 } |
|
188 |
|
189 return 0; |
|
190 } |
|
191 |
|
192 @Override |
|
193 public int getInt(int columnIndex) { |
|
194 if (hasPinnedSites()) { |
|
195 final PinnedSite site = getPinnedSite(currentPosition); |
|
196 |
|
197 if (site != null) { |
|
198 return 0; |
|
199 } |
|
200 } |
|
201 |
|
202 if (!super.isBeforeFirst() && !super.isAfterLast()) { |
|
203 return super.getInt(columnIndex); |
|
204 } |
|
205 |
|
206 return 0; |
|
207 } |
|
208 |
|
209 @Override |
|
210 public String getString(int columnIndex) { |
|
211 if (hasPinnedSites()) { |
|
212 final PinnedSite site = getPinnedSite(currentPosition); |
|
213 |
|
214 if (site != null) { |
|
215 if (columnIndex == topCursor.getColumnIndex(URLColumns.URL)) { |
|
216 return site.url; |
|
217 } else if (columnIndex == topCursor.getColumnIndex(URLColumns.TITLE)) { |
|
218 return site.title; |
|
219 } |
|
220 |
|
221 return ""; |
|
222 } |
|
223 } |
|
224 |
|
225 if (!super.isBeforeFirst() && !super.isAfterLast()) { |
|
226 return super.getString(columnIndex); |
|
227 } |
|
228 |
|
229 return ""; |
|
230 } |
|
231 } |