translate_bubble_view.cc revision f2477e01787aa58f445919b809d89e252beef54f
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. 4 5#include "chrome/browser/ui/views/translate/translate_bubble_view.h" 6 7#include <algorithm> 8#include <string> 9#include <vector> 10 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/browser.h" 22#include "chrome/browser/ui/translate/translate_bubble_model_impl.h" 23#include "chrome/common/url_constants.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" 38 39namespace { 40 41views::LabelButton* CreateLabelButton(views::ButtonListener* listener, 42 const string16& label, int id) { 43 views::LabelButton* button = new views::LabelButton(listener, label); 44 button->set_id(id); 45 button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 46 return button; 47} 48 49views::Link* CreateLink(views::LinkListener* listener, 50 int resource_id, 51 int id) { 52 views::Link* link = new views::Link( 53 l10n_util::GetStringUTF16(resource_id)); 54 link->set_listener(listener); 55 link->set_id(id); 56 return link; 57} 58 59void GetTranslateLanguages(content::WebContents* web_contents, 60 std::string* source, 61 std::string* target) { 62 DCHECK(source != NULL); 63 DCHECK(target != NULL); 64 65 TranslateTabHelper* translate_tab_helper = 66 TranslateTabHelper::FromWebContents(web_contents); 67 *source = translate_tab_helper->language_state().original_language(); 68 69 Profile* profile = 70 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 71 Profile* original_profile = profile->GetOriginalProfile(); 72 PrefService* prefs = original_profile->GetPrefs(); 73 if (!web_contents->GetBrowserContext()->IsOffTheRecord()) { 74 std::string auto_translate_language = 75 TranslateManager::GetAutoTargetLanguage(*source, prefs); 76 if (!auto_translate_language.empty()) { 77 *target = auto_translate_language; 78 return; 79 } 80 } 81 *target = TranslateManager::GetTargetLanguage(prefs); 82} 83 84// TODO(hajimehoshi): The interface to offer denial choices should be another 85// control instead of Combobox. See crbug/305494. 86class TranslateDenialComboboxModel : public ui::ComboboxModel { 87 public: 88 enum { 89 INDEX_NOPE = 0, 90 INDEX_NEVER_TRANSLATE_LANGUAGE = 2, 91 INDEX_NEVER_TRANSLATE_SITE = 4, 92 }; 93 94 explicit TranslateDenialComboboxModel( 95 const string16& original_language_name) { 96 items_.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY)); 97 items_.push_back(string16()); 98 items_.push_back(l10n_util::GetStringFUTF16( 99 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG, 100 original_language_name)); 101 items_.push_back(string16()); 102 items_.push_back(l10n_util::GetStringUTF16( 103 IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE)); 104 } 105 virtual ~TranslateDenialComboboxModel() {} 106 107 private: 108 // Overridden from ui::ComboboxModel: 109 virtual int GetItemCount() const OVERRIDE { 110 return items_.size(); 111 } 112 virtual string16 GetItemAt(int index) OVERRIDE { 113 return items_[index]; 114 } 115 virtual bool IsItemSeparatorAt(int index) OVERRIDE { 116 return items_[index].empty(); 117 } 118 virtual int GetDefaultIndex() const OVERRIDE { 119 return 0; 120 } 121 122 std::vector<string16> items_; 123 124 DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel); 125}; 126 127} // namespace 128 129// static 130TranslateBubbleView* TranslateBubbleView::translate_bubble_view_ = NULL; 131 132TranslateBubbleView::~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); 138} 139 140// static 141void TranslateBubbleView::ShowBubble(views::View* anchor_view, 142 content::WebContents* web_contents, 143 TranslateBubbleModel::ViewState type, 144 Browser* browser) { 145 if (IsShowing()) { 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) { 151 return; 152 } 153 translate_bubble_view_->SwitchView(type); 154 return; 155 } 156 157 std::string source_language; 158 std::string target_language; 159 GetTranslateLanguages(web_contents, &source_language, &target_language); 160 161 scoped_ptr<TranslateUIDelegate> ui_delegate( 162 new TranslateUIDelegate(web_contents, source_language, target_language)); 163 scoped_ptr<TranslateBubbleModel> model( 164 new TranslateBubbleModelImpl(type, ui_delegate.Pass())); 165 TranslateBubbleView* view = new TranslateBubbleView(anchor_view, 166 model.Pass(), 167 browser, 168 web_contents); 169 views::BubbleDelegateView::CreateBubble(view)->Show(); 170} 171 172// static 173bool TranslateBubbleView::IsShowing() { 174 return translate_bubble_view_ != NULL; 175} 176 177// static 178TranslateBubbleView* TranslateBubbleView::GetCurrentBubble() { 179 return translate_bubble_view_; 180} 181 182void TranslateBubbleView::Init() { 183 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 184 0, 0, 0)); 185 186 before_translate_view_ = CreateViewBeforeTranslate(); 187 translating_view_ = CreateViewTranslating(); 188 after_translate_view_ = CreateViewAfterTranslate(); 189 error_view_ = CreateViewError(); 190 advanced_view_ = CreateViewAdvanced(); 191 192 AddChildView(before_translate_view_); 193 AddChildView(translating_view_); 194 AddChildView(after_translate_view_); 195 AddChildView(error_view_); 196 AddChildView(advanced_view_); 197 198 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE)); 199 200 UpdateChildVisibilities(); 201} 202 203void TranslateBubbleView::ButtonPressed(views::Button* sender, 204 const ui::Event& event) { 205 HandleButtonPressed(static_cast<ButtonID>(sender->id())); 206} 207 208void TranslateBubbleView::WindowClosing() { 209 // The operations for |model_| are valid only when a WebContents is alive. 210 // TODO(hajimehoshi): TranslateBubbleViewModel(Impl) should not hold a 211 // WebContents as a member variable because the WebContents might be destroyed 212 // while the TranslateBubbleViewModel(Impl) is still alive. Instead, 213 // TranslateBubbleViewModel should take a reference of a WebContents at each 214 // method. (crbug/320497) 215 if (!translate_executed_ && web_contents()) 216 model_->TranslationDeclined(); 217 218 // We have to reset |translate_bubble_view_| here, not in our destructor, 219 // because we'll be destroyed asynchronously and the shown state will be 220 // checked before then. 221 DCHECK_EQ(translate_bubble_view_, this); 222 translate_bubble_view_ = NULL; 223} 224 225bool TranslateBubbleView::AcceleratorPressed( 226 const ui::Accelerator& accelerator) { 227 switch (model_->GetViewState()) { 228 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE: { 229 if (accelerator.key_code() == ui::VKEY_RETURN) { 230 HandleButtonPressed(BUTTON_ID_TRANSLATE); 231 return true; 232 } 233 break; 234 } 235 case TranslateBubbleModel::VIEW_STATE_TRANSLATING: 236 break; 237 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE: { 238 if (accelerator.key_code() == ui::VKEY_RETURN) { 239 HandleButtonPressed(BUTTON_ID_SHOW_ORIGINAL); 240 return true; 241 } 242 break; 243 } 244 case TranslateBubbleModel::VIEW_STATE_ERROR: 245 break; 246 case TranslateBubbleModel::VIEW_STATE_ADVANCED: { 247 if (accelerator.key_code() == ui::VKEY_RETURN) { 248 HandleButtonPressed(BUTTON_ID_DONE); 249 return true; 250 } 251 break; 252 } 253 } 254 return BubbleDelegateView::AcceleratorPressed(accelerator); 255} 256 257gfx::Size TranslateBubbleView::GetPreferredSize() { 258 int width = 0; 259 for (int i = 0; i < child_count(); i++) { 260 views::View* child = child_at(i); 261 width = std::max(width, child->GetPreferredSize().width()); 262 } 263 int height = GetCurrentView()->GetPreferredSize().height(); 264 return gfx::Size(width, height); 265} 266 267void TranslateBubbleView::OnSelectedIndexChanged(views::Combobox* combobox) { 268 HandleComboboxSelectedIndexChanged(static_cast<ComboboxID>(combobox->id())); 269} 270 271void TranslateBubbleView::LinkClicked(views::Link* source, int event_flags) { 272 HandleLinkClicked(static_cast<LinkID>(source->id())); 273} 274 275void TranslateBubbleView::WebContentsDestroyed( 276 content::WebContents* web_contents) { 277 GetWidget()->CloseNow(); 278} 279 280TranslateBubbleModel::ViewState TranslateBubbleView::GetViewState() const { 281 return model_->GetViewState(); 282} 283 284TranslateBubbleView::TranslateBubbleView( 285 views::View* anchor_view, 286 scoped_ptr<TranslateBubbleModel> model, 287 Browser* browser, 288 content::WebContents* web_contents) 289 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), 290 WebContentsObserver(web_contents), 291 before_translate_view_(NULL), 292 translating_view_(NULL), 293 after_translate_view_(NULL), 294 error_view_(NULL), 295 advanced_view_(NULL), 296 denial_combobox_(NULL), 297 source_language_combobox_(NULL), 298 target_language_combobox_(NULL), 299 always_translate_checkbox_(NULL), 300 model_(model.Pass()), 301 is_in_incognito_window_( 302 web_contents ? 303 web_contents->GetBrowserContext()->IsOffTheRecord() : false), 304 browser_(browser), 305 translate_executed_(false) { 306 if (model_->GetViewState() != 307 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) { 308 translate_executed_ = true; 309 } 310 311 set_margins(gfx::Insets(views::kPanelVertMargin, views::kPanelHorizMargin, 312 views::kPanelVertMargin, views::kPanelHorizMargin)); 313 314 translate_bubble_view_ = this; 315} 316 317views::View* TranslateBubbleView::GetCurrentView() { 318 switch (model_->GetViewState()) { 319 case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE: 320 return before_translate_view_; 321 case TranslateBubbleModel::VIEW_STATE_TRANSLATING: 322 return translating_view_; 323 case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE: 324 return after_translate_view_; 325 case TranslateBubbleModel::VIEW_STATE_ERROR: 326 return error_view_; 327 case TranslateBubbleModel::VIEW_STATE_ADVANCED: 328 return advanced_view_; 329 } 330 NOTREACHED(); 331 return NULL; 332} 333 334void TranslateBubbleView::HandleButtonPressed( 335 TranslateBubbleView::ButtonID sender_id) { 336 switch (sender_id) { 337 case BUTTON_ID_TRANSLATE: { 338 translate_executed_ = true; 339 model_->Translate(); 340 break; 341 } 342 case BUTTON_ID_DONE: { 343 if (always_translate_checkbox_) 344 model_->SetAlwaysTranslate(always_translate_checkbox_->checked()); 345 translate_executed_ = true; 346 model_->Translate(); 347 break; 348 } 349 case BUTTON_ID_CANCEL: { 350 model_->GoBackFromAdvanced(); 351 UpdateChildVisibilities(); 352 SizeToContents(); 353 break; 354 } 355 case BUTTON_ID_TRY_AGAIN: { 356 translate_executed_ = true; 357 model_->Translate(); 358 break; 359 } 360 case BUTTON_ID_SHOW_ORIGINAL: { 361 model_->RevertTranslation(); 362 StartFade(false); 363 break; 364 } 365 case BUTTON_ID_ALWAYS_TRANSLATE: { 366 // Do nothing. The state of the checkbox affects only when the 'Done' 367 // button is pressed. 368 break; 369 } 370 } 371} 372 373void TranslateBubbleView::HandleLinkClicked( 374 TranslateBubbleView::LinkID sender_id) { 375 switch (sender_id) { 376 case LINK_ID_ADVANCED: { 377 SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED); 378 break; 379 } 380 case LINK_ID_LEARN_MORE: { 381 browser_->OpenURL(content::OpenURLParams( 382 GURL(chrome::kAboutGoogleTranslateURL), 383 content::Referrer(), 384 NEW_FOREGROUND_TAB, 385 content::PAGE_TRANSITION_LINK, 386 false)); 387 break; 388 } 389 } 390} 391 392void TranslateBubbleView::HandleComboboxSelectedIndexChanged( 393 TranslateBubbleView::ComboboxID sender_id) { 394 switch (sender_id) { 395 case COMBOBOX_ID_DENIAL: { 396 int index = denial_combobox_->selected_index(); 397 switch (index) { 398 case TranslateDenialComboboxModel::INDEX_NOPE: 399 if (!translate_executed_) 400 model_->TranslationDeclined(); 401 StartFade(false); 402 break; 403 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_LANGUAGE: 404 model_->SetNeverTranslateLanguage(true); 405 StartFade(false); 406 break; 407 case TranslateDenialComboboxModel::INDEX_NEVER_TRANSLATE_SITE: 408 model_->SetNeverTranslateSite(true); 409 StartFade(false); 410 break; 411 default: 412 NOTREACHED(); 413 break; 414 } 415 break; 416 } 417 case COMBOBOX_ID_SOURCE_LANGUAGE: { 418 if (model_->GetOriginalLanguageIndex() == 419 source_language_combobox_->selected_index()) { 420 break; 421 } 422 model_->UpdateOriginalLanguageIndex( 423 source_language_combobox_->selected_index()); 424 UpdateAdvancedView(); 425 break; 426 } 427 case COMBOBOX_ID_TARGET_LANGUAGE: { 428 if (model_->GetTargetLanguageIndex() == 429 target_language_combobox_->selected_index()) { 430 break; 431 } 432 model_->UpdateTargetLanguageIndex( 433 target_language_combobox_->selected_index()); 434 UpdateAdvancedView(); 435 break; 436 } 437 } 438} 439 440void TranslateBubbleView::UpdateChildVisibilities() { 441 for (int i = 0; i < child_count(); i++) { 442 views::View* view = child_at(i); 443 view->SetVisible(view == GetCurrentView()); 444 } 445} 446 447views::View* TranslateBubbleView::CreateViewBeforeTranslate() { 448 views::Label* message_label = new views::Label( 449 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE)); 450 451 string16 original_language_name = 452 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex()); 453 denial_combobox_ = new views::Combobox( 454 new TranslateDenialComboboxModel(original_language_name)); 455 denial_combobox_->set_id(COMBOBOX_ID_DENIAL); 456 denial_combobox_->set_listener(this); 457 458 views::View* view = new views::View(); 459 views::GridLayout* layout = new views::GridLayout(view); 460 view->SetLayoutManager(layout); 461 462 using views::GridLayout; 463 464 enum { 465 COLUMN_SET_ID_MESSAGE, 466 COLUMN_SET_ID_CONTENT, 467 }; 468 469 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE); 470 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 471 0, GridLayout::USE_PREF, 0, 0); 472 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 473 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 474 0, GridLayout::USE_PREF, 0, 0); 475 cs->AddPaddingColumn(1, 0); 476 477 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT); 478 cs->AddPaddingColumn(1, 0); 479 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 480 0, GridLayout::USE_PREF, 0, 0); 481 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 482 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 483 0, GridLayout::USE_PREF, 0, 0); 484 485 layout->StartRow(0, COLUMN_SET_ID_MESSAGE); 486 layout->AddView(message_label); 487 layout->AddView(CreateLink(this, 488 IDS_TRANSLATE_BUBBLE_ADVANCED, 489 LINK_ID_ADVANCED)); 490 491 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 492 493 layout->StartRow(0, COLUMN_SET_ID_CONTENT); 494 layout->AddView(denial_combobox_); 495 layout->AddView(CreateLabelButton( 496 this, 497 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT), 498 BUTTON_ID_TRANSLATE)); 499 500 return view; 501} 502 503views::View* TranslateBubbleView::CreateViewTranslating() { 504 string16 target_language_name = 505 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex()); 506 views::Label* label = new views::Label( 507 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATING)); 508 509 views::View* view = new views::View(); 510 views::GridLayout* layout = new views::GridLayout(view); 511 view->SetLayoutManager(layout); 512 513 using views::GridLayout; 514 515 enum { 516 COLUMN_SET_ID_MESSAGE, 517 COLUMN_SET_ID_CONTENT, 518 }; 519 520 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE); 521 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 522 0, views::GridLayout::USE_PREF, 0, 0); 523 cs->AddPaddingColumn(1, 0); 524 525 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT); 526 cs->AddPaddingColumn(1, 0); 527 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 528 0, GridLayout::USE_PREF, 0, 0); 529 530 layout->StartRow(0, COLUMN_SET_ID_MESSAGE); 531 layout->AddView(label); 532 533 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 534 535 layout->StartRow(0, COLUMN_SET_ID_CONTENT); 536 views::LabelButton* revert_button = CreateLabelButton( 537 this, 538 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT), 539 BUTTON_ID_SHOW_ORIGINAL); 540 revert_button->SetEnabled(false); 541 layout->AddView(revert_button); 542 543 return view; 544} 545 546views::View* TranslateBubbleView::CreateViewAfterTranslate() { 547 views::Label* label = new views::Label( 548 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATED)); 549 550 views::View* view = new views::View(); 551 views::GridLayout* layout = new views::GridLayout(view); 552 view->SetLayoutManager(layout); 553 554 using views::GridLayout; 555 556 enum { 557 COLUMN_SET_ID_MESSAGE, 558 COLUMN_SET_ID_CONTENT, 559 }; 560 561 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE); 562 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 563 0, views::GridLayout::USE_PREF, 0, 0); 564 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 565 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 566 0, views::GridLayout::USE_PREF, 0, 0); 567 cs->AddPaddingColumn(1, 0); 568 569 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT); 570 cs->AddPaddingColumn(1, 0); 571 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 572 0, GridLayout::USE_PREF, 0, 0); 573 574 layout->StartRow(0, COLUMN_SET_ID_MESSAGE); 575 layout->AddView(label); 576 layout->AddView(CreateLink(this, 577 IDS_TRANSLATE_BUBBLE_ADVANCED, 578 LINK_ID_ADVANCED)); 579 580 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 581 582 layout->StartRow(0, COLUMN_SET_ID_CONTENT); 583 layout->AddView(CreateLabelButton( 584 this, 585 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT), 586 BUTTON_ID_SHOW_ORIGINAL)); 587 588 return view; 589} 590 591views::View* TranslateBubbleView::CreateViewError() { 592 views::Label* label = new views::Label( 593 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE)); 594 595 views::View* view = new views::View(); 596 views::GridLayout* layout = new views::GridLayout(view); 597 view->SetLayoutManager(layout); 598 599 using views::GridLayout; 600 601 enum { 602 COLUMN_SET_ID_MESSAGE, 603 COLUMN_SET_ID_CONTENT, 604 }; 605 606 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_MESSAGE); 607 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 608 0, GridLayout::USE_PREF, 0, 0); 609 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 610 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 611 0, GridLayout::USE_PREF, 0, 0); 612 cs->AddPaddingColumn(1, 0); 613 614 cs = layout->AddColumnSet(COLUMN_SET_ID_CONTENT); 615 cs->AddPaddingColumn(1, 0); 616 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 617 0, GridLayout::USE_PREF, 0, 0); 618 619 layout->StartRow(0, COLUMN_SET_ID_MESSAGE); 620 layout->AddView(label); 621 layout->AddView(CreateLink(this, 622 IDS_TRANSLATE_BUBBLE_ADVANCED, 623 LINK_ID_ADVANCED)); 624 625 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 626 627 layout->StartRow(0, COLUMN_SET_ID_CONTENT); 628 layout->AddView(CreateLabelButton( 629 this, 630 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN), 631 BUTTON_ID_TRY_AGAIN)); 632 633 return view; 634} 635 636// TODO(hajimehoshi): Revice this later to show a specific message for each 637// error. (crbug/307350) 638views::View* TranslateBubbleView::CreateViewAdvanced() { 639 views::Label* source_language_label = new views::Label( 640 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE)); 641 642 views::Label* target_language_label = new views::Label( 643 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE)); 644 645 int source_default_index = model_->GetOriginalLanguageIndex(); 646 source_language_combobox_model_.reset( 647 new LanguageComboboxModel(source_default_index, model_.get())); 648 source_language_combobox_ = 649 new views::Combobox(source_language_combobox_model_.get()); 650 651 source_language_combobox_->set_id(COMBOBOX_ID_SOURCE_LANGUAGE); 652 source_language_combobox_->set_listener(this); 653 654 int target_default_index = model_->GetTargetLanguageIndex(); 655 target_language_combobox_model_.reset( 656 new LanguageComboboxModel(target_default_index, model_.get())); 657 target_language_combobox_ = 658 new views::Combobox(target_language_combobox_model_.get()); 659 660 target_language_combobox_->set_id(COMBOBOX_ID_TARGET_LANGUAGE); 661 target_language_combobox_->set_listener(this); 662 663 // In an incognito window, "Always translate" checkbox shouldn't be shown. 664 if (!is_in_incognito_window_) { 665 always_translate_checkbox_ = new views::Checkbox(string16()); 666 always_translate_checkbox_->set_id(BUTTON_ID_ALWAYS_TRANSLATE); 667 always_translate_checkbox_->set_listener(this); 668 } 669 670 views::View* view = new views::View(); 671 views::GridLayout* layout = new views::GridLayout(view); 672 view->SetLayoutManager(layout); 673 674 using views::GridLayout; 675 676 enum { 677 COLUMN_SET_ID_LANGUAGES, 678 COLUMN_SET_ID_BUTTONS, 679 }; 680 681 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES); 682 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 683 0, GridLayout::USE_PREF, 0, 0); 684 cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); 685 cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 686 0, GridLayout::USE_PREF, 0, 0); 687 cs->AddPaddingColumn(1, 0); 688 689 cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS); 690 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 691 0, GridLayout::USE_PREF, 0, 0); 692 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing); 693 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 694 0, GridLayout::USE_PREF, 0, 0); 695 cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing); 696 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 697 0, GridLayout::USE_PREF, 0, 0); 698 699 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES); 700 layout->AddView(source_language_label); 701 layout->AddView(source_language_combobox_); 702 703 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 704 705 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES); 706 layout->AddView(target_language_label); 707 layout->AddView(target_language_combobox_); 708 709 if (!is_in_incognito_window_) { 710 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 711 layout->StartRow(0, COLUMN_SET_ID_LANGUAGES); 712 layout->SkipColumns(1); 713 layout->AddView(always_translate_checkbox_); 714 } 715 716 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 717 718 layout->StartRow(0, COLUMN_SET_ID_BUTTONS); 719 layout->AddView(CreateLink(this, 720 IDS_TRANSLATE_BUBBLE_LEARN_MORE, 721 LINK_ID_LEARN_MORE)); 722 views::LabelButton* cancel_button = CreateLabelButton( 723 this, l10n_util::GetStringUTF16(IDS_CANCEL), BUTTON_ID_CANCEL); 724 layout->AddView(cancel_button); 725 views::LabelButton* done_button = CreateLabelButton( 726 this, l10n_util::GetStringUTF16(IDS_DONE), BUTTON_ID_DONE); 727 done_button->SetIsDefault(true); 728 layout->AddView(done_button); 729 730 UpdateAdvancedView(); 731 732 return view; 733} 734 735void TranslateBubbleView::SwitchView( 736 TranslateBubbleModel::ViewState view_state) { 737 if (model_->GetViewState() == view_state) 738 return; 739 740 model_->SetViewState(view_state); 741 UpdateChildVisibilities(); 742 SizeToContents(); 743} 744 745void TranslateBubbleView::UpdateAdvancedView() { 746 DCHECK(source_language_combobox_); 747 DCHECK(target_language_combobox_); 748 749 string16 source_language_name = 750 model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex()); 751 string16 target_language_name = 752 model_->GetLanguageNameAt(model_->GetTargetLanguageIndex()); 753 754 // "Always translate" checkbox doesn't exist in an incognito window. 755 if (always_translate_checkbox_) { 756 always_translate_checkbox_->SetText( 757 l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ALWAYS)); 758 always_translate_checkbox_->SetChecked( 759 model_->ShouldAlwaysTranslate()); 760 } 761} 762