OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "chrome/browser/ui/views/first_run_search_engine_view.h" | 5 #include "chrome/browser/ui/views/first_run_search_engine_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/i18n/rtl.h" | 11 #include "base/i18n/rtl.h" |
12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
13 #include "base/time.h" | 13 #include "base/time.h" |
14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
15 #include "chrome/browser/first_run/first_run.h" | 15 #include "chrome/browser/first_run/first_run.h" |
16 #include "chrome/browser/first_run/first_run_dialog.h" | 16 #include "chrome/browser/first_run/first_run_dialog.h" |
17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
18 #include "chrome/browser/search_engines/search_engine_type.h" | 18 #include "chrome/browser/search_engines/search_engine_type.h" |
19 #include "chrome/browser/search_engines/template_url.h" | 19 #include "chrome/browser/search_engines/template_url.h" |
20 #include "chrome/browser/search_engines/template_url_service.h" | 20 #include "chrome/browser/search_engines/template_url_service.h" |
21 #include "chrome/browser/search_engines/template_url_service_factory.h" | 21 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 22 #include "chrome/browser/themes/theme_service.h" |
22 #include "grit/chromium_strings.h" | 23 #include "grit/chromium_strings.h" |
23 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
24 #include "grit/google_chrome_strings.h" | 25 #include "grit/google_chrome_strings.h" |
25 #include "grit/locale_settings.h" | 26 #include "grit/locale_settings.h" |
26 #include "grit/theme_resources.h" | 27 #include "grit/theme_resources.h" |
27 #include "ui/base/accessibility/accessible_view_state.h" | 28 #include "ui/base/accessibility/accessible_view_state.h" |
28 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
29 #include "ui/base/resource/resource_bundle.h" | 30 #include "ui/base/resource/resource_bundle.h" |
30 #include "ui/gfx/canvas.h" | 31 #include "ui/gfx/canvas.h" |
31 #include "ui/gfx/font.h" | 32 #include "ui/gfx/font.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 ResourceBundle::GetSharedInstance().GetBitmapNamed(logo_id); | 97 ResourceBundle::GetSharedInstance().GetBitmapNamed(logo_id); |
97 logo_image->SetImage(logo_bmp); | 98 logo_image->SetImage(logo_bmp); |
98 if (use_small_logos) | 99 if (use_small_logos) |
99 logo_image->SetImageSize(gfx::Size(kSmallLogoWidth, kSmallLogoHeight)); | 100 logo_image->SetImageSize(gfx::Size(kSmallLogoWidth, kSmallLogoHeight)); |
100 // Tooltip text provides accessibility for low-vision users. | 101 // Tooltip text provides accessibility for low-vision users. |
101 logo_image->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); | 102 logo_image->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); |
102 choice_view_ = logo_image; | 103 choice_view_ = logo_image; |
103 } else { | 104 } else { |
104 // No logo -- we must show a text label. | 105 // No logo -- we must show a text label. |
105 views::Label* logo_label = new views::Label(search_engine_->short_name()); | 106 views::Label* logo_label = new views::Label(search_engine_->short_name()); |
106 logo_label->SetColor(SK_ColorDKGRAY); | 107 logo_label->SetBackgroundColor(SK_ColorWHITE); |
| 108 logo_label->SetEnabledColor(SK_ColorDKGRAY); |
107 logo_label->SetFont(logo_label->font().DeriveFont(3, gfx::Font::BOLD)); | 109 logo_label->SetFont(logo_label->font().DeriveFont(3, gfx::Font::BOLD)); |
108 logo_label->SetHorizontalAlignment(views::Label::ALIGN_CENTER); | 110 logo_label->SetHorizontalAlignment(views::Label::ALIGN_CENTER); |
109 logo_label->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); | 111 logo_label->SetTooltipText(WideToUTF16Hack(search_engine_->short_name())); |
110 logo_label->SetMultiLine(true); | 112 logo_label->SetMultiLine(true); |
111 logo_label->SizeToFit(kSmallLogoWidth); | 113 logo_label->SizeToFit(kSmallLogoWidth); |
112 choice_view_ = logo_label; | 114 choice_view_ = logo_label; |
113 } | 115 } |
114 | 116 |
115 // The accessible name of the button provides accessibility for | 117 // The accessible name of the button provides accessibility for |
116 // screenreaders. It uses the browser name rather than the text of the | 118 // screenreaders. It uses the browser name rather than the text of the |
(...skipping 16 matching lines...) Expand all Loading... |
133 } else { | 135 } else { |
134 return choice_view_->GetPreferredSize().height(); | 136 return choice_view_->GetPreferredSize().height(); |
135 } | 137 } |
136 } | 138 } |
137 | 139 |
138 void SearchEngineChoice::SetChoiceViewBounds(int x, int y, int width, | 140 void SearchEngineChoice::SetChoiceViewBounds(int x, int y, int width, |
139 int height) { | 141 int height) { |
140 choice_view_->SetBounds(x, y, width, height); | 142 choice_view_->SetBounds(x, y, width, height); |
141 } | 143 } |
142 | 144 |
143 FirstRunSearchEngineView::FirstRunSearchEngineView( | 145 FirstRunSearchEngineView::FirstRunSearchEngineView(Profile* profile, |
144 Profile* profile, bool randomize) | 146 bool randomize) |
145 : background_image_(NULL), | 147 : background_image_(NULL), |
146 profile_(profile), | 148 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)), |
147 text_direction_is_rtl_(base::i18n::IsRTL()), | 149 text_direction_is_rtl_(base::i18n::IsRTL()), |
| 150 template_url_service_loaded_(false), |
| 151 added_to_view_hierarchy_(false), |
148 randomize_(randomize) { | 152 randomize_(randomize) { |
149 // Don't show ourselves until all the search engines have loaded from | 153 // Don't show ourselves until all the search engines have loaded from |
150 // the profile -- otherwise we have nothing to show. | 154 // the profile -- otherwise we have nothing to show. |
151 SetVisible(false); | 155 SetVisible(false); |
152 | 156 |
153 // Start loading the search engines for the given profile. | 157 // Start loading the search engines for the given profile. |
154 search_engines_model_ = TemplateURLServiceFactory::GetForProfile(profile_); | 158 DCHECK(template_url_service_); |
155 if (search_engines_model_) { | 159 DCHECK(!template_url_service_->loaded()); |
156 DCHECK(!search_engines_model_->loaded()); | 160 template_url_service_->AddObserver(this); |
157 search_engines_model_->AddObserver(this); | 161 template_url_service_->Load(); |
158 search_engines_model_->Load(); | |
159 } else { | |
160 NOTREACHED(); | |
161 } | |
162 SetupControls(); | |
163 } | 162 } |
164 | 163 |
165 FirstRunSearchEngineView::~FirstRunSearchEngineView() { | 164 FirstRunSearchEngineView::~FirstRunSearchEngineView() { |
166 search_engines_model_->RemoveObserver(this); | 165 template_url_service_->RemoveObserver(this); |
167 } | 166 } |
168 | 167 |
169 string16 FirstRunSearchEngineView::GetWindowTitle() const { | 168 string16 FirstRunSearchEngineView::GetWindowTitle() const { |
170 return l10n_util::GetStringUTF16(IDS_FIRSTRUN_DLG_TITLE); | 169 return l10n_util::GetStringUTF16(IDS_FIRSTRUN_DLG_TITLE); |
171 } | 170 } |
172 | 171 |
173 void FirstRunSearchEngineView::ButtonPressed(views::Button* sender, | 172 void FirstRunSearchEngineView::ButtonPressed(views::Button* sender, |
174 const views::Event& event) { | 173 const views::Event& event) { |
175 SearchEngineChoice* choice = static_cast<SearchEngineChoice*>(sender); | 174 SearchEngineChoice* choice = static_cast<SearchEngineChoice*>(sender); |
176 TemplateURLService* template_url_service = | 175 DCHECK(template_url_service_); |
177 TemplateURLServiceFactory::GetForProfile(profile_); | 176 template_url_service_->SetSearchEngineDialogSlot(choice->slot()); |
178 DCHECK(template_url_service); | |
179 template_url_service->SetSearchEngineDialogSlot(choice->slot()); | |
180 const TemplateURL* default_search = choice->GetSearchEngine(); | 177 const TemplateURL* default_search = choice->GetSearchEngine(); |
181 if (default_search) | 178 if (default_search) |
182 template_url_service->SetDefaultSearchProvider(default_search); | 179 template_url_service_->SetDefaultSearchProvider(default_search); |
183 | 180 |
184 MessageLoop::current()->Quit(); | 181 MessageLoop::current()->Quit(); |
185 } | 182 } |
186 | 183 |
187 void FirstRunSearchEngineView::OnPaint(gfx::Canvas* canvas) { | 184 void FirstRunSearchEngineView::OnPaint(gfx::Canvas* canvas) { |
188 // Fill in behind the background image with the standard gray toolbar color. | 185 // Fill in behind the background image with the standard gray toolbar color. |
189 canvas->FillRectInt(SkColorSetRGB(237, 238, 237), 0, 0, width(), | 186 canvas->FillRectInt(GetThemeProvider()->GetColor(ThemeService::COLOR_TOOLBAR), |
190 background_image_->height()); | 187 0, 0, width(), background_image_->height()); |
191 // The rest of the dialog background should be white. | 188 // The rest of the dialog background should be white. |
192 DCHECK(height() > background_image_->height()); | 189 DCHECK(height() > background_image_->height()); |
193 canvas->FillRectInt(SK_ColorWHITE, 0, background_image_->height(), width(), | 190 canvas->FillRectInt(SK_ColorWHITE, 0, background_image_->height(), width(), |
194 height() - background_image_->height()); | 191 height() - background_image_->height()); |
195 } | 192 } |
196 | 193 |
197 void FirstRunSearchEngineView::OnTemplateURLServiceChanged() { | 194 void FirstRunSearchEngineView::OnTemplateURLServiceChanged() { |
198 using views::ImageView; | |
199 | |
200 // We only watch the search engine model change once, on load. Remove | 195 // We only watch the search engine model change once, on load. Remove |
201 // observer so we don't try to redraw if engines change under us. | 196 // observer so we don't try to redraw if engines change under us. |
202 search_engines_model_->RemoveObserver(this); | 197 template_url_service_->RemoveObserver(this); |
203 | 198 |
204 // Add search engines in search_engines_model_ to buttons list. The | 199 template_url_service_loaded_ = true; |
205 // first three will always be from prepopulated data. | 200 AddSearchEnginesIfPossible(); |
206 std::vector<const TemplateURL*> template_urls = | |
207 search_engines_model_->GetTemplateURLs(); | |
208 | |
209 // If we have fewer than two search engines, end search engine dialog | |
210 // immediately, leaving imported default search engine setting intact. | |
211 if (template_urls.size() < 2) { | |
212 MessageLoop::current()->Quit(); | |
213 return; | |
214 } | |
215 | |
216 std::vector<const TemplateURL*>::iterator search_engine_iter; | |
217 | |
218 // Is user's default search engine included in first three prepopulated | |
219 // set? If not, we need to expand the dialog to include a fourth engine. | |
220 const TemplateURL* default_search_engine = | |
221 search_engines_model_->GetDefaultSearchProvider(); | |
222 // If the user's default choice is not in the first three search engines | |
223 // in template_urls, store it in |default_choice| and provide it as a | |
224 // fourth option. | |
225 SearchEngineChoice* default_choice = NULL; | |
226 | |
227 // First, see if we have 4 logos to show (in which case we use small logos). | |
228 // We show 4 logos when the default search engine the user has chosen is | |
229 // not one of the first three prepopulated engines. | |
230 if (template_urls.size() > 3) { | |
231 for (search_engine_iter = template_urls.begin() + 3; | |
232 search_engine_iter != template_urls.end(); | |
233 ++search_engine_iter) { | |
234 if (default_search_engine == *search_engine_iter) { | |
235 default_choice = new SearchEngineChoice(this, *search_engine_iter, | |
236 true); | |
237 } | |
238 } | |
239 } | |
240 | |
241 // Now that we know what size the logos should be, create new search engine | |
242 // choices for the view. If there are 2 search engines, only show 2 | |
243 // choices; for 3 or more, show 3 (unless the default is not one of the | |
244 // top 3, in which case show 4). | |
245 for (search_engine_iter = template_urls.begin(); | |
246 search_engine_iter < template_urls.begin() + | |
247 (template_urls.size() < 3 ? 2 : 3); | |
248 ++search_engine_iter) { | |
249 // Push first three engines into buttons: | |
250 SearchEngineChoice* choice = new SearchEngineChoice(this, | |
251 *search_engine_iter, default_choice != NULL); | |
252 search_engine_choices_.push_back(choice); | |
253 AddChildView(choice->GetView()); // The logo or text view. | |
254 AddChildView(choice); // The button associated with the choice. | |
255 } | |
256 // Push the default choice to the fourth position. | |
257 if (default_choice) { | |
258 search_engine_choices_.push_back(default_choice); | |
259 AddChildView(default_choice->GetView()); // The logo or text view. | |
260 AddChildView(default_choice); // The button associated with the choice. | |
261 } | |
262 | |
263 // Randomize order of logos if option has been set. | |
264 if (randomize_) { | |
265 std::random_shuffle(search_engine_choices_.begin(), | |
266 search_engine_choices_.end(), | |
267 base::RandGenerator); | |
268 // Assign to each choice the position in which it is shown on the screen. | |
269 std::vector<SearchEngineChoice*>::iterator it; | |
270 int slot = 0; | |
271 for (it = search_engine_choices_.begin(); | |
272 it != search_engine_choices_.end(); | |
273 it++) { | |
274 (*it)->set_slot(slot++); | |
275 } | |
276 } | |
277 | |
278 // Now that we know how many logos to show, lay out and become visible. | |
279 SetVisible(true); | |
280 Layout(); | |
281 SchedulePaint(); | |
282 | |
283 // If the widget has detected that a screenreader is running, change the | |
284 // button names from "Choose" to the name of the search engine. This works | |
285 // around a bug that JAWS ignores the accessible name of a native button. | |
286 if (GetWidget() && GetWidget()->IsAccessibleWidget()) { | |
287 std::vector<SearchEngineChoice*>::iterator it; | |
288 for (it = search_engine_choices_.begin(); | |
289 it != search_engine_choices_.end(); | |
290 it++) { | |
291 (*it)->SetText((*it)->GetSearchEngine()->short_name()); | |
292 } | |
293 } | |
294 | |
295 // This will tell screenreaders that they should read the full text | |
296 // of this dialog to the user now (rather than waiting for the user | |
297 // to explore it). | |
298 GetWidget()->NotifyAccessibilityEvent( | |
299 this, ui::AccessibilityTypes::EVENT_ALERT, true); | |
300 } | 201 } |
301 | 202 |
302 gfx::Size FirstRunSearchEngineView::GetPreferredSize() { | 203 gfx::Size FirstRunSearchEngineView::GetPreferredSize() { |
303 return views::Widget::GetLocalizedContentsSize( | 204 return views::Widget::GetLocalizedContentsSize( |
304 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_WIDTH_CHARS, | 205 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_WIDTH_CHARS, |
305 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_HEIGHT_LINES); | 206 IDS_FIRSTRUN_SEARCH_ENGINE_SELECTION_HEIGHT_LINES); |
306 } | 207 } |
307 | 208 |
308 void FirstRunSearchEngineView::SetupControls() { | |
309 using views::Background; | |
310 using views::ImageView; | |
311 using views::Label; | |
312 | |
313 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
314 background_image_ = new views::ImageView(); | |
315 background_image_->SetImage(rb.GetBitmapNamed(IDR_SEARCH_ENGINE_DIALOG_TOP)); | |
316 background_image_->EnableCanvasFlippingForRTLUI(true); | |
317 if (text_direction_is_rtl_) { | |
318 background_image_->SetHorizontalAlignment(ImageView::LEADING); | |
319 } else { | |
320 background_image_->SetHorizontalAlignment(ImageView::TRAILING); | |
321 } | |
322 | |
323 AddChildView(background_image_); | |
324 | |
325 int label_width = GetPreferredSize().width() - 2 * views::kPanelHorizMargin; | |
326 | |
327 // Add title and text asking the user to choose a search engine: | |
328 title_label_ = new Label(l10n_util::GetStringUTF16( | |
329 IDS_FR_SEARCH_MAIN_LABEL)); | |
330 title_label_->SetColor(SK_ColorBLACK); | |
331 title_label_->SetFont(title_label_->font().DeriveFont(3, gfx::Font::BOLD)); | |
332 title_label_->SetMultiLine(true); | |
333 title_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); | |
334 title_label_->SizeToFit(label_width); | |
335 AddChildView(title_label_); | |
336 | |
337 text_label_ = new Label(l10n_util::GetStringFUTF16( | |
338 IDS_FR_SEARCH_TEXT, | |
339 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); | |
340 text_label_->SetColor(SK_ColorBLACK); | |
341 text_label_->SetFont(text_label_->font().DeriveFont(1, gfx::Font::NORMAL)); | |
342 text_label_->SetMultiLine(true); | |
343 text_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); | |
344 text_label_->SizeToFit(label_width); | |
345 AddChildView(text_label_); | |
346 } | |
347 | |
348 void FirstRunSearchEngineView::Layout() { | 209 void FirstRunSearchEngineView::Layout() { |
349 // Disable the close button. | 210 // Disable the close button. |
350 GetWidget()->EnableClose(false); | 211 GetWidget()->EnableClose(false); |
351 | 212 |
352 gfx::Size pref_size = background_image_->GetPreferredSize(); | 213 gfx::Size pref_size = background_image_->GetPreferredSize(); |
353 background_image_->SetBounds(0, 0, GetPreferredSize().width(), | 214 background_image_->SetBounds(0, 0, GetPreferredSize().width(), |
354 pref_size.height()); | 215 pref_size.height()); |
355 | 216 |
356 // General vertical spacing between elements: | 217 // General vertical spacing between elements: |
357 const int kVertSpacing = 8; | 218 const int kVertSpacing = 8; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 | 311 |
451 if (num_choices > 3) { | 312 if (num_choices > 3) { |
452 next_h_space = search_engine_choices_[2]->x() + logo_width + | 313 next_h_space = search_engine_choices_[2]->x() + logo_width + |
453 logo_padding; | 314 logo_padding; |
454 search_engine_choices_[3]->SetBounds(next_h_space, next_v_space, | 315 search_engine_choices_[3]->SetBounds(next_h_space, next_v_space, |
455 button_width, button_height); | 316 button_width, button_height); |
456 } | 317 } |
457 } // if (search_engine_choices.size() > 0) | 318 } // if (search_engine_choices.size() > 0) |
458 } | 319 } |
459 | 320 |
| 321 void FirstRunSearchEngineView::ViewHierarchyChanged(bool is_add, |
| 322 View* parent, |
| 323 View* child) { |
| 324 View::ViewHierarchyChanged(is_add, parent, child); |
| 325 |
| 326 if (is_add && (child == this)) { |
| 327 background_image_ = new views::ImageView(); |
| 328 background_image_->SetImage( |
| 329 ResourceBundle::GetSharedInstance().GetBitmapNamed( |
| 330 IDR_SEARCH_ENGINE_DIALOG_TOP)); |
| 331 background_image_->EnableCanvasFlippingForRTLUI(true); |
| 332 background_image_->SetHorizontalAlignment(text_direction_is_rtl_ ? |
| 333 views::ImageView::LEADING : views::ImageView::TRAILING); |
| 334 |
| 335 AddChildView(background_image_); |
| 336 |
| 337 int label_width = GetPreferredSize().width() - 2 * views::kPanelHorizMargin; |
| 338 |
| 339 // Add title and text asking the user to choose a search engine: |
| 340 title_label_ = new views::Label(l10n_util::GetStringUTF16( |
| 341 IDS_FR_SEARCH_MAIN_LABEL)); |
| 342 title_label_->SetBackgroundColor( |
| 343 GetThemeProvider()->GetColor(ThemeService::COLOR_TOOLBAR)); |
| 344 title_label_->SetEnabledColor(SK_ColorBLACK); |
| 345 title_label_->SetFont(title_label_->font().DeriveFont(3, gfx::Font::BOLD)); |
| 346 title_label_->SetMultiLine(true); |
| 347 title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 348 title_label_->SizeToFit(label_width); |
| 349 AddChildView(title_label_); |
| 350 |
| 351 text_label_ = new views::Label(l10n_util::GetStringFUTF16( |
| 352 IDS_FR_SEARCH_TEXT, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); |
| 353 text_label_->SetBackgroundColor(SK_ColorWHITE); |
| 354 text_label_->SetEnabledColor(SK_ColorBLACK); |
| 355 text_label_->SetFont(text_label_->font().DeriveFont(1, gfx::Font::NORMAL)); |
| 356 text_label_->SetMultiLine(true); |
| 357 text_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 358 text_label_->SizeToFit(label_width); |
| 359 AddChildView(text_label_); |
| 360 |
| 361 added_to_view_hierarchy_ = true; |
| 362 AddSearchEnginesIfPossible(); |
| 363 } |
| 364 } |
| 365 |
460 void FirstRunSearchEngineView::GetAccessibleState( | 366 void FirstRunSearchEngineView::GetAccessibleState( |
461 ui::AccessibleViewState* state) { | 367 ui::AccessibleViewState* state) { |
462 state->role = ui::AccessibilityTypes::ROLE_ALERT; | 368 state->role = ui::AccessibilityTypes::ROLE_ALERT; |
463 } | 369 } |
| 370 |
| 371 void FirstRunSearchEngineView::AddSearchEnginesIfPossible() { |
| 372 if (!template_url_service_loaded_ || !added_to_view_hierarchy_) |
| 373 return; |
| 374 |
| 375 // Add search engines in template_url_service_ to buttons list. The |
| 376 // first three will always be from prepopulated data. |
| 377 std::vector<const TemplateURL*> template_urls = |
| 378 template_url_service_->GetTemplateURLs(); |
| 379 |
| 380 // If we have fewer than two search engines, end search engine dialog |
| 381 // immediately, leaving imported default search engine setting intact. |
| 382 if (template_urls.size() < 2) { |
| 383 MessageLoop::current()->Quit(); |
| 384 return; |
| 385 } |
| 386 |
| 387 std::vector<const TemplateURL*>::iterator search_engine_iter; |
| 388 |
| 389 // Is user's default search engine included in first three prepopulated |
| 390 // set? If not, we need to expand the dialog to include a fourth engine. |
| 391 const TemplateURL* default_search_engine = |
| 392 template_url_service_->GetDefaultSearchProvider(); |
| 393 // If the user's default choice is not in the first three search engines |
| 394 // in template_urls, store it in |default_choice| and provide it as a |
| 395 // fourth option. |
| 396 SearchEngineChoice* default_choice = NULL; |
| 397 |
| 398 // First, see if we have 4 logos to show (in which case we use small logos). |
| 399 // We show 4 logos when the default search engine the user has chosen is |
| 400 // not one of the first three prepopulated engines. |
| 401 if (template_urls.size() > 3) { |
| 402 for (search_engine_iter = template_urls.begin() + 3; |
| 403 search_engine_iter != template_urls.end(); |
| 404 ++search_engine_iter) { |
| 405 if (default_search_engine == *search_engine_iter) { |
| 406 default_choice = new SearchEngineChoice(this, *search_engine_iter, |
| 407 true); |
| 408 } |
| 409 } |
| 410 } |
| 411 |
| 412 // Now that we know what size the logos should be, create new search engine |
| 413 // choices for the view. If there are 2 search engines, only show 2 |
| 414 // choices; for 3 or more, show 3 (unless the default is not one of the |
| 415 // top 3, in which case show 4). |
| 416 for (search_engine_iter = template_urls.begin(); |
| 417 search_engine_iter < template_urls.begin() + |
| 418 (template_urls.size() < 3 ? 2 : 3); |
| 419 ++search_engine_iter) { |
| 420 // Push first three engines into buttons: |
| 421 SearchEngineChoice* choice = new SearchEngineChoice(this, |
| 422 *search_engine_iter, default_choice != NULL); |
| 423 search_engine_choices_.push_back(choice); |
| 424 AddChildView(choice->GetView()); // The logo or text view. |
| 425 AddChildView(choice); // The button associated with the choice. |
| 426 } |
| 427 // Push the default choice to the fourth position. |
| 428 if (default_choice) { |
| 429 search_engine_choices_.push_back(default_choice); |
| 430 AddChildView(default_choice->GetView()); // The logo or text view. |
| 431 AddChildView(default_choice); // The button associated with the choice. |
| 432 } |
| 433 |
| 434 // Randomize order of logos if option has been set. |
| 435 if (randomize_) { |
| 436 std::random_shuffle(search_engine_choices_.begin(), |
| 437 search_engine_choices_.end(), |
| 438 base::RandGenerator); |
| 439 // Assign to each choice the position in which it is shown on the screen. |
| 440 std::vector<SearchEngineChoice*>::iterator it; |
| 441 int slot = 0; |
| 442 for (it = search_engine_choices_.begin(); |
| 443 it != search_engine_choices_.end(); |
| 444 it++) { |
| 445 (*it)->set_slot(slot++); |
| 446 } |
| 447 } |
| 448 |
| 449 // Now that we know how many logos to show, lay out and become visible. |
| 450 SetVisible(true); |
| 451 Layout(); |
| 452 SchedulePaint(); |
| 453 |
| 454 // If the widget has detected that a screenreader is running, change the |
| 455 // button names from "Choose" to the name of the search engine. This works |
| 456 // around a bug that JAWS ignores the accessible name of a native button. |
| 457 if (GetWidget() && GetWidget()->IsAccessibleWidget()) { |
| 458 std::vector<SearchEngineChoice*>::iterator it; |
| 459 for (it = search_engine_choices_.begin(); |
| 460 it != search_engine_choices_.end(); |
| 461 it++) { |
| 462 (*it)->SetText((*it)->GetSearchEngine()->short_name()); |
| 463 } |
| 464 } |
| 465 |
| 466 // This will tell screenreaders that they should read the full text |
| 467 // of this dialog to the user now (rather than waiting for the user |
| 468 // to explore it). |
| 469 GetWidget()->NotifyAccessibilityEvent( |
| 470 this, ui::AccessibilityTypes::EVENT_ALERT, true); |
| 471 } |
OLD | NEW |