Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: chrome/browser/ui/views/extensions/extension_message_bubble_view.cc

Issue 1881773002: [Extensions UI] Convert ExtensionMessageBubbles to ToolbarActionsBarBubbles (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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/extensions/extension_message_bubble_view.h"
6
7 #include <utility>
8
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chrome/browser/ui/layout_constants.h"
14 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h"
15 #include "chrome/browser/ui/view_ids.h"
16 #include "chrome/grit/locale_settings.h"
17 #include "ui/accessibility/ax_view_state.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/views/controls/button/label_button.h"
20 #include "ui/views/controls/label.h"
21 #include "ui/views/controls/link.h"
22 #include "ui/views/layout/grid_layout.h"
23 #include "ui/views/view.h"
24 #include "ui/views/widget/widget.h"
25
26 namespace {
27
28 // Layout constants.
29 const int kExtensionListPadding = 10;
30 const int kInsetBottomRight = 13;
31 const int kInsetLeft = 14;
32 const int kInsetTop = 9;
33 const int kHeadlineMessagePadding = 4;
34 const int kHeadlineRowPadding = 10;
35 const int kMessageBubblePadding = 11;
36
37 // How long to wait until showing the bubble (in seconds).
38 int g_bubble_appearance_wait_time = 5;
39
40 } // namespace
41
42 namespace extensions {
43
44 ExtensionMessageBubbleView::ExtensionMessageBubbleView(
45 views::View* anchor_view,
46 views::BubbleBorder::Arrow arrow_location,
47 std::unique_ptr<ToolbarActionsBarBubbleDelegate> delegate)
48 : BubbleDelegateView(anchor_view, arrow_location),
49 delegate_(std::move(delegate)),
50 anchor_view_(anchor_view),
51 headline_(NULL),
52 learn_more_(NULL),
53 dismiss_button_(NULL),
54 link_clicked_(false),
55 action_taken_(false),
56 weak_factory_(this) {
57 DCHECK(anchor_view->GetWidget());
58 set_close_on_deactivate(delegate_->ShouldCloseOnDeactivate());
59 set_close_on_esc(true);
60
61 // Compensate for built-in vertical padding in the anchor view's image.
62 set_anchor_view_insets(gfx::Insets(
63 GetLayoutConstant(LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET), 0));
64 }
65
66 void ExtensionMessageBubbleView::Show() {
67 // Not showing the bubble right away (during startup) has a few benefits:
68 // We don't have to worry about focus being lost due to the Omnibox (or to
69 // other things that want focus at startup). This allows Esc to work to close
70 // the bubble and also solves the keyboard accessibility problem that comes
71 // with focus being lost (we don't have a good generic mechanism of injecting
72 // bubbles into the focus cycle). Another benefit of delaying the show is
73 // that fade-in works (the fade-in isn't apparent if the the bubble appears at
74 // startup).
75 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
76 FROM_HERE, base::Bind(&ExtensionMessageBubbleView::ShowBubble,
77 weak_factory_.GetWeakPtr()),
78 base::TimeDelta::FromSeconds(g_bubble_appearance_wait_time));
79 }
80
81 void ExtensionMessageBubbleView::OnWidgetDestroying(views::Widget* widget) {
82 // To catch Esc, we monitor destroy message. Unless the link has been clicked,
83 // we assume Dismiss was the action taken.
84 if (!link_clicked_ && !action_taken_) {
85 bool closed_on_deactivation = close_reason() == CloseReason::DEACTIVATION;
86 delegate_->OnBubbleClosed(
87 closed_on_deactivation
88 ? ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_DEACTIVATION
89 : ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION);
90 }
91 }
92
93 void ExtensionMessageBubbleView::set_bubble_appearance_wait_time_for_testing(
94 int time_in_seconds) {
95 g_bubble_appearance_wait_time = time_in_seconds;
96 }
97
98 ////////////////////////////////////////////////////////////////////////////////
99 // ExtensionMessageBubbleView - private.
100
101 ExtensionMessageBubbleView::~ExtensionMessageBubbleView() {}
102
103 void ExtensionMessageBubbleView::ShowBubble() {
104 // Since we delay in showing the bubble, the applicable extension(s) may
105 // have been removed.
106 if (delegate_->ShouldShow()) {
107 delegate_->OnBubbleShown();
108 GetWidget()->Show();
109 } else {
110 GetWidget()->Close();
111 }
112 }
113
114 void ExtensionMessageBubbleView::Init() {
115 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
116
117 views::GridLayout* layout = views::GridLayout::CreatePanel(this);
118 layout->SetInsets(kInsetTop, kInsetLeft,
119 kInsetBottomRight, kInsetBottomRight);
120 SetLayoutManager(layout);
121
122 const int headline_column_set_id = 0;
123 views::ColumnSet* top_columns = layout->AddColumnSet(headline_column_set_id);
124 top_columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
125 0, views::GridLayout::USE_PREF, 0, 0);
126 top_columns->AddPaddingColumn(1, 0);
127 layout->StartRow(0, headline_column_set_id);
128
129 headline_ = new views::Label(delegate_->GetHeadingText(),
130 rb.GetFontList(ui::ResourceBundle::MediumFont));
131 layout->AddView(headline_);
132
133 layout->AddPaddingRow(0, kHeadlineRowPadding);
134
135 const int text_column_set_id = 1;
136 views::ColumnSet* upper_columns = layout->AddColumnSet(text_column_set_id);
137 upper_columns->AddColumn(
138 views::GridLayout::LEADING, views::GridLayout::LEADING,
139 0, views::GridLayout::USE_PREF, 0, 0);
140 layout->StartRow(0, text_column_set_id);
141
142 views::Label* message = new views::Label();
143 message->SetMultiLine(true);
144 message->SetHorizontalAlignment(gfx::ALIGN_LEFT);
145 message->SetText(
146 delegate_->GetBodyText(anchor_view_->id() == VIEW_ID_BROWSER_ACTION));
147 message->SizeToFit(views::Widget::GetLocalizedContentsWidth(
148 IDS_EXTENSION_WIPEOUT_BUBBLE_WIDTH_CHARS));
149 layout->AddView(message);
150
151 base::string16 item_list_text = delegate_->GetItemListText();
152 if (!item_list_text.empty()) {
153 const int extension_list_column_set_id = 2;
154 views::ColumnSet* middle_columns =
155 layout->AddColumnSet(extension_list_column_set_id);
156 middle_columns->AddPaddingColumn(0, kExtensionListPadding);
157 middle_columns->AddColumn(
158 views::GridLayout::LEADING, views::GridLayout::CENTER,
159 0, views::GridLayout::USE_PREF, 0, 0);
160
161 layout->StartRowWithPadding(0, extension_list_column_set_id,
162 0, kHeadlineMessagePadding);
163 views::Label* extensions = new views::Label();
164 extensions->SetMultiLine(true);
165 extensions->SetHorizontalAlignment(gfx::ALIGN_LEFT);
166
167 extensions->SetText(item_list_text);
168 extensions->SizeToFit(views::Widget::GetLocalizedContentsWidth(
169 IDS_EXTENSION_WIPEOUT_BUBBLE_WIDTH_CHARS));
170 layout->AddView(extensions);
171 }
172
173 base::string16 action_button = delegate_->GetActionButtonText();
174
175 const int action_row_column_set_id = 3;
176 views::ColumnSet* bottom_columns =
177 layout->AddColumnSet(action_row_column_set_id);
178 bottom_columns->AddColumn(views::GridLayout::LEADING,
179 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
180 bottom_columns->AddPaddingColumn(1, 0);
181 bottom_columns->AddColumn(views::GridLayout::TRAILING,
182 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
183 if (!action_button.empty()) {
184 bottom_columns->AddColumn(views::GridLayout::TRAILING,
185 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
186 }
187 layout->StartRowWithPadding(0, action_row_column_set_id,
188 0, kMessageBubblePadding);
189
190 learn_more_ = new views::Link(delegate_->GetLearnMoreButtonText());
191 learn_more_->set_listener(this);
192 layout->AddView(learn_more_);
193
194 if (!action_button.empty()) {
195 action_button_ = new views::LabelButton(this, action_button);
196 action_button_->SetStyle(views::Button::STYLE_BUTTON);
197 layout->AddView(action_button_);
198 }
199
200 dismiss_button_ =
201 new views::LabelButton(this, delegate_->GetDismissButtonText());
202 dismiss_button_->SetStyle(views::Button::STYLE_BUTTON);
203 layout->AddView(dismiss_button_);
204 }
205
206 void ExtensionMessageBubbleView::ButtonPressed(views::Button* sender,
207 const ui::Event& event) {
208 action_taken_ = true;
209 ToolbarActionsBarBubbleDelegate::CloseAction close_action;
210 if (sender == action_button_) {
211 close_action = ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE;
212 } else {
213 DCHECK_EQ(dismiss_button_, sender);
214 close_action = ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION;
215 }
216 delegate_->OnBubbleClosed(close_action);
217 GetWidget()->Close();
218 }
219
220 void ExtensionMessageBubbleView::LinkClicked(views::Link* source,
221 int event_flags) {
222 DCHECK_EQ(learn_more_, source);
223 link_clicked_ = true;
224 delegate_->OnBubbleClosed(ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE);
225 GetWidget()->Close();
226 }
227
228 void ExtensionMessageBubbleView::GetAccessibleState(
229 ui::AXViewState* state) {
230 state->role = ui::AX_ROLE_ALERT;
231 }
232
233 void ExtensionMessageBubbleView::ViewHierarchyChanged(
234 const ViewHierarchyChangedDetails& details) {
235 if (details.is_add && details.child == this)
236 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
237 }
238
239 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698