1 // Copyright (c) 2012 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/infobars/before_translate_infobar.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "chrome/browser/translate/translate_infobar_delegate.h" 9 #include "grit/generated_resources.h" 10 #include "ui/base/l10n/l10n_util.h" 11 #include "ui/views/controls/button/label_button.h" 12 #include "ui/views/controls/button/menu_button.h" 13 #include "ui/views/controls/label.h" 14 #include "ui/views/controls/menu/menu_item_view.h" 15 16 BeforeTranslateInfoBar::BeforeTranslateInfoBar( 17 InfoBarService* owner, 18 TranslateInfoBarDelegate* delegate) 19 : TranslateInfoBarBase(owner, delegate), 20 label_1_(NULL), 21 label_2_(NULL), 22 language_menu_button_(NULL), 23 accept_button_(NULL), 24 deny_button_(NULL), 25 never_translate_button_(NULL), 26 always_translate_button_(NULL), 27 options_menu_button_(NULL), 28 options_menu_model_(delegate) { 29 } 30 31 BeforeTranslateInfoBar::~BeforeTranslateInfoBar() { 32 } 33 34 void BeforeTranslateInfoBar::Layout() { 35 TranslateInfoBarBase::Layout(); 36 37 int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth()); 38 gfx::Size label_1_size = label_1_->GetPreferredSize(); 39 label_1_->SetBounds(StartX(), OffsetY(label_1_size), 40 std::min(label_1_size.width(), available_width), label_1_size.height()); 41 available_width = std::max(0, available_width - label_1_size.width()); 42 43 gfx::Size language_button_size = language_menu_button_->GetPreferredSize(); 44 language_menu_button_->SetBounds( 45 label_1_->bounds().right() + kButtonInLabelSpacing, 46 OffsetY(language_button_size), language_button_size.width(), 47 language_button_size.height()); 48 49 gfx::Size label_2_size = label_2_->GetPreferredSize(); 50 label_2_->SetBounds( 51 language_menu_button_->bounds().right() + kButtonInLabelSpacing, 52 OffsetY(label_2_size), std::min(label_2_size.width(), available_width), 53 label_2_size.height()); 54 55 gfx::Size accept_button_size = accept_button_->GetPreferredSize(); 56 accept_button_->SetBounds(label_2_->bounds().right() + kEndOfLabelSpacing, 57 OffsetY(accept_button_size), accept_button_size.width(), 58 accept_button_size.height()); 59 60 gfx::Size deny_button_size = deny_button_->GetPreferredSize(); 61 deny_button_->SetBounds( 62 accept_button_->bounds().right() + kButtonButtonSpacing, 63 OffsetY(deny_button_size), deny_button_size.width(), 64 deny_button_size.height()); 65 66 if (never_translate_button_) { 67 gfx::Size never_button_size = never_translate_button_->GetPreferredSize(); 68 never_translate_button_->SetBounds( 69 deny_button_->bounds().right() + kButtonButtonSpacing, 70 OffsetY(never_button_size), never_button_size.width(), 71 never_button_size.height()); 72 } 73 74 if (always_translate_button_) { 75 gfx::Size always_button_size = always_translate_button_->GetPreferredSize(); 76 always_translate_button_->SetBounds( 77 deny_button_->bounds().right() + kButtonButtonSpacing, 78 OffsetY(always_button_size), always_button_size.width(), 79 always_button_size.height()); 80 } 81 82 gfx::Size options_size = options_menu_button_->GetPreferredSize(); 83 options_menu_button_->SetBounds(EndX() - options_size.width(), 84 OffsetY(options_size), options_size.width(), options_size.height()); 85 } 86 87 void BeforeTranslateInfoBar::ViewHierarchyChanged( 88 const ViewHierarchyChangedDetails& details) { 89 if (!details.is_add || (details.child != this) || (label_1_ != NULL)) { 90 TranslateInfoBarBase::ViewHierarchyChanged(details); 91 return; 92 } 93 94 size_t offset = 0; 95 string16 text(l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE, 96 string16(), &offset)); 97 98 label_1_ = CreateLabel(text.substr(0, offset)); 99 AddChildView(label_1_); 100 101 language_menu_button_ = CreateMenuButton(string16(), this); 102 TranslateInfoBarDelegate* delegate = GetDelegate(); 103 language_menu_model_.reset(new TranslateLanguageMenuModel( 104 TranslateLanguageMenuModel::ORIGINAL, delegate, this, 105 language_menu_button_, false)); 106 AddChildView(language_menu_button_); 107 108 label_2_ = CreateLabel(text.substr(offset)); 109 AddChildView(label_2_); 110 111 accept_button_ = CreateLabelButton(this, 112 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_ACCEPT), false); 113 AddChildView(accept_button_); 114 115 deny_button_ = CreateLabelButton(this, 116 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_DENY), false); 117 AddChildView(deny_button_); 118 119 const string16& language( 120 delegate->language_name_at(delegate->original_language_index())); 121 if (delegate->ShouldShowNeverTranslateShortcut()) { 122 DCHECK(!delegate->ShouldShowAlwaysTranslateShortcut()); 123 never_translate_button_ = CreateLabelButton(this, 124 l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_NEVER_TRANSLATE, 125 language), false); 126 AddChildView(never_translate_button_); 127 } else if (delegate->ShouldShowAlwaysTranslateShortcut()) { 128 always_translate_button_ = CreateLabelButton(this, 129 l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_ALWAYS_TRANSLATE, 130 language), false); 131 AddChildView(always_translate_button_); 132 } 133 134 options_menu_button_ = CreateMenuButton( 135 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), this); 136 AddChildView(options_menu_button_); 137 138 // This must happen after adding all other children so InfoBarView can ensure 139 // the close button is the last child. 140 TranslateInfoBarBase::ViewHierarchyChanged(details); 141 142 // This must happen after adding all children because it triggers layout, 143 // which assumes that particular children (e.g. the close button) have already 144 // been added. 145 UpdateLanguageButtonText(language_menu_button_, 146 delegate->language_name_at(delegate->original_language_index())); 147 } 148 149 int BeforeTranslateInfoBar::ContentMinimumWidth() const { 150 return 151 (kButtonInLabelSpacing + 152 language_menu_button_->GetPreferredSize().width() + 153 kButtonInLabelSpacing) + 154 (kEndOfLabelSpacing + accept_button_->GetPreferredSize().width()) + 155 (kButtonButtonSpacing + deny_button_->GetPreferredSize().width()) + 156 ((never_translate_button_ == NULL) ? 0 : 157 (kButtonButtonSpacing + 158 never_translate_button_->GetPreferredSize().width())) + 159 ((always_translate_button_ == NULL) ? 0 : 160 (kButtonButtonSpacing + 161 always_translate_button_->GetPreferredSize().width())) + 162 (kEndOfLabelSpacing + options_menu_button_->GetPreferredSize().width()); 163 } 164 165 void BeforeTranslateInfoBar::ButtonPressed(views::Button* sender, 166 const ui::Event& event) { 167 if (!owner()) 168 return; // We're closing; don't call anything, it might access the owner. 169 TranslateInfoBarDelegate* delegate = GetDelegate(); 170 if (sender == accept_button_) { 171 delegate->Translate(); 172 } else if (sender == deny_button_) { 173 delegate->TranslationDeclined(); 174 RemoveSelf(); 175 } else if (sender == never_translate_button_) { 176 delegate->NeverTranslatePageLanguage(); 177 } else if (sender == always_translate_button_) { 178 delegate->AlwaysTranslatePageLanguage(); 179 } else { 180 TranslateInfoBarBase::ButtonPressed(sender, event); 181 } 182 } 183 184 void BeforeTranslateInfoBar::OnMenuButtonClicked(views::View* source, 185 const gfx::Point& point) { 186 if (!owner()) 187 return; // We're closing; don't call anything, it might access the owner. 188 if (source == language_menu_button_) { 189 RunMenuAt(language_menu_model_.get(), language_menu_button_, 190 views::MenuItemView::TOPLEFT); 191 } else { 192 DCHECK_EQ(options_menu_button_, source); 193 RunMenuAt(&options_menu_model_, options_menu_button_, 194 views::MenuItemView::TOPRIGHT); 195 } 196 } 197