Refactor views app list services to allow more code sharing
[chromium-blink-merge.git] / chrome / browser / ui / views / translate / translate_bubble_view.cc
blobba6c6bd7bac67d0e51a0c70cf9ccad1de13c3b66
1 // Copyright 2013 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.
5 #include "chrome/browser/ui/views/translate/translate_bubble_view.h"
7 #include <algorithm>
8 #include <string>
9 #include <vector>
11 #include "base/i18n/string_compare.h"
12 #include "base/memory/singleton.h"
13 #include "base/metrics/histogram.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/translate/translate_service.h"
19 #include "chrome/browser/translate/translate_tab_helper.h"
20 #include "chrome/browser/ui/chrome_pages.h"
21 #include "chrome/browser/ui/translate/translate_bubble_model_impl.h"
22 #include "chrome/common/url_constants.h"
23 #include "components/translate/core/browser/translate_download_manager.h"
24 #include "components/translate/core/browser/translate_manager.h"
25 #include "components/translate/core/browser/translate_ui_delegate.h"
26 #include "content/public/browser/web_contents.h"
27 #include "grit/generated_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/models/combobox_model.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/views/controls/button/checkbox.h"
32 #include "ui/views/controls/button/label_button.h"
33 #include "ui/views/controls/combobox/combobox.h"
34 #include "ui/views/controls/label.h"
35 #include "ui/views/controls/link.h"
36 #include "ui/views/layout/box_layout.h"
37 #include "ui/views/layout/grid_layout.h"
38 #include "ui/views/layout/layout_constants.h"
39 #include "ui/views/widget/widget.h"
41 namespace {
43 views::LabelButton* CreateLabelButton(views::ButtonListener* listener,
44 const base::string16& label,
45 int id) {
46 views::LabelButton* button = new views::LabelButton(listener, label);
47 button->set_id(id);
48 button->SetStyle(views::Button::STYLE_BUTTON);
49 return button;
52 views::Link* CreateLink(views::LinkListener* listener,
53 int resource_id,
54 int id) {
55 views::Link* link = new views::Link(
56 l10n_util::GetStringUTF16(resource_id));
57 link->set_listener(listener);
58 link->set_id(id);
59 return link;
62 class TranslateDenialComboboxModel : public ui::ComboboxModel {
63 public:
64 enum {
65 INDEX_NOPE = 0,
66 INDEX_NEVER_TRANSLATE_LANGUAGE = 2,
67 INDEX_NEVER_TRANSLATE_SITE = 4,
70 explicit TranslateDenialComboboxModel(
71 const base::string16& original_language_name) {
72 items_.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
73 items_.push_back(base::string16());
74 items_.push_back(l10n_util::GetStringFUTF16(
75 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
76 original_language_name));
77 items_.push_back(base::string16());
78 items_.push_back(l10n_util::GetStringUTF16(
79 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
81 virtual ~TranslateDenialComboboxModel() {}
83 private:
84 // Overridden from ui::ComboboxModel:
85 virtual int GetItemCount() const OVERRIDE {
86 return items_.size();
88 virtual base::string16 GetItemAt(int index) OVERRIDE {
89 return items_[index];
91 virtual bool IsItemSeparatorAt(int index) OVERRIDE {
92 return items_[index].empty();
94 virtual int GetDefaultIndex() const OVERRIDE {
95 return 0;
98 std::vector<base::string16> items_;
100 DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel);
103 } // namespace
105 // static
106 TranslateBubbleView* TranslateBubbleView::translate_bubble_view_ = NULL;
108 TranslateBubbleView::~TranslateBubbleView() {
109 // A child view could refer to a model which is owned by this class when
110 // the child view is destructed. For example, |source_language_combobx_model_|
111 // is referred by Combobox's destructor. Before destroying the models,
112 // removing the child views is needed.
113 RemoveAllChildViews(true);
116 // static
117 void TranslateBubbleView::ShowBubble(views::View* anchor_view,
118 content::WebContents* web_contents,
119 translate::TranslateStep step,
120 TranslateErrors::Type error_type) {
121 if (IsShowing()) {
122 // When the user reads the advanced setting panel, the bubble should not be
123 // changed because he/she is focusing on the bubble.
124 if (translate_bubble_view_->web_contents() == web_contents &&
125 translate_bubble_view_->model()->GetViewState() ==
126 TranslateBubbleModel::VIEW_STATE_ADVANCED) {
127 return;
129 if (step != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
130 TranslateBubbleModel::ViewState state =
131 TranslateBubbleModelImpl::TranslateStepToViewState(step);
132 translate_bubble_view_->SwitchView(state);
133 } else {
134 translate_bubble_view_->SwitchToErrorView(error_type);
136 return;
139 std::string source_language;
140 std::string target_language;
141 TranslateTabHelper::GetTranslateLanguages(web_contents,
142 &source_language, &target_language);
144 scoped_ptr<TranslateUIDelegate> ui_delegate(new TranslateUIDelegate(
145 TranslateTabHelper::FromWebContents(web_contents),
146 TranslateTabHelper::GetManagerFromWebContents(web_contents),
147 source_language,
148 target_language));
149 scoped_ptr<TranslateBubbleModel> model(
150 new TranslateBubbleModelImpl(step, ui_delegate.Pass()));
151 TranslateBubbleView* view = new TranslateBubbleView(anchor_view,
152 model.Pass(),
153 error_type,
154 web_contents);
155 views::BubbleDelegateView::CreateBubble(view)->Show();
158 // static
159 bool TranslateBubbleView::IsShowing() {
160 return translate_bubble_view_ != NULL;
163 // static
164 TranslateBubbleView* TranslateBubbleView::GetCurrentBubble() {
165 return translate_bubble_view_;
168 void TranslateBubbleView::Init() {
169 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
170 0, 0, 0));
172 before_translate_view_ = CreateViewBeforeTranslate();
173 translating_view_ = CreateViewTranslating();
174 after_translate_view_ = CreateViewAfterTranslate();
175 error_view_ = CreateViewError();
176 advanced_view_ = CreateViewAdvanced();
178 AddChildView(before_translate_view_);
179 AddChildView(translating_view_);
180 AddChildView(after_translate_view_);
181 AddChildView(error_view_);
182 AddChildView(advanced_view_);
184 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
186 UpdateChildVisibilities();
188 if (model_->GetViewState() == TranslateBubbleModel::VIEW_STATE_ERROR)
189 model_->ShowError(error_type_);
192 void TranslateBubbleView::ButtonPressed(views::Button* sender,
193 const ui::Event& event) {
194 HandleButtonPressed(static_cast<ButtonID>(sender->id()));
197 void TranslateBubbleView::WindowClosing() {
198 // The operations for |model_| are valid only when a WebContents is alive.
199 // TODO(hajimehoshi): TranslateBubbleViewModel(Impl) should not hold a
200 // WebContents as a member variable because the WebContents might be destroyed
201 // while the TranslateBubbleViewModel(Impl) is still alive. Instead,
202 // TranslateBubbleViewModel should take a reference of a WebContents at each
203 // method. (crbug/320497)
204 if (!translate_executed_ && web_contents())
205 model_->TranslationDeclined(denial_button_clicked_);
207 // We have to reset |translate_bubble_view_| here, not in our destructor,
208 // because we'll be destroyed asynchronously and the shown state will be
209 // checked before then.
210 DCHECK_EQ(translate_bubble_view_, this);
211 translate_bubble_view_ = NULL;
214 bool TranslateBubbleView::AcceleratorPressed(
215 const ui::Accelerator& accelerator) {
216 switch (model_->GetViewState()) {
217 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE: {
218 if (accelerator.key_code() == ui::VKEY_RETURN) {
219 HandleButtonPressed(BUTTON_ID_TRANSLATE);
220 return true;
222 break;
224 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
225 break;
226 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE: {
227 if (accelerator.key_code() == ui::VKEY_RETURN) {
228 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL);
229 return true;
231 break;
233 case TranslateBubbleModel::VIEW_STATE_ERROR:
234 break;
235 case TranslateBubbleModel::VIEW_STATE_ADVANCED: {
236 if (accelerator.key_code() == ui::VKEY_RETURN) {
237 HandleButtonPressed(BUTTON_ID_DONE);
238 return true;
240 break;
243 return BubbleDelegateView::AcceleratorPressed(accelerator);
246 gfx::Size TranslateBubbleView::GetPreferredSize() {
247 int width = 0;
248 for (int i = 0; i < child_count(); i++) {
249 views::View* child = child_at(i);
250 width = std::max(width, child->GetPreferredSize().width());
252 int height = GetCurrentView()->GetPreferredSize().height();
253 return gfx::Size(width, height);
256 void TranslateBubbleView::OnPerformAction(views::Combobox* combobox) {
257 HandleComboboxPerformAction(static_cast<ComboboxID>(combobox->id()));
260 void TranslateBubbleView::LinkClicked(views::Link* source, int event_flags) {
261 HandleLinkClicked(static_cast<LinkID>(source->id()));
264 void TranslateBubbleView::WebContentsDestroyed(
265 content::WebContents* web_contents) {
266 GetWidget()->CloseNow();
269 TranslateBubbleModel::ViewState TranslateBubbleView::GetViewState() const {
270 return model_->GetViewState();
273 TranslateBubbleView::TranslateBubbleView(
274 views::View* anchor_view,
275 scoped_ptr<TranslateBubbleModel> model,
276 TranslateErrors::Type error_type,
277 content::WebContents* web_contents)
278 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
279 WebContentsObserver(web_contents),
280 before_translate_view_(NULL),
281 translating_view_(NULL),
282 after_translate_view_(NULL),
283 error_view_(NULL),
284 advanced_view_(NULL),
285 denial_combobox_(NULL),
286 source_language_combobox_(NULL),
287 target_language_combobox_(NULL),
288 always_translate_checkbox_(NULL),
289 advanced_cancel_button_(NULL),
290 advanced_done_button_(NULL),
291 model_(model.Pass()),
292 error_type_(error_type),
293 is_in_incognito_window_(
294 web_contents ?
295 web_contents->GetBrowserContext()->IsOffTheRecord() : false),
296 translate_executed_(false),
297 denial_button_clicked_(false) {
298 if (model_->GetViewState() !=
299 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) {
300 translate_executed_ = true;
303 set_margins(gfx::Insets(views::kPanelVertMargin, views::kPanelHorizMargin,
304 views::kPanelVertMargin, views::kPanelHorizMargin));
306 translate_bubble_view_ = this;
309 views::View* TranslateBubbleView::GetCurrentView() {
310 switch (model_->GetViewState()) {
311 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE:
312 return before_translate_view_;
313 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
314 return translating_view_;
315 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE:
316 return after_translate_view_;
317 case TranslateBubbleModel::VIEW_STATE_ERROR:
318 return error_view_;
319 case TranslateBubbleModel::VIEW_STATE_ADVANCED:
320 return advanced_view_;
322 NOTREACHED();
323 return NULL;
326 void TranslateBubbleView::HandleButtonPressed(
327 TranslateBubbleView::ButtonID sender_id) {
328 switch (sender_id) {
329 case BUTTON_ID_TRANSLATE: {
330 translate_executed_ = true;
331 model_->Translate();
332 break;
334 case BUTTON_ID_DONE: {
335 if (always_translate_checkbox_)
336 model_->SetAlwaysTranslate(always_translate_checkbox_->checked());
337 if (model_->IsPageTranslatedInCurrentLanguages()) {
338 model_->GoBackFromAdvanced();
339 UpdateChildVisibilities();
340 SizeToContents();
341 } else {
342 translate_executed_ = true;
343 model_->Translate();
344 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
346 break;
348 case BUTTON_ID_CANCEL: {
349 model_->GoBackFromAdvanced();
350 UpdateChildVisibilities();
351 SizeToContents();
352 break;
354 case BUTTON_ID_TRY_AGAIN: {
355 translate_executed_ = true;
356 model_->Translate();
357 break;
359 case BUTTON_ID_SHOW_ORIGINAL: {
360 model_->RevertTranslation();
361 GetWidget()->Close();
362 break;
364 case BUTTON_ID_ALWAYS_TRANSLATE: {
365 // Do nothing. The state of the checkbox affects only when the 'Done'
366 // button is pressed.
367 break;
372 void TranslateBubbleView::HandleLinkClicked(
373 TranslateBubbleView::LinkID sender_id) {
374 switch (sender_id) {
375 case LINK_ID_ADVANCED: {
376 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
377 break;
379 case LINK_ID_LANGUAGE_SETTINGS: {
380 GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
381 web_contents()->OpenURL(content::OpenURLParams(
382 url,
383 content::Referrer(),
384 NEW_FOREGROUND_TAB,
385 content::PAGE_TRANSITION_LINK,
386 false));
387 break;
392 void TranslateBubbleView::HandleComboboxPerformAction(
393 TranslateBubbleView::ComboboxID sender_id) {
394 switch (sender_id) {
395 case COMBOBOX_ID_DENIAL: {
396 denial_button_clicked_ = true;
397 int index = denial_combobox_->selected_index();
398 switch (index) {
399 case TranslateDenialComboboxModel::INDEX_NOPE:
400 break;
401 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_LANGUAGE:
402 model_->SetNeverTranslateLanguage(true);
403 break;
404 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_SITE:
405 model_->SetNeverTranslateSite(true);
406 break;
407 default:
408 NOTREACHED();
409 break;
411 GetWidget()->Close();
412 break;
414 case COMBOBOX_ID_SOURCE_LANGUAGE: {
415 if (model_->GetOriginalLanguageIndex() ==
416 source_language_combobox_->selected_index()) {
417 break;
419 model_->UpdateOriginalLanguageIndex(
420 source_language_combobox_->selected_index());
421 UpdateAdvancedView();
422 break;
424 case COMBOBOX_ID_TARGET_LANGUAGE: {
425 if (model_->GetTargetLanguageIndex() ==
426 target_language_combobox_->selected_index()) {
427 break;
429 model_->UpdateTargetLanguageIndex(
430 target_language_combobox_->selected_index());
431 UpdateAdvancedView();
432 break;
437 void TranslateBubbleView::UpdateChildVisibilities() {
438 for (int i = 0; i < child_count(); i++) {
439 views::View* view = child_at(i);
440 view->SetVisible(view == GetCurrentView());
444 views::View* TranslateBubbleView::CreateViewBeforeTranslate() {
445 views::Label* message_label = new views::Label(
446 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE));
448 base::string16 original_language_name =
449 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
450 denial_combobox_ = new views::Combobox(
451 new TranslateDenialComboboxModel(original_language_name));
452 denial_combobox_->set_id(COMBOBOX_ID_DENIAL);
453 denial_combobox_->set_listener(this);
454 denial_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
456 views::View* view = new views::View();
457 views::GridLayout* layout = new views::GridLayout(view);
458 view->SetLayoutManager(layout);
460 using views::GridLayout;
462 enum {
463 COLUMN_SET_ID_MESSAGE,
464 COLUMN_SET_ID_CONTENT,
467 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
468 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
469 0, GridLayout::USE_PREF, 0, 0);
470 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
471 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
472 0, GridLayout::USE_PREF, 0, 0);
473 cs->AddPaddingColumn(1, 0);
475 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
476 cs->AddPaddingColumn(1, 0);
477 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
478 0, GridLayout::USE_PREF, 0, 0);
479 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
480 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
481 0, GridLayout::USE_PREF, 0, 0);
483 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
484 layout->AddView(message_label);
485 layout->AddView(CreateLink(this,
486 IDS_TRANSLATE_BUBBLE_ADVANCED,
487 LINK_ID_ADVANCED));
489 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
491 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
492 layout->AddView(CreateLabelButton(
493 this,
494 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT),
495 BUTTON_ID_TRANSLATE));
496 layout->AddView(denial_combobox_);
498 return view;
501 views::View* TranslateBubbleView::CreateViewTranslating() {
502 base::string16 target_language_name =
503 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
504 views::Label* label = new views::Label(
505 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATING));
507 views::View* view = new views::View();
508 views::GridLayout* layout = new views::GridLayout(view);
509 view->SetLayoutManager(layout);
511 using views::GridLayout;
513 enum {
514 COLUMN_SET_ID_MESSAGE,
515 COLUMN_SET_ID_CONTENT,
518 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
519 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
520 0, views::GridLayout::USE_PREF, 0, 0);
521 cs->AddPaddingColumn(1, 0);
523 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
524 cs->AddPaddingColumn(1, 0);
525 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
526 0, GridLayout::USE_PREF, 0, 0);
528 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
529 layout->AddView(label);
531 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
533 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
534 views::LabelButton* revert_button = CreateLabelButton(
535 this,
536 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
537 BUTTON_ID_SHOW_ORIGINAL);
538 revert_button->SetEnabled(false);
539 layout->AddView(revert_button);
541 return view;
544 views::View* TranslateBubbleView::CreateViewAfterTranslate() {
545 views::Label* label = new views::Label(
546 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATED));
548 views::View* view = new views::View();
549 views::GridLayout* layout = new views::GridLayout(view);
550 view->SetLayoutManager(layout);
552 using views::GridLayout;
554 enum {
555 COLUMN_SET_ID_MESSAGE,
556 COLUMN_SET_ID_CONTENT,
559 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
560 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
561 0, views::GridLayout::USE_PREF, 0, 0);
562 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
563 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
564 0, views::GridLayout::USE_PREF, 0, 0);
565 cs->AddPaddingColumn(1, 0);
567 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
568 cs->AddPaddingColumn(1, 0);
569 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
570 0, GridLayout::USE_PREF, 0, 0);
572 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
573 layout->AddView(label);
574 layout->AddView(CreateLink(this,
575 IDS_TRANSLATE_BUBBLE_ADVANCED,
576 LINK_ID_ADVANCED));
578 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
580 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
581 layout->AddView(CreateLabelButton(
582 this,
583 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
584 BUTTON_ID_SHOW_ORIGINAL));
586 return view;
589 views::View* TranslateBubbleView::CreateViewError() {
590 views::Label* label = new views::Label(
591 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE));
593 views::View* view = new views::View();
594 views::GridLayout* layout = new views::GridLayout(view);
595 view->SetLayoutManager(layout);
597 using views::GridLayout;
599 enum {
600 COLUMN_SET_ID_MESSAGE,
601 COLUMN_SET_ID_CONTENT,
604 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
605 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
606 0, GridLayout::USE_PREF, 0, 0);
607 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
608 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
609 0, GridLayout::USE_PREF, 0, 0);
610 cs->AddPaddingColumn(1, 0);
612 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
613 cs->AddPaddingColumn(1, 0);
614 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
615 0, GridLayout::USE_PREF, 0, 0);
617 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
618 layout->AddView(label);
619 layout->AddView(CreateLink(this,
620 IDS_TRANSLATE_BUBBLE_ADVANCED,
621 LINK_ID_ADVANCED));
623 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
625 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
626 layout->AddView(CreateLabelButton(
627 this,
628 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN),
629 BUTTON_ID_TRY_AGAIN));
631 return view;
634 // TODO(hajimehoshi): Revice this later to show a specific message for each
635 // error. (crbug/307350)
636 views::View* TranslateBubbleView::CreateViewAdvanced() {
637 views::Label* source_language_label = new views::Label(
638 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE));
640 views::Label* target_language_label = new views::Label(
641 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE));
643 int source_default_index = model_->GetOriginalLanguageIndex();
644 source_language_combobox_model_.reset(
645 new LanguageComboboxModel(source_default_index, model_.get()));
646 source_language_combobox_ =
647 new views::Combobox(source_language_combobox_model_.get());
649 source_language_combobox_->set_id(COMBOBOX_ID_SOURCE_LANGUAGE);
650 source_language_combobox_->set_listener(this);
652 int target_default_index = model_->GetTargetLanguageIndex();
653 target_language_combobox_model_.reset(
654 new LanguageComboboxModel(target_default_index, model_.get()));
655 target_language_combobox_ =
656 new views::Combobox(target_language_combobox_model_.get());
658 target_language_combobox_->set_id(COMBOBOX_ID_TARGET_LANGUAGE);
659 target_language_combobox_->set_listener(this);
661 // In an incognito window, "Always translate" checkbox shouldn't be shown.
662 if (!is_in_incognito_window_) {
663 always_translate_checkbox_ = new views::Checkbox(base::string16());
664 always_translate_checkbox_->set_id(BUTTON_ID_ALWAYS_TRANSLATE);
665 always_translate_checkbox_->set_listener(this);
668 views::View* view = new views::View();
669 views::GridLayout* layout = new views::GridLayout(view);
670 view->SetLayoutManager(layout);
672 using views::GridLayout;
674 enum {
675 COLUMN_SET_ID_LANGUAGES,
676 COLUMN_SET_ID_BUTTONS,
679 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
680 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER,
681 0, GridLayout::USE_PREF, 0, 0);
682 cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
683 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER,
684 0, GridLayout::USE_PREF, 0, 0);
685 cs->AddPaddingColumn(1, 0);
687 cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
688 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
689 0, GridLayout::USE_PREF, 0, 0);
690 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
691 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
692 0, GridLayout::USE_PREF, 0, 0);
693 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
694 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
695 0, GridLayout::USE_PREF, 0, 0);
697 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
698 layout->AddView(source_language_label);
699 layout->AddView(source_language_combobox_);
701 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
703 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
704 layout->AddView(target_language_label);
705 layout->AddView(target_language_combobox_);
707 if (!is_in_incognito_window_) {
708 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
709 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
710 layout->SkipColumns(1);
711 layout->AddView(always_translate_checkbox_);
714 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
716 layout->StartRow(0, COLUMN_SET_ID_BUTTONS);
717 layout->AddView(CreateLink(this,
718 IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS,
719 LINK_ID_LANGUAGE_SETTINGS));
720 advanced_done_button_ = CreateLabelButton(
721 this, l10n_util::GetStringUTF16(IDS_DONE), BUTTON_ID_DONE);
722 advanced_done_button_->SetIsDefault(true);
723 advanced_cancel_button_ = CreateLabelButton(
724 this, l10n_util::GetStringUTF16(IDS_CANCEL), BUTTON_ID_CANCEL);
725 layout->AddView(advanced_done_button_);
726 layout->AddView(advanced_cancel_button_);
728 UpdateAdvancedView();
730 return view;
733 void TranslateBubbleView::SwitchView(
734 TranslateBubbleModel::ViewState view_state) {
735 if (model_->GetViewState() == view_state)
736 return;
738 model_->SetViewState(view_state);
739 UpdateChildVisibilities();
740 if (view_state == TranslateBubbleModel::VIEW_STATE_ADVANCED)
741 UpdateAdvancedView();
742 SizeToContents();
745 void TranslateBubbleView::SwitchToErrorView(TranslateErrors::Type error_type) {
746 SwitchView(TranslateBubbleModel::VIEW_STATE_ERROR);
747 error_type_ = error_type;
748 model_->ShowError(error_type);
751 void TranslateBubbleView::UpdateAdvancedView() {
752 DCHECK(source_language_combobox_);
753 DCHECK(target_language_combobox_);
754 DCHECK(advanced_done_button_);
756 base::string16 source_language_name =
757 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
758 base::string16 target_language_name =
759 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
761 // "Always translate" checkbox doesn't exist in an incognito window.
762 if (always_translate_checkbox_) {
763 always_translate_checkbox_->SetText(
764 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ALWAYS));
765 always_translate_checkbox_->SetChecked(
766 model_->ShouldAlwaysTranslate());
769 base::string16 label;
770 if (model_->IsPageTranslatedInCurrentLanguages())
771 label = l10n_util::GetStringUTF16(IDS_DONE);
772 else
773 label = l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT);
774 advanced_done_button_->SetText(label);