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/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"
40 views::LabelButton
* CreateLabelButton(views::ButtonListener
* listener
,
41 const base::string16
& label
,
43 views::LabelButton
* button
= new views::LabelButton(listener
, label
);
45 button
->SetStyle(views::Button::STYLE_BUTTON
);
49 views::Link
* CreateLink(views::LinkListener
* listener
,
52 views::Link
* link
= new views::Link(
53 l10n_util::GetStringUTF16(resource_id
));
54 link
->set_listener(listener
);
59 void GetTranslateLanguages(content::WebContents
* web_contents
,
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();
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
;
81 *target
= TranslateManager::GetTargetLanguage(prefs
);
84 class TranslateDenialComboboxModel
: public ui::ComboboxModel
{
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() {}
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
{
120 std::vector
<base::string16
> items_
;
122 DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel
);
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);
139 void TranslateBubbleView::ShowBubble(views::View
* anchor_view
,
140 content::WebContents
* web_contents
,
141 TranslateBubbleModel::ViewState type
,
142 TranslateErrors::Type error_type
) {
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
) {
151 if (type
!= TranslateBubbleModel::VIEW_STATE_ERROR
)
152 translate_bubble_view_
->SwitchView(type
);
154 translate_bubble_view_
->SwitchToErrorView(error_type
);
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
,
170 views::BubbleDelegateView::CreateBubble(view
)->Show();
174 bool TranslateBubbleView::IsShowing() {
175 return translate_bubble_view_
!= NULL
;
179 TranslateBubbleView
* TranslateBubbleView::GetCurrentBubble() {
180 return translate_bubble_view_
;
183 void TranslateBubbleView::Init() {
184 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical
,
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
);
239 case TranslateBubbleModel::VIEW_STATE_TRANSLATING
:
241 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE
: {
242 if (accelerator
.key_code() == ui::VKEY_RETURN
) {
243 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL
);
248 case TranslateBubbleModel::VIEW_STATE_ERROR
:
250 case TranslateBubbleModel::VIEW_STATE_ADVANCED
: {
251 if (accelerator
.key_code() == ui::VKEY_RETURN
) {
252 HandleButtonPressed(BUTTON_ID_DONE
);
258 return BubbleDelegateView::AcceleratorPressed(accelerator
);
261 gfx::Size
TranslateBubbleView::GetPreferredSize() {
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_
)
280 denial_button_clicked_
= true;
281 int index
= combobox
->selected_index();
283 case TranslateDenialComboboxModel::INDEX_NOPE
:
285 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_LANGUAGE
:
286 model_
->SetNeverTranslateLanguage(true);
288 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_SITE
:
289 model_
->SetNeverTranslateSite(true);
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
),
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_(
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
:
357 case TranslateBubbleModel::VIEW_STATE_ADVANCED
:
358 return advanced_view_
;
364 void TranslateBubbleView::HandleButtonPressed(
365 TranslateBubbleView::ButtonID sender_id
) {
367 case BUTTON_ID_TRANSLATE
: {
368 translate_executed_
= true;
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();
380 translate_executed_
= true;
382 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING
);
386 case BUTTON_ID_CANCEL
: {
387 model_
->GoBackFromAdvanced();
388 UpdateChildVisibilities();
392 case BUTTON_ID_TRY_AGAIN
: {
393 translate_executed_
= true;
397 case BUTTON_ID_SHOW_ORIGINAL
: {
398 model_
->RevertTranslation();
402 case BUTTON_ID_ALWAYS_TRANSLATE
: {
403 // Do nothing. The state of the checkbox affects only when the 'Done'
404 // button is pressed.
410 void TranslateBubbleView::HandleLinkClicked(
411 TranslateBubbleView::LinkID sender_id
) {
413 case LINK_ID_ADVANCED
: {
414 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED
);
417 case LINK_ID_LANGUAGE_SETTINGS
: {
418 std::string url
= std::string(chrome::kChromeUISettingsURL
) +
419 chrome::kLanguageOptionsSubPage
;
420 web_contents()->OpenURL(content::OpenURLParams(
424 content::PAGE_TRANSITION_LINK
,
431 void TranslateBubbleView::HandleComboboxSelectedIndexChanged(
432 TranslateBubbleView::ComboboxID sender_id
) {
434 case COMBOBOX_ID_DENIAL
: {
438 case COMBOBOX_ID_SOURCE_LANGUAGE
: {
439 if (model_
->GetOriginalLanguageIndex() ==
440 source_language_combobox_
->selected_index()) {
443 model_
->UpdateOriginalLanguageIndex(
444 source_language_combobox_
->selected_index());
445 UpdateAdvancedView();
448 case COMBOBOX_ID_TARGET_LANGUAGE
: {
449 if (model_
->GetTargetLanguageIndex() ==
450 target_language_combobox_
->selected_index()) {
453 model_
->UpdateTargetLanguageIndex(
454 target_language_combobox_
->selected_index());
455 UpdateAdvancedView();
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
;
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
,
513 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
515 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
516 layout
->AddView(denial_combobox_
);
517 layout
->AddView(CreateLabelButton(
519 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT
),
520 BUTTON_ID_TRANSLATE
));
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
;
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(
560 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT
),
561 BUTTON_ID_SHOW_ORIGINAL
);
562 revert_button
->SetEnabled(false);
563 layout
->AddView(revert_button
);
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
;
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
,
602 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
604 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
605 layout
->AddView(CreateLabelButton(
607 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT
),
608 BUTTON_ID_SHOW_ORIGINAL
));
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
;
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
,
647 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
649 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
650 layout
->AddView(CreateLabelButton(
652 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN
),
653 BUTTON_ID_TRY_AGAIN
));
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
;
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();
757 void TranslateBubbleView::SwitchView(
758 TranslateBubbleModel::ViewState view_state
) {
759 if (model_
->GetViewState() == view_state
)
762 model_
->SetViewState(view_state
);
763 UpdateChildVisibilities();
764 if (view_state
== TranslateBubbleModel::VIEW_STATE_ADVANCED
)
765 UpdateAdvancedView();
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
);
797 label
= l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT
);
798 advanced_done_button_
->SetText(label
);