Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / views / translate / translate_bubble_view.cc
blobc195505279c2e99c3bb06054d017ca9a8cdce577
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 "content/public/browser/web_contents.h"
24 #include "grit/generated_resources.h"
25 #include "ui/base/l10n/l10n_util.h"
26 #include "ui/base/models/combobox_model.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/views/controls/button/checkbox.h"
29 #include "ui/views/controls/button/label_button.h"
30 #include "ui/views/controls/combobox/combobox.h"
31 #include "ui/views/controls/label.h"
32 #include "ui/views/controls/link.h"
33 #include "ui/views/layout/box_layout.h"
34 #include "ui/views/layout/grid_layout.h"
35 #include "ui/views/layout/layout_constants.h"
36 #include "ui/views/widget/widget.h"
38 namespace {
40 views::LabelButton* CreateLabelButton(views::ButtonListener* listener,
41 const base::string16& label,
42 int id) {
43 views::LabelButton* button = new views::LabelButton(listener, label);
44 button->set_id(id);
45 button->SetStyle(views::Button::STYLE_BUTTON);
46 return button;
49 views::Link* CreateLink(views::LinkListener* listener,
50 int resource_id,
51 int id) {
52 views::Link* link = new views::Link(
53 l10n_util::GetStringUTF16(resource_id));
54 link->set_listener(listener);
55 link->set_id(id);
56 return link;
59 void GetTranslateLanguages(content::WebContents* web_contents,
60 std::string* source,
61 std::string* target) {
62 DCHECK(source != NULL);
63 DCHECK(target != NULL);
65 TranslateTabHelper* translate_tab_helper =
66 TranslateTabHelper::FromWebContents(web_contents);
67 *source = translate_tab_helper->language_state().original_language();
69 Profile* profile =
70 Profile::FromBrowserContext(web_contents->GetBrowserContext());
71 Profile* original_profile = profile->GetOriginalProfile();
72 PrefService* prefs = original_profile->GetPrefs();
73 if (!web_contents->GetBrowserContext()->IsOffTheRecord()) {
74 std::string auto_translate_language =
75 TranslateManager::GetAutoTargetLanguage(*source, prefs);
76 if (!auto_translate_language.empty()) {
77 *target = auto_translate_language;
78 return;
81 *target = TranslateManager::GetTargetLanguage(prefs);
84 class TranslateDenialComboboxModel : public ui::ComboboxModel {
85 public:
86 enum {
87 INDEX_NOPE = 0,
88 INDEX_NEVER_TRANSLATE_LANGUAGE = 2,
89 INDEX_NEVER_TRANSLATE_SITE = 4,
92 explicit TranslateDenialComboboxModel(
93 const base::string16& original_language_name) {
94 items_.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
95 items_.push_back(base::string16());
96 items_.push_back(l10n_util::GetStringFUTF16(
97 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
98 original_language_name));
99 items_.push_back(base::string16());
100 items_.push_back(l10n_util::GetStringUTF16(
101 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
103 virtual ~TranslateDenialComboboxModel() {}
105 private:
106 // Overridden from ui::ComboboxModel:
107 virtual int GetItemCount() const OVERRIDE {
108 return items_.size();
110 virtual base::string16 GetItemAt(int index) OVERRIDE {
111 return items_[index];
113 virtual bool IsItemSeparatorAt(int index) OVERRIDE {
114 return items_[index].empty();
116 virtual int GetDefaultIndex() const OVERRIDE {
117 return 0;
120 std::vector<base::string16> items_;
122 DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel);
125 } // namespace
127 // static
128 TranslateBubbleView* TranslateBubbleView::translate_bubble_view_ = NULL;
130 TranslateBubbleView::~TranslateBubbleView() {
131 // A child view could refer to a model which is owned by this class when
132 // the child view is destructed. For example, |source_language_combobx_model_|
133 // is referred by Combobox's destructor. Before destroying the models,
134 // removing the child views is needed.
135 RemoveAllChildViews(true);
138 // static
139 void TranslateBubbleView::ShowBubble(views::View* anchor_view,
140 content::WebContents* web_contents,
141 TranslateBubbleModel::ViewState type,
142 TranslateErrors::Type error_type) {
143 if (IsShowing()) {
144 // When the user reads the advanced setting panel, the bubble should not be
145 // changed because he/she is focusing on the bubble.
146 if (translate_bubble_view_->web_contents() == web_contents &&
147 translate_bubble_view_->model()->GetViewState() ==
148 TranslateBubbleModel::VIEW_STATE_ADVANCED) {
149 return;
151 if (type != TranslateBubbleModel::VIEW_STATE_ERROR)
152 translate_bubble_view_->SwitchView(type);
153 else
154 translate_bubble_view_->SwitchToErrorView(error_type);
155 return;
158 std::string source_language;
159 std::string target_language;
160 GetTranslateLanguages(web_contents, &source_language, &target_language);
162 scoped_ptr<TranslateUIDelegate> ui_delegate(
163 new TranslateUIDelegate(web_contents, source_language, target_language));
164 scoped_ptr<TranslateBubbleModel> model(
165 new TranslateBubbleModelImpl(type, ui_delegate.Pass()));
166 TranslateBubbleView* view = new TranslateBubbleView(anchor_view,
167 model.Pass(),
168 error_type,
169 web_contents);
170 views::BubbleDelegateView::CreateBubble(view)->Show();
173 // static
174 bool TranslateBubbleView::IsShowing() {
175 return translate_bubble_view_ != NULL;
178 // static
179 TranslateBubbleView* TranslateBubbleView::GetCurrentBubble() {
180 return translate_bubble_view_;
183 void TranslateBubbleView::Init() {
184 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
185 0, 0, 0));
187 before_translate_view_ = CreateViewBeforeTranslate();
188 translating_view_ = CreateViewTranslating();
189 after_translate_view_ = CreateViewAfterTranslate();
190 error_view_ = CreateViewError();
191 advanced_view_ = CreateViewAdvanced();
193 AddChildView(before_translate_view_);
194 AddChildView(translating_view_);
195 AddChildView(after_translate_view_);
196 AddChildView(error_view_);
197 AddChildView(advanced_view_);
199 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
201 UpdateChildVisibilities();
203 if (model_->GetViewState() == TranslateBubbleModel::VIEW_STATE_ERROR)
204 model_->ShowError(error_type_);
207 void TranslateBubbleView::ButtonPressed(views::Button* sender,
208 const ui::Event& event) {
209 HandleButtonPressed(static_cast<ButtonID>(sender->id()));
212 void TranslateBubbleView::WindowClosing() {
213 // The operations for |model_| are valid only when a WebContents is alive.
214 // TODO(hajimehoshi): TranslateBubbleViewModel(Impl) should not hold a
215 // WebContents as a member variable because the WebContents might be destroyed
216 // while the TranslateBubbleViewModel(Impl) is still alive. Instead,
217 // TranslateBubbleViewModel should take a reference of a WebContents at each
218 // method. (crbug/320497)
219 if (!translate_executed_ && web_contents())
220 model_->TranslationDeclined(denial_button_clicked_);
222 // We have to reset |translate_bubble_view_| here, not in our destructor,
223 // because we'll be destroyed asynchronously and the shown state will be
224 // checked before then.
225 DCHECK_EQ(translate_bubble_view_, this);
226 translate_bubble_view_ = NULL;
229 bool TranslateBubbleView::AcceleratorPressed(
230 const ui::Accelerator& accelerator) {
231 switch (model_->GetViewState()) {
232 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE: {
233 if (accelerator.key_code() == ui::VKEY_RETURN) {
234 HandleButtonPressed(BUTTON_ID_TRANSLATE);
235 return true;
237 break;
239 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
240 break;
241 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE: {
242 if (accelerator.key_code() == ui::VKEY_RETURN) {
243 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL);
244 return true;
246 break;
248 case TranslateBubbleModel::VIEW_STATE_ERROR:
249 break;
250 case TranslateBubbleModel::VIEW_STATE_ADVANCED: {
251 if (accelerator.key_code() == ui::VKEY_RETURN) {
252 HandleButtonPressed(BUTTON_ID_DONE);
253 return true;
255 break;
258 return BubbleDelegateView::AcceleratorPressed(accelerator);
261 gfx::Size TranslateBubbleView::GetPreferredSize() {
262 int width = 0;
263 for (int i = 0; i < child_count(); i++) {
264 views::View* child = child_at(i);
265 width = std::max(width, child->GetPreferredSize().width());
267 int height = GetCurrentView()->GetPreferredSize().height();
268 return gfx::Size(width, height);
271 void TranslateBubbleView::OnSelectedIndexChanged(views::Combobox* combobox) {
272 HandleComboboxSelectedIndexChanged(static_cast<ComboboxID>(combobox->id()));
275 void TranslateBubbleView::OnComboboxTextButtonClicked(
276 views::Combobox* combobox) {
277 if (combobox != denial_combobox_)
278 return;
280 denial_button_clicked_ = true;
281 int index = combobox->selected_index();
282 switch (index) {
283 case TranslateDenialComboboxModel::INDEX_NOPE:
284 break;
285 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_LANGUAGE:
286 model_->SetNeverTranslateLanguage(true);
287 break;
288 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_SITE:
289 model_->SetNeverTranslateSite(true);
290 break;
291 default:
292 NOTREACHED();
293 break;
295 StartFade(false);
298 void TranslateBubbleView::LinkClicked(views::Link* source, int event_flags) {
299 HandleLinkClicked(static_cast<LinkID>(source->id()));
302 void TranslateBubbleView::WebContentsDestroyed(
303 content::WebContents* web_contents) {
304 GetWidget()->CloseNow();
307 TranslateBubbleModel::ViewState TranslateBubbleView::GetViewState() const {
308 return model_->GetViewState();
311 TranslateBubbleView::TranslateBubbleView(
312 views::View* anchor_view,
313 scoped_ptr<TranslateBubbleModel> model,
314 TranslateErrors::Type error_type,
315 content::WebContents* web_contents)
316 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
317 WebContentsObserver(web_contents),
318 before_translate_view_(NULL),
319 translating_view_(NULL),
320 after_translate_view_(NULL),
321 error_view_(NULL),
322 advanced_view_(NULL),
323 denial_combobox_(NULL),
324 source_language_combobox_(NULL),
325 target_language_combobox_(NULL),
326 always_translate_checkbox_(NULL),
327 advanced_cancel_button_(NULL),
328 advanced_done_button_(NULL),
329 model_(model.Pass()),
330 error_type_(error_type),
331 is_in_incognito_window_(
332 web_contents ?
333 web_contents->GetBrowserContext()->IsOffTheRecord() : false),
334 translate_executed_(false),
335 denial_button_clicked_(false) {
336 if (model_->GetViewState() !=
337 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) {
338 translate_executed_ = true;
341 set_margins(gfx::Insets(views::kPanelVertMargin, views::kPanelHorizMargin,
342 views::kPanelVertMargin, views::kPanelHorizMargin));
344 translate_bubble_view_ = this;
347 views::View* TranslateBubbleView::GetCurrentView() {
348 switch (model_->GetViewState()) {
349 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE:
350 return before_translate_view_;
351 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
352 return translating_view_;
353 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE:
354 return after_translate_view_;
355 case TranslateBubbleModel::VIEW_STATE_ERROR:
356 return error_view_;
357 case TranslateBubbleModel::VIEW_STATE_ADVANCED:
358 return advanced_view_;
360 NOTREACHED();
361 return NULL;
364 void TranslateBubbleView::HandleButtonPressed(
365 TranslateBubbleView::ButtonID sender_id) {
366 switch (sender_id) {
367 case BUTTON_ID_TRANSLATE: {
368 translate_executed_ = true;
369 model_->Translate();
370 break;
372 case BUTTON_ID_DONE: {
373 if (always_translate_checkbox_)
374 model_->SetAlwaysTranslate(always_translate_checkbox_->checked());
375 if (model_->IsPageTranslatedInCurrentLanguages()) {
376 model_->GoBackFromAdvanced();
377 UpdateChildVisibilities();
378 SizeToContents();
379 } else {
380 translate_executed_ = true;
381 model_->Translate();
382 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
384 break;
386 case BUTTON_ID_CANCEL: {
387 model_->GoBackFromAdvanced();
388 UpdateChildVisibilities();
389 SizeToContents();
390 break;
392 case BUTTON_ID_TRY_AGAIN: {
393 translate_executed_ = true;
394 model_->Translate();
395 break;
397 case BUTTON_ID_SHOW_ORIGINAL: {
398 model_->RevertTranslation();
399 StartFade(false);
400 break;
402 case BUTTON_ID_ALWAYS_TRANSLATE: {
403 // Do nothing. The state of the checkbox affects only when the 'Done'
404 // button is pressed.
405 break;
410 void TranslateBubbleView::HandleLinkClicked(
411 TranslateBubbleView::LinkID sender_id) {
412 switch (sender_id) {
413 case LINK_ID_ADVANCED: {
414 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
415 break;
417 case LINK_ID_LANGUAGE_SETTINGS: {
418 std::string url = std::string(chrome::kChromeUISettingsURL) +
419 chrome::kLanguageOptionsSubPage;
420 web_contents()->OpenURL(content::OpenURLParams(
421 GURL(url),
422 content::Referrer(),
423 NEW_FOREGROUND_TAB,
424 content::PAGE_TRANSITION_LINK,
425 false));
426 break;
431 void TranslateBubbleView::HandleComboboxSelectedIndexChanged(
432 TranslateBubbleView::ComboboxID sender_id) {
433 switch (sender_id) {
434 case COMBOBOX_ID_DENIAL: {
435 // do nothing
436 break;
438 case COMBOBOX_ID_SOURCE_LANGUAGE: {
439 if (model_->GetOriginalLanguageIndex() ==
440 source_language_combobox_->selected_index()) {
441 break;
443 model_->UpdateOriginalLanguageIndex(
444 source_language_combobox_->selected_index());
445 UpdateAdvancedView();
446 break;
448 case COMBOBOX_ID_TARGET_LANGUAGE: {
449 if (model_->GetTargetLanguageIndex() ==
450 target_language_combobox_->selected_index()) {
451 break;
453 model_->UpdateTargetLanguageIndex(
454 target_language_combobox_->selected_index());
455 UpdateAdvancedView();
456 break;
461 void TranslateBubbleView::UpdateChildVisibilities() {
462 for (int i = 0; i < child_count(); i++) {
463 views::View* view = child_at(i);
464 view->SetVisible(view == GetCurrentView());
468 views::View* TranslateBubbleView::CreateViewBeforeTranslate() {
469 views::Label* message_label = new views::Label(
470 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE));
472 base::string16 original_language_name =
473 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
474 denial_combobox_ = new views::Combobox(
475 new TranslateDenialComboboxModel(original_language_name));
476 denial_combobox_->set_id(COMBOBOX_ID_DENIAL);
477 denial_combobox_->set_listener(this);
478 denial_combobox_->SetStyle(views::Combobox::STYLE_NOTIFY_ON_CLICK);
480 views::View* view = new views::View();
481 views::GridLayout* layout = new views::GridLayout(view);
482 view->SetLayoutManager(layout);
484 using views::GridLayout;
486 enum {
487 COLUMN_SET_ID_MESSAGE,
488 COLUMN_SET_ID_CONTENT,
491 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
492 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
493 0, GridLayout::USE_PREF, 0, 0);
494 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
495 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
496 0, 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);
503 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
504 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
505 0, GridLayout::USE_PREF, 0, 0);
507 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
508 layout->AddView(message_label);
509 layout->AddView(CreateLink(this,
510 IDS_TRANSLATE_BUBBLE_ADVANCED,
511 LINK_ID_ADVANCED));
513 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
515 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
516 layout->AddView(denial_combobox_);
517 layout->AddView(CreateLabelButton(
518 this,
519 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT),
520 BUTTON_ID_TRANSLATE));
522 return view;
525 views::View* TranslateBubbleView::CreateViewTranslating() {
526 base::string16 target_language_name =
527 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
528 views::Label* label = new views::Label(
529 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATING));
531 views::View* view = new views::View();
532 views::GridLayout* layout = new views::GridLayout(view);
533 view->SetLayoutManager(layout);
535 using views::GridLayout;
537 enum {
538 COLUMN_SET_ID_MESSAGE,
539 COLUMN_SET_ID_CONTENT,
542 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
543 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
544 0, views::GridLayout::USE_PREF, 0, 0);
545 cs->AddPaddingColumn(1, 0);
547 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
548 cs->AddPaddingColumn(1, 0);
549 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
550 0, GridLayout::USE_PREF, 0, 0);
552 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
553 layout->AddView(label);
555 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
557 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
558 views::LabelButton* revert_button = CreateLabelButton(
559 this,
560 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
561 BUTTON_ID_SHOW_ORIGINAL);
562 revert_button->SetEnabled(false);
563 layout->AddView(revert_button);
565 return view;
568 views::View* TranslateBubbleView::CreateViewAfterTranslate() {
569 views::Label* label = new views::Label(
570 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATED));
572 views::View* view = new views::View();
573 views::GridLayout* layout = new views::GridLayout(view);
574 view->SetLayoutManager(layout);
576 using views::GridLayout;
578 enum {
579 COLUMN_SET_ID_MESSAGE,
580 COLUMN_SET_ID_CONTENT,
583 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
584 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
585 0, views::GridLayout::USE_PREF, 0, 0);
586 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
587 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
588 0, views::GridLayout::USE_PREF, 0, 0);
589 cs->AddPaddingColumn(1, 0);
591 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
592 cs->AddPaddingColumn(1, 0);
593 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
594 0, GridLayout::USE_PREF, 0, 0);
596 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
597 layout->AddView(label);
598 layout->AddView(CreateLink(this,
599 IDS_TRANSLATE_BUBBLE_ADVANCED,
600 LINK_ID_ADVANCED));
602 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
604 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
605 layout->AddView(CreateLabelButton(
606 this,
607 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
608 BUTTON_ID_SHOW_ORIGINAL));
610 return view;
613 views::View* TranslateBubbleView::CreateViewError() {
614 views::Label* label = new views::Label(
615 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE));
617 views::View* view = new views::View();
618 views::GridLayout* layout = new views::GridLayout(view);
619 view->SetLayoutManager(layout);
621 using views::GridLayout;
623 enum {
624 COLUMN_SET_ID_MESSAGE,
625 COLUMN_SET_ID_CONTENT,
628 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
629 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
630 0, GridLayout::USE_PREF, 0, 0);
631 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
632 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
633 0, GridLayout::USE_PREF, 0, 0);
634 cs->AddPaddingColumn(1, 0);
636 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
637 cs->AddPaddingColumn(1, 0);
638 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
639 0, GridLayout::USE_PREF, 0, 0);
641 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
642 layout->AddView(label);
643 layout->AddView(CreateLink(this,
644 IDS_TRANSLATE_BUBBLE_ADVANCED,
645 LINK_ID_ADVANCED));
647 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
649 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
650 layout->AddView(CreateLabelButton(
651 this,
652 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN),
653 BUTTON_ID_TRY_AGAIN));
655 return view;
658 // TODO(hajimehoshi): Revice this later to show a specific message for each
659 // error. (crbug/307350)
660 views::View* TranslateBubbleView::CreateViewAdvanced() {
661 views::Label* source_language_label = new views::Label(
662 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE));
664 views::Label* target_language_label = new views::Label(
665 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE));
667 int source_default_index = model_->GetOriginalLanguageIndex();
668 source_language_combobox_model_.reset(
669 new LanguageComboboxModel(source_default_index, model_.get()));
670 source_language_combobox_ =
671 new views::Combobox(source_language_combobox_model_.get());
673 source_language_combobox_->set_id(COMBOBOX_ID_SOURCE_LANGUAGE);
674 source_language_combobox_->set_listener(this);
676 int target_default_index = model_->GetTargetLanguageIndex();
677 target_language_combobox_model_.reset(
678 new LanguageComboboxModel(target_default_index, model_.get()));
679 target_language_combobox_ =
680 new views::Combobox(target_language_combobox_model_.get());
682 target_language_combobox_->set_id(COMBOBOX_ID_TARGET_LANGUAGE);
683 target_language_combobox_->set_listener(this);
685 // In an incognito window, "Always translate" checkbox shouldn't be shown.
686 if (!is_in_incognito_window_) {
687 always_translate_checkbox_ = new views::Checkbox(base::string16());
688 always_translate_checkbox_->set_id(BUTTON_ID_ALWAYS_TRANSLATE);
689 always_translate_checkbox_->set_listener(this);
692 views::View* view = new views::View();
693 views::GridLayout* layout = new views::GridLayout(view);
694 view->SetLayoutManager(layout);
696 using views::GridLayout;
698 enum {
699 COLUMN_SET_ID_LANGUAGES,
700 COLUMN_SET_ID_BUTTONS,
703 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
704 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER,
705 0, GridLayout::USE_PREF, 0, 0);
706 cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
707 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER,
708 0, GridLayout::USE_PREF, 0, 0);
709 cs->AddPaddingColumn(1, 0);
711 cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
712 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
713 0, GridLayout::USE_PREF, 0, 0);
714 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
715 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
716 0, GridLayout::USE_PREF, 0, 0);
717 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
718 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
719 0, GridLayout::USE_PREF, 0, 0);
721 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
722 layout->AddView(source_language_label);
723 layout->AddView(source_language_combobox_);
725 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
727 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
728 layout->AddView(target_language_label);
729 layout->AddView(target_language_combobox_);
731 if (!is_in_incognito_window_) {
732 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
733 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
734 layout->SkipColumns(1);
735 layout->AddView(always_translate_checkbox_);
738 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
740 layout->StartRow(0, COLUMN_SET_ID_BUTTONS);
741 layout->AddView(CreateLink(this,
742 IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS,
743 LINK_ID_LANGUAGE_SETTINGS));
744 advanced_cancel_button_ = CreateLabelButton(
745 this, l10n_util::GetStringUTF16(IDS_CANCEL), BUTTON_ID_CANCEL);
746 layout->AddView(advanced_cancel_button_);
747 advanced_done_button_ = CreateLabelButton(
748 this, l10n_util::GetStringUTF16(IDS_DONE), BUTTON_ID_DONE);
749 advanced_done_button_->SetIsDefault(true);
750 layout->AddView(advanced_done_button_);
752 UpdateAdvancedView();
754 return view;
757 void TranslateBubbleView::SwitchView(
758 TranslateBubbleModel::ViewState view_state) {
759 if (model_->GetViewState() == view_state)
760 return;
762 model_->SetViewState(view_state);
763 UpdateChildVisibilities();
764 if (view_state == TranslateBubbleModel::VIEW_STATE_ADVANCED)
765 UpdateAdvancedView();
766 SizeToContents();
769 void TranslateBubbleView::SwitchToErrorView(TranslateErrors::Type error_type) {
770 SwitchView(TranslateBubbleModel::VIEW_STATE_ERROR);
771 error_type_ = error_type;
772 model_->ShowError(error_type);
775 void TranslateBubbleView::UpdateAdvancedView() {
776 DCHECK(source_language_combobox_);
777 DCHECK(target_language_combobox_);
778 DCHECK(advanced_done_button_);
780 base::string16 source_language_name =
781 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
782 base::string16 target_language_name =
783 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
785 // "Always translate" checkbox doesn't exist in an incognito window.
786 if (always_translate_checkbox_) {
787 always_translate_checkbox_->SetText(
788 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ALWAYS));
789 always_translate_checkbox_->SetChecked(
790 model_->ShouldAlwaysTranslate());
793 base::string16 label;
794 if (model_->IsPageTranslatedInCurrentLanguages())
795 label = l10n_util::GetStringUTF16(IDS_DONE);
796 else
797 label = l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT);
798 advanced_done_button_->SetText(label);