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"
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/chrome_translate_client.h"
19 #include "chrome/browser/translate/translate_service.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/models/simple_combobox_model.h"
31 #include "ui/base/resource/resource_bundle.h"
32 #include "ui/views/controls/button/checkbox.h"
33 #include "ui/views/controls/button/label_button.h"
34 #include "ui/views/controls/combobox/combobox.h"
35 #include "ui/views/controls/label.h"
36 #include "ui/views/controls/link.h"
37 #include "ui/views/layout/box_layout.h"
38 #include "ui/views/layout/grid_layout.h"
39 #include "ui/views/layout/layout_constants.h"
40 #include "ui/views/widget/widget.h"
44 enum DenialComboboxIndexes {
46 INDEX_NEVER_TRANSLATE_LANGUAGE = 2,
47 INDEX_NEVER_TRANSLATE_SITE = 4,
50 views::LabelButton* CreateLabelButton(views::ButtonListener* listener,
51 const base::string16& label,
53 views::LabelButton* button = new views::LabelButton(listener, label);
55 button->SetStyle(views::Button::STYLE_BUTTON);
59 views::Link* CreateLink(views::LinkListener* listener,
62 views::Link* link = new views::Link(
63 l10n_util::GetStringUTF16(resource_id));
64 link->set_listener(listener);
72 TranslateBubbleView* TranslateBubbleView::translate_bubble_view_ = NULL;
74 TranslateBubbleView::~TranslateBubbleView() {
75 // A child view could refer to a model which is owned by this class when
76 // the child view is destructed. For example, |source_language_combobx_model_|
77 // is referred by Combobox's destructor. Before destroying the models,
78 // removing the child views is needed.
79 RemoveAllChildViews(true);
83 void TranslateBubbleView::ShowBubble(views::View* anchor_view,
84 content::WebContents* web_contents,
85 translate::TranslateStep step,
86 TranslateErrors::Type error_type) {
88 // When the user reads the advanced setting panel, the bubble should not be
89 // changed because he/she is focusing on the bubble.
90 if (translate_bubble_view_->web_contents() == web_contents &&
91 translate_bubble_view_->model()->GetViewState() ==
92 TranslateBubbleModel::VIEW_STATE_ADVANCED) {
95 if (step != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
96 TranslateBubbleModel::ViewState state =
97 TranslateBubbleModelImpl::TranslateStepToViewState(step);
98 translate_bubble_view_->SwitchView(state);
100 translate_bubble_view_->SwitchToErrorView(error_type);
105 std::string source_language;
106 std::string target_language;
107 ChromeTranslateClient::GetTranslateLanguages(
108 web_contents, &source_language, &target_language);
110 scoped_ptr<TranslateUIDelegate> ui_delegate(new TranslateUIDelegate(
111 ChromeTranslateClient::GetManagerFromWebContents(web_contents)
115 scoped_ptr<TranslateBubbleModel> model(
116 new TranslateBubbleModelImpl(step, ui_delegate.Pass()));
117 TranslateBubbleView* view = new TranslateBubbleView(anchor_view,
121 views::BubbleDelegateView::CreateBubble(view)->Show();
125 bool TranslateBubbleView::IsShowing() {
126 return translate_bubble_view_ != NULL;
130 TranslateBubbleView* TranslateBubbleView::GetCurrentBubble() {
131 return translate_bubble_view_;
134 void TranslateBubbleView::Init() {
135 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
138 before_translate_view_ = CreateViewBeforeTranslate();
139 translating_view_ = CreateViewTranslating();
140 after_translate_view_ = CreateViewAfterTranslate();
141 error_view_ = CreateViewError();
142 advanced_view_ = CreateViewAdvanced();
144 AddChildView(before_translate_view_);
145 AddChildView(translating_view_);
146 AddChildView(after_translate_view_);
147 AddChildView(error_view_);
148 AddChildView(advanced_view_);
150 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
152 UpdateChildVisibilities();
154 if (model_->GetViewState() == TranslateBubbleModel::VIEW_STATE_ERROR)
155 model_->ShowError(error_type_);
158 void TranslateBubbleView::ButtonPressed(views::Button* sender,
159 const ui::Event& event) {
160 HandleButtonPressed(static_cast<ButtonID>(sender->id()));
163 void TranslateBubbleView::WindowClosing() {
164 // The operations for |model_| are valid only when a WebContents is alive.
165 // TODO(hajimehoshi): TranslateBubbleViewModel(Impl) should not hold a
166 // WebContents as a member variable because the WebContents might be destroyed
167 // while the TranslateBubbleViewModel(Impl) is still alive. Instead,
168 // TranslateBubbleViewModel should take a reference of a WebContents at each
169 // method. (crbug/320497)
170 if (!translate_executed_ && web_contents())
171 model_->TranslationDeclined(denial_button_clicked_);
173 // We have to reset |translate_bubble_view_| here, not in our destructor,
174 // because we'll be destroyed asynchronously and the shown state will be
175 // checked before then.
176 DCHECK_EQ(translate_bubble_view_, this);
177 translate_bubble_view_ = NULL;
180 bool TranslateBubbleView::AcceleratorPressed(
181 const ui::Accelerator& accelerator) {
182 switch (model_->GetViewState()) {
183 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE: {
184 if (accelerator.key_code() == ui::VKEY_RETURN) {
185 HandleButtonPressed(BUTTON_ID_TRANSLATE);
190 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
192 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE: {
193 if (accelerator.key_code() == ui::VKEY_RETURN) {
194 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL);
199 case TranslateBubbleModel::VIEW_STATE_ERROR:
201 case TranslateBubbleModel::VIEW_STATE_ADVANCED: {
202 if (accelerator.key_code() == ui::VKEY_RETURN) {
203 HandleButtonPressed(BUTTON_ID_DONE);
209 return BubbleDelegateView::AcceleratorPressed(accelerator);
212 gfx::Size TranslateBubbleView::GetPreferredSize() const {
214 for (int i = 0; i < child_count(); i++) {
215 const views::View* child = child_at(i);
216 width = std::max(width, child->GetPreferredSize().width());
218 int height = GetCurrentView()->GetPreferredSize().height();
219 return gfx::Size(width, height);
222 void TranslateBubbleView::OnPerformAction(views::Combobox* combobox) {
223 HandleComboboxPerformAction(static_cast<ComboboxID>(combobox->id()));
226 void TranslateBubbleView::LinkClicked(views::Link* source, int event_flags) {
227 HandleLinkClicked(static_cast<LinkID>(source->id()));
230 void TranslateBubbleView::WebContentsDestroyed() {
231 GetWidget()->CloseNow();
234 TranslateBubbleModel::ViewState TranslateBubbleView::GetViewState() const {
235 return model_->GetViewState();
238 TranslateBubbleView::TranslateBubbleView(
239 views::View* anchor_view,
240 scoped_ptr<TranslateBubbleModel> model,
241 TranslateErrors::Type error_type,
242 content::WebContents* web_contents)
243 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
244 WebContentsObserver(web_contents),
245 before_translate_view_(NULL),
246 translating_view_(NULL),
247 after_translate_view_(NULL),
249 advanced_view_(NULL),
250 denial_combobox_(NULL),
251 source_language_combobox_(NULL),
252 target_language_combobox_(NULL),
253 always_translate_checkbox_(NULL),
254 advanced_cancel_button_(NULL),
255 advanced_done_button_(NULL),
256 model_(model.Pass()),
257 error_type_(error_type),
258 is_in_incognito_window_(
260 web_contents->GetBrowserContext()->IsOffTheRecord() : false),
261 translate_executed_(false),
262 denial_button_clicked_(false) {
263 if (model_->GetViewState() !=
264 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) {
265 translate_executed_ = true;
268 set_margins(gfx::Insets(views::kPanelVertMargin, views::kPanelHorizMargin,
269 views::kPanelVertMargin, views::kPanelHorizMargin));
271 translate_bubble_view_ = this;
274 views::View* TranslateBubbleView::GetCurrentView() const {
275 switch (model_->GetViewState()) {
276 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE:
277 return before_translate_view_;
278 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
279 return translating_view_;
280 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE:
281 return after_translate_view_;
282 case TranslateBubbleModel::VIEW_STATE_ERROR:
284 case TranslateBubbleModel::VIEW_STATE_ADVANCED:
285 return advanced_view_;
291 void TranslateBubbleView::HandleButtonPressed(
292 TranslateBubbleView::ButtonID sender_id) {
294 case BUTTON_ID_TRANSLATE: {
295 translate_executed_ = true;
299 case BUTTON_ID_DONE: {
300 if (always_translate_checkbox_)
301 model_->SetAlwaysTranslate(always_translate_checkbox_->checked());
302 if (model_->IsPageTranslatedInCurrentLanguages()) {
303 model_->GoBackFromAdvanced();
304 UpdateChildVisibilities();
307 translate_executed_ = true;
309 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
313 case BUTTON_ID_CANCEL: {
314 model_->GoBackFromAdvanced();
315 UpdateChildVisibilities();
319 case BUTTON_ID_TRY_AGAIN: {
320 translate_executed_ = true;
324 case BUTTON_ID_SHOW_ORIGINAL: {
325 model_->RevertTranslation();
326 GetWidget()->Close();
329 case BUTTON_ID_ALWAYS_TRANSLATE: {
330 // Do nothing. The state of the checkbox affects only when the 'Done'
331 // button is pressed.
337 void TranslateBubbleView::HandleLinkClicked(
338 TranslateBubbleView::LinkID sender_id) {
340 case LINK_ID_ADVANCED: {
341 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
344 case LINK_ID_LANGUAGE_SETTINGS: {
345 GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
346 web_contents()->OpenURL(content::OpenURLParams(
350 content::PAGE_TRANSITION_LINK,
357 void TranslateBubbleView::HandleComboboxPerformAction(
358 TranslateBubbleView::ComboboxID sender_id) {
360 case COMBOBOX_ID_DENIAL: {
361 denial_button_clicked_ = true;
362 int index = denial_combobox_->selected_index();
366 case INDEX_NEVER_TRANSLATE_LANGUAGE:
367 model_->SetNeverTranslateLanguage(true);
369 case INDEX_NEVER_TRANSLATE_SITE:
370 model_->SetNeverTranslateSite(true);
376 GetWidget()->Close();
379 case COMBOBOX_ID_SOURCE_LANGUAGE: {
380 if (model_->GetOriginalLanguageIndex() ==
381 source_language_combobox_->selected_index()) {
384 model_->UpdateOriginalLanguageIndex(
385 source_language_combobox_->selected_index());
386 UpdateAdvancedView();
389 case COMBOBOX_ID_TARGET_LANGUAGE: {
390 if (model_->GetTargetLanguageIndex() ==
391 target_language_combobox_->selected_index()) {
394 model_->UpdateTargetLanguageIndex(
395 target_language_combobox_->selected_index());
396 UpdateAdvancedView();
402 void TranslateBubbleView::UpdateChildVisibilities() {
403 for (int i = 0; i < child_count(); i++) {
404 views::View* view = child_at(i);
405 view->SetVisible(view == GetCurrentView());
409 views::View* TranslateBubbleView::CreateViewBeforeTranslate() {
410 views::Label* message_label = new views::Label(
411 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE));
413 base::string16 original_language_name =
414 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
416 std::vector<base::string16> items;
417 items.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
418 items.push_back(base::string16());
419 items.push_back(l10n_util::GetStringFUTF16(
420 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
421 original_language_name));
422 items.push_back(base::string16());
423 items.push_back(l10n_util::GetStringUTF16(
424 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
426 denial_combobox_model_.reset(new ui::SimpleComboboxModel(items));
427 denial_combobox_ = new views::Combobox(denial_combobox_model_.get());
428 denial_combobox_->set_id(COMBOBOX_ID_DENIAL);
429 denial_combobox_->set_listener(this);
430 denial_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
432 views::View* view = new views::View();
433 views::GridLayout* layout = new views::GridLayout(view);
434 view->SetLayoutManager(layout);
436 using views::GridLayout;
439 COLUMN_SET_ID_MESSAGE,
440 COLUMN_SET_ID_CONTENT,
443 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
444 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
445 0, GridLayout::USE_PREF, 0, 0);
446 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
447 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
448 0, GridLayout::USE_PREF, 0, 0);
449 cs->AddPaddingColumn(1, 0);
451 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
452 cs->AddPaddingColumn(1, 0);
453 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
454 0, GridLayout::USE_PREF, 0, 0);
455 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
456 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
457 0, GridLayout::USE_PREF, 0, 0);
459 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
460 layout->AddView(message_label);
461 layout->AddView(CreateLink(this,
462 IDS_TRANSLATE_BUBBLE_ADVANCED,
465 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
467 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
468 layout->AddView(CreateLabelButton(
470 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT),
471 BUTTON_ID_TRANSLATE));
472 layout->AddView(denial_combobox_);
477 views::View* TranslateBubbleView::CreateViewTranslating() {
478 base::string16 target_language_name =
479 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
480 views::Label* label = new views::Label(
481 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATING));
483 views::View* view = new views::View();
484 views::GridLayout* layout = new views::GridLayout(view);
485 view->SetLayoutManager(layout);
487 using views::GridLayout;
490 COLUMN_SET_ID_MESSAGE,
491 COLUMN_SET_ID_CONTENT,
494 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
495 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
496 0, views::GridLayout::USE_PREF, 0, 0);
497 cs->AddPaddingColumn(1, 0);
499 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
500 cs->AddPaddingColumn(1, 0);
501 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
502 0, GridLayout::USE_PREF, 0, 0);
504 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
505 layout->AddView(label);
507 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
509 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
510 views::LabelButton* revert_button = CreateLabelButton(
512 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
513 BUTTON_ID_SHOW_ORIGINAL);
514 revert_button->SetEnabled(false);
515 layout->AddView(revert_button);
520 views::View* TranslateBubbleView::CreateViewAfterTranslate() {
521 views::Label* label = new views::Label(
522 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATED));
524 views::View* view = new views::View();
525 views::GridLayout* layout = new views::GridLayout(view);
526 view->SetLayoutManager(layout);
528 using views::GridLayout;
531 COLUMN_SET_ID_MESSAGE,
532 COLUMN_SET_ID_CONTENT,
535 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
536 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
537 0, views::GridLayout::USE_PREF, 0, 0);
538 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
539 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
540 0, views::GridLayout::USE_PREF, 0, 0);
541 cs->AddPaddingColumn(1, 0);
543 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
544 cs->AddPaddingColumn(1, 0);
545 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
546 0, GridLayout::USE_PREF, 0, 0);
548 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
549 layout->AddView(label);
550 layout->AddView(CreateLink(this,
551 IDS_TRANSLATE_BUBBLE_ADVANCED,
554 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
556 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
557 layout->AddView(CreateLabelButton(
559 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
560 BUTTON_ID_SHOW_ORIGINAL));
565 views::View* TranslateBubbleView::CreateViewError() {
566 views::Label* label = new views::Label(
567 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE));
569 views::View* view = new views::View();
570 views::GridLayout* layout = new views::GridLayout(view);
571 view->SetLayoutManager(layout);
573 using views::GridLayout;
576 COLUMN_SET_ID_MESSAGE,
577 COLUMN_SET_ID_CONTENT,
580 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
581 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
582 0, GridLayout::USE_PREF, 0, 0);
583 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
584 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
585 0, GridLayout::USE_PREF, 0, 0);
586 cs->AddPaddingColumn(1, 0);
588 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
589 cs->AddPaddingColumn(1, 0);
590 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
591 0, GridLayout::USE_PREF, 0, 0);
593 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
594 layout->AddView(label);
595 layout->AddView(CreateLink(this,
596 IDS_TRANSLATE_BUBBLE_ADVANCED,
599 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
601 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
602 layout->AddView(CreateLabelButton(
604 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN),
605 BUTTON_ID_TRY_AGAIN));
610 // TODO(hajimehoshi): Revice this later to show a specific message for each
611 // error. (crbug/307350)
612 views::View* TranslateBubbleView::CreateViewAdvanced() {
613 views::Label* source_language_label = new views::Label(
614 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE));
616 views::Label* target_language_label = new views::Label(
617 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE));
619 int source_default_index = model_->GetOriginalLanguageIndex();
620 source_language_combobox_model_.reset(
621 new LanguageComboboxModel(source_default_index, model_.get()));
622 source_language_combobox_ =
623 new views::Combobox(source_language_combobox_model_.get());
625 source_language_combobox_->set_id(COMBOBOX_ID_SOURCE_LANGUAGE);
626 source_language_combobox_->set_listener(this);
628 int target_default_index = model_->GetTargetLanguageIndex();
629 target_language_combobox_model_.reset(
630 new LanguageComboboxModel(target_default_index, model_.get()));
631 target_language_combobox_ =
632 new views::Combobox(target_language_combobox_model_.get());
634 target_language_combobox_->set_id(COMBOBOX_ID_TARGET_LANGUAGE);
635 target_language_combobox_->set_listener(this);
637 // In an incognito window, "Always translate" checkbox shouldn't be shown.
638 if (!is_in_incognito_window_) {
639 always_translate_checkbox_ = new views::Checkbox(base::string16());
640 always_translate_checkbox_->set_id(BUTTON_ID_ALWAYS_TRANSLATE);
641 always_translate_checkbox_->set_listener(this);
644 views::View* view = new views::View();
645 views::GridLayout* layout = new views::GridLayout(view);
646 view->SetLayoutManager(layout);
648 using views::GridLayout;
651 COLUMN_SET_ID_LANGUAGES,
652 COLUMN_SET_ID_BUTTONS,
655 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
656 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER,
657 0, GridLayout::USE_PREF, 0, 0);
658 cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
659 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER,
660 0, GridLayout::USE_PREF, 0, 0);
661 cs->AddPaddingColumn(1, 0);
663 cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
664 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
665 0, GridLayout::USE_PREF, 0, 0);
666 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
667 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
668 0, GridLayout::USE_PREF, 0, 0);
669 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
670 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
671 0, GridLayout::USE_PREF, 0, 0);
673 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
674 layout->AddView(source_language_label);
675 layout->AddView(source_language_combobox_);
677 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
679 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
680 layout->AddView(target_language_label);
681 layout->AddView(target_language_combobox_);
683 if (!is_in_incognito_window_) {
684 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
685 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
686 layout->SkipColumns(1);
687 layout->AddView(always_translate_checkbox_);
690 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
692 layout->StartRow(0, COLUMN_SET_ID_BUTTONS);
693 layout->AddView(CreateLink(this,
694 IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS,
695 LINK_ID_LANGUAGE_SETTINGS));
696 advanced_done_button_ = CreateLabelButton(
697 this, l10n_util::GetStringUTF16(IDS_DONE), BUTTON_ID_DONE);
698 advanced_done_button_->SetIsDefault(true);
699 advanced_cancel_button_ = CreateLabelButton(
700 this, l10n_util::GetStringUTF16(IDS_CANCEL), BUTTON_ID_CANCEL);
701 layout->AddView(advanced_done_button_);
702 layout->AddView(advanced_cancel_button_);
704 UpdateAdvancedView();
709 void TranslateBubbleView::SwitchView(
710 TranslateBubbleModel::ViewState view_state) {
711 if (model_->GetViewState() == view_state)
714 model_->SetViewState(view_state);
715 UpdateChildVisibilities();
716 if (view_state == TranslateBubbleModel::VIEW_STATE_ADVANCED)
717 UpdateAdvancedView();
721 void TranslateBubbleView::SwitchToErrorView(TranslateErrors::Type error_type) {
722 SwitchView(TranslateBubbleModel::VIEW_STATE_ERROR);
723 error_type_ = error_type;
724 model_->ShowError(error_type);
727 void TranslateBubbleView::UpdateAdvancedView() {
728 DCHECK(source_language_combobox_);
729 DCHECK(target_language_combobox_);
730 DCHECK(advanced_done_button_);
732 base::string16 source_language_name =
733 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
734 base::string16 target_language_name =
735 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
737 // "Always translate" checkbox doesn't exist in an incognito window.
738 if (always_translate_checkbox_) {
739 always_translate_checkbox_->SetText(
740 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ALWAYS));
741 always_translate_checkbox_->SetChecked(
742 model_->ShouldAlwaysTranslate());
745 base::string16 label;
746 if (model_->IsPageTranslatedInCurrentLanguages())
747 label = l10n_util::GetStringUTF16(IDS_DONE);
749 label = l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT);
750 advanced_done_button_->SetText(label);