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/after_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 AfterTranslateInfoBar::AfterTranslateInfoBar( 17 InfoBarService* owner, 18 TranslateInfoBarDelegate* delegate) 19 : TranslateInfoBarBase(owner, delegate), 20 label_1_(NULL), 21 label_2_(NULL), 22 label_3_(NULL), 23 original_language_menu_button_(NULL), 24 target_language_menu_button_(NULL), 25 revert_button_(NULL), 26 options_menu_button_(NULL), 27 options_menu_model_(delegate), 28 swapped_language_buttons_(false) { 29 autodetermined_source_language_ = 30 delegate->original_language_index() == TranslateInfoBarDelegate::kNoIndex; 31 } 32 33 AfterTranslateInfoBar::~AfterTranslateInfoBar() { 34 } 35 36 void AfterTranslateInfoBar::Layout() { 37 TranslateInfoBarBase::Layout(); 38 39 int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth()); 40 gfx::Size label_1_size = label_1_->GetPreferredSize(); 41 label_1_->SetBounds(StartX(), OffsetY(label_1_size), 42 std::min(label_1_size.width(), available_width), label_1_size.height()); 43 available_width = std::max(0, available_width - label_1_size.width()); 44 45 views::MenuButton* first_button = original_language_menu_button_; 46 views::MenuButton* second_button = target_language_menu_button_; 47 if (swapped_language_buttons_ || autodetermined_source_language_) 48 std::swap(first_button, second_button); 49 gfx::Size first_button_size = first_button->GetPreferredSize(); 50 first_button->SetBounds(label_1_->bounds().right() + kButtonInLabelSpacing, 51 OffsetY(first_button_size), first_button_size.width(), 52 first_button_size.height()); 53 54 gfx::Size label_2_size = label_2_->GetPreferredSize(); 55 label_2_->SetBounds(first_button->bounds().right() + kButtonInLabelSpacing, 56 OffsetY(label_2_size), std::min(label_2_size.width(), available_width), 57 label_2_size.height()); 58 available_width = std::max(0, available_width - label_2_size.width()); 59 60 if (!autodetermined_source_language_) { 61 gfx::Size second_button_size = second_button->GetPreferredSize(); 62 second_button->SetBounds(label_2_->bounds().right() + kButtonInLabelSpacing, 63 OffsetY(second_button_size), second_button_size.width(), 64 second_button_size.height()); 65 66 gfx::Size label_3_size = label_3_->GetPreferredSize(); 67 label_3_->SetBounds(second_button->bounds().right() + kButtonInLabelSpacing, 68 OffsetY(label_3_size), std::min(label_3_size.width(), available_width), 69 label_3_size.height()); 70 } 71 72 gfx::Size revert_button_size = revert_button_->GetPreferredSize(); 73 revert_button_->SetBounds( 74 (label_3_ ? label_3_ : label_2_)->bounds().right() + 75 kButtonInLabelSpacing, 76 OffsetY(revert_button_size), 77 revert_button_size.width(), 78 revert_button_size.height()); 79 80 gfx::Size options_size = options_menu_button_->GetPreferredSize(); 81 options_menu_button_->SetBounds(EndX() - options_size.width(), 82 OffsetY(options_size), options_size.width(), options_size.height()); 83 } 84 85 void AfterTranslateInfoBar::ViewHierarchyChanged( 86 const ViewHierarchyChangedDetails& details) { 87 if (!details.is_add || (details.child != this) || (label_1_ != NULL)) { 88 TranslateInfoBarBase::ViewHierarchyChanged(details); 89 return; 90 } 91 92 std::vector<string16> strings; 93 TranslateInfoBarDelegate::GetAfterTranslateStrings( 94 &strings, &swapped_language_buttons_, autodetermined_source_language_); 95 DCHECK_EQ(autodetermined_source_language_ ? 2U : 3U, strings.size()); 96 97 label_1_ = CreateLabel(strings[0]); 98 AddChildView(label_1_); 99 100 TranslateInfoBarDelegate* delegate = GetDelegate(); 101 original_language_menu_button_ = CreateMenuButton(string16(), this); 102 original_language_menu_model_.reset(new TranslateLanguageMenuModel( 103 TranslateLanguageMenuModel::ORIGINAL, delegate, this, 104 original_language_menu_button_, true)); 105 target_language_menu_button_ = CreateMenuButton(string16(), this); 106 target_language_menu_model_.reset(new TranslateLanguageMenuModel( 107 TranslateLanguageMenuModel::TARGET, delegate, this, 108 target_language_menu_button_, true)); 109 AddChildView((swapped_language_buttons_ || autodetermined_source_language_) ? 110 target_language_menu_button_ : original_language_menu_button_); 111 112 label_2_ = CreateLabel(strings[1]); 113 AddChildView(label_2_); 114 115 if (!autodetermined_source_language_) { 116 AddChildView(swapped_language_buttons_ ? 117 original_language_menu_button_ : target_language_menu_button_); 118 119 label_3_ = CreateLabel(strings[2]); 120 AddChildView(label_3_); 121 } 122 123 revert_button_ = CreateLabelButton(this, 124 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_REVERT), false); 125 AddChildView(revert_button_); 126 127 options_menu_button_ = CreateMenuButton( 128 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), this); 129 AddChildView(options_menu_button_); 130 131 // This must happen after adding all other children so InfoBarView can ensure 132 // the close button is the last child. 133 TranslateInfoBarBase::ViewHierarchyChanged(details); 134 135 // These must happen after adding all children because they trigger layout, 136 // which assumes that particular children (e.g. the close button) have already 137 // been added. 138 if (!autodetermined_source_language_) { 139 UpdateLanguageButtonText(original_language_menu_button_, 140 delegate->language_name_at(delegate->original_language_index())); 141 } 142 UpdateLanguageButtonText(target_language_menu_button_, 143 delegate->language_name_at(delegate->target_language_index())); 144 } 145 146 void AfterTranslateInfoBar::ButtonPressed(views::Button* sender, 147 const ui::Event& event) { 148 if (!owner()) 149 return; // We're closing; don't call anything, it might access the owner. 150 if (sender == revert_button_) 151 GetDelegate()->RevertTranslation(); 152 else 153 TranslateInfoBarBase::ButtonPressed(sender, event); 154 } 155 156 int AfterTranslateInfoBar::ContentMinimumWidth() const { 157 return 158 (kButtonInLabelSpacing + 159 original_language_menu_button_->GetPreferredSize().width() + 160 kButtonInLabelSpacing) + 161 (kButtonInLabelSpacing + 162 target_language_menu_button_->GetPreferredSize().width() + 163 kButtonInLabelSpacing) + 164 (kButtonInLabelSpacing + revert_button_->GetPreferredSize().width()) + 165 (kEndOfLabelSpacing + options_menu_button_->GetPreferredSize().width()); 166 } 167 168 void AfterTranslateInfoBar::OnMenuButtonClicked(views::View* source, 169 const gfx::Point& point) { 170 if (!owner()) 171 return; // We're closing; don't call anything, it might access the owner. 172 if (source == original_language_menu_button_) { 173 RunMenuAt(original_language_menu_model_.get(), 174 original_language_menu_button_, views::MenuItemView::TOPLEFT); 175 } else if (source == target_language_menu_button_) { 176 RunMenuAt(target_language_menu_model_.get(), target_language_menu_button_, 177 views::MenuItemView::TOPLEFT); 178 } else { 179 DCHECK_EQ(options_menu_button_, source); 180 RunMenuAt(&options_menu_model_, options_menu_button_, 181 views::MenuItemView::TOPRIGHT); 182 } 183 } 184