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 "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"
41 views::LabelButton
* CreateLabelButton(views::ButtonListener
* listener
,
42 const base::string16
& label
,
44 views::LabelButton
* button
= new views::LabelButton(listener
, label
);
46 button
->SetStyle(views::Button::STYLE_BUTTON
);
50 views::Link
* CreateLink(views::LinkListener
* listener
,
53 views::Link
* link
= new views::Link(
54 l10n_util::GetStringUTF16(resource_id
));
55 link
->set_listener(listener
);
60 void GetTranslateLanguages(content::WebContents
* web_contents
,
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
);
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
;
83 *target
= TranslateManager::GetTargetLanguage(prefs
);
86 class TranslateDenialComboboxModel
: public ui::ComboboxModel
{
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() {}
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
{
122 std::vector
<base::string16
> items_
;
124 DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel
);
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);
141 void TranslateBubbleView::ShowBubble(views::View
* anchor_view
,
142 content::WebContents
* web_contents
,
143 TranslateTabHelper::TranslateStep step
,
144 TranslateErrors::Type error_type
) {
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
) {
153 if (step
!= TranslateTabHelper::TRANSLATE_ERROR
) {
154 TranslateBubbleModel::ViewState state
=
155 TranslateBubbleModelImpl::TranslateStepToViewState(step
);
156 translate_bubble_view_
->SwitchView(state
);
158 translate_bubble_view_
->SwitchToErrorView(error_type
);
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
,
175 views::BubbleDelegateView::CreateBubble(view
)->Show();
179 bool TranslateBubbleView::IsShowing() {
180 return translate_bubble_view_
!= NULL
;
184 TranslateBubbleView
* TranslateBubbleView::GetCurrentBubble() {
185 return translate_bubble_view_
;
188 void TranslateBubbleView::Init() {
189 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical
,
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
);
244 case TranslateBubbleModel::VIEW_STATE_TRANSLATING
:
246 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE
: {
247 if (accelerator
.key_code() == ui::VKEY_RETURN
) {
248 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL
);
253 case TranslateBubbleModel::VIEW_STATE_ERROR
:
255 case TranslateBubbleModel::VIEW_STATE_ADVANCED
: {
256 if (accelerator
.key_code() == ui::VKEY_RETURN
) {
257 HandleButtonPressed(BUTTON_ID_DONE
);
263 return BubbleDelegateView::AcceleratorPressed(accelerator
);
266 gfx::Size
TranslateBubbleView::GetPreferredSize() {
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
),
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_(
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
:
339 case TranslateBubbleModel::VIEW_STATE_ADVANCED
:
340 return advanced_view_
;
346 void TranslateBubbleView::HandleButtonPressed(
347 TranslateBubbleView::ButtonID sender_id
) {
349 case BUTTON_ID_TRANSLATE
: {
350 translate_executed_
= true;
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();
362 translate_executed_
= true;
364 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING
);
368 case BUTTON_ID_CANCEL
: {
369 model_
->GoBackFromAdvanced();
370 UpdateChildVisibilities();
374 case BUTTON_ID_TRY_AGAIN
: {
375 translate_executed_
= true;
379 case BUTTON_ID_SHOW_ORIGINAL
: {
380 model_
->RevertTranslation();
384 case BUTTON_ID_ALWAYS_TRANSLATE
: {
385 // Do nothing. The state of the checkbox affects only when the 'Done'
386 // button is pressed.
392 void TranslateBubbleView::HandleLinkClicked(
393 TranslateBubbleView::LinkID sender_id
) {
395 case LINK_ID_ADVANCED
: {
396 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED
);
399 case LINK_ID_LANGUAGE_SETTINGS
: {
400 std::string url
= std::string(chrome::kChromeUISettingsURL
) +
401 chrome::kLanguageOptionsSubPage
;
402 web_contents()->OpenURL(content::OpenURLParams(
406 content::PAGE_TRANSITION_LINK
,
413 void TranslateBubbleView::HandleComboboxPerformAction(
414 TranslateBubbleView::ComboboxID sender_id
) {
416 case COMBOBOX_ID_DENIAL
: {
417 denial_button_clicked_
= true;
418 int index
= denial_combobox_
->selected_index();
420 case TranslateDenialComboboxModel::INDEX_NOPE
:
422 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_LANGUAGE
:
423 model_
->SetNeverTranslateLanguage(true);
425 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_SITE
:
426 model_
->SetNeverTranslateSite(true);
435 case COMBOBOX_ID_SOURCE_LANGUAGE
: {
436 if (model_
->GetOriginalLanguageIndex() ==
437 source_language_combobox_
->selected_index()) {
440 model_
->UpdateOriginalLanguageIndex(
441 source_language_combobox_
->selected_index());
442 UpdateAdvancedView();
445 case COMBOBOX_ID_TARGET_LANGUAGE
: {
446 if (model_
->GetTargetLanguageIndex() ==
447 target_language_combobox_
->selected_index()) {
450 model_
->UpdateTargetLanguageIndex(
451 target_language_combobox_
->selected_index());
452 UpdateAdvancedView();
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
;
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
,
510 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
512 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
513 layout
->AddView(CreateLabelButton(
515 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT
),
516 BUTTON_ID_TRANSLATE
));
517 layout
->AddView(denial_combobox_
);
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
;
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(
557 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT
),
558 BUTTON_ID_SHOW_ORIGINAL
);
559 revert_button
->SetEnabled(false);
560 layout
->AddView(revert_button
);
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
;
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
,
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_REVERT
),
605 BUTTON_ID_SHOW_ORIGINAL
));
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
;
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
,
644 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
646 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
647 layout
->AddView(CreateLabelButton(
649 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN
),
650 BUTTON_ID_TRY_AGAIN
));
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
;
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();
754 void TranslateBubbleView::SwitchView(
755 TranslateBubbleModel::ViewState view_state
) {
756 if (model_
->GetViewState() == view_state
)
759 model_
->SetViewState(view_state
);
760 UpdateChildVisibilities();
761 if (view_state
== TranslateBubbleModel::VIEW_STATE_ADVANCED
)
762 UpdateAdvancedView();
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
);
794 label
= l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT
);
795 advanced_done_button_
->SetText(label
);