Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / views / translate / translate_bubble_view.cc
blob145d4443bc4e3254bda6499a9afbe77ac7487f26
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/chrome_translate_client.h"
19 #include "chrome/browser/translate/translate_service.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 "chrome/grit/generated_resources.h"
24 #include "components/translate/core/browser/translate_download_manager.h"
25 #include "components/translate/core/browser/translate_manager.h"
26 #include "components/translate/core/browser/translate_ui_delegate.h"
27 #include "content/public/browser/web_contents.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/models/combobox_model.h"
30 #include "ui/base/models/simple_combobox_model.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"
41 namespace {
43 enum DenialComboboxIndexes {
44 INDEX_NOPE = 0,
45 INDEX_NEVER_TRANSLATE_LANGUAGE = 2,
46 INDEX_NEVER_TRANSLATE_SITE = 4,
49 views::LabelButton* CreateLabelButton(views::ButtonListener* listener,
50 const base::string16& label,
51 int id) {
52 views::LabelButton* button = new views::LabelButton(listener, label);
53 button->set_id(id);
54 button->SetStyle(views::Button::STYLE_BUTTON);
55 return button;
58 views::Link* CreateLink(views::LinkListener* listener,
59 int resource_id,
60 int id) {
61 views::Link* link = new views::Link(
62 l10n_util::GetStringUTF16(resource_id));
63 link->set_listener(listener);
64 link->set_id(id);
65 return link;
68 } // namespace
70 // static
71 TranslateBubbleView* TranslateBubbleView::translate_bubble_view_ = NULL;
73 TranslateBubbleView::~TranslateBubbleView() {
74 // A child view could refer to a model which is owned by this class when
75 // the child view is destructed. For example, |source_language_combobx_model_|
76 // is referred by Combobox's destructor. Before destroying the models,
77 // removing the child views is needed.
78 RemoveAllChildViews(true);
81 // static
82 void TranslateBubbleView::ShowBubble(
83 views::View* anchor_view,
84 content::WebContents* web_contents,
85 translate::TranslateStep step,
86 translate::TranslateErrors::Type error_type,
87 bool is_user_gesture) {
88 if (IsShowing()) {
89 // When the user reads the advanced setting panel, the bubble should not be
90 // changed because he/she is focusing on the bubble.
91 if (translate_bubble_view_->web_contents() == web_contents &&
92 translate_bubble_view_->model()->GetViewState() ==
93 TranslateBubbleModel::VIEW_STATE_ADVANCED) {
94 return;
96 if (step != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
97 TranslateBubbleModel::ViewState state =
98 TranslateBubbleModelImpl::TranslateStepToViewState(step);
99 translate_bubble_view_->SwitchView(state);
100 } else {
101 translate_bubble_view_->SwitchToErrorView(error_type);
103 return;
104 } else {
105 if (step == translate::TRANSLATE_STEP_AFTER_TRANSLATE &&
106 !is_user_gesture) {
107 return;
111 std::string source_language;
112 std::string target_language;
113 ChromeTranslateClient::GetTranslateLanguages(
114 web_contents, &source_language, &target_language);
116 scoped_ptr<translate::TranslateUIDelegate> ui_delegate(
117 new translate::TranslateUIDelegate(
118 ChromeTranslateClient::GetManagerFromWebContents(web_contents)
119 ->GetWeakPtr(),
120 source_language,
121 target_language));
122 scoped_ptr<TranslateBubbleModel> model(
123 new TranslateBubbleModelImpl(step, ui_delegate.Pass()));
124 TranslateBubbleView* view = new TranslateBubbleView(anchor_view,
125 model.Pass(),
126 error_type,
127 web_contents);
128 if (is_user_gesture)
129 views::BubbleDelegateView::CreateBubble(view)->Show();
130 else
131 views::BubbleDelegateView::CreateBubble(view)->ShowInactive();
134 // static
135 void TranslateBubbleView::CloseBubble() {
136 if (!IsShowing())
137 return;
139 translate_bubble_view_->GetWidget()->Close();
142 // static
143 bool TranslateBubbleView::IsShowing() {
144 return translate_bubble_view_ != NULL;
147 // static
148 TranslateBubbleView* TranslateBubbleView::GetCurrentBubble() {
149 return translate_bubble_view_;
152 void TranslateBubbleView::Init() {
153 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
154 0, 0, 0));
156 before_translate_view_ = CreateViewBeforeTranslate();
157 translating_view_ = CreateViewTranslating();
158 after_translate_view_ = CreateViewAfterTranslate();
159 error_view_ = CreateViewError();
160 advanced_view_ = CreateViewAdvanced();
162 AddChildView(before_translate_view_);
163 AddChildView(translating_view_);
164 AddChildView(after_translate_view_);
165 AddChildView(error_view_);
166 AddChildView(advanced_view_);
168 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
170 UpdateChildVisibilities();
172 if (model_->GetViewState() == TranslateBubbleModel::VIEW_STATE_ERROR)
173 model_->ShowError(error_type_);
176 void TranslateBubbleView::ButtonPressed(views::Button* sender,
177 const ui::Event& event) {
178 HandleButtonPressed(static_cast<ButtonID>(sender->id()));
181 void TranslateBubbleView::WindowClosing() {
182 // The operations for |model_| are valid only when a WebContents is alive.
183 // TODO(hajimehoshi): TranslateBubbleViewModel(Impl) should not hold a
184 // WebContents as a member variable because the WebContents might be destroyed
185 // while the TranslateBubbleViewModel(Impl) is still alive. Instead,
186 // TranslateBubbleViewModel should take a reference of a WebContents at each
187 // method. (crbug/320497)
188 if (!translate_executed_ && web_contents())
189 model_->TranslationDeclined(denial_button_clicked_);
191 // We have to reset |translate_bubble_view_| here, not in our destructor,
192 // because we'll be destroyed asynchronously and the shown state will be
193 // checked before then.
194 DCHECK_EQ(translate_bubble_view_, this);
195 translate_bubble_view_ = NULL;
198 bool TranslateBubbleView::AcceleratorPressed(
199 const ui::Accelerator& accelerator) {
200 switch (model_->GetViewState()) {
201 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE: {
202 if (accelerator.key_code() == ui::VKEY_RETURN) {
203 HandleButtonPressed(BUTTON_ID_TRANSLATE);
204 return true;
206 break;
208 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
209 break;
210 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE: {
211 if (accelerator.key_code() == ui::VKEY_RETURN) {
212 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL);
213 return true;
215 break;
217 case TranslateBubbleModel::VIEW_STATE_ERROR:
218 break;
219 case TranslateBubbleModel::VIEW_STATE_ADVANCED: {
220 if (accelerator.key_code() == ui::VKEY_RETURN) {
221 HandleButtonPressed(BUTTON_ID_DONE);
222 return true;
224 break;
227 return BubbleDelegateView::AcceleratorPressed(accelerator);
230 gfx::Size TranslateBubbleView::GetPreferredSize() const {
231 int width = 0;
232 for (int i = 0; i < child_count(); i++) {
233 const views::View* child = child_at(i);
234 width = std::max(width, child->GetPreferredSize().width());
236 int height = GetCurrentView()->GetPreferredSize().height();
237 return gfx::Size(width, height);
240 void TranslateBubbleView::OnPerformAction(views::Combobox* combobox) {
241 HandleComboboxPerformAction(static_cast<ComboboxID>(combobox->id()));
244 void TranslateBubbleView::LinkClicked(views::Link* source, int event_flags) {
245 HandleLinkClicked(static_cast<LinkID>(source->id()));
248 void TranslateBubbleView::WebContentsDestroyed() {
249 GetWidget()->CloseNow();
252 TranslateBubbleModel::ViewState TranslateBubbleView::GetViewState() const {
253 return model_->GetViewState();
256 TranslateBubbleView::TranslateBubbleView(
257 views::View* anchor_view,
258 scoped_ptr<TranslateBubbleModel> model,
259 translate::TranslateErrors::Type error_type,
260 content::WebContents* web_contents)
261 : ManagedFullScreenBubbleDelegateView(anchor_view, web_contents),
262 WebContentsObserver(web_contents),
263 before_translate_view_(NULL),
264 translating_view_(NULL),
265 after_translate_view_(NULL),
266 error_view_(NULL),
267 advanced_view_(NULL),
268 denial_combobox_(NULL),
269 source_language_combobox_(NULL),
270 target_language_combobox_(NULL),
271 always_translate_checkbox_(NULL),
272 advanced_cancel_button_(NULL),
273 advanced_done_button_(NULL),
274 model_(model.Pass()),
275 error_type_(error_type),
276 is_in_incognito_window_(
277 web_contents ? web_contents->GetBrowserContext()->IsOffTheRecord()
278 : false),
279 translate_executed_(false),
280 denial_button_clicked_(false) {
281 if (model_->GetViewState() !=
282 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) {
283 translate_executed_ = true;
286 set_margins(gfx::Insets(views::kPanelVertMargin, views::kPanelHorizMargin,
287 views::kPanelVertMargin, views::kPanelHorizMargin));
289 translate_bubble_view_ = this;
292 views::View* TranslateBubbleView::GetCurrentView() const {
293 switch (model_->GetViewState()) {
294 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE:
295 return before_translate_view_;
296 case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
297 return translating_view_;
298 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE:
299 return after_translate_view_;
300 case TranslateBubbleModel::VIEW_STATE_ERROR:
301 return error_view_;
302 case TranslateBubbleModel::VIEW_STATE_ADVANCED:
303 return advanced_view_;
305 NOTREACHED();
306 return NULL;
309 void TranslateBubbleView::HandleButtonPressed(
310 TranslateBubbleView::ButtonID sender_id) {
311 switch (sender_id) {
312 case BUTTON_ID_TRANSLATE: {
313 translate_executed_ = true;
314 model_->Translate();
315 break;
317 case BUTTON_ID_DONE: {
318 if (always_translate_checkbox_)
319 model_->SetAlwaysTranslate(always_translate_checkbox_->checked());
320 if (model_->IsPageTranslatedInCurrentLanguages()) {
321 model_->GoBackFromAdvanced();
322 UpdateChildVisibilities();
323 SizeToContents();
324 } else {
325 translate_executed_ = true;
326 model_->Translate();
327 SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
329 break;
331 case BUTTON_ID_CANCEL: {
332 model_->GoBackFromAdvanced();
333 UpdateChildVisibilities();
334 SizeToContents();
335 break;
337 case BUTTON_ID_TRY_AGAIN: {
338 translate_executed_ = true;
339 model_->Translate();
340 break;
342 case BUTTON_ID_SHOW_ORIGINAL: {
343 model_->RevertTranslation();
344 GetWidget()->Close();
345 break;
347 case BUTTON_ID_ALWAYS_TRANSLATE: {
348 // Do nothing. The state of the checkbox affects only when the 'Done'
349 // button is pressed.
350 break;
355 void TranslateBubbleView::HandleLinkClicked(
356 TranslateBubbleView::LinkID sender_id) {
357 switch (sender_id) {
358 case LINK_ID_ADVANCED: {
359 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
360 break;
362 case LINK_ID_LANGUAGE_SETTINGS: {
363 GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
364 web_contents()->OpenURL(content::OpenURLParams(
365 url,
366 content::Referrer(),
367 NEW_FOREGROUND_TAB,
368 ui::PAGE_TRANSITION_LINK,
369 false));
370 break;
375 void TranslateBubbleView::HandleComboboxPerformAction(
376 TranslateBubbleView::ComboboxID sender_id) {
377 switch (sender_id) {
378 case COMBOBOX_ID_DENIAL: {
379 denial_button_clicked_ = true;
380 int index = denial_combobox_->selected_index();
381 switch (index) {
382 case INDEX_NOPE:
383 break;
384 case INDEX_NEVER_TRANSLATE_LANGUAGE:
385 model_->SetNeverTranslateLanguage(true);
386 break;
387 case INDEX_NEVER_TRANSLATE_SITE:
388 model_->SetNeverTranslateSite(true);
389 break;
390 default:
391 NOTREACHED();
392 break;
394 GetWidget()->Close();
395 break;
397 case COMBOBOX_ID_SOURCE_LANGUAGE: {
398 if (model_->GetOriginalLanguageIndex() ==
399 source_language_combobox_->selected_index()) {
400 break;
402 model_->UpdateOriginalLanguageIndex(
403 source_language_combobox_->selected_index());
404 UpdateAdvancedView();
405 break;
407 case COMBOBOX_ID_TARGET_LANGUAGE: {
408 if (model_->GetTargetLanguageIndex() ==
409 target_language_combobox_->selected_index()) {
410 break;
412 model_->UpdateTargetLanguageIndex(
413 target_language_combobox_->selected_index());
414 UpdateAdvancedView();
415 break;
420 void TranslateBubbleView::UpdateChildVisibilities() {
421 for (int i = 0; i < child_count(); i++) {
422 views::View* view = child_at(i);
423 view->SetVisible(view == GetCurrentView());
427 views::View* TranslateBubbleView::CreateViewBeforeTranslate() {
428 views::Label* message_label = new views::Label(
429 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE));
431 base::string16 original_language_name =
432 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
434 std::vector<base::string16> items;
435 items.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
436 items.push_back(base::string16());
437 items.push_back(l10n_util::GetStringFUTF16(
438 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
439 original_language_name));
440 items.push_back(base::string16());
441 items.push_back(l10n_util::GetStringUTF16(
442 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
444 denial_combobox_model_.reset(new ui::SimpleComboboxModel(items));
445 denial_combobox_ = new views::Combobox(denial_combobox_model_.get());
446 denial_combobox_->set_id(COMBOBOX_ID_DENIAL);
447 denial_combobox_->set_listener(this);
448 denial_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
450 views::View* view = new views::View();
451 views::GridLayout* layout = new views::GridLayout(view);
452 view->SetLayoutManager(layout);
454 using views::GridLayout;
456 enum {
457 COLUMN_SET_ID_MESSAGE,
458 COLUMN_SET_ID_CONTENT,
461 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
462 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
463 0, GridLayout::USE_PREF, 0, 0);
464 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
465 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
466 0, GridLayout::USE_PREF, 0, 0);
467 cs->AddPaddingColumn(1, 0);
469 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
470 cs->AddPaddingColumn(1, 0);
471 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
472 0, GridLayout::USE_PREF, 0, 0);
473 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
474 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
475 0, GridLayout::USE_PREF, 0, 0);
477 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
478 layout->AddView(message_label);
479 layout->AddView(CreateLink(this,
480 IDS_TRANSLATE_BUBBLE_ADVANCED,
481 LINK_ID_ADVANCED));
483 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
485 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
486 layout->AddView(CreateLabelButton(
487 this,
488 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT),
489 BUTTON_ID_TRANSLATE));
490 layout->AddView(denial_combobox_);
492 return view;
495 views::View* TranslateBubbleView::CreateViewTranslating() {
496 base::string16 target_language_name =
497 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
498 views::Label* label = new views::Label(
499 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATING));
501 views::View* view = new views::View();
502 views::GridLayout* layout = new views::GridLayout(view);
503 view->SetLayoutManager(layout);
505 using views::GridLayout;
507 enum {
508 COLUMN_SET_ID_MESSAGE,
509 COLUMN_SET_ID_CONTENT,
512 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
513 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
514 0, views::GridLayout::USE_PREF, 0, 0);
515 cs->AddPaddingColumn(1, 0);
517 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
518 cs->AddPaddingColumn(1, 0);
519 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
520 0, GridLayout::USE_PREF, 0, 0);
522 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
523 layout->AddView(label);
525 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
527 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
528 views::LabelButton* revert_button = CreateLabelButton(
529 this,
530 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
531 BUTTON_ID_SHOW_ORIGINAL);
532 revert_button->SetEnabled(false);
533 layout->AddView(revert_button);
535 return view;
538 views::View* TranslateBubbleView::CreateViewAfterTranslate() {
539 views::Label* label = new views::Label(
540 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATED));
542 views::View* view = new views::View();
543 views::GridLayout* layout = new views::GridLayout(view);
544 view->SetLayoutManager(layout);
546 using views::GridLayout;
548 enum {
549 COLUMN_SET_ID_MESSAGE,
550 COLUMN_SET_ID_CONTENT,
553 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
554 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
555 0, views::GridLayout::USE_PREF, 0, 0);
556 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
557 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
558 0, views::GridLayout::USE_PREF, 0, 0);
559 cs->AddPaddingColumn(1, 0);
561 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
562 cs->AddPaddingColumn(1, 0);
563 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
564 0, GridLayout::USE_PREF, 0, 0);
566 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
567 layout->AddView(label);
568 layout->AddView(CreateLink(this,
569 IDS_TRANSLATE_BUBBLE_ADVANCED,
570 LINK_ID_ADVANCED));
572 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
574 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
575 layout->AddView(CreateLabelButton(
576 this,
577 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT),
578 BUTTON_ID_SHOW_ORIGINAL));
580 return view;
583 views::View* TranslateBubbleView::CreateViewError() {
584 views::Label* label = new views::Label(
585 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE));
587 views::View* view = new views::View();
588 views::GridLayout* layout = new views::GridLayout(view);
589 view->SetLayoutManager(layout);
591 using views::GridLayout;
593 enum {
594 COLUMN_SET_ID_MESSAGE,
595 COLUMN_SET_ID_CONTENT,
598 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE);
599 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
600 0, GridLayout::USE_PREF, 0, 0);
601 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
602 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
603 0, GridLayout::USE_PREF, 0, 0);
604 cs->AddPaddingColumn(1, 0);
606 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT);
607 cs->AddPaddingColumn(1, 0);
608 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
609 0, GridLayout::USE_PREF, 0, 0);
611 layout->StartRow(0, COLUMN_SET_ID_MESSAGE);
612 layout->AddView(label);
613 layout->AddView(CreateLink(this,
614 IDS_TRANSLATE_BUBBLE_ADVANCED,
615 LINK_ID_ADVANCED));
617 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
619 layout->StartRow(0, COLUMN_SET_ID_CONTENT);
620 layout->AddView(CreateLabelButton(
621 this,
622 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN),
623 BUTTON_ID_TRY_AGAIN));
625 return view;
628 // TODO(hajimehoshi): Revice this later to show a specific message for each
629 // error. (crbug/307350)
630 views::View* TranslateBubbleView::CreateViewAdvanced() {
631 views::Label* source_language_label = new views::Label(
632 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE));
634 views::Label* target_language_label = new views::Label(
635 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE));
637 int source_default_index = model_->GetOriginalLanguageIndex();
638 source_language_combobox_model_.reset(
639 new LanguageComboboxModel(source_default_index, model_.get()));
640 source_language_combobox_ =
641 new views::Combobox(source_language_combobox_model_.get());
643 source_language_combobox_->set_id(COMBOBOX_ID_SOURCE_LANGUAGE);
644 source_language_combobox_->set_listener(this);
646 int target_default_index = model_->GetTargetLanguageIndex();
647 target_language_combobox_model_.reset(
648 new LanguageComboboxModel(target_default_index, model_.get()));
649 target_language_combobox_ =
650 new views::Combobox(target_language_combobox_model_.get());
652 target_language_combobox_->set_id(COMBOBOX_ID_TARGET_LANGUAGE);
653 target_language_combobox_->set_listener(this);
655 // In an incognito window, "Always translate" checkbox shouldn't be shown.
656 if (!is_in_incognito_window_) {
657 always_translate_checkbox_ = new views::Checkbox(base::string16());
658 always_translate_checkbox_->set_id(BUTTON_ID_ALWAYS_TRANSLATE);
659 always_translate_checkbox_->set_listener(this);
662 views::View* view = new views::View();
663 views::GridLayout* layout = new views::GridLayout(view);
664 view->SetLayoutManager(layout);
666 using views::GridLayout;
668 enum {
669 COLUMN_SET_ID_LANGUAGES,
670 COLUMN_SET_ID_BUTTONS,
673 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
674 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER,
675 0, GridLayout::USE_PREF, 0, 0);
676 cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
677 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER,
678 0, GridLayout::USE_PREF, 0, 0);
679 cs->AddPaddingColumn(1, 0);
681 cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
682 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
683 0, GridLayout::USE_PREF, 0, 0);
684 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
685 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
686 0, GridLayout::USE_PREF, 0, 0);
687 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
688 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
689 0, GridLayout::USE_PREF, 0, 0);
691 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
692 layout->AddView(source_language_label);
693 layout->AddView(source_language_combobox_);
695 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
697 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
698 layout->AddView(target_language_label);
699 layout->AddView(target_language_combobox_);
701 if (!is_in_incognito_window_) {
702 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
703 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES);
704 layout->SkipColumns(1);
705 layout->AddView(always_translate_checkbox_);
708 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
710 layout->StartRow(0, COLUMN_SET_ID_BUTTONS);
711 layout->AddView(CreateLink(this,
712 IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS,
713 LINK_ID_LANGUAGE_SETTINGS));
714 advanced_done_button_ = CreateLabelButton(
715 this, l10n_util::GetStringUTF16(IDS_DONE), BUTTON_ID_DONE);
716 advanced_done_button_->SetIsDefault(true);
717 advanced_cancel_button_ = CreateLabelButton(
718 this, l10n_util::GetStringUTF16(IDS_CANCEL), BUTTON_ID_CANCEL);
719 layout->AddView(advanced_done_button_);
720 layout->AddView(advanced_cancel_button_);
722 UpdateAdvancedView();
724 return view;
727 void TranslateBubbleView::SwitchView(
728 TranslateBubbleModel::ViewState view_state) {
729 if (model_->GetViewState() == view_state)
730 return;
732 model_->SetViewState(view_state);
733 UpdateChildVisibilities();
734 if (view_state == TranslateBubbleModel::VIEW_STATE_ADVANCED)
735 UpdateAdvancedView();
736 SizeToContents();
739 void TranslateBubbleView::SwitchToErrorView(
740 translate::TranslateErrors::Type error_type) {
741 SwitchView(TranslateBubbleModel::VIEW_STATE_ERROR);
742 error_type_ = error_type;
743 model_->ShowError(error_type);
746 void TranslateBubbleView::UpdateAdvancedView() {
747 DCHECK(source_language_combobox_);
748 DCHECK(target_language_combobox_);
749 DCHECK(advanced_done_button_);
751 base::string16 source_language_name =
752 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
753 base::string16 target_language_name =
754 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
756 // "Always translate" checkbox doesn't exist in an incognito window.
757 if (always_translate_checkbox_) {
758 always_translate_checkbox_->SetText(
759 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ALWAYS));
760 always_translate_checkbox_->SetChecked(
761 model_->ShouldAlwaysTranslate());
764 base::string16 label;
765 if (model_->IsPageTranslatedInCurrentLanguages())
766 label = l10n_util::GetStringUTF16(IDS_DONE);
767 else
768 label = l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT);
769 advanced_done_button_->SetText(label);