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

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

Issue 6788014: Fix DCHECK() in infobar animation. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 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 | Annotate | Revision Log
« 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/message_loop.h" 7 #include "base/message_loop.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/tab_contents/infobar_delegate.h" 9 #include "chrome/browser/tab_contents/infobar_delegate.h"
10 #include "chrome/browser/ui/views/infobars/infobar_background.h" 10 #include "chrome/browser/ui/views/infobars/infobar_background.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 49
50 const int InfoBarView::kTabWidth = (kCurveWidth + kTabIconPadding) * 2 + 50 const int InfoBarView::kTabWidth = (kCurveWidth + kTabIconPadding) * 2 +
51 kMaxIconWidth; 51 kMaxIconWidth;
52 52
53 InfoBarView::InfoBarView(InfoBarDelegate* delegate) 53 InfoBarView::InfoBarView(InfoBarDelegate* delegate)
54 : InfoBar(delegate), 54 : InfoBar(delegate),
55 icon_(NULL), 55 icon_(NULL),
56 close_button_(NULL), 56 close_button_(NULL),
57 ALLOW_THIS_IN_INITIALIZER_LIST(delete_factory_(this)), 57 ALLOW_THIS_IN_INITIALIZER_LIST(delete_factory_(this)),
58 target_height_(kDefaultTargetHeight), 58 target_height_(kDefaultTargetHeight),
59 tab_height_(0),
60 bar_height_(0),
59 fill_path_(new SkPath), 61 fill_path_(new SkPath),
60 stroke_path_(new SkPath) { 62 stroke_path_(new SkPath) {
61 set_parent_owned(false); // InfoBar deletes itself at the appropriate time. 63 set_parent_owned(false); // InfoBar deletes itself at the appropriate time.
62 64
63 InfoBarDelegate::Type infobar_type = delegate->GetInfoBarType(); 65 InfoBarDelegate::Type infobar_type = delegate->GetInfoBarType();
64 set_background(new InfoBarBackground(infobar_type)); 66 set_background(new InfoBarBackground(infobar_type));
65 } 67 }
66 68
67 InfoBarView::~InfoBarView() { 69 InfoBarView::~InfoBarView() {
68 } 70 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 (*func)(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &icon_info); 144 (*func)(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &icon_info);
143 text_button->SetIcon(*IconUtil::CreateSkBitmapFromHICON(icon_info.hIcon, 145 text_button->SetIcon(*IconUtil::CreateSkBitmapFromHICON(icon_info.hIcon,
144 gfx::Size(GetSystemMetrics(SM_CXSMICON), 146 gfx::Size(GetSystemMetrics(SM_CXSMICON),
145 GetSystemMetrics(SM_CYSMICON)))); 147 GetSystemMetrics(SM_CYSMICON))));
146 } 148 }
147 #endif 149 #endif
148 return text_button; 150 return text_button;
149 } 151 }
150 152
151 void InfoBarView::Layout() { 153 void InfoBarView::Layout() {
154 // Calculate the fill and stroke paths. We do this here, rather than in
155 // PlatformSpecificRecalculateHeight(), because this is also reached when our
156 // width is changed, which affects both paths.
157 stroke_path_->rewind();
158 fill_path_->rewind();
159 if (tab_height_) {
160 int divider_y = tab_height_ - 1;
161 stroke_path_->moveTo(
162 SkIntToScalar(GetMirroredXWithWidthInView(0, kTabWidth)),
163 SkIntToScalar(divider_y));
164 stroke_path_->rCubicTo(
165 SkScalarDiv(kCurveWidth, 2), 0.0,
166 SkScalarDiv(kCurveWidth, 2),
167 SkIntToScalar(-divider_y),
168 SkIntToScalar(kCurveWidth),
169 SkIntToScalar(-divider_y));
170 stroke_path_->rLineTo(SkScalarMulAdd(kTabIconPadding, 2, kMaxIconWidth),
171 0.0);
172 stroke_path_->rCubicTo(
173 SkScalarDiv(kCurveWidth, 2), 0.0,
174 SkScalarDiv(kCurveWidth, 2),
175 SkIntToScalar(divider_y),
176 SkIntToScalar(kCurveWidth),
177 SkIntToScalar(divider_y));
178
179 // Create the fill portion of the tab. Because the fill is inside the
180 // bounds and will not cover the separator, we need to extend downward by a
181 // pixel before closing.
182 *fill_path_ = *stroke_path_;
183 fill_path_->rLineTo(0.0, 1.0);
184 fill_path_->rLineTo(-SkIntToScalar(kTabWidth), 0.0);
185 fill_path_->close();
186
187 // Fill and stroke have different opinions about how to treat paths.
188 // Because in Skia integral coordinates represent pixel boundaries,
189 // offsetting the path makes it go exactly through pixel centers; this
190 // results in lines that are exactly where we expect, instead of having odd
191 // "off by one" issues. Were we to do this for |fill_path|, however, which
192 // tries to fill "inside" the path (using some questionable math), we'd get
193 // a fill at a very different place than we'd want.
194 stroke_path_->offset(SK_ScalarHalf, SK_ScalarHalf);
195 }
196 if (bar_height_) {
197 fill_path_->addRect(0.0, SkIntToScalar(tab_height_), SkIntToScalar(width()),
198 SkIntToScalar(height()));
199 }
200
152 int start_x = kHorizontalPadding; 201 int start_x = kHorizontalPadding;
153 if (icon_ != NULL) { 202 if (icon_ != NULL) {
154 // Center the icon horizontally within the tab, and vertically between the 203 // Center the icon horizontally within the tab, and vertically between the
155 // entire height (tab + bar). 204 // entire height (tab + bar).
156 gfx::Size icon_size = icon_->GetPreferredSize(); 205 gfx::Size icon_size = icon_->GetPreferredSize();
157 int center_x = std::max((kTabWidth - icon_size.width()) / 2, 0); 206 int center_x = std::max((kTabWidth - icon_size.width()) / 2, 0);
158 int full_height = target_height_ + kTabHeight; 207 int full_height = target_height_ + kTabHeight;
159 208
160 // This duplicates OffsetY except centered within the entire height (tab + 209 // This duplicates OffsetY except centered within the entire height (tab +
161 // bar) instead of just within the bar. 210 // bar) instead of just within the bar.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 287
239 void InfoBarView::PaintChildren(gfx::Canvas* canvas) { 288 void InfoBarView::PaintChildren(gfx::Canvas* canvas) {
240 canvas->Save(); 289 canvas->Save();
241 290
242 // TODO(scr): This really should be the |fill_path_|, but the clipPath seems 291 // TODO(scr): This really should be the |fill_path_|, but the clipPath seems
243 // broken on non-Windows platforms (crbug.com/75154). For now, just clip to 292 // broken on non-Windows platforms (crbug.com/75154). For now, just clip to
244 // the bar bounds. 293 // the bar bounds.
245 // 294 //
246 // gfx::CanvasSkia* canvas_skia = canvas->AsCanvasSkia(); 295 // gfx::CanvasSkia* canvas_skia = canvas->AsCanvasSkia();
247 // canvas_skia->clipPath(*fill_path_); 296 // canvas_skia->clipPath(*fill_path_);
248 int tab_height = AnimatedTabHeight(); 297 DCHECK_EQ(tab_height_ + bar_height_, height())
249 int bar_height = AnimatedBarHeight(); 298 << "Infobar piecewise heights do not match overall height";
250 DCHECK_EQ(tab_height + bar_height, height()) 299 canvas->ClipRectInt(0, tab_height_, width(), bar_height_);
251 << "Animation progressed between OnBoundsChanged & PaintChildren.";
252 canvas->ClipRectInt(0, tab_height, width(), bar_height);
253
254 views::View::PaintChildren(canvas); 300 views::View::PaintChildren(canvas);
255 canvas->Restore(); 301 canvas->Restore();
256 } 302 }
257 303
258 void InfoBarView::ButtonPressed(views::Button* sender, 304 void InfoBarView::ButtonPressed(views::Button* sender,
259 const views::Event& event) { 305 const views::Event& event) {
260 if (sender == close_button_) { 306 if (sender == close_button_) {
261 if (delegate()) 307 if (delegate())
262 delegate()->InfoBarDismissed(); 308 delegate()->InfoBarDismissed();
263 RemoveInfoBar(); 309 RemoveInfoBar();
264 } 310 }
265 } 311 }
266 312
267 int InfoBarView::ContentMinimumWidth() const { 313 int InfoBarView::ContentMinimumWidth() const {
268 return 0; 314 return 0;
269 } 315 }
270 316
317 void InfoBarView::SetTargetHeight(int height) {
318 if (target_height_ != height) {
319 target_height_ = height;
320 RecalculateHeight();
321 }
322 }
323
271 int InfoBarView::StartX() const { 324 int InfoBarView::StartX() const {
272 // Ensure we don't return a value greater than EndX(), so children can safely 325 // Ensure we don't return a value greater than EndX(), so children can safely
273 // set something's width to "EndX() - StartX()" without risking that being 326 // set something's width to "EndX() - StartX()" without risking that being
274 // negative. 327 // negative.
275 return std::min(EndX(), 328 return std::min(EndX(),
276 ((icon_ != NULL) ? icon_->bounds().right() : 0) + kHorizontalPadding); 329 ((icon_ != NULL) ? icon_->bounds().right() : 0) + kHorizontalPadding);
277 } 330 }
278 331
279 int InfoBarView::EndX() const { 332 int InfoBarView::EndX() const {
280 const int kCloseButtonSpacing = 12; 333 const int kCloseButtonSpacing = 12;
281 return close_button_->x() - kCloseButtonSpacing; 334 return close_button_->x() - kCloseButtonSpacing;
282 } 335 }
283 336
284 int InfoBarView::CenterY(const gfx::Size prefsize) const { 337 int InfoBarView::CenterY(const gfx::Size prefsize) const {
285 return std::max((target_height_ - prefsize.height()) / 2, 0); 338 return std::max((target_height_ - prefsize.height()) / 2, 0);
286 } 339 }
287 340
288 int InfoBarView::OffsetY(const gfx::Size prefsize) const { 341 int InfoBarView::OffsetY(const gfx::Size prefsize) const {
289 return CenterY(prefsize) + AnimatedTabHeight() - 342 return CenterY(prefsize) + tab_height_ - (target_height_ - bar_height_);
290 (target_height_ - AnimatedBarHeight());
291 } 343 }
292 344
293 void InfoBarView::PlatformSpecificHide(bool animate) { 345 void InfoBarView::PlatformSpecificHide(bool animate) {
294 if (!animate) 346 if (!animate)
295 return; 347 return;
296 348
297 bool restore_focus = true; 349 bool restore_focus = true;
298 #if defined(OS_WIN) 350 #if defined(OS_WIN)
299 // Do not restore focus (and active state with it) on Windows if some other 351 // Do not restore focus (and active state with it) on Windows if some other
300 // top-level window became active. 352 // top-level window became active.
301 if (GetWidget() && 353 if (GetWidget() &&
302 !ui::DoesWindowBelongToActiveWindow(GetWidget()->GetNativeView())) 354 !ui::DoesWindowBelongToActiveWindow(GetWidget()->GetNativeView()))
303 restore_focus = false; 355 restore_focus = false;
304 #endif // defined(OS_WIN) 356 #endif // defined(OS_WIN)
305 DestroyFocusTracker(restore_focus); 357 DestroyFocusTracker(restore_focus);
306 } 358 }
307 359
360 void InfoBarView::PlatformSpecificRecalculateHeight() {
361 int old_tab_height = tab_height_;
362 int old_bar_height = bar_height_;
363 tab_height_ = static_cast<int>(kTabHeight * animation()->GetCurrentValue());
364 bar_height_ =
365 static_cast<int>(target_height_ * animation()->GetCurrentValue());
366
367 // Don't re-layout if nothing has changed, e.g. because the animation step was
368 // not large enough to actually change the heights by at least a pixel.
369 if ((old_tab_height != tab_height_) || (old_bar_height != bar_height_)) {
370 // Ensure that notifying our container of our size change will result in a
371 // re-layout.
372 InvalidateLayout();
373 }
374 }
375
308 void InfoBarView::GetAccessibleState(ui::AccessibleViewState* state) { 376 void InfoBarView::GetAccessibleState(ui::AccessibleViewState* state) {
309 if (delegate()) { 377 if (delegate()) {
310 state->name = l10n_util::GetStringUTF16( 378 state->name = l10n_util::GetStringUTF16(
311 (delegate()->GetInfoBarType() == InfoBarDelegate::WARNING_TYPE) ? 379 (delegate()->GetInfoBarType() == InfoBarDelegate::WARNING_TYPE) ?
312 IDS_ACCNAME_INFOBAR_WARNING : IDS_ACCNAME_INFOBAR_PAGE_ACTION); 380 IDS_ACCNAME_INFOBAR_WARNING : IDS_ACCNAME_INFOBAR_PAGE_ACTION);
313 } 381 }
314 state->role = ui::AccessibilityTypes::ROLE_ALERT; 382 state->role = ui::AccessibilityTypes::ROLE_ALERT;
315 } 383 }
316 384
317 int InfoBarView::AnimatedTabHeight() const {
318 return static_cast<int>(kTabHeight * animation()->GetCurrentValue());
319 }
320
321 int InfoBarView::AnimatedBarHeight() const {
322 return static_cast<int>(target_height_ * animation()->GetCurrentValue());
323 }
324
325 gfx::Size InfoBarView::GetPreferredSize() { 385 gfx::Size InfoBarView::GetPreferredSize() {
326 return gfx::Size(0, AnimatedTabHeight() + AnimatedBarHeight()); 386 return gfx::Size(0, tab_height_ + bar_height_);
327 }
328
329 void InfoBarView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
330 int tab_height = AnimatedTabHeight();
331 int bar_height = AnimatedBarHeight();
332 int divider_y = tab_height - 1;
333 DCHECK_EQ(tab_height + bar_height, height())
334 << "Animation progressed between Layout & OnBoundsChanged.";
335
336 int mirrored_x = GetMirroredXWithWidthInView(0, kTabWidth);
337 stroke_path_->rewind();
338 fill_path_->rewind();
339
340 if (tab_height) {
341 stroke_path_->moveTo(SkIntToScalar(mirrored_x),
342 SkIntToScalar(divider_y));
343 stroke_path_->rCubicTo(
344 SkScalarDiv(kCurveWidth, 2), 0.0,
345 SkScalarDiv(kCurveWidth, 2),
346 SkIntToScalar(-divider_y),
347 SkIntToScalar(kCurveWidth),
348 SkIntToScalar(-divider_y));
349 stroke_path_->rLineTo(SkScalarMulAdd(kTabIconPadding, 2, kMaxIconWidth),
350 0.0);
351 stroke_path_->rCubicTo(
352 SkScalarDiv(kCurveWidth, 2), 0.0,
353 SkScalarDiv(kCurveWidth, 2),
354 SkIntToScalar(divider_y),
355 SkIntToScalar(kCurveWidth),
356 SkIntToScalar(divider_y));
357
358 // Create the fill portion of the tab. Because the fill is inside the
359 // bounds and will not cover the separator, we need to extend downward by a
360 // pixel before closing.
361 *fill_path_ = *stroke_path_;
362 fill_path_->rLineTo(0.0, 1.0);
363 fill_path_->rLineTo(-SkIntToScalar(kTabWidth), 0.0);
364 fill_path_->close();
365
366 // Fill and stroke have different opinions about how to treat paths.
367 // Because in Skia integral coordinates represent pixel boundaries,
368 // offsetting the path makes it go exactly through pixel centers; this
369 // results in lines that are exactly where we expect, instead of having odd
370 // "off by one" issues. Were we to do this for |fill_path|, however, which
371 // tries to fill "inside" the path (using some questionable math), we'd get
372 // a fill at a very different place than we'd want.
373 stroke_path_->offset(SK_ScalarHalf, SK_ScalarHalf);
374 }
375 if (bar_height) {
376 fill_path_->addRect(0.0, SkIntToScalar(tab_height),
377 SkIntToScalar(width()), SkIntToScalar(height()));
378 }
379 } 387 }
380 388
381 void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) { 389 void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) {
382 // This will trigger some screen readers to read the entire contents of this 390 // This will trigger some screen readers to read the entire contents of this
383 // infobar. 391 // infobar.
384 if (focused_before && focused_now && !this->Contains(focused_before) && 392 if (focused_before && focused_now && !this->Contains(focused_before) &&
385 this->Contains(focused_now) && GetWidget()) { 393 this->Contains(focused_now) && GetWidget()) {
386 GetWidget()->NotifyAccessibilityEvent( 394 GetWidget()->NotifyAccessibilityEvent(
387 this, ui::AccessibilityTypes::EVENT_ALERT, true); 395 this, ui::AccessibilityTypes::EVENT_ALERT, true);
388 } 396 }
389 } 397 }
390 398
391 void InfoBarView::DestroyFocusTracker(bool restore_focus) { 399 void InfoBarView::DestroyFocusTracker(bool restore_focus) {
392 if (focus_tracker_ != NULL) { 400 if (focus_tracker_ != NULL) {
393 if (restore_focus) 401 if (restore_focus)
394 focus_tracker_->FocusLastFocusedExternalView(); 402 focus_tracker_->FocusLastFocusedExternalView();
395 focus_tracker_->SetFocusManager(NULL); 403 focus_tracker_->SetFocusManager(NULL);
396 focus_tracker_.reset(); 404 focus_tracker_.reset();
397 } 405 }
398 } 406 }
399 407
400 void InfoBarView::DeleteSelf() { 408 void InfoBarView::DeleteSelf() {
401 delete this; 409 delete this;
402 } 410 }
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