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