Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java

Issue 2271413002: bluetooth: Implement RSSI indicator on android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bluetooth-impl-rssi-tx-power
Patch Set: Draft of LevelListDrawable and StateListDrawable Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser; 5 package org.chromium.chrome.browser;
6 6
7 import android.app.Activity; 7 import android.app.Activity;
8 import android.app.Dialog; 8 import android.app.Dialog;
9 import android.content.Context; 9 import android.content.Context;
10 import android.content.DialogInterface; 10 import android.content.DialogInterface;
11 import android.graphics.Color; 11 import android.graphics.Color;
12 import android.graphics.drawable.ColorDrawable; 12 import android.graphics.drawable.ColorDrawable;
13 import android.graphics.drawable.Drawable;
13 import android.text.SpannableString; 14 import android.text.SpannableString;
14 import android.text.method.LinkMovementMethod; 15 import android.text.method.LinkMovementMethod;
15 import android.view.Gravity; 16 import android.view.Gravity;
16 import android.view.LayoutInflater; 17 import android.view.LayoutInflater;
17 import android.view.View; 18 import android.view.View;
18 import android.view.ViewGroup; 19 import android.view.ViewGroup;
19 import android.view.ViewGroup.LayoutParams; 20 import android.view.ViewGroup.LayoutParams;
20 import android.view.Window; 21 import android.view.Window;
21 import android.widget.AdapterView; 22 import android.widget.AdapterView;
22 import android.widget.ArrayAdapter; 23 import android.widget.ArrayAdapter;
23 import android.widget.Button; 24 import android.widget.Button;
25 import android.widget.ImageView;
24 import android.widget.LinearLayout; 26 import android.widget.LinearLayout;
25 import android.widget.ListView; 27 import android.widget.ListView;
26 import android.widget.ProgressBar; 28 import android.widget.ProgressBar;
29 import android.widget.RelativeLayout;
27 import android.widget.TextView; 30 import android.widget.TextView;
28 31
32 import org.chromium.base.Log;
29 import org.chromium.base.ApiCompatibilityUtils; 33 import org.chromium.base.ApiCompatibilityUtils;
30 import org.chromium.base.VisibleForTesting; 34 import org.chromium.base.VisibleForTesting;
31 import org.chromium.chrome.R; 35 import org.chromium.chrome.R;
32 import org.chromium.chrome.browser.util.MathUtils; 36 import org.chromium.chrome.browser.util.MathUtils;
33 import org.chromium.ui.base.DeviceFormFactor; 37 import org.chromium.ui.base.DeviceFormFactor;
34 import org.chromium.ui.widget.TextViewWithClickableSpans; 38 import org.chromium.ui.widget.TextViewWithClickableSpans;
35 39
36 import java.util.HashMap; 40 import java.util.HashMap;
37 import java.util.HashSet; 41 import java.util.HashSet;
38 import java.util.Map; 42 import java.util.Map;
(...skipping 19 matching lines...) Expand all
58 */ 62 */
59 void onItemSelected(String id); 63 void onItemSelected(String id);
60 } 64 }
61 65
62 /** 66 /**
63 * A class representing one data row in the picker. 67 * A class representing one data row in the picker.
64 */ 68 */
65 public static class ItemChooserRow { 69 public static class ItemChooserRow {
66 private final String mKey; 70 private final String mKey;
67 private String mDescription; 71 private String mDescription;
72 private Drawable mIcon;
73 private String mIconDescription;
74
75 public ItemChooserRow(
76 String key, String description, Drawable icon, String iconDescri ption) {
77 mKey = key;
78 mDescription = description;
79 mIcon = icon;
80 mIconDescription = iconDescription;
81 }
68 82
69 public ItemChooserRow(String key, String description) { 83 public ItemChooserRow(String key, String description) {
70 mKey = key; 84 this(key, description, null, null);
71 mDescription = description; 85 }
86
87 public Drawable getIcon() {
88 return mIcon;
72 } 89 }
73 90
74 @Override 91 @Override
75 public boolean equals(Object obj) { 92 public boolean equals(Object obj) {
76 if (!(obj instanceof ItemChooserRow)) return false; 93 if (!(obj instanceof ItemChooserRow)) return false;
77 if (this == obj) return true; 94 if (this == obj) return true;
78 ItemChooserRow item = (ItemChooserRow) obj; 95 ItemChooserRow item = (ItemChooserRow) obj;
79 return mKey.equals(item.mKey) && mDescription.equals(item.mDescripti on); 96
97 if (mIcon == null ^ item.mIcon == null) return false;
98
99 if (mIcon != null && item.mIcon != null
100 && !mIcon.getConstantState().equals(item.mIcon.getConstantSt ate()))
101 return false;
102
103 if (mIconDescription == null ^ item.mIconDescription == null) return false;
104
105 if (mIconDescription != null && mIconDescription.equals(item.mIconDe scription)) {
106 return false;
107 }
108
109 if (mKey.equals(item.mKey) && mDescription.equals(item.mDescription) ) return true;
110
111 return false;
80 } 112 }
81 113
82 @Override 114 @Override
83 public int hashCode() { 115 public int hashCode() {
84 return mKey.hashCode() + mDescription.hashCode(); 116 return mKey.hashCode() + mDescription.hashCode() + mIcon.hashCode();
117 }
118
119 @Override
120 public String toString() {
121 return mKey + ":" + mDescription + ":" + mIcon.toString();
85 } 122 }
86 } 123 }
87 124
88 /** 125 /**
89 * The labels to show in the dialog. 126 * The labels to show in the dialog.
90 */ 127 */
91 public static class ItemChooserLabels { 128 public static class ItemChooserLabels {
92 // The title at the top of the dialog. 129 // The title at the top of the dialog.
93 public final CharSequence title; 130 public final CharSequence title;
94 // The message to show while there are no results. 131 // The message to show while there are no results.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 public class ItemAdapter extends ArrayAdapter<ItemChooserRow> 168 public class ItemAdapter extends ArrayAdapter<ItemChooserRow>
132 implements AdapterView.OnItemClickListener { 169 implements AdapterView.OnItemClickListener {
133 private final LayoutInflater mInflater; 170 private final LayoutInflater mInflater;
134 171
135 // The background color of the highlighted item. 172 // The background color of the highlighted item.
136 private final int mBackgroundHighlightColor; 173 private final int mBackgroundHighlightColor;
137 174
138 // The color of the non-highlighted text. 175 // The color of the non-highlighted text.
139 private final int mDefaultTextColor; 176 private final int mDefaultTextColor;
140 177
178 // The color of disabled text.
179 private final int mDisabledTextColor;
180
181 // Indicates whether rows will contain an icon.
182 private boolean mUsingIcon;
183
141 // The zero-based index of the item currently selected in the dialog, 184 // The zero-based index of the item currently selected in the dialog,
142 // or -1 (INVALID_POSITION) if nothing is selected. 185 // or -1 (INVALID_POSITION) if nothing is selected.
143 private int mSelectedItem = ListView.INVALID_POSITION; 186 private int mSelectedItem = ListView.INVALID_POSITION;
144 187
145 // A set of keys that are marked as disabled in the dialog. 188 // A set of keys that are marked as disabled in the dialog.
146 private Set<String> mDisabledEntries = new HashSet<String>(); 189 private Set<String> mDisabledEntries = new HashSet<String>();
147 190
148 // Item descriptions are counted in a map. 191 // Item descriptions are counted in a map.
149 private Map<String, Integer> mItemDescriptionMap = new HashMap<>(); 192 private Map<String, Integer> mItemDescriptionMap = new HashMap<>();
150 193
151 // Map of keys to items so that we can access the items in O(1). 194 // Map of keys to items so that we can access the items in O(1).
152 private Map<String, ItemChooserRow> mKeyToItemMap = new HashMap<>(); 195 private Map<String, ItemChooserRow> mKeyToItemMap = new HashMap<>();
153 196
154 public ItemAdapter(Context context, int resource) { 197 public ItemAdapter(Context context, int resource, boolean usingIcon) {
155 super(context, resource); 198 super(context, resource);
156 199
157 mInflater = LayoutInflater.from(context); 200 mInflater = LayoutInflater.from(context);
158 201
202 mUsingIcon = usingIcon;
203
159 mBackgroundHighlightColor = ApiCompatibilityUtils.getColor(getContex t().getResources(), 204 mBackgroundHighlightColor = ApiCompatibilityUtils.getColor(getContex t().getResources(),
160 R.color.light_active_color); 205 R.color.light_active_color);
161 mDefaultTextColor = ApiCompatibilityUtils.getColor(getContext().getR esources(), 206 mDefaultTextColor = ApiCompatibilityUtils.getColor(getContext().getR esources(),
162 R.color.default_text_color); 207 R.color.default_text_color);
208 mDisabledTextColor = ApiCompatibilityUtils.getColor(
209 getContext().getResources(), R.color.primary_text_disabled_m aterial_light);
163 } 210 }
164 211
165 @Override 212 @Override
166 public boolean isEmpty() { 213 public boolean isEmpty() {
167 boolean isEmpty = super.isEmpty(); 214 boolean isEmpty = super.isEmpty();
168 if (isEmpty) { 215 if (isEmpty) {
169 assert mKeyToItemMap.isEmpty(); 216 assert mKeyToItemMap.isEmpty();
170 assert mDisabledEntries.isEmpty(); 217 assert mDisabledEntries.isEmpty();
171 assert mItemDescriptionMap.isEmpty(); 218 assert mItemDescriptionMap.isEmpty();
172 } else { 219 } else {
173 assert !mKeyToItemMap.isEmpty(); 220 assert !mKeyToItemMap.isEmpty();
174 assert !mItemDescriptionMap.isEmpty(); 221 assert !mItemDescriptionMap.isEmpty();
175 } 222 }
176 return isEmpty; 223 return isEmpty;
177 } 224 }
178 225
179 public void addOrUpdate(ItemChooserRow item) { 226 public void addOrUpdate(ItemChooserRow item, boolean didUpdateOldDrawable) {
Ian Wen 2016/10/14 01:39:51 I see many equal checks here and above. Which lead
180 ItemChooserRow oldItem = mKeyToItemMap.get(item.mKey); 227 ItemChooserRow oldItem = mKeyToItemMap.get(item.mKey);
228
181 if (oldItem != null) { 229 if (oldItem != null) {
182 if (oldItem.equals(item)) { 230 if (oldItem.equals(item) && !didUpdateOldDrawable) {
183 // No need to update anything. 231 // No need to update anything.
184 return; 232 return;
185 } 233 }
234
186 if (!oldItem.mDescription.equals(item.mDescription)) { 235 if (!oldItem.mDescription.equals(item.mDescription)) {
187 removeFromDescriptionsMap(oldItem.mDescription); 236 removeFromDescriptionsMap(oldItem.mDescription);
188 oldItem.mDescription = item.mDescription; 237 oldItem.mDescription = item.mDescription;
189 addToDescriptionsMap(oldItem.mDescription); 238 addToDescriptionsMap(oldItem.mDescription);
190 } 239 }
240
241 if (item.mIcon != null && (oldItem.mIcon == null
242 || !item.mIcon.getConstantStat e().equals(
243 oldItem.mIcon.getCo nstantState()))) {
244 oldItem.mIcon = item.mIcon;
245 }
246
191 notifyDataSetChanged(); 247 notifyDataSetChanged();
192 return; 248 return;
193 } 249 }
194 ItemChooserRow result = mKeyToItemMap.put(item.mKey, item); 250 ItemChooserRow result = mKeyToItemMap.put(item.mKey, item);
195 assert result == null; 251 assert result == null;
196 252
197 addToDescriptionsMap(item.mDescription); 253 addToDescriptionsMap(item.mDescription);
198 add(item); 254 add(item);
199 } 255 }
200 256
257 public ItemChooserRow getItemChooserRow(String key) {
258 return mKeyToItemMap.get(key);
259 }
260
201 @Override 261 @Override
202 public void remove(ItemChooserRow item) { 262 public void remove(ItemChooserRow item) {
203 ItemChooserRow oldItem = mKeyToItemMap.remove(item.mKey); 263 ItemChooserRow oldItem = mKeyToItemMap.remove(item.mKey);
204 if (oldItem == null) return; 264 if (oldItem == null) return;
205 int oldItemPosition = getPosition(oldItem); 265 int oldItemPosition = getPosition(oldItem);
206 // If the removed item is the item that is currently selected, desel ect it 266 // If the removed item is the item that is currently selected, desel ect it
207 // and disable the confirm button. Otherwise if the removed item is before 267 // and disable the confirm button. Otherwise if the removed item is before
208 // the currently selected item, the currently selected item's index needs 268 // the currently selected item, the currently selected item's index needs
209 // to be adjusted by one. 269 // to be adjusted by one.
210 if (oldItemPosition == mSelectedItem) { 270 if (oldItemPosition == mSelectedItem) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 return 1; 345 return 1;
286 } 346 }
287 347
288 @Override 348 @Override
289 public long getItemId(int position) { 349 public long getItemId(int position) {
290 return position; 350 return position;
291 } 351 }
292 352
293 @Override 353 @Override
294 public View getView(int position, View convertView, ViewGroup parent) { 354 public View getView(int position, View convertView, ViewGroup parent) {
295 TextView view; 355 RelativeLayout view;
296 if (convertView instanceof TextView) { 356 if (convertView instanceof RelativeLayout) {
Ian Wen 2016/10/14 01:39:51 Can the view be of a different type? If not I woul
297 view = (TextView) convertView; 357 view = (RelativeLayout) convertView;
298 } else { 358 } else {
299 view = (TextView) mInflater.inflate( 359 view = (RelativeLayout) mInflater.inflate(
300 R.layout.item_chooser_dialog_row, parent, false); 360 R.layout.item_chooser_dialog_row, parent, false);
301 } 361 View icon = view.findViewById(R.id.icon);
302 362 if (mUsingIcon) {
Ian Wen 2016/10/14 01:39:51 Instead of using this boolean, shall we grab the c
303 // Set highlighting for currently selected item. 363 icon.setVisibility(View.VISIBLE);
304 if (position == mSelectedItem) {
305 view.setBackgroundColor(mBackgroundHighlightColor);
306 view.setTextColor(Color.WHITE);
307 } else {
308 view.setBackground(null);
309 if (!isEnabled(position)) {
310 view.setTextColor(ApiCompatibilityUtils.getColor(getContext( ).getResources(),
311 R.color.primary_text_disabled_material_light));
312 } else { 364 } else {
313 view.setTextColor(mDefaultTextColor); 365 icon.setVisibility(View.GONE);
314 } 366 }
315 } 367 }
316 368
317 view.setText(getDisplayText(position)); 369 boolean selected = position == mSelectedItem;
370 TextView description = (TextView) view.findViewById(R.id.description );
371 description.setText(getDisplayText(position));
372
373 if (selected) {
Ian Wen 2016/10/14 01:39:51 The color manipulation could be simplified by colo
374 view.setBackgroundColor(mBackgroundHighlightColor);
375 description.setTextColor(Color.WHITE);
376 } else {
377 view.setBackground(null);
378 description.setTextColor(
379 isEnabled(position) ? mDefaultTextColor : mDisabledTextC olor);
380 }
381
382 if (mUsingIcon) {
383 ImageView icon = (ImageView) view.findViewById(R.id.icon);
384 Drawable d = getItem(position).mIcon;
385 icon.setVisibility(d == null ? View.INVISIBLE : View.VISIBLE);
386 if (d != null) {
387 icon.setImageLevel(d.getLevel());
388 }
389 icon.setImageDrawable(d);
390 icon.setSelected(selected);
391 icon.invalidateDrawable(d);
392 icon.setContentDescription(getItem(position).mIconDescription);
393 }
394
318 return view; 395 return view;
319 } 396 }
320 397
321 @Override 398 @Override
322 public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { 399 public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
323 mSelectedItem = position; 400 mSelectedItem = position;
324 mConfirmButton.setEnabled(true); 401 mConfirmButton.setEnabled(true);
325 mItemAdapter.notifyDataSetChanged(); 402 mItemAdapter.notifyDataSetChanged();
326 } 403 }
327 404
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 // The maximum height of the listview in the dialog (in dp). 453 // The maximum height of the listview in the dialog (in dp).
377 private static final int MAX_HEIGHT_DP = (int) (LIST_ROW_HEIGHT_DP * 8.5); 454 private static final int MAX_HEIGHT_DP = (int) (LIST_ROW_HEIGHT_DP * 8.5);
378 455
379 /** 456 /**
380 * Creates the ItemChooserPopup and displays it (and starts waiting for data ). 457 * Creates the ItemChooserPopup and displays it (and starts waiting for data ).
381 * 458 *
382 * @param activity Activity which is used for launching a dialog. 459 * @param activity Activity which is used for launching a dialog.
383 * @param callback The callback used to communicate back what was selected. 460 * @param callback The callback used to communicate back what was selected.
384 * @param labels The labels to show in the dialog. 461 * @param labels The labels to show in the dialog.
385 */ 462 */
386 public ItemChooserDialog( 463 public ItemChooserDialog(Activity activity, ItemSelectedCallback callback,
387 Activity activity, ItemSelectedCallback callback, ItemChooserLabels labels) { 464 ItemChooserLabels labels, boolean usingIcon) {
388 mActivity = activity; 465 mActivity = activity;
389 mItemSelectedCallback = callback; 466 mItemSelectedCallback = callback;
390 mLabels = labels; 467 mLabels = labels;
391 468
392 LinearLayout dialogContainer = (LinearLayout) LayoutInflater.from(mActiv ity).inflate( 469 LinearLayout dialogContainer = (LinearLayout) LayoutInflater.from(mActiv ity).inflate(
393 R.layout.item_chooser_dialog, null); 470 R.layout.item_chooser_dialog, null);
394 471
395 mListView = (ListView) dialogContainer.findViewById(R.id.items); 472 mListView = (ListView) dialogContainer.findViewById(R.id.items);
396 mProgressBar = (ProgressBar) dialogContainer.findViewById(R.id.progress) ; 473 mProgressBar = (ProgressBar) dialogContainer.findViewById(R.id.progress) ;
397 mStatus = (TextView) dialogContainer.findViewById(R.id.status); 474 mStatus = (TextView) dialogContainer.findViewById(R.id.status);
(...skipping 13 matching lines...) Expand all
411 mConfirmButton.setEnabled(false); 488 mConfirmButton.setEnabled(false);
412 mConfirmButton.setOnClickListener(new View.OnClickListener() { 489 mConfirmButton.setOnClickListener(new View.OnClickListener() {
413 @Override 490 @Override
414 public void onClick(View v) { 491 public void onClick(View v) {
415 mItemSelectedCallback.onItemSelected(mItemAdapter.getSelectedIte mKey()); 492 mItemSelectedCallback.onItemSelected(mItemAdapter.getSelectedIte mKey());
416 mDialog.setOnDismissListener(null); 493 mDialog.setOnDismissListener(null);
417 mDialog.dismiss(); 494 mDialog.dismiss();
418 } 495 }
419 }); 496 });
420 497
421 mItemAdapter = new ItemAdapter(mActivity, R.layout.item_chooser_dialog_r ow); 498 mItemAdapter = new ItemAdapter(mActivity, R.layout.item_chooser_dialog_r ow, usingIcon);
422 mItemAdapter.setNotifyOnChange(true); 499 mItemAdapter.setNotifyOnChange(true);
423 mListView.setAdapter(mItemAdapter); 500 mListView.setAdapter(mItemAdapter);
424 mListView.setEmptyView(mEmptyMessage); 501 mListView.setEmptyView(mEmptyMessage);
425 mListView.setOnItemClickListener(mItemAdapter); 502 mListView.setOnItemClickListener(mItemAdapter);
426 mListView.setDivider(null); 503 mListView.setDivider(null);
427 setState(State.STARTING); 504 setState(State.STARTING);
428 505
429 // The list is the main element in the dialog and it should grow and 506 // The list is the main element in the dialog and it should grow and
430 // shrink according to the size of the screen available. 507 // shrink according to the size of the screen available.
431 View listViewContainer = dialogContainer.findViewById(R.id.container); 508 View listViewContainer = dialogContainer.findViewById(R.id.container);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 mDialog.dismiss(); 562 mDialog.dismiss();
486 } 563 }
487 564
488 /** 565 /**
489 * Add an item to the end of the list to show in the dialog if the item 566 * Add an item to the end of the list to show in the dialog if the item
490 * was not in the chooser. Otherwise update the items description. 567 * was not in the chooser. Otherwise update the items description.
491 * 568 *
492 * @param item The item to be added to the end of the chooser or updated. 569 * @param item The item to be added to the end of the chooser or updated.
493 */ 570 */
494 public void addOrUpdateItem(ItemChooserRow item) { 571 public void addOrUpdateItem(ItemChooserRow item) {
572 addOrUpdateItem(item, false /* didUpdateOldDrawable */);
Ian Wen 2016/10/14 01:39:51 I would remove this comment.
573 }
574
575 public void addOrUpdateItem(ItemChooserRow item, boolean didUpdateOldDrawabl e) {
495 mProgressBar.setVisibility(View.GONE); 576 mProgressBar.setVisibility(View.GONE);
496 mItemAdapter.addOrUpdate(item); 577 mItemAdapter.addOrUpdate(item, didUpdateOldDrawable);
497 setState(State.PROGRESS_UPDATE_AVAILABLE); 578 setState(State.PROGRESS_UPDATE_AVAILABLE);
498 } 579 }
499 580
581 public ItemChooserRow getItemChooserRow(String key) {
582 return mItemAdapter.getItemChooserRow(key);
583 }
584
500 /** 585 /**
501 * Remove an item that is shown in the dialog. 586 * Remove an item that is shown in the dialog.
502 * 587 *
503 * @param item The item to be removed in the chooser. 588 * @param item The item to be removed in the chooser.
504 */ 589 */
505 public void removeItemFromList(ItemChooserRow item) { 590 public void removeItemFromList(ItemChooserRow item) {
506 mItemAdapter.remove(item); 591 mItemAdapter.remove(item);
507 setState(State.DISCOVERY_IDLE); 592 setState(State.DISCOVERY_IDLE);
508 } 593 }
509 594
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 } 660 }
576 661
577 /** 662 /**
578 * Returns the ItemAdapter associated with this class. For use with tests on ly. 663 * Returns the ItemAdapter associated with this class. For use with tests on ly.
579 */ 664 */
580 @VisibleForTesting 665 @VisibleForTesting
581 public ItemAdapter getItemAdapterForTesting() { 666 public ItemAdapter getItemAdapterForTesting() {
582 return mItemAdapter; 667 return mItemAdapter;
583 } 668 }
584 } 669 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698