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