OLD | NEW |
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/tabs/tab_strip.h" | 5 #include "chrome/browser/ui/views/tabs/tab_strip.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 | 110 |
111 // Amount to adjust the clip by when the tab is stacked after the active index. | 111 // Amount to adjust the clip by when the tab is stacked after the active index. |
112 const int kStackedTabRightClip = 20; | 112 const int kStackedTabRightClip = 20; |
113 | 113 |
114 #if defined(OS_MACOSX) | 114 #if defined(OS_MACOSX) |
115 const int kPinnedToNonPinnedOffset = 2; | 115 const int kPinnedToNonPinnedOffset = 2; |
116 #else | 116 #else |
117 const int kPinnedToNonPinnedOffset = 3; | 117 const int kPinnedToNonPinnedOffset = 3; |
118 #endif | 118 #endif |
119 | 119 |
120 // The vertical offset of the tab strip button. | 120 // Returns the offset from the top of the tabstrip at which the new tab button's |
121 const int kNewTabButtonVerticalOffset = 7; | 121 // visible region begins. |
| 122 int GetNewTabButtonTopOffset() { |
| 123 // The vertical distance between the bottom of the new tab button and the |
| 124 // bottom of the tabstrip. |
| 125 const int kNewTabButtonBottomOffset = 4; |
| 126 return Tab::GetMinimumInactiveSize().height() - kNewTabButtonBottomOffset - |
| 127 GetLayoutSize(NEW_TAB_BUTTON).height(); |
| 128 } |
122 | 129 |
123 // Returns the width needed for the new tab button (and padding). | 130 // Returns the width needed for the new tab button (and padding). |
124 int GetNewTabButtonWidth() { | 131 int GetNewTabButtonWidth() { |
125 return GetLayoutSize(NEW_TAB_BUTTON).width() - | 132 return GetLayoutSize(NEW_TAB_BUTTON).width() - |
126 GetLayoutConstant(TABSTRIP_NEW_TAB_BUTTON_OVERLAP); | 133 GetLayoutConstant(TABSTRIP_NEW_TAB_BUTTON_OVERLAP); |
127 } | 134 } |
128 | 135 |
129 skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(SkAlpha alpha) { | 136 skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(SkAlpha alpha) { |
130 SkLayerDrawLooper::Builder looper_builder; | 137 SkLayerDrawLooper::Builder looper_builder; |
131 looper_builder.addLayer(); | 138 looper_builder.addLayer(); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 const bool pressed = state() == views::CustomButton::STATE_PRESSED; | 376 const bool pressed = state() == views::CustomButton::STATE_PRESSED; |
370 double hover_value = | 377 double hover_value = |
371 (state() == views::CustomButton::STATE_HOVERED) ? 1 : 0; | 378 (state() == views::CustomButton::STATE_HOVERED) ? 1 : 0; |
372 if (hover_animation_->is_animating()) | 379 if (hover_animation_->is_animating()) |
373 hover_value = hover_animation_->GetCurrentValue(); | 380 hover_value = hover_animation_->GetCurrentValue(); |
374 const float scale = canvas->image_scale(); | 381 const float scale = canvas->image_scale(); |
375 | 382 |
376 SkPath fill; | 383 SkPath fill; |
377 if (ui::MaterialDesignController::IsModeMaterial()) { | 384 if (ui::MaterialDesignController::IsModeMaterial()) { |
378 // Fill. | 385 // Fill. |
379 fill.moveTo(9.75 * scale, 16 * scale); | 386 const float fill_bottom = (visible_height - 2) * scale; |
| 387 const float diag_height = fill_bottom - 3.5 * scale; |
| 388 const float diag_width = diag_height * Tab::GetInverseDiagonalSlope(); |
| 389 fill.moveTo(diag_width + 4 * scale, fill_bottom); |
380 fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, | 390 fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, |
381 -1.5 * scale); | 391 -1.5 * scale); |
382 fill.rLineTo(-5.75 * scale, -12.5 * scale); | 392 fill.rLineTo(-diag_width, -diag_height); |
383 fill.rCubicTo(0, -0.5 * scale, 0.25 * scale, -scale, scale, -scale); | 393 fill.rCubicTo(0, -0.5 * scale, 0.25 * scale, -scale, scale, -scale); |
384 fill.rLineTo(23.25 * scale, 0); | 394 fill.lineTo((width() - 4) * scale - diag_width, scale); |
385 fill.rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, | 395 fill.rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, |
386 1.5 * scale); | 396 1.5 * scale); |
387 fill.rLineTo(5.75 * scale, 12.5 * scale); | 397 fill.rLineTo(diag_width, diag_height); |
388 fill.rCubicTo(0, 0.5 * scale, -0.25 * scale, scale, -scale, scale); | 398 fill.rCubicTo(0, 0.5 * scale, -0.25 * scale, scale, -scale, scale); |
389 fill.close(); | 399 fill.close(); |
390 PaintFill(pressed, hover_value, scale, fill, canvas); | 400 PaintFill(pressed, hover_value, scale, fill, canvas); |
391 | 401 |
392 // Stroke. | 402 // Stroke. |
393 gfx::ScopedCanvas scoped_canvas(canvas); | 403 gfx::ScopedCanvas scoped_canvas(canvas); |
394 canvas->UndoDeviceScaleFactor(); | 404 canvas->UndoDeviceScaleFactor(); |
395 SkPath stroke; | 405 SkPath stroke; |
396 GetBorderPath(0, scale, false, &stroke); | 406 GetBorderPath(0, scale, false, &stroke); |
397 // We want to draw a drop shadow either inside or outside the stroke, | 407 // We want to draw a drop shadow either inside or outside the stroke, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 0, alpha); | 444 0, alpha); |
435 } | 445 } |
436 } | 446 } |
437 | 447 |
438 bool NewTabButton::GetHitTestMask(gfx::Path* mask) const { | 448 bool NewTabButton::GetHitTestMask(gfx::Path* mask) const { |
439 DCHECK(mask); | 449 DCHECK(mask); |
440 | 450 |
441 if (ui::MaterialDesignController::IsModeMaterial()) { | 451 if (ui::MaterialDesignController::IsModeMaterial()) { |
442 SkPath border; | 452 SkPath border; |
443 const float scale = GetWidget()->GetCompositor()->device_scale_factor(); | 453 const float scale = GetWidget()->GetCompositor()->device_scale_factor(); |
444 GetBorderPath(kNewTabButtonVerticalOffset * scale, scale, | 454 GetBorderPath(GetNewTabButtonTopOffset() * scale, scale, |
445 tab_strip_->SizeTabButtonToTopOfTabStrip(), &border); | 455 tab_strip_->SizeTabButtonToTopOfTabStrip(), &border); |
446 mask->addPath(border, SkMatrix::MakeScale(1 / scale)); | 456 mask->addPath(border, SkMatrix::MakeScale(1 / scale)); |
447 } else if (tab_strip_->SizeTabButtonToTopOfTabStrip()) { | 457 } else if (tab_strip_->SizeTabButtonToTopOfTabStrip()) { |
448 // When the button is sized to the top of the tab strip, we want the hit | 458 // When the button is sized to the top of the tab strip, we want the hit |
449 // test mask to be defined as the complete (rectangular) bounds of the | 459 // test mask to be defined as the complete (rectangular) bounds of the |
450 // button. | 460 // button. |
451 gfx::Rect button_bounds(GetContentsBounds()); | 461 gfx::Rect button_bounds(GetContentsBounds()); |
452 button_bounds.set_x(GetMirroredXForRect(button_bounds)); | 462 button_bounds.set_x(GetMirroredXForRect(button_bounds)); |
453 mask->addRect(RectToSkRect(button_bounds)); | 463 mask->addRect(RectToSkRect(button_bounds)); |
454 } else { | 464 } else { |
455 SkScalar w = SkIntToScalar(width()); | 465 SkScalar w = SkIntToScalar(width()); |
456 SkScalar v_offset = SkIntToScalar(kNewTabButtonVerticalOffset); | 466 SkScalar v_offset = SkIntToScalar(GetNewTabButtonTopOffset()); |
457 | 467 |
458 // These values are defined by the shape of the new tab image. Should that | 468 // These values are defined by the shape of the new tab image. Should that |
459 // image ever change, these values will need to be updated. They're so | 469 // image ever change, these values will need to be updated. They're so |
460 // custom it's not really worth defining constants for. | 470 // custom it's not really worth defining constants for. |
461 // These values are correct for regular and USE_ASH versions of the image. | 471 // These values are correct for regular and USE_ASH versions of the image. |
462 mask->moveTo(0, v_offset + 1); | 472 mask->moveTo(0, v_offset + 1); |
463 mask->lineTo(w - 7, v_offset + 1); | 473 mask->lineTo(w - 7, v_offset + 1); |
464 mask->lineTo(w - 4, v_offset + 4); | 474 mask->lineTo(w - 4, v_offset + 4); |
465 mask->lineTo(w, v_offset + 16); | 475 mask->lineTo(w, v_offset + 16); |
466 mask->lineTo(w - 1, v_offset + 17); | 476 mask->lineTo(w - 1, v_offset + 17); |
467 mask->lineTo(7, v_offset + 17); | 477 mask->lineTo(7, v_offset + 17); |
468 mask->lineTo(4, v_offset + 13); | 478 mask->lineTo(4, v_offset + 13); |
469 mask->lineTo(0, v_offset + 1); | 479 mask->lineTo(0, v_offset + 1); |
470 mask->close(); | 480 mask->close(); |
471 } | 481 } |
472 | 482 |
473 return true; | 483 return true; |
474 } | 484 } |
475 | 485 |
476 void NewTabButton::GetBorderPath(float button_y, | 486 void NewTabButton::GetBorderPath(float button_y, |
477 float scale, | 487 float scale, |
478 bool extend_to_top, | 488 bool extend_to_top, |
479 SkPath* path) const { | 489 SkPath* path) const { |
480 path->moveTo(9.75 * scale - 1, button_y + 16 * scale + 1); | 490 const float inverse_slope = Tab::GetInverseDiagonalSlope(); |
| 491 const float fill_bottom = |
| 492 (GetLayoutSize(NEW_TAB_BUTTON).height() - 2) * scale; |
| 493 const float stroke_bottom = button_y + fill_bottom + 1; |
| 494 const float diag_height = fill_bottom - 3.5 * scale; |
| 495 const float diag_width = diag_height * inverse_slope; |
| 496 path->moveTo(diag_width + 4 * scale - 1, stroke_bottom); |
481 path->rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, | 497 path->rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, |
482 -1.5 * scale); | 498 -1.5 * scale); |
483 path->rLineTo(-5.75 * scale, -12.5 * scale); | 499 path->rLineTo(-diag_width, -diag_height); |
484 if (extend_to_top) { | 500 if (extend_to_top) { |
485 // Create the vertical extension by extending the side diagonals at the | 501 // Create the vertical extension by extending the side diagonals at the |
486 // upper left and lower right corners until they reach the top and bottom of | 502 // upper left and lower right corners until they reach the top and bottom of |
487 // the border, respectively (in other words, "un-round-off" those corners | 503 // the border, respectively (in other words, "un-round-off" those corners |
488 // and turn them into sharp points). Then extend upward from the corner | 504 // and turn them into sharp points). Then extend upward from the corner |
489 // points to the top of the bounds. | 505 // points to the top of the bounds. |
490 const float dy = scale + 2; | 506 const float dy = scale + 2; |
491 const float dx = 11.5 / 25 * dy; | 507 const float dx = inverse_slope * dy; |
492 path->rLineTo(-dx, -dy); | 508 path->rLineTo(-dx, -dy); |
493 path->rLineTo(0, -button_y - scale + 1); | 509 path->rLineTo(0, -button_y - scale + 1); |
494 path->lineTo(34 * scale + 1 + dx, 0); | 510 path->lineTo((width() - 2) * scale + 1 + dx, 0); |
495 path->rLineTo(0, button_y + 16 * scale + 1); | 511 path->rLineTo(0, stroke_bottom); |
496 } else { | 512 } else { |
497 path->rCubicTo(-0.5 * scale, -1.125 * scale, 0.5 * scale, -scale - 2, scale, | 513 path->rCubicTo(-0.5 * scale, -1.125 * scale, 0.5 * scale, -scale - 2, scale, |
498 -scale - 2); | 514 -scale - 2); |
499 path->rLineTo(23.25 * scale + 2, 0); | 515 path->lineTo((width() - 4) * scale - diag_width + 1, scale - 1); |
500 path->rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, | 516 path->rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, |
501 1.5 * scale); | 517 1.5 * scale); |
502 path->rLineTo(5.75 * scale, 12.5 * scale); | 518 path->rLineTo(diag_width, diag_height); |
503 path->rCubicTo(0.5 * scale, 1.125 * scale, -0.5 * scale, scale + 2, -scale, | 519 path->rCubicTo(0.5 * scale, 1.125 * scale, -0.5 * scale, scale + 2, -scale, |
504 scale + 2); | 520 scale + 2); |
505 } | 521 } |
506 path->close(); | 522 path->close(); |
507 } | 523 } |
508 | 524 |
509 void NewTabButton::PaintFill(bool pressed, | 525 void NewTabButton::PaintFill(bool pressed, |
510 double hover_value, | 526 double hover_value, |
511 float scale, | 527 float scale, |
512 const SkPath& fill, | 528 const SkPath& fill, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 // The new tab background is mirrored in RTL mode, but the theme background | 573 // The new tab background is mirrored in RTL mode, but the theme background |
558 // should never be mirrored. Mirror it here to compensate. | 574 // should never be mirrored. Mirror it here to compensate. |
559 float x_scale = 1.0f; | 575 float x_scale = 1.0f; |
560 int x = GetMirroredX() + background_offset_.x(); | 576 int x = GetMirroredX() + background_offset_.x(); |
561 if (base::i18n::IsRTL()) { | 577 if (base::i18n::IsRTL()) { |
562 x_scale = -1.0f; | 578 x_scale = -1.0f; |
563 // Offset by |width| such that the same region is painted as if there was | 579 // Offset by |width| such that the same region is painted as if there was |
564 // no flip. | 580 // no flip. |
565 x += size.width(); | 581 x += size.width(); |
566 } | 582 } |
567 canvas->TileImageInt(*background, x, kNewTabButtonVerticalOffset + offset_y, | 583 canvas->TileImageInt(*background, x, GetNewTabButtonTopOffset() + offset_y, |
568 x_scale, 1.0f, 0, 0, size.width(), size.height()); | 584 x_scale, 1.0f, 0, 0, size.width(), size.height()); |
569 | 585 |
570 // For non-MD, adjust the alpha of the fill to match that of inactive tabs | 586 // For non-MD, adjust the alpha of the fill to match that of inactive tabs |
571 // (except for pressed buttons, which get a different value). For MD, we do | 587 // (except for pressed buttons, which get a different value). For MD, we do |
572 // this with an opacity recorder in TabStrip::PaintChildren() so the fill | 588 // this with an opacity recorder in TabStrip::PaintChildren() so the fill |
573 // and stroke are both affected, to better match how tabs are handled, but | 589 // and stroke are both affected, to better match how tabs are handled, but |
574 // in non-MD, the button stroke is already lighter than the tab stroke, and | 590 // in non-MD, the button stroke is already lighter than the tab stroke, and |
575 // using the opacity recorder washes it out too much. | 591 // using the opacity recorder washes it out too much. |
576 static const SkAlpha kPressedAlpha = 145; | 592 static const SkAlpha kPressedAlpha = 145; |
577 const SkAlpha alpha = | 593 const SkAlpha alpha = |
(...skipping 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1655 | 1671 |
1656 /////////////////////////////////////////////////////////////////////////////// | 1672 /////////////////////////////////////////////////////////////////////////////// |
1657 // TabStrip, private: | 1673 // TabStrip, private: |
1658 | 1674 |
1659 void TabStrip::Init() { | 1675 void TabStrip::Init() { |
1660 set_id(VIEW_ID_TAB_STRIP); | 1676 set_id(VIEW_ID_TAB_STRIP); |
1661 // So we get enter/exit on children to switch stacked layout on and off. | 1677 // So we get enter/exit on children to switch stacked layout on and off. |
1662 set_notify_enter_exit_on_child(true); | 1678 set_notify_enter_exit_on_child(true); |
1663 | 1679 |
1664 newtab_button_bounds_.set_size(GetLayoutSize(NEW_TAB_BUTTON)); | 1680 newtab_button_bounds_.set_size(GetLayoutSize(NEW_TAB_BUTTON)); |
1665 newtab_button_bounds_.Inset(0, 0, 0, -kNewTabButtonVerticalOffset); | 1681 newtab_button_bounds_.Inset(0, 0, 0, -GetNewTabButtonTopOffset()); |
1666 newtab_button_ = new NewTabButton(this, this); | 1682 newtab_button_ = new NewTabButton(this, this); |
1667 newtab_button_->SetTooltipText( | 1683 newtab_button_->SetTooltipText( |
1668 l10n_util::GetStringUTF16(IDS_TOOLTIP_NEW_TAB)); | 1684 l10n_util::GetStringUTF16(IDS_TOOLTIP_NEW_TAB)); |
1669 newtab_button_->SetAccessibleName( | 1685 newtab_button_->SetAccessibleName( |
1670 l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)); | 1686 l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)); |
1671 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1687 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
1672 views::ImageButton::ALIGN_BOTTOM); | 1688 views::ImageButton::ALIGN_BOTTOM); |
1673 newtab_button_->SetEventTargeter( | 1689 newtab_button_->SetEventTargeter( |
1674 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(newtab_button_))); | 1690 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(newtab_button_))); |
1675 AddChildView(newtab_button_); | 1691 AddChildView(newtab_button_); |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2844 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); | 2860 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); |
2845 if (view) | 2861 if (view) |
2846 return view; | 2862 return view; |
2847 } | 2863 } |
2848 Tab* tab = FindTabForEvent(point); | 2864 Tab* tab = FindTabForEvent(point); |
2849 if (tab) | 2865 if (tab) |
2850 return ConvertPointToViewAndGetEventHandler(this, tab, point); | 2866 return ConvertPointToViewAndGetEventHandler(this, tab, point); |
2851 } | 2867 } |
2852 return this; | 2868 return this; |
2853 } | 2869 } |
OLD | NEW |