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

Side by Side Diff: chrome/browser/ui/views/infobars/infobar_view.cc

Issue 1700383002: [MD] Fix clipping of infobar child elements (particularly close button). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: adjust comment Created 4 years, 10 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
« no previous file with comments | « chrome/browser/ui/views/infobars/infobar_view.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/infobars/infobar_view.h" 5 #include "chrome/browser/ui/views/infobars/infobar_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 72
73 73
74 // InfoBarView ---------------------------------------------------------------- 74 // InfoBarView ----------------------------------------------------------------
75 75
76 // static 76 // static
77 const int InfoBarView::kButtonButtonSpacing = views::kRelatedButtonHSpacing; 77 const int InfoBarView::kButtonButtonSpacing = views::kRelatedButtonHSpacing;
78 const int InfoBarView::kEndOfLabelSpacing = views::kItemLabelSpacing; 78 const int InfoBarView::kEndOfLabelSpacing = views::kItemLabelSpacing;
79 79
80 InfoBarView::InfoBarView(scoped_ptr<infobars::InfoBarDelegate> delegate) 80 InfoBarView::InfoBarView(scoped_ptr<infobars::InfoBarDelegate> delegate)
81 : infobars::InfoBar(std::move(delegate)), 81 : infobars::InfoBar(std::move(delegate)),
82 views::ExternalFocusTracker(this, NULL), 82 views::ExternalFocusTracker(this, nullptr),
83 icon_(NULL), 83 child_container_(new views::View()),
84 close_button_(NULL) { 84 icon_(nullptr),
85 close_button_(nullptr) {
85 set_owned_by_client(); // InfoBar deletes itself at the appropriate time. 86 set_owned_by_client(); // InfoBar deletes itself at the appropriate time.
86 set_background( 87 set_background(
87 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType())); 88 new InfoBarBackground(infobars::InfoBar::delegate()->GetInfoBarType()));
89
90 AddChildView(child_container_);
91
92 if (ui::MaterialDesignController::IsModeMaterial()) {
93 child_container_->SetPaintToLayer(true);
94 child_container_->layer()->SetMasksToBounds(true);
95 // Since MD doesn't use a gradient, we can set a solid bg color.
96 child_container_->set_background(
97 views::Background::CreateSolidBackground(infobars::InfoBar::GetTopColor(
98 infobars::InfoBar::delegate()->GetInfoBarType())));
99 }
88 } 100 }
89 101
90 InfoBarView::~InfoBarView() { 102 InfoBarView::~InfoBarView() {
91 // We should have closed any open menus in PlatformSpecificHide(), then 103 // We should have closed any open menus in PlatformSpecificHide(), then
92 // subclasses' RunMenu() functions should have prevented opening any new ones 104 // subclasses' RunMenu() functions should have prevented opening any new ones
93 // once we became unowned. 105 // once we became unowned.
94 DCHECK(!menu_runner_.get()); 106 DCHECK(!menu_runner_.get());
95 } 107 }
96 108
97 views::Label* InfoBarView::CreateLabel(const base::string16& text) const { 109 views::Label* InfoBarView::CreateLabel(const base::string16& text) const {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 fill_path_.close(); 213 fill_path_.close();
202 } 214 }
203 } 215 }
204 if (bar_height()) { 216 if (bar_height()) {
205 fill_path_.addRect( 217 fill_path_.addRect(
206 0.0, SkIntToScalar(arrow_height()), SkIntToScalar(width()), 218 0.0, SkIntToScalar(arrow_height()), SkIntToScalar(width()),
207 SkIntToScalar( 219 SkIntToScalar(
208 height() - InfoBarContainerDelegate::kSeparatorLineHeight)); 220 height() - InfoBarContainerDelegate::kSeparatorLineHeight));
209 } 221 }
210 222
223 child_container_->SetBounds(0, arrow_height(), width(), bar_height());
224 // |child_container_| should be the only child.
225 DCHECK_EQ(1, child_count());
226
227 // Even though other views are technically grandchildren, we'll lay them out
228 // here on behalf of |child_container_|.
211 int start_x = kEdgeItemPadding; 229 int start_x = kEdgeItemPadding;
212 if (icon_ != NULL) { 230 if (icon_ != NULL) {
213 icon_->SetPosition(gfx::Point(start_x, OffsetY(icon_))); 231 icon_->SetPosition(gfx::Point(start_x, OffsetY(icon_)));
214 start_x = icon_->bounds().right() + kIconToLabelSpacing; 232 start_x = icon_->bounds().right() + kIconToLabelSpacing;
215 } 233 }
216 234
217 int content_minimum_width = ContentMinimumWidth(); 235 int content_minimum_width = ContentMinimumWidth();
218 close_button_->SetPosition(gfx::Point( 236 close_button_->SetPosition(gfx::Point(
219 std::max( 237 std::max(
220 start_x + content_minimum_width + 238 start_x + content_minimum_width +
221 ((content_minimum_width > 0) ? kBeforeCloseButtonSpacing : 0), 239 ((content_minimum_width > 0) ? kBeforeCloseButtonSpacing : 0),
222 width() - kEdgeItemPadding - close_button_->width()), 240 width() - kEdgeItemPadding - close_button_->width()),
223 OffsetY(close_button_))); 241 OffsetY(close_button_)));
224 } 242 }
225 243
226 void InfoBarView::ViewHierarchyChanged( 244 void InfoBarView::ViewHierarchyChanged(
227 const ViewHierarchyChangedDetails& details) { 245 const ViewHierarchyChangedDetails& details) {
228 View::ViewHierarchyChanged(details); 246 View::ViewHierarchyChanged(details);
229 247
230 if (details.is_add && (details.child == this) && (close_button_ == NULL)) { 248 if (details.is_add && (details.child == this) && (close_button_ == NULL)) {
231 gfx::Image image = delegate()->GetIcon(); 249 gfx::Image image = delegate()->GetIcon();
232 if (!image.IsEmpty()) { 250 if (!image.IsEmpty()) {
233 icon_ = new views::ImageView; 251 icon_ = new views::ImageView;
234 icon_->SetImage(image.ToImageSkia()); 252 icon_->SetImage(image.ToImageSkia());
235 icon_->SizeToPreferredSize(); 253 icon_->SizeToPreferredSize();
236 AddChildView(icon_); 254 child_container_->AddChildView(icon_);
237 } 255 }
238 256
239 if (ui::MaterialDesignController::IsModeMaterial()) { 257 if (ui::MaterialDesignController::IsModeMaterial()) {
240 BarControlButton* close = new BarControlButton(this); 258 BarControlButton* close = new BarControlButton(this);
241 close->SetIcon(gfx::VectorIconId::BAR_CLOSE, 259 close->SetIcon(gfx::VectorIconId::BAR_CLOSE,
242 base::Bind(&GetInfobarTextColor)); 260 base::Bind(&GetInfobarTextColor));
243 close->set_request_focus_on_press(false); 261 close->set_request_focus_on_press(false);
244 close_button_ = close; 262 close_button_ = close;
245 } else { 263 } else {
246 close_button_ = new views::ImageButton(this); 264 close_button_ = new views::ImageButton(this);
247 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 265 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
248 close_button_->SetImage(views::CustomButton::STATE_NORMAL, 266 close_button_->SetImage(views::CustomButton::STATE_NORMAL,
249 rb.GetImageNamed(IDR_CLOSE_1).ToImageSkia()); 267 rb.GetImageNamed(IDR_CLOSE_1).ToImageSkia());
250 close_button_->SetImage(views::CustomButton::STATE_HOVERED, 268 close_button_->SetImage(views::CustomButton::STATE_HOVERED,
251 rb.GetImageNamed(IDR_CLOSE_1_H).ToImageSkia()); 269 rb.GetImageNamed(IDR_CLOSE_1_H).ToImageSkia());
252 close_button_->SetImage(views::CustomButton::STATE_PRESSED, 270 close_button_->SetImage(views::CustomButton::STATE_PRESSED,
253 rb.GetImageNamed(IDR_CLOSE_1_P).ToImageSkia()); 271 rb.GetImageNamed(IDR_CLOSE_1_P).ToImageSkia());
254 } 272 }
255 close_button_->SizeToPreferredSize(); 273 close_button_->SizeToPreferredSize();
256 close_button_->SetAccessibleName( 274 close_button_->SetAccessibleName(
257 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); 275 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
258 close_button_->SetFocusable(true); 276 close_button_->SetFocusable(true);
259 AddChildView(close_button_); 277 child_container_->AddChildView(close_button_);
260 } else if ((close_button_ != NULL) && (details.parent == this) && 278 } else if ((close_button_ != NULL) && (details.parent == this) &&
261 (details.child != close_button_) && (close_button_->parent() == this) && 279 (details.child != close_button_) && (close_button_->parent() == this) &&
262 (child_at(child_count() - 1) != close_button_)) { 280 (child_at(child_count() - 1) != close_button_)) {
263 // For accessibility, ensure the close button is the last child view. 281 // For accessibility, ensure the close button is the last child view.
264 RemoveChildView(close_button_); 282 RemoveChildView(close_button_);
265 AddChildView(close_button_); 283 child_container_->AddChildView(close_button_);
266 } 284 }
267 285
268 // Ensure the infobar is tall enough to display its contents. 286 // Ensure the infobar is tall enough to display its contents.
269 int height = ui::MaterialDesignController::IsModeMaterial() 287 int height = ui::MaterialDesignController::IsModeMaterial()
270 ? InfoBarContainerDelegate::kDefaultBarTargetHeightMd 288 ? InfoBarContainerDelegate::kDefaultBarTargetHeightMd
271 : InfoBarContainerDelegate::kDefaultBarTargetHeight; 289 : InfoBarContainerDelegate::kDefaultBarTargetHeight;
272 const int kMinimumVerticalPadding = 6; 290 const int kMinimumVerticalPadding = 6;
273 for (int i = 0; i < child_count(); ++i) { 291 for (int i = 0; i < child_count(); ++i) {
274 const int child_height = child_at(i)->height(); 292 const int child_height = child_at(i)->height();
275 height = std::max(height, child_height + kMinimumVerticalPadding); 293 height = std::max(height, child_height + kMinimumVerticalPadding);
276 } 294 }
277 SetBarTargetHeight(height); 295 SetBarTargetHeight(height);
278 } 296 }
279 297
280 void InfoBarView::PaintChildren(const ui::PaintContext& context) {
281 // TODO(scr): This really should be the |fill_path_|, but the clipPath seems
282 // broken on non-Windows platforms (crbug.com/75154). For now, just clip to
283 // the bar bounds.
284 //
285 // canvas->sk_canvas()->clipPath(fill_path_);
286 DCHECK_EQ(total_height(), height())
287 << "Infobar piecewise heights do not match overall height";
288 ui::ClipRecorder clip_recorder(context);
289 clip_recorder.ClipRect(gfx::Rect(0, arrow_height(), width(), bar_height()));
290 views::View::PaintChildren(context);
291 }
292
293 void InfoBarView::ButtonPressed(views::Button* sender, 298 void InfoBarView::ButtonPressed(views::Button* sender,
294 const ui::Event& event) { 299 const ui::Event& event) {
295 if (!owner()) 300 if (!owner())
296 return; // We're closing; don't call anything, it might access the owner. 301 return; // We're closing; don't call anything, it might access the owner.
297 if (sender == close_button_) { 302 if (sender == close_button_) {
298 delegate()->InfoBarDismissed(); 303 delegate()->InfoBarDismissed();
299 RemoveSelf(); 304 RemoveSelf();
300 } 305 }
301 } 306 }
302 307
303 int InfoBarView::ContentMinimumWidth() const { 308 int InfoBarView::ContentMinimumWidth() const {
304 return 0; 309 return 0;
305 } 310 }
306 311
307 int InfoBarView::StartX() const { 312 int InfoBarView::StartX() const {
308 // Ensure we don't return a value greater than EndX(), so children can safely 313 // Ensure we don't return a value greater than EndX(), so children can safely
309 // set something's width to "EndX() - StartX()" without risking that being 314 // set something's width to "EndX() - StartX()" without risking that being
310 // negative. 315 // negative.
311 return std::min(EndX(), (icon_ != NULL) ? 316 return std::min(EndX(), (icon_ != NULL) ?
312 (icon_->bounds().right() + kIconToLabelSpacing) : kEdgeItemPadding); 317 (icon_->bounds().right() + kIconToLabelSpacing) : kEdgeItemPadding);
313 } 318 }
314 319
315 int InfoBarView::EndX() const { 320 int InfoBarView::EndX() const {
316 return close_button_->x() - kBeforeCloseButtonSpacing; 321 return close_button_->x() - kBeforeCloseButtonSpacing;
317 } 322 }
318 323
319 int InfoBarView::OffsetY(views::View* view) const { 324 int InfoBarView::OffsetY(views::View* view) const {
320 return arrow_height() + 325 return std::max((bar_target_height() - view->height()) / 2, 0) -
321 std::max((bar_target_height() - view->height()) / 2, 0) - 326 (bar_target_height() - bar_height());
322 (bar_target_height() - bar_height());
323 } 327 }
324 328
325 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate() 329 const infobars::InfoBarContainer::Delegate* InfoBarView::container_delegate()
326 const { 330 const {
327 const infobars::InfoBarContainer* infobar_container = container(); 331 const infobars::InfoBarContainer* infobar_container = container();
328 return infobar_container ? infobar_container->delegate() : NULL; 332 return infobar_container ? infobar_container->delegate() : NULL;
329 } 333 }
330 334
331 void InfoBarView::RunMenuAt(ui::MenuModel* menu_model, 335 void InfoBarView::RunMenuAt(ui::MenuModel* menu_model,
332 views::MenuButton* button, 336 views::MenuButton* button,
333 views::MenuAnchorPosition anchor) { 337 views::MenuAnchorPosition anchor) {
334 DCHECK(owner()); // We'd better not open any menus while we're closing. 338 DCHECK(owner()); // We'd better not open any menus while we're closing.
335 gfx::Point screen_point; 339 gfx::Point screen_point;
336 views::View::ConvertPointToScreen(button, &screen_point); 340 views::View::ConvertPointToScreen(button, &screen_point);
337 menu_runner_.reset( 341 menu_runner_.reset(
338 new views::MenuRunner(menu_model, views::MenuRunner::HAS_MNEMONICS)); 342 new views::MenuRunner(menu_model, views::MenuRunner::HAS_MNEMONICS));
339 // Ignore the result since we don't need to handle a deleted menu specially. 343 // Ignore the result since we don't need to handle a deleted menu specially.
340 ignore_result(menu_runner_->RunMenuAt(GetWidget(), 344 ignore_result(menu_runner_->RunMenuAt(GetWidget(),
341 button, 345 button,
342 gfx::Rect(screen_point, button->size()), 346 gfx::Rect(screen_point, button->size()),
343 anchor, 347 anchor,
344 ui::MENU_SOURCE_NONE)); 348 ui::MENU_SOURCE_NONE));
345 } 349 }
346 350
351 void InfoBarView::AddViewToContentArea(views::View* view) {
352 child_container_->AddChildView(view);
353 }
354
347 // static 355 // static
348 void InfoBarView::AssignWidthsSorted(Labels* labels, int available_width) { 356 void InfoBarView::AssignWidthsSorted(Labels* labels, int available_width) {
349 if (labels->empty()) 357 if (labels->empty())
350 return; 358 return;
351 gfx::Size back_label_size(labels->back()->GetPreferredSize()); 359 gfx::Size back_label_size(labels->back()->GetPreferredSize());
352 back_label_size.set_width( 360 back_label_size.set_width(
353 std::min(back_label_size.width(), 361 std::min(back_label_size.width(),
354 available_width / static_cast<int>(labels->size()))); 362 available_width / static_cast<int>(labels->size())));
355 labels->back()->SetSize(back_label_size); 363 labels->back()->SetSize(back_label_size);
356 labels->pop_back(); 364 labels->pop_back();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 void InfoBarView::OnWillChangeFocus(View* focused_before, View* focused_now) { 421 void InfoBarView::OnWillChangeFocus(View* focused_before, View* focused_now) {
414 views::ExternalFocusTracker::OnWillChangeFocus(focused_before, focused_now); 422 views::ExternalFocusTracker::OnWillChangeFocus(focused_before, focused_now);
415 423
416 // This will trigger some screen readers to read the entire contents of this 424 // This will trigger some screen readers to read the entire contents of this
417 // infobar. 425 // infobar.
418 if (focused_before && focused_now && !Contains(focused_before) && 426 if (focused_before && focused_now && !Contains(focused_before) &&
419 Contains(focused_now)) { 427 Contains(focused_now)) {
420 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true); 428 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
421 } 429 }
422 } 430 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/infobars/infobar_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698