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.
5 #include "chrome/browser/ui/views/infobars/after_translate_infobar.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/translate/options_menu_model.h"
9 #include "chrome/browser/translate/translate_infobar_delegate.h"
10 #include "chrome/browser/ui/views/infobars/translate_language_menu_model.h"
11 #include "grit/generated_resources.h"
12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/views/controls/button/label_button.h"
14 #include "ui/views/controls/button/menu_button.h"
15 #include "ui/views/controls/label.h"
16 #include "ui/views/controls/menu/menu_item_view.h"
18 AfterTranslateInfoBar::AfterTranslateInfoBar(
19 scoped_ptr
<TranslateInfoBarDelegate
> delegate
)
20 : TranslateInfoBarBase(delegate
.Pass()),
24 original_language_menu_button_(NULL
),
25 target_language_menu_button_(NULL
),
27 options_menu_button_(NULL
),
28 swapped_language_buttons_(false) {
29 autodetermined_source_language_
=
30 GetDelegate()->original_language_index() ==
31 TranslateInfoBarDelegate::kNoIndex
;
34 AfterTranslateInfoBar::~AfterTranslateInfoBar() {
37 void AfterTranslateInfoBar::Layout() {
38 TranslateInfoBarBase::Layout();
42 labels
.push_back(label_1_
);
43 labels
.push_back(label_2_
);
44 labels
.push_back(label_3_
);
45 AssignWidths(&labels
, std::max(0, EndX() - x
- NonLabelWidth()));
47 label_1_
->SetPosition(gfx::Point(x
, OffsetY(label_1_
)));
48 if (!label_1_
->text().empty())
49 x
= label_1_
->bounds().right() + kButtonInLabelSpacing
;
51 views::MenuButton
* first_button
, * second_button
;
52 GetButtons(&first_button
, &second_button
);
53 first_button
->SetPosition(gfx::Point(x
, OffsetY(first_button
)));
54 x
= first_button
->bounds().right();
56 label_2_
->SetPosition(
57 gfx::Point(x
+ kButtonInLabelSpacing
, OffsetY(label_2_
)));
58 if (!label_2_
->text().empty())
59 x
= label_2_
->bounds().right();
61 if (!autodetermined_source_language_
) {
62 x
+= label_2_
->text().empty() ?
63 kButtonButtonSpacing
: kButtonInLabelSpacing
;
64 second_button
->SetPosition(gfx::Point(x
, OffsetY(second_button
)));
65 x
= second_button
->bounds().right();
67 label_3_
->SetPosition(
68 gfx::Point(x
+ kButtonInLabelSpacing
, OffsetY(label_3_
)));
69 if (!label_3_
->text().empty())
70 x
= label_3_
->bounds().right();
73 revert_button_
->SetPosition(
74 gfx::Point(x
+ kEndOfLabelSpacing
, OffsetY(revert_button_
)));
76 options_menu_button_
->SetPosition(gfx::Point(
77 EndX() - options_menu_button_
->width(), OffsetY(options_menu_button_
)));
80 void AfterTranslateInfoBar::ViewHierarchyChanged(
81 const ViewHierarchyChangedDetails
& details
) {
82 if (!details
.is_add
|| (details
.child
!= this) || (label_1_
!= NULL
)) {
83 TranslateInfoBarBase::ViewHierarchyChanged(details
);
87 std::vector
<base::string16
> strings
;
88 TranslateInfoBarDelegate::GetAfterTranslateStrings(
89 &strings
, &swapped_language_buttons_
, autodetermined_source_language_
);
90 DCHECK_EQ(autodetermined_source_language_
? 2U : 3U, strings
.size());
92 label_1_
= CreateLabel(strings
[0]);
93 AddChildView(label_1_
);
95 TranslateInfoBarDelegate
* delegate
= GetDelegate();
96 original_language_menu_button_
= CreateMenuButton(base::string16(), this);
97 original_language_menu_model_
.reset(new TranslateLanguageMenuModel(
98 TranslateLanguageMenuModel::ORIGINAL
, delegate
, this,
99 original_language_menu_button_
, true));
100 target_language_menu_button_
= CreateMenuButton(base::string16(), this);
101 target_language_menu_model_
.reset(new TranslateLanguageMenuModel(
102 TranslateLanguageMenuModel::TARGET
, delegate
, this,
103 target_language_menu_button_
, true));
105 views::MenuButton
* first_button
, * second_button
;
106 GetButtons(&first_button
, &second_button
);
107 AddChildView(first_button
);
109 label_2_
= CreateLabel(strings
[1]);
110 AddChildView(label_2_
);
112 // These views may not always be shown, but adding them unconditionally
113 // prevents leaks and reduces NULL-checking elsewhere.
114 AddChildView(second_button
);
115 if (autodetermined_source_language_
)
116 second_button
->SetVisible(false);
117 label_3_
= CreateLabel(autodetermined_source_language_
?
118 base::string16() : strings
[2]);
119 AddChildView(label_3_
);
121 revert_button_
= CreateLabelButton(this,
122 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_REVERT
), false);
123 AddChildView(revert_button_
);
125 options_menu_button_
= CreateMenuButton(
126 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS
), this);
127 options_menu_model_
.reset(new OptionsMenuModel(delegate
));
128 AddChildView(options_menu_button_
);
130 // This must happen after adding all other children so InfoBarView can ensure
131 // the close button is the last child.
132 TranslateInfoBarBase::ViewHierarchyChanged(details
);
134 // These must happen after adding all children because they trigger layout,
135 // which assumes that particular children (e.g. the close button) have already
137 UpdateLanguageButtonText(original_language_menu_button_
,
138 delegate
->language_name_at(delegate
->original_language_index()));
139 UpdateLanguageButtonText(target_language_menu_button_
,
140 delegate
->language_name_at(delegate
->target_language_index()));
143 void AfterTranslateInfoBar::ButtonPressed(views::Button
* sender
,
144 const ui::Event
& event
) {
146 return; // We're closing; don't call anything, it might access the owner.
147 if (sender
== revert_button_
)
148 GetDelegate()->RevertTranslation();
150 TranslateInfoBarBase::ButtonPressed(sender
, event
);
153 int AfterTranslateInfoBar::ContentMinimumWidth() {
154 return label_1_
->GetMinimumSize().width() +
155 label_2_
->GetMinimumSize().width() + label_3_
->GetMinimumSize().width() +
159 void AfterTranslateInfoBar::OnMenuButtonClicked(views::View
* source
,
160 const gfx::Point
& point
) {
162 return; // We're closing; don't call anything, it might access the owner.
163 if (source
== original_language_menu_button_
) {
164 RunMenuAt(original_language_menu_model_
.get(),
165 original_language_menu_button_
, views::MenuItemView::TOPLEFT
);
166 } else if (source
== target_language_menu_button_
) {
167 RunMenuAt(target_language_menu_model_
.get(), target_language_menu_button_
,
168 views::MenuItemView::TOPLEFT
);
170 DCHECK_EQ(options_menu_button_
, source
);
171 RunMenuAt(options_menu_model_
.get(), options_menu_button_
,
172 views::MenuItemView::TOPRIGHT
);
176 void AfterTranslateInfoBar::GetButtons(
177 views::MenuButton
** first_button
,
178 views::MenuButton
** second_button
) const {
179 *first_button
= original_language_menu_button_
;
180 *second_button
= target_language_menu_button_
;
181 if (swapped_language_buttons_
|| autodetermined_source_language_
)
182 std::swap(*first_button
, *second_button
);
185 int AfterTranslateInfoBar::NonLabelWidth() const {
186 views::MenuButton
* first_button
, *second_button
;
187 GetButtons(&first_button
, &second_button
);
188 int width
= (label_1_
->text().empty() ? 0 : kButtonInLabelSpacing
) +
189 first_button
->width() +
190 (label_2_
->text().empty() ? 0 : kButtonInLabelSpacing
);
191 if (!autodetermined_source_language_
) {
193 (label_2_
->text().empty() ?
194 kButtonButtonSpacing
: kButtonInLabelSpacing
) +
195 second_button
->width() +
196 (label_3_
->text().empty() ? 0 : kButtonInLabelSpacing
);
198 return width
+ kEndOfLabelSpacing
+ revert_button_
->width() +
199 kEndOfLabelSpacing
+ options_menu_button_
->width();