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_service.h"
19 #include "chrome/browser/translate/translate_tab_helper.h"
20 #include "chrome/browser/ui/chrome_pages.h"
21 #include "chrome/browser/ui/translate/translate_bubble_model_impl.h"
22 #include "chrome/common/url_constants.h"
23 #include "components/translate/core/browser/translate_download_manager.h"
24 #include "components/translate/core/browser/translate_manager.h"
25 #include "components/translate/core/browser/translate_ui_delegate.h"
26 #include "content/public/browser/web_contents.h"
27 #include "grit/generated_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/models/combobox_model.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/views/controls/button/checkbox.h"
32 #include "ui/views/controls/button/label_button.h"
33 #include "ui/views/controls/combobox/combobox.h"
34 #include "ui/views/controls/label.h"
35 #include "ui/views/controls/link.h"
36 #include "ui/views/layout/box_layout.h"
37 #include "ui/views/layout/grid_layout.h"
38 #include "ui/views/layout/layout_constants.h"
39 #include "ui/views/widget/widget.h"
43 views::LabelButton
* CreateLabelButton(views::ButtonListener
* listener
,
44 const base::string16
& label
,
46 views::LabelButton
* button
= new views::LabelButton(listener
, label
);
48 button
->SetStyle(views::Button::STYLE_BUTTON
);
52 views::Link
* CreateLink(views::LinkListener
* listener
,
55 views::Link
* link
= new views::Link(
56 l10n_util::GetStringUTF16(resource_id
));
57 link
->set_listener(listener
);
62 class TranslateDenialComboboxModel
: public ui::ComboboxModel
{
66 INDEX_NEVER_TRANSLATE_LANGUAGE
= 2,
67 INDEX_NEVER_TRANSLATE_SITE
= 4,
70 explicit TranslateDenialComboboxModel(
71 const base::string16
& original_language_name
) {
72 items_
.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY
));
73 items_
.push_back(base::string16());
74 items_
.push_back(l10n_util::GetStringFUTF16(
75 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG
,
76 original_language_name
));
77 items_
.push_back(base::string16());
78 items_
.push_back(l10n_util::GetStringUTF16(
79 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE
));
81 virtual ~TranslateDenialComboboxModel() {}
84 // Overridden from ui::ComboboxModel:
85 virtual int GetItemCount() const OVERRIDE
{
88 virtual base::string16
GetItemAt(int index
) OVERRIDE
{
91 virtual bool IsItemSeparatorAt(int index
) OVERRIDE
{
92 return items_
[index
].empty();
94 virtual int GetDefaultIndex() const OVERRIDE
{
98 std::vector
<base::string16
> items_
;
100 DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel
);
106 TranslateBubbleView
* TranslateBubbleView::translate_bubble_view_
= NULL
;
108 TranslateBubbleView::~TranslateBubbleView() {
109 // A child view could refer to a model which is owned by this class when
110 // the child view is destructed. For example, |source_language_combobx_model_|
111 // is referred by Combobox's destructor. Before destroying the models,
112 // removing the child views is needed.
113 RemoveAllChildViews(true);
117 void TranslateBubbleView::ShowBubble(views::View
* anchor_view
,
118 content::WebContents
* web_contents
,
119 translate::TranslateStep step
,
120 TranslateErrors::Type error_type
) {
122 // When the user reads the advanced setting panel, the bubble should not be
123 // changed because he/she is focusing on the bubble.
124 if (translate_bubble_view_
->web_contents() == web_contents
&&
125 translate_bubble_view_
->model()->GetViewState() ==
126 TranslateBubbleModel::VIEW_STATE_ADVANCED
) {
129 if (step
!= translate::TRANSLATE_STEP_TRANSLATE_ERROR
) {
130 TranslateBubbleModel::ViewState state
=
131 TranslateBubbleModelImpl::TranslateStepToViewState(step
);
132 translate_bubble_view_
->SwitchView(state
);
134 translate_bubble_view_
->SwitchToErrorView(error_type
);
139 std::string source_language
;
140 std::string target_language
;
141 TranslateTabHelper::GetTranslateLanguages(web_contents
,
142 &source_language
, &target_language
);
144 scoped_ptr
<TranslateUIDelegate
> ui_delegate(new TranslateUIDelegate(
145 TranslateTabHelper::FromWebContents(web_contents
),
146 TranslateTabHelper::GetManagerFromWebContents(web_contents
),
149 scoped_ptr
<TranslateBubbleModel
> model(
150 new TranslateBubbleModelImpl(step
, ui_delegate
.Pass()));
151 TranslateBubbleView
* view
= new TranslateBubbleView(anchor_view
,
155 views::BubbleDelegateView::CreateBubble(view
)->Show();
159 bool TranslateBubbleView::IsShowing() {
160 return translate_bubble_view_
!= NULL
;
164 TranslateBubbleView
* TranslateBubbleView::GetCurrentBubble() {
165 return translate_bubble_view_
;
168 void TranslateBubbleView::Init() {
169 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical
,
172 before_translate_view_
= CreateViewBeforeTranslate();
173 translating_view_
= CreateViewTranslating();
174 after_translate_view_
= CreateViewAfterTranslate();
175 error_view_
= CreateViewError();
176 advanced_view_
= CreateViewAdvanced();
178 AddChildView(before_translate_view_
);
179 AddChildView(translating_view_
);
180 AddChildView(after_translate_view_
);
181 AddChildView(error_view_
);
182 AddChildView(advanced_view_
);
184 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN
, ui::EF_NONE
));
186 UpdateChildVisibilities();
188 if (model_
->GetViewState() == TranslateBubbleModel::VIEW_STATE_ERROR
)
189 model_
->ShowError(error_type_
);
192 void TranslateBubbleView::ButtonPressed(views::Button
* sender
,
193 const ui::Event
& event
) {
194 HandleButtonPressed(static_cast<ButtonID
>(sender
->id()));
197 void TranslateBubbleView::WindowClosing() {
198 // The operations for |model_| are valid only when a WebContents is alive.
199 // TODO(hajimehoshi): TranslateBubbleViewModel(Impl) should not hold a
200 // WebContents as a member variable because the WebContents might be destroyed
201 // while the TranslateBubbleViewModel(Impl) is still alive. Instead,
202 // TranslateBubbleViewModel should take a reference of a WebContents at each
203 // method. (crbug/320497)
204 if (!translate_executed_
&& web_contents())
205 model_
->TranslationDeclined(denial_button_clicked_
);
207 // We have to reset |translate_bubble_view_| here, not in our destructor,
208 // because we'll be destroyed asynchronously and the shown state will be
209 // checked before then.
210 DCHECK_EQ(translate_bubble_view_
, this);
211 translate_bubble_view_
= NULL
;
214 bool TranslateBubbleView::AcceleratorPressed(
215 const ui::Accelerator
& accelerator
) {
216 switch (model_
->GetViewState()) {
217 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE
: {
218 if (accelerator
.key_code() == ui::VKEY_RETURN
) {
219 HandleButtonPressed(BUTTON_ID_TRANSLATE
);
224 case TranslateBubbleModel::VIEW_STATE_TRANSLATING
:
226 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE
: {
227 if (accelerator
.key_code() == ui::VKEY_RETURN
) {
228 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL
);
233 case TranslateBubbleModel::VIEW_STATE_ERROR
:
235 case TranslateBubbleModel::VIEW_STATE_ADVANCED
: {
236 if (accelerator
.key_code() == ui::VKEY_RETURN
) {
237 HandleButtonPressed(BUTTON_ID_DONE
);
243 return BubbleDelegateView::AcceleratorPressed(accelerator
);
246 gfx::Size
TranslateBubbleView::GetPreferredSize() {
248 for (int i
= 0; i
< child_count(); i
++) {
249 views::View
* child
= child_at(i
);
250 width
= std::max(width
, child
->GetPreferredSize().width());
252 int height
= GetCurrentView()->GetPreferredSize().height();
253 return gfx::Size(width
, height
);
256 void TranslateBubbleView::OnPerformAction(views::Combobox
* combobox
) {
257 HandleComboboxPerformAction(static_cast<ComboboxID
>(combobox
->id()));
260 void TranslateBubbleView::LinkClicked(views::Link
* source
, int event_flags
) {
261 HandleLinkClicked(static_cast<LinkID
>(source
->id()));
264 void TranslateBubbleView::WebContentsDestroyed(
265 content::WebContents
* web_contents
) {
266 GetWidget()->CloseNow();
269 TranslateBubbleModel::ViewState
TranslateBubbleView::GetViewState() const {
270 return model_
->GetViewState();
273 TranslateBubbleView::TranslateBubbleView(
274 views::View
* anchor_view
,
275 scoped_ptr
<TranslateBubbleModel
> model
,
276 TranslateErrors::Type error_type
,
277 content::WebContents
* web_contents
)
278 : BubbleDelegateView(anchor_view
, views::BubbleBorder::TOP_RIGHT
),
279 WebContentsObserver(web_contents
),
280 before_translate_view_(NULL
),
281 translating_view_(NULL
),
282 after_translate_view_(NULL
),
284 advanced_view_(NULL
),
285 denial_combobox_(NULL
),
286 source_language_combobox_(NULL
),
287 target_language_combobox_(NULL
),
288 always_translate_checkbox_(NULL
),
289 advanced_cancel_button_(NULL
),
290 advanced_done_button_(NULL
),
291 model_(model
.Pass()),
292 error_type_(error_type
),
293 is_in_incognito_window_(
295 web_contents
->GetBrowserContext()->IsOffTheRecord() : false),
296 translate_executed_(false),
297 denial_button_clicked_(false) {
298 if (model_
->GetViewState() !=
299 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE
) {
300 translate_executed_
= true;
303 set_margins(gfx::Insets(views::kPanelVertMargin
, views::kPanelHorizMargin
,
304 views::kPanelVertMargin
, views::kPanelHorizMargin
));
306 translate_bubble_view_
= this;
309 views::View
* TranslateBubbleView::GetCurrentView() {
310 switch (model_
->GetViewState()) {
311 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE
:
312 return before_translate_view_
;
313 case TranslateBubbleModel::VIEW_STATE_TRANSLATING
:
314 return translating_view_
;
315 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE
:
316 return after_translate_view_
;
317 case TranslateBubbleModel::VIEW_STATE_ERROR
:
319 case TranslateBubbleModel::VIEW_STATE_ADVANCED
:
320 return advanced_view_
;
326 void TranslateBubbleView::HandleButtonPressed(
327 TranslateBubbleView::ButtonID sender_id
) {
329 case BUTTON_ID_TRANSLATE
: {
330 translate_executed_
= true;
334 case BUTTON_ID_DONE
: {
335 if (always_translate_checkbox_
)
336 model_
->SetAlwaysTranslate(always_translate_checkbox_
->checked());
337 if (model_
->IsPageTranslatedInCurrentLanguages()) {
338 model_
->GoBackFromAdvanced();
339 UpdateChildVisibilities();
342 translate_executed_
= true;
344 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING
);
348 case BUTTON_ID_CANCEL
: {
349 model_
->GoBackFromAdvanced();
350 UpdateChildVisibilities();
354 case BUTTON_ID_TRY_AGAIN
: {
355 translate_executed_
= true;
359 case BUTTON_ID_SHOW_ORIGINAL
: {
360 model_
->RevertTranslation();
361 GetWidget()->Close();
364 case BUTTON_ID_ALWAYS_TRANSLATE
: {
365 // Do nothing. The state of the checkbox affects only when the 'Done'
366 // button is pressed.
372 void TranslateBubbleView::HandleLinkClicked(
373 TranslateBubbleView::LinkID sender_id
) {
375 case LINK_ID_ADVANCED
: {
376 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED
);
379 case LINK_ID_LANGUAGE_SETTINGS
: {
380 GURL url
= chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage
);
381 web_contents()->OpenURL(content::OpenURLParams(
385 content::PAGE_TRANSITION_LINK
,
392 void TranslateBubbleView::HandleComboboxPerformAction(
393 TranslateBubbleView::ComboboxID sender_id
) {
395 case COMBOBOX_ID_DENIAL
: {
396 denial_button_clicked_
= true;
397 int index
= denial_combobox_
->selected_index();
399 case TranslateDenialComboboxModel::INDEX_NOPE
:
401 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_LANGUAGE
:
402 model_
->SetNeverTranslateLanguage(true);
404 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_SITE
:
405 model_
->SetNeverTranslateSite(true);
411 GetWidget()->Close();
414 case COMBOBOX_ID_SOURCE_LANGUAGE
: {
415 if (model_
->GetOriginalLanguageIndex() ==
416 source_language_combobox_
->selected_index()) {
419 model_
->UpdateOriginalLanguageIndex(
420 source_language_combobox_
->selected_index());
421 UpdateAdvancedView();
424 case COMBOBOX_ID_TARGET_LANGUAGE
: {
425 if (model_
->GetTargetLanguageIndex() ==
426 target_language_combobox_
->selected_index()) {
429 model_
->UpdateTargetLanguageIndex(
430 target_language_combobox_
->selected_index());
431 UpdateAdvancedView();
437 void TranslateBubbleView::UpdateChildVisibilities() {
438 for (int i
= 0; i
< child_count(); i
++) {
439 views::View
* view
= child_at(i
);
440 view
->SetVisible(view
== GetCurrentView());
444 views::View
* TranslateBubbleView::CreateViewBeforeTranslate() {
445 views::Label
* message_label
= new views::Label(
446 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE
));
448 base::string16 original_language_name
=
449 model_
->GetLanguageNameAt(model_
->GetOriginalLanguageIndex());
450 denial_combobox_
= new views::Combobox(
451 new TranslateDenialComboboxModel(original_language_name
));
452 denial_combobox_
->set_id(COMBOBOX_ID_DENIAL
);
453 denial_combobox_
->set_listener(this);
454 denial_combobox_
->SetStyle(views::Combobox::STYLE_ACTION
);
456 views::View
* view
= new views::View();
457 views::GridLayout
* layout
= new views::GridLayout(view
);
458 view
->SetLayoutManager(layout
);
460 using views::GridLayout
;
463 COLUMN_SET_ID_MESSAGE
,
464 COLUMN_SET_ID_CONTENT
,
467 views::ColumnSet
* cs
= layout
->AddColumnSet(COLUMN_SET_ID_MESSAGE
);
468 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
469 0, GridLayout::USE_PREF
, 0, 0);
470 cs
->AddPaddingColumn(0, views::kRelatedButtonHSpacing
);
471 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
472 0, GridLayout::USE_PREF
, 0, 0);
473 cs
->AddPaddingColumn(1, 0);
475 cs
= layout
->AddColumnSet(COLUMN_SET_ID_CONTENT
);
476 cs
->AddPaddingColumn(1, 0);
477 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
478 0, GridLayout::USE_PREF
, 0, 0);
479 cs
->AddPaddingColumn(0, views::kRelatedButtonHSpacing
);
480 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
481 0, GridLayout::USE_PREF
, 0, 0);
483 layout
->StartRow(0, COLUMN_SET_ID_MESSAGE
);
484 layout
->AddView(message_label
);
485 layout
->AddView(CreateLink(this,
486 IDS_TRANSLATE_BUBBLE_ADVANCED
,
489 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
491 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
492 layout
->AddView(CreateLabelButton(
494 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT
),
495 BUTTON_ID_TRANSLATE
));
496 layout
->AddView(denial_combobox_
);
501 views::View
* TranslateBubbleView::CreateViewTranslating() {
502 base::string16 target_language_name
=
503 model_
->GetLanguageNameAt(model_
->GetTargetLanguageIndex());
504 views::Label
* label
= new views::Label(
505 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATING
));
507 views::View
* view
= new views::View();
508 views::GridLayout
* layout
= new views::GridLayout(view
);
509 view
->SetLayoutManager(layout
);
511 using views::GridLayout
;
514 COLUMN_SET_ID_MESSAGE
,
515 COLUMN_SET_ID_CONTENT
,
518 views::ColumnSet
* cs
= layout
->AddColumnSet(COLUMN_SET_ID_MESSAGE
);
519 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
520 0, views::GridLayout::USE_PREF
, 0, 0);
521 cs
->AddPaddingColumn(1, 0);
523 cs
= layout
->AddColumnSet(COLUMN_SET_ID_CONTENT
);
524 cs
->AddPaddingColumn(1, 0);
525 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
526 0, GridLayout::USE_PREF
, 0, 0);
528 layout
->StartRow(0, COLUMN_SET_ID_MESSAGE
);
529 layout
->AddView(label
);
531 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
533 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
534 views::LabelButton
* revert_button
= CreateLabelButton(
536 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT
),
537 BUTTON_ID_SHOW_ORIGINAL
);
538 revert_button
->SetEnabled(false);
539 layout
->AddView(revert_button
);
544 views::View
* TranslateBubbleView::CreateViewAfterTranslate() {
545 views::Label
* label
= new views::Label(
546 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATED
));
548 views::View
* view
= new views::View();
549 views::GridLayout
* layout
= new views::GridLayout(view
);
550 view
->SetLayoutManager(layout
);
552 using views::GridLayout
;
555 COLUMN_SET_ID_MESSAGE
,
556 COLUMN_SET_ID_CONTENT
,
559 views::ColumnSet
* cs
= layout
->AddColumnSet(COLUMN_SET_ID_MESSAGE
);
560 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
561 0, views::GridLayout::USE_PREF
, 0, 0);
562 cs
->AddPaddingColumn(0, views::kRelatedButtonHSpacing
);
563 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
564 0, views::GridLayout::USE_PREF
, 0, 0);
565 cs
->AddPaddingColumn(1, 0);
567 cs
= layout
->AddColumnSet(COLUMN_SET_ID_CONTENT
);
568 cs
->AddPaddingColumn(1, 0);
569 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
570 0, GridLayout::USE_PREF
, 0, 0);
572 layout
->StartRow(0, COLUMN_SET_ID_MESSAGE
);
573 layout
->AddView(label
);
574 layout
->AddView(CreateLink(this,
575 IDS_TRANSLATE_BUBBLE_ADVANCED
,
578 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
580 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
581 layout
->AddView(CreateLabelButton(
583 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT
),
584 BUTTON_ID_SHOW_ORIGINAL
));
589 views::View
* TranslateBubbleView::CreateViewError() {
590 views::Label
* label
= new views::Label(
591 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE
));
593 views::View
* view
= new views::View();
594 views::GridLayout
* layout
= new views::GridLayout(view
);
595 view
->SetLayoutManager(layout
);
597 using views::GridLayout
;
600 COLUMN_SET_ID_MESSAGE
,
601 COLUMN_SET_ID_CONTENT
,
604 views::ColumnSet
* cs
= layout
->AddColumnSet(COLUMN_SET_ID_MESSAGE
);
605 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
606 0, GridLayout::USE_PREF
, 0, 0);
607 cs
->AddPaddingColumn(0, views::kRelatedButtonHSpacing
);
608 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
609 0, GridLayout::USE_PREF
, 0, 0);
610 cs
->AddPaddingColumn(1, 0);
612 cs
= layout
->AddColumnSet(COLUMN_SET_ID_CONTENT
);
613 cs
->AddPaddingColumn(1, 0);
614 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
615 0, GridLayout::USE_PREF
, 0, 0);
617 layout
->StartRow(0, COLUMN_SET_ID_MESSAGE
);
618 layout
->AddView(label
);
619 layout
->AddView(CreateLink(this,
620 IDS_TRANSLATE_BUBBLE_ADVANCED
,
623 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
625 layout
->StartRow(0, COLUMN_SET_ID_CONTENT
);
626 layout
->AddView(CreateLabelButton(
628 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN
),
629 BUTTON_ID_TRY_AGAIN
));
634 // TODO(hajimehoshi): Revice this later to show a specific message for each
635 // error. (crbug/307350)
636 views::View
* TranslateBubbleView::CreateViewAdvanced() {
637 views::Label
* source_language_label
= new views::Label(
638 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE
));
640 views::Label
* target_language_label
= new views::Label(
641 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE
));
643 int source_default_index
= model_
->GetOriginalLanguageIndex();
644 source_language_combobox_model_
.reset(
645 new LanguageComboboxModel(source_default_index
, model_
.get()));
646 source_language_combobox_
=
647 new views::Combobox(source_language_combobox_model_
.get());
649 source_language_combobox_
->set_id(COMBOBOX_ID_SOURCE_LANGUAGE
);
650 source_language_combobox_
->set_listener(this);
652 int target_default_index
= model_
->GetTargetLanguageIndex();
653 target_language_combobox_model_
.reset(
654 new LanguageComboboxModel(target_default_index
, model_
.get()));
655 target_language_combobox_
=
656 new views::Combobox(target_language_combobox_model_
.get());
658 target_language_combobox_
->set_id(COMBOBOX_ID_TARGET_LANGUAGE
);
659 target_language_combobox_
->set_listener(this);
661 // In an incognito window, "Always translate" checkbox shouldn't be shown.
662 if (!is_in_incognito_window_
) {
663 always_translate_checkbox_
= new views::Checkbox(base::string16());
664 always_translate_checkbox_
->set_id(BUTTON_ID_ALWAYS_TRANSLATE
);
665 always_translate_checkbox_
->set_listener(this);
668 views::View
* view
= new views::View();
669 views::GridLayout
* layout
= new views::GridLayout(view
);
670 view
->SetLayoutManager(layout
);
672 using views::GridLayout
;
675 COLUMN_SET_ID_LANGUAGES
,
676 COLUMN_SET_ID_BUTTONS
,
679 views::ColumnSet
* cs
= layout
->AddColumnSet(COLUMN_SET_ID_LANGUAGES
);
680 cs
->AddColumn(GridLayout::TRAILING
, GridLayout::CENTER
,
681 0, GridLayout::USE_PREF
, 0, 0);
682 cs
->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing
);
683 cs
->AddColumn(GridLayout::FILL
, GridLayout::CENTER
,
684 0, GridLayout::USE_PREF
, 0, 0);
685 cs
->AddPaddingColumn(1, 0);
687 cs
= layout
->AddColumnSet(COLUMN_SET_ID_BUTTONS
);
688 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
689 0, GridLayout::USE_PREF
, 0, 0);
690 cs
->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing
);
691 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
692 0, GridLayout::USE_PREF
, 0, 0);
693 cs
->AddPaddingColumn(0, views::kRelatedButtonHSpacing
);
694 cs
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
,
695 0, GridLayout::USE_PREF
, 0, 0);
697 layout
->StartRow(0, COLUMN_SET_ID_LANGUAGES
);
698 layout
->AddView(source_language_label
);
699 layout
->AddView(source_language_combobox_
);
701 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
703 layout
->StartRow(0, COLUMN_SET_ID_LANGUAGES
);
704 layout
->AddView(target_language_label
);
705 layout
->AddView(target_language_combobox_
);
707 if (!is_in_incognito_window_
) {
708 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
709 layout
->StartRow(0, COLUMN_SET_ID_LANGUAGES
);
710 layout
->SkipColumns(1);
711 layout
->AddView(always_translate_checkbox_
);
714 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
716 layout
->StartRow(0, COLUMN_SET_ID_BUTTONS
);
717 layout
->AddView(CreateLink(this,
718 IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS
,
719 LINK_ID_LANGUAGE_SETTINGS
));
720 advanced_done_button_
= CreateLabelButton(
721 this, l10n_util::GetStringUTF16(IDS_DONE
), BUTTON_ID_DONE
);
722 advanced_done_button_
->SetIsDefault(true);
723 advanced_cancel_button_
= CreateLabelButton(
724 this, l10n_util::GetStringUTF16(IDS_CANCEL
), BUTTON_ID_CANCEL
);
725 layout
->AddView(advanced_done_button_
);
726 layout
->AddView(advanced_cancel_button_
);
728 UpdateAdvancedView();
733 void TranslateBubbleView::SwitchView(
734 TranslateBubbleModel::ViewState view_state
) {
735 if (model_
->GetViewState() == view_state
)
738 model_
->SetViewState(view_state
);
739 UpdateChildVisibilities();
740 if (view_state
== TranslateBubbleModel::VIEW_STATE_ADVANCED
)
741 UpdateAdvancedView();
745 void TranslateBubbleView::SwitchToErrorView(TranslateErrors::Type error_type
) {
746 SwitchView(TranslateBubbleModel::VIEW_STATE_ERROR
);
747 error_type_
= error_type
;
748 model_
->ShowError(error_type
);
751 void TranslateBubbleView::UpdateAdvancedView() {
752 DCHECK(source_language_combobox_
);
753 DCHECK(target_language_combobox_
);
754 DCHECK(advanced_done_button_
);
756 base::string16 source_language_name
=
757 model_
->GetLanguageNameAt(model_
->GetOriginalLanguageIndex());
758 base::string16 target_language_name
=
759 model_
->GetLanguageNameAt(model_
->GetTargetLanguageIndex());
761 // "Always translate" checkbox doesn't exist in an incognito window.
762 if (always_translate_checkbox_
) {
763 always_translate_checkbox_
->SetText(
764 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ALWAYS
));
765 always_translate_checkbox_
->SetChecked(
766 model_
->ShouldAlwaysTranslate());
769 base::string16 label
;
770 if (model_
->IsPageTranslatedInCurrentLanguages())
771 label
= l10n_util::GetStringUTF16(IDS_DONE
);
773 label
= l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT
);
774 advanced_done_button_
->SetText(label
);