OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.chrome.browser.locale; | |
6 | |
7 import android.content.Context; | |
8 import android.content.DialogInterface; | |
9 import android.os.Bundle; | |
10 import android.support.annotation.Nullable; | |
11 import android.view.View; | |
12 import android.widget.RadioButton; | |
13 import android.widget.RadioGroup; | |
14 import android.widget.RadioGroup.OnCheckedChangeListener; | |
15 | |
16 import org.chromium.base.library_loader.LibraryLoader; | |
17 import org.chromium.chrome.R; | |
18 import org.chromium.chrome.browser.infobar.InfoBarControlLayout; | |
19 import org.chromium.chrome.browser.search_engines.TemplateUrlService; | |
20 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl ; | |
21 import org.chromium.chrome.browser.widget.PromoDialog; | |
22 | |
23 import java.util.ArrayList; | |
24 import java.util.List; | |
25 import java.util.Random; | |
26 | |
27 /** A dialog that forces the user to choose a default search engine. */ | |
28 public class DefaultSearchEnginePromoDialog extends PromoDialog implements OnChe ckedChangeListener { | |
29 /** Used to determine the promo dialog contents. */ | |
30 private final int mDialogType; | |
31 | |
32 /** Run when the dialog is dismissed after the user has chosen a search engi ne. */ | |
33 private final Runnable mOnDismissed; | |
34 | |
35 private RadioGroup mRadioGroup; | |
36 private String mSelectedKeyword; | |
37 | |
38 /** | |
39 * Construct and show the dialog. Will be asynchronous if the TemplateUrlSe rvice has not yet | |
40 * been loaded. | |
41 */ | |
42 public static void create( | |
Ted C
2017/04/26 20:21:52
maybe this should be called show?
gone
2017/04/26 21:45:15
Done.
| |
43 final Context context, final int dialogType, @Nullable final Runnabl e onDismissed) { | |
Ted C
2017/04/26 20:21:52
Should/can dialogType have an associated IntDef?
gone
2017/04/26 21:45:15
Seems like it'd be fine to move it to always be ca
| |
44 assert LibraryLoader.isInitialized(); | |
45 | |
46 // Load up the search engines. | |
47 final TemplateUrlService instance = TemplateUrlService.getInstance(); | |
48 instance.registerLoadListener(new TemplateUrlService.LoadListener() { | |
49 @Override | |
50 public void onTemplateUrlServiceLoaded() { | |
51 instance.unregisterLoadListener(this); | |
52 new DefaultSearchEnginePromoDialog(context, dialogType, onDismis sed).show(); | |
53 } | |
54 }); | |
55 instance.load(); | |
56 } | |
57 | |
58 private DefaultSearchEnginePromoDialog( | |
59 Context context, int dialogType, @Nullable Runnable onDismissed) { | |
60 super(context); | |
61 mDialogType = dialogType; | |
62 mOnDismissed = onDismissed; | |
63 setOnDismissListener(this); | |
64 | |
65 // No one should be able to bypass this dialog by clicking outside or by hitting back. | |
66 setCancelable(false); | |
67 setCanceledOnTouchOutside(false); | |
68 } | |
69 | |
70 @Override | |
71 protected DialogParams getDialogParams() { | |
72 PromoDialog.DialogParams params = new PromoDialog.DialogParams(); | |
73 params.headerStringResource = R.string.search_engine_dialog_title; | |
74 params.footerStringResource = R.string.search_engine_dialog_footer; | |
75 params.primaryButtonStringResource = R.string.ok; | |
76 return params; | |
77 } | |
78 | |
79 @Override | |
80 protected void onCreate(Bundle savedInstanceState) { | |
81 super.onCreate(savedInstanceState); | |
82 assert LibraryLoader.isInitialized(); | |
Ted C
2017/04/26 20:21:52
Since this happens in the one place you create it
gone
2017/04/26 21:45:15
Done.
| |
83 | |
84 // Set up the general UI. | |
85 InfoBarControlLayout controls = addControlLayout(); | |
86 updateButtonState(); | |
87 | |
88 // Load up the search engines. | |
89 TemplateUrlService instance = TemplateUrlService.getInstance(); | |
90 assert instance.isLoaded(); | |
91 List<TemplateUrl> engines = null; | |
92 if (mDialogType == LocaleManager.SEARCH_ENGINE_PROMO_SHOW_EXISTING) { | |
93 engines = instance.getSearchEngines(); | |
94 } else { | |
95 // TODO(dfalcantara): Handle the new user case. | |
96 assert false; | |
97 } | |
98 | |
99 List<CharSequence> engineNames = new ArrayList<>(); | |
100 List<String> engineKeywords = new ArrayList<>(); | |
101 shuffleEngines(engines, engineNames, engineKeywords); | |
102 | |
103 // Add the search engines to the dialog. | |
104 mRadioGroup = controls.addRadioButtons( | |
105 engineNames, engineKeywords, InfoBarControlLayout.INVALID_INDEX) ; | |
106 mRadioGroup.setOnCheckedChangeListener(this); | |
107 } | |
108 | |
109 @Override | |
110 public void onCheckedChanged(RadioGroup group, int checkedId) { | |
111 mSelectedKeyword = null; | |
112 | |
113 // Run through the RadioGroup to figure out which one was checked. | |
114 for (int i = 0; i < group.getChildCount(); i++) { | |
115 View child = group.getChildAt(i); | |
116 assert child instanceof RadioButton; | |
117 | |
118 RadioButton button = (RadioButton) child; | |
119 if (button.isChecked()) { | |
120 assert mSelectedKeyword == null; | |
121 mSelectedKeyword = (String) button.getTag(); | |
122 } | |
123 } | |
124 | |
125 updateButtonState(); | |
126 } | |
127 | |
128 @Override | |
129 public void onClick(View view) { | |
130 if (view.getId() == R.id.button_primary) { | |
131 if (mSelectedKeyword == null) { | |
132 updateButtonState(); | |
133 return; | |
134 } | |
135 | |
136 dismiss(); | |
137 } else { | |
138 assert false : "Unhandled click."; | |
139 } | |
140 | |
141 // Don't propagate the click to the parent to prevent circumventing the dialog. | |
142 } | |
143 | |
144 @Override | |
145 public void onDismiss(DialogInterface dialog) { | |
146 if (mSelectedKeyword == null) { | |
147 // This shouldn't happen, but in case it does, finish the Activity s o that the user has | |
148 // to respond to the dialog next time. | |
149 if (getOwnerActivity() != null) getOwnerActivity().finish(); | |
Ted C
2017/04/26 20:21:52
should this be finish and remove task?
gone
2017/04/26 21:45:15
I'd argue for a regular finish() so that the activ
| |
150 } else { | |
151 TemplateUrlService.getInstance().setSearchEngine(mSelectedKeyword.to String()); | |
152 if (mOnDismissed != null) mOnDismissed.run(); | |
153 // TODO(dfalcantara): Prevent the dialog from appearing again. | |
154 } | |
155 } | |
156 | |
157 private void updateButtonState() { | |
158 findViewById(R.id.button_primary).setEnabled(mSelectedKeyword != null); | |
159 } | |
160 | |
161 private void shuffleEngines( | |
162 List<TemplateUrl> engines, List<CharSequence> names, List<String> ke ywords) { | |
163 ArrayList<Integer> indices = new ArrayList<>(); | |
Ted C
2017/04/26 20:21:52
Could we use:
https://developer.android.com/refere
gone
2017/04/26 21:45:15
Works for me.
| |
164 for (int i = 0; i < engines.size(); i++) indices.add(i); | |
165 | |
166 Random generator = new Random(); | |
167 for (int i = 0; i < indices.size(); i++) { | |
168 int remaining = indices.size() - i; | |
169 int shuffleIndex = i + generator.nextInt(remaining); | |
170 | |
171 if (shuffleIndex != i) { | |
172 int temp = indices.get(i); | |
173 indices.set(i, indices.get(shuffleIndex)); | |
174 indices.set(shuffleIndex, temp); | |
175 } | |
176 } | |
177 | |
178 for (Integer index : indices) { | |
179 TemplateUrl engine = engines.get(index); | |
180 names.add(engine.getShortName()); | |
181 keywords.add(engine.getKeyword()); | |
182 } | |
183 } | |
184 } | |
OLD | NEW |