NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / views / translate / translate_bubble_view.cc
blobb5a285befa35af1a3388c87b5ca698f26db580ee
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_manager.h"
19 #include "chrome/browser/translate/translate_tab_helper.h"
20 #include "chrome/browser/translate/translate_ui_delegate.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 "content/public/browser/web_contents.h"
25 #include "grit/generated_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/models/combobox_model.h"
28 #include "ui/base/resource/resource_bundle.h"
29 #include "ui/views/controls/button/checkbox.h"
30 #include "ui/views/controls/button/label_button.h"
31 #include "ui/views/controls/combobox/combobox.h"
32 #include "ui/views/controls/label.h"
33 #include "ui/views/controls/link.h"
34 #include "ui/views/layout/box_layout.h"
35 #include "ui/views/layout/grid_layout.h"
36 #include "ui/views/layout/layout_constants.h"
37 #include "ui/views/widget/widget.h"
39 namespace {
41 views::LabelButton* CreateLabelButton(views::ButtonListener* listener,
42 const base::string16& label,
43 int id) {
44 views::LabelButton* button = new views::LabelButton(listener, label);
45 button->set_id(id);
46 button->SetStyle(views::Button::STYLE_BUTTON);
47 return button;
50 views::Link* CreateLink(views::LinkListener* listener,
51 int resource_id,
52 int id) {
53 views::Link* link = new views::Link(
54 l10n_util::GetStringUTF16(resource_id));
55 link->set_listener(listener);
56 link->set_id(id);
57 return link;
60 void GetTranslateLanguages(content::WebContents* web_contents,
61 std::string* source,
62 std::string* target) {
63 DCHECK(source != NULL);
64 DCHECK(target != NULL);
66 TranslateTabHelper* translate_tab_helper =
67 TranslateTabHelper::FromWebContents(web_contents);
68 *source = translate_tab_helper->GetLanguageState().original_language();
69 *source = TranslateDownloadManager::GetLanguageCode(*source);
71 Profile* profile =
72 Profile::FromBrowserContext(web_contents->GetBrowserContext());
73 Profile* original_profile = profile->GetOriginalProfile();
74 PrefService* prefs = original_profile->GetPrefs();
75 if (!web_contents->GetBrowserContext()->IsOffTheRecord()) {
76 std::string auto_translate_language =
77 TranslateManager::GetAutoTargetLanguage(*source, prefs);
78 if (!auto_translate_language.empty()) {
79 *target = auto_translate_language;
80 return;
83 *target = TranslateManager::GetTargetLanguage(prefs);
86 class TranslateDenialComboboxModel : public ui::ComboboxModel {
87 public:
88 enum {
89 INDEX_NOPE = 0,
90 INDEX_NEVER_TRANSLATE_LANGUAGE = 2,
91 INDEX_NEVER_TRANSLATE_SITE = 4,
94 explicit TranslateDenialComboboxModel(
95 const base::string16& original_language_name) {
96 items_.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
97 items_.push_back(base::string16());
98 items_.push_back(l10n_util::GetStringFUTF16(
99 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
100 original_language_name));
101 items_.push_back(base::string16());
102 items_.push_back(l10n_util::GetStringUTF16(
103 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
105 virtual ~TranslateDenialComboboxModel() {}
107 private:
108 // Overridden from ui::ComboboxModel:
109 virtual int GetItemCount() const OVERRIDE {
110 return items_.size();
112 virtual base::string16 GetItemAt(int index) OVERRIDE {
113 return items_[index];
115 virtual bool IsItemSeparatorAt(int index) OVERRIDE {
116 return items_[index].empty();
118 virtual int GetDefaultIndex() const OVERRIDE {
119 return 0;
122 std::vector<base::string16> items_;
124 DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel);
127 } // namespace
129 // static
130 TranslateBubbleView* TranslateBubbleView::translate_bubble_view_ = NULL;
132 TranslateBubbleView::~TranslateBubbleView() {
133 // A child view could refer to a model which is owned by this class when
134 // the child view is destructed. For example, |source_language_combobx_model_|
135 // is referred by Combobox's destructor. Before destroying the models,
136 // removing the child views is needed.
137 RemoveAllChildViews(true);
140 // static
141 void TranslateBubbleView::ShowBubble(views::View* anchor_view,
142 content::WebContents* web_contents,
143 TranslateTabHelper::TranslateStep step,
144 TranslateErrors::Type error_type) {
145 if (IsShowing()) {
146 // When the user reads the advanced setting panel, the bubble should not be
147 // changed because he/she is focusing on the bubble.
148 if (translate_bubble_view_->web_contents() == web_contents &&
149 translate_bubble_view_->model()->GetViewState() ==
150 TranslateBubbleModel::VIEW_STATE_ADVANCED) {
151 return;
153 if (step != TranslateTabHelper::TRANSLATE_ERROR) {
154 TranslateBubbleModel::ViewState state =
155 TranslateBubbleModelImpl::TranslateStepToViewState(step);
156 translate_bubble_view_->SwitchView(state);
157 } else {
158 translate_bubble_view_->SwitchToErrorView(error_type);
160 return;
163 std::string source_language;
164 std::string target_language;
165 GetTranslateLanguages(web_contents, &source_language, &target_language);
167 scoped_ptr<TranslateUIDelegate> ui_delegate(
168 new TranslateUIDelegate(web_contents, source_language, target_language));
169 scoped_ptr<TranslateBubbleModel> model(
170 new TranslateBubbleModelImpl(step, ui_delegate.Pass()));
171 TranslateBubbleView* view = new TranslateBubbleView(anchor_view,
172 model.Pass(),
173 error_type,
174 web_contents);
175 views::BubbleDelegateView::CreateBubble(view)->Show();
178 // static
179 bool TranslateBubbleView::IsShowing() {
180 return translate_bubble_view_ != NULL;
183 // static
184 TranslateBubbleView* TranslateBubbleView::GetCurrentBubble() {
185 return translate_bubble_view_;
188 void TranslateBubbleView::Init() {
189 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
190 0, 0, 0));
192 before_translate_view_ = CreateViewBeforeTranslate();
193 translating_view_ = CreateViewTranslating();
194 after_translate_view_ = CreateViewAfterTranslate();
195 error_view_ = CreateViewError();
196 advanced_view_ = CreateViewAdvanced();
198 AddChildView(before_translate_view_);
199 AddChildView(translating_view_);
200 AddChildView(after_translate_view_);
201 AddChildView(error_view_);
202 AddChildView(advanced_view_);
204 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
206 UpdateChildVisibilities();
208 if (model_->GetViewState() == TranslateBubbleModel::VIEW_STATE_ERROR)
209 model_->ShowError(error_type_);
212 void TranslateBubbleView::ButtonPressed(views::Button* sender,
213 const ui::Event& event) {
214 HandleButtonPressed(static_cast<ButtonID>(sender->id()));
217 void TranslateBubbleView::WindowClosing() {
218 // The operations for |model_| are valid only when a WebContents is alive.
219 // TODO(hajimehoshi): TranslateBubbleViewModel(Impl) should not hold a
220 // WebContents as a member variable because the WebContents might be destroyed
221 // while the TranslateBubbleViewModel(Impl) is still alive. Instead,
222 // TranslateBubbleViewModel should take a reference of a WebContents at each
223 // method. (crbug/320497)
224 if (!translate_executed_ && web_contents())
225 model_->TranslationDeclined(denial_button_clicked_);
227 // We have to reset |translate_bubble_view_| here, not in our destructor,
228 // because we'll be destroyed asynchronously and the shown state will be
229 // checked before then.
230 DCHECK_EQ(translate_bubble_view_, this);
231 translate_bubble_view_ = NULL;
234 bool TranslateBubbleView::AcceleratorPressed(
235 const ui::Accelerator& accelerator) {
236 switch (model_->GetViewState()) {
237 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE: {
238 if (accelerator.key_code() == ui::VKEY_RETURN) {
239 HandleButtonPressed(BUTTON_ID_TRANSLATE);
240 return true;
242 break;
244 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
245 break;
246 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE: {
247 if (accelerator.key_code() == ui::VKEY_RETURN) {
248 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL);
249 return true;
251 break;
253 case TranslateBubbleModel::VIEW_STATE_ERROR:
254 break;
255 case TranslateBubbleModel::VIEW_STATE_ADVANCED: {
256 if (accelerator.key_code() == ui::VKEY_RETURN) {
257 HandleButtonPressed(BUTTON_ID_DONE);
258 return true;
260 break;
263 return BubbleDelegateView::AcceleratorPressed(accelerator);
266 gfx::Size TranslateBubbleView::GetPreferredSize() {
267 int width = 0;
268 for (int i = 0; i < child_count(); i++) {
269 views::View* child = child_at(i);
270 width = std::max(width, child->GetPreferredSize().width());
272 int height = GetCurrentView()->GetPreferredSize().height();
273 return gfx::Size(width, height);
276 void TranslateBubbleView::OnPerformAction(views::Combobox* combobox) {
277 HandleComboboxPerformAction(static_cast<ComboboxID>(combobox->id()));
280 void TranslateBubbleView::LinkClicked(views::Link* source, int event_flags) {
281 HandleLinkClicked(static_cast<LinkID>(source->id()));
284 void TranslateBubbleView::WebContentsDestroyed(
285 content::WebContents* web_contents) {
286 GetWidget()->CloseNow();
289 TranslateBubbleModel::ViewState TranslateBubbleView::GetViewState() const {
290 return model_->GetViewState();
293 TranslateBubbleView::TranslateBubbleView(
294 views::View* anchor_view,
295 scoped_ptr<TranslateBubbleModel> model,
296 TranslateErrors::Type error_type,
297 content::WebContents* web_contents)
298 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
299 WebContentsObserver(web_contents),
300 before_translate_view_(NULL),
301 translating_view_(NULL),
302 after_translate_view_(NULL),
303 error_view_(NULL),
304 advanced_view_(NULL),
305 denial_combobox_(NULL),
306 source_language_combobox_(NULL),
307 target_language_combobox_(NULL),
308 always_translate_checkbox_(NULL),
309 advanced_cancel_button_(NULL),
310 advanced_done_button_(NULL),
311 model_(model.Pass()),
312 error_type_(error_type),
313 is_in_incognito_window_(
314 web_contents ?
315 web_contents->GetBrowserContext()->IsOffTheRecord() : false),
316 translate_executed_(false),
317 denial_button_clicked_(false) {
318 if (model_->GetViewState() !=
319 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) {
320 translate_executed_ = true;
323 set_margins(gfx::Insets(views::kPanelVertMargin, views::kPanelHorizMargin,
324 views::kPanelVertMargin, views::kPanelHorizMargin));
326 translate_bubble_view_ = this;
329 views::View* TranslateBubbleView::GetCurrentView() {
330 switch (model_->GetViewState()) {
331 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE:
332 return before_translate_view_;
333 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
334 return translating_view_;
335 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE:
336 return after_translate_view_;
337 case TranslateBubbleModel::VIEW_STATE_ERROR:
338 return error_view_;
339 case TranslateBubbleModel::VIEW_STATE_ADVANCED:
340 return advanced_view_;
342 NOTREACHED();
343 return NULL;
346 void TranslateBubbleView::HandleButtonPressed(
347 TranslateBubbleView::ButtonID sender_id) {
348 switch (sender_id) {
349 case BUTTON_ID_TRANSLATE: {
350 translate_executed_ = true;
351 model_->Translate();
352 break;
354 case BUTTON_ID_DONE: {
355 if (always_translate_checkbox_)
356 model_->SetAlwaysTranslate(always_translate_checkbox_->checked());
357 if (model_->IsPageTranslatedInCurrentLanguages()) {
358 model_->GoBackFromAdvanced();
359 UpdateChildVisibilities();
360 SizeToContents();
361 } else {
362 translate_executed_ = true;
363 model_->Translate();
364 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
366 break;
368 case BUTTON_ID_CANCEL: {
369 model_->GoBackFromAdvanced();
370 UpdateChildVisibilities();
371 SizeToContents();
372 break;
374 case BUTTON_ID_TRY_AGAIN: {
375 translate_executed_ = true;
376 model_->Translate();
377 break;
379 case BUTTON_ID_SHOW_ORIGINAL: {
380 model_->RevertTranslation();
381 StartFade(false);
382 break;
384 case BUTTON_ID_ALWAYS_TRANSLATE: {
385 // Do nothing. The state of the checkbox affects only when the 'Done'
386 // button is pressed.
387 break;
392 void TranslateBubbleView::HandleLinkClicked(
393 TranslateBubbleView::LinkID sender_id) {
394 switch (sender_id) {
395 case LINK_ID_ADVANCED: {
396 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
397 break;
399 case LINK_ID_LANGUAGE_SETTINGS: {
400 std::string url = std::string(chrome::kChromeUISettingsURL) +
401 chrome::kLanguageOptionsSubPage;
402 web_contents()->OpenURL(content::OpenURLParams(
403 GURL(url),
404 content::Referrer(),
405 NEW_FOREGROUND_TAB,
406 content::PAGE_TRANSITION_LINK,
407 false));
408 break;
413 void TranslateBubbleView::HandleComboboxPerformAction(
414 TranslateBubbleView::ComboboxID sender_id) {
415 switch (sender_id) {
416 case COMBOBOX_ID_DENIAL: {
417 denial_button_clicked_ = true;
418 int index = denial_combobox_->selected_index();
419 switch (index) {
420 case TranslateDenialComboboxModel::INDEX_NOPE:
421 break;
422 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_LANGUAGE:
423 model_->SetNeverTranslateLanguage(true);
424 break;
425 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_SITE:
426 model_->SetNeverTranslateSite(true);
427 break;
428 default:
429 NOTREACHED();
430 break;
432 StartFade(false);
433 break;
435 case COMBOBOX_ID_SOURCE_LANGUAGE: {
436 if (model_->GetOriginalLanguageIndex() ==
437 source_language_combobox_->selected_index()) {
438 break;
440 model_->UpdateOriginalLanguageIndex(
441 source_language_combobox_->selected_index());
442 UpdateAdvancedView();
443 break;
445 case COMBOBOX_ID_TARGET_LANGUAGE: {
446 if (model_->GetTargetLanguageIndex() ==
447 target_language_combobox_->selected_index()) {
448 break;
450 model_->UpdateTargetLanguageIndex(
451 target_language_combobox_->selected_index());
452 UpdateAdvancedView();
453 break;
458 void TranslateBubbleView::UpdateChildVisibilities() {
459 for (int i = 0; i < child_count(); i++) {
460 views::View* view = child_at(i);
461 view->SetVisible(view == GetCurrentView());
465 views::View* TranslateBubbleView::CreateViewBeforeTranslate() {
466 views::Label* message_label = new views::Label(
467 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE));
469 base::string16 original_language_name =
470 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
471 denial_combobox_ = new views::Combobox(
472 new TranslateDenialComboboxModel(original_language_name));
473 denial_combobox_->set_id(COMBOBOX_ID_DENIAL);
474 denial_combobox_->set_listener(this);
475 denial_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
477 views::View* view = new views::View();
478 views::GridLayout* layout = new views::GridLayout(view);
479 view->SetLayoutManager(layout);
481 using views::GridLayout;
483 enum {
484 COLUMN_SET_ID_MESSAGE,
485 COLUMN_SET_ID_CONTENT,
488 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
489 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
490 0, GridLayout::USE_PREF, 0, 0);
491 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
492 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
493 0, GridLayout::USE_PREF, 0, 0);
494 cs->AddPaddingColumn(1, 0);
496 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
497 cs->AddPaddingColumn(1, 0);
498 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
499 0, GridLayout::USE_PREF, 0, 0);
500 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
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(message_label);
506 layout->AddView(CreateLink(this,
507 IDS_TRANSLATE_BUBBLE_ADVANCED,
508 LINK_ID_ADVANCED));
510 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
512 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
513 layout->AddView(CreateLabelButton(
514 this,
515 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT),
516 BUTTON_ID_TRANSLATE));
517 layout->AddView(denial_combobox_);
519 return view;
522 views::View* TranslateBubbleView::CreateViewTranslating() {
523 base::string16 target_language_name =
524 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
525 views::Label* label = new views::Label(
526 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATING));
528 views::View* view = new views::View();
529 views::GridLayout* layout = new views::GridLayout(view);
530 view->SetLayoutManager(layout);
532 using views::GridLayout;
534 enum {
535 COLUMN_SET_ID_MESSAGE,
536 COLUMN_SET_ID_CONTENT,
539 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
540 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
541 0, views::GridLayout::USE_PREF, 0, 0);
542 cs->AddPaddingColumn(1, 0);
544 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
545 cs->AddPaddingColumn(1, 0);
546 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
547 0, GridLayout::USE_PREF, 0, 0);
549 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
550 layout->AddView(label);
552 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
554 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
555 views::LabelButton* revert_button = CreateLabelButton(
556 this,
557 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
558 BUTTON_ID_SHOW_ORIGINAL);
559 revert_button->SetEnabled(false);
560 layout->AddView(revert_button);
562 return view;
565 views::View* TranslateBubbleView::CreateViewAfterTranslate() {
566 views::Label* label = new views::Label(
567 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATED));
569 views::View* view = new views::View();
570 views::GridLayout* layout = new views::GridLayout(view);
571 view->SetLayoutManager(layout);
573 using views::GridLayout;
575 enum {
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, views::GridLayout::USE_PREF, 0, 0);
583 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
584 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
585 0, views::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,
597 LINK_ID_ADVANCED));
599 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
601 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
602 layout->AddView(CreateLabelButton(
603 this,
604 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
605 BUTTON_ID_SHOW_ORIGINAL));
607 return view;
610 views::View* TranslateBubbleView::CreateViewError() {
611 views::Label* label = new views::Label(
612 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE));
614 views::View* view = new views::View();
615 views::GridLayout* layout = new views::GridLayout(view);
616 view->SetLayoutManager(layout);
618 using views::GridLayout;
620 enum {
621 COLUMN_SET_ID_MESSAGE,
622 COLUMN_SET_ID_CONTENT,
625 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
626 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
627 0, GridLayout::USE_PREF, 0, 0);
628 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
629 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
630 0, GridLayout::USE_PREF, 0, 0);
631 cs->AddPaddingColumn(1, 0);
633 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
634 cs->AddPaddingColumn(1, 0);
635 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
636 0, GridLayout::USE_PREF, 0, 0);
638 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
639 layout->AddView(label);
640 layout->AddView(CreateLink(this,
641 IDS_TRANSLATE_BUBBLE_ADVANCED,
642 LINK_ID_ADVANCED));
644 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
646 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
647 layout->AddView(CreateLabelButton(
648 this,
649 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN),
650 BUTTON_ID_TRY_AGAIN));
652 return view;
655 // TODO(hajimehoshi): Revice this later to show a specific message for each
656 // error. (crbug/307350)
657 views::View* TranslateBubbleView::CreateViewAdvanced() {
658 views::Label* source_language_label = new views::Label(
659 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE));
661 views::Label* target_language_label = new views::Label(
662 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE));
664 int source_default_index = model_->GetOriginalLanguageIndex();
665 source_language_combobox_model_.reset(
666 new LanguageComboboxModel(source_default_index, model_.get()));
667 source_language_combobox_ =
668 new views::Combobox(source_language_combobox_model_.get());
670 source_language_combobox_->set_id(COMBOBOX_ID_SOURCE_LANGUAGE);
671 source_language_combobox_->set_listener(this);
673 int target_default_index = model_->GetTargetLanguageIndex();
674 target_language_combobox_model_.reset(
675 new LanguageComboboxModel(target_default_index, model_.get()));
676 target_language_combobox_ =
677 new views::Combobox(target_language_combobox_model_.get());
679 target_language_combobox_->set_id(COMBOBOX_ID_TARGET_LANGUAGE);
680 target_language_combobox_->set_listener(this);
682 // In an incognito window, "Always translate" checkbox shouldn't be shown.
683 if (!is_in_incognito_window_) {
684 always_translate_checkbox_ = new views::Checkbox(base::string16());
685 always_translate_checkbox_->set_id(BUTTON_ID_ALWAYS_TRANSLATE);
686 always_translate_checkbox_->set_listener(this);
689 views::View* view = new views::View();
690 views::GridLayout* layout = new views::GridLayout(view);
691 view->SetLayoutManager(layout);
693 using views::GridLayout;
695 enum {
696 COLUMN_SET_ID_LANGUAGES,
697 COLUMN_SET_ID_BUTTONS,
700 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
701 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER,
702 0, GridLayout::USE_PREF, 0, 0);
703 cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
704 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER,
705 0, GridLayout::USE_PREF, 0, 0);
706 cs->AddPaddingColumn(1, 0);
708 cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
709 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
710 0, GridLayout::USE_PREF, 0, 0);
711 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
712 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
713 0, GridLayout::USE_PREF, 0, 0);
714 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
715 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
716 0, GridLayout::USE_PREF, 0, 0);
718 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
719 layout->AddView(source_language_label);
720 layout->AddView(source_language_combobox_);
722 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
724 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
725 layout->AddView(target_language_label);
726 layout->AddView(target_language_combobox_);
728 if (!is_in_incognito_window_) {
729 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
730 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
731 layout->SkipColumns(1);
732 layout->AddView(always_translate_checkbox_);
735 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
737 layout->StartRow(0, COLUMN_SET_ID_BUTTONS);
738 layout->AddView(CreateLink(this,
739 IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS,
740 LINK_ID_LANGUAGE_SETTINGS));
741 advanced_done_button_ = CreateLabelButton(
742 this, l10n_util::GetStringUTF16(IDS_DONE), BUTTON_ID_DONE);
743 advanced_done_button_->SetIsDefault(true);
744 advanced_cancel_button_ = CreateLabelButton(
745 this, l10n_util::GetStringUTF16(IDS_CANCEL), BUTTON_ID_CANCEL);
746 layout->AddView(advanced_done_button_);
747 layout->AddView(advanced_cancel_button_);
749 UpdateAdvancedView();
751 return view;
754 void TranslateBubbleView::SwitchView(
755 TranslateBubbleModel::ViewState view_state) {
756 if (model_->GetViewState() == view_state)
757 return;
759 model_->SetViewState(view_state);
760 UpdateChildVisibilities();
761 if (view_state == TranslateBubbleModel::VIEW_STATE_ADVANCED)
762 UpdateAdvancedView();
763 SizeToContents();
766 void TranslateBubbleView::SwitchToErrorView(TranslateErrors::Type error_type) {
767 SwitchView(TranslateBubbleModel::VIEW_STATE_ERROR);
768 error_type_ = error_type;
769 model_->ShowError(error_type);
772 void TranslateBubbleView::UpdateAdvancedView() {
773 DCHECK(source_language_combobox_);
774 DCHECK(target_language_combobox_);
775 DCHECK(advanced_done_button_);
777 base::string16 source_language_name =
778 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
779 base::string16 target_language_name =
780 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
782 // "Always translate" checkbox doesn't exist in an incognito window.
783 if (always_translate_checkbox_) {
784 always_translate_checkbox_->SetText(
785 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ALWAYS));
786 always_translate_checkbox_->SetChecked(
787 model_->ShouldAlwaysTranslate());
790 base::string16 label;
791 if (model_->IsPageTranslatedInCurrentLanguages())
792 label = l10n_util::GetStringUTF16(IDS_DONE);
793 else
794 label = l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT);
795 advanced_done_button_->SetText(label);