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