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 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <windowsx.h> | 8 #include <windowsx.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 #include "ui/gfx/win/hwnd_util.h" | 68 #include "ui/gfx/win/hwnd_util.h" |
69 #include "ui/views/widget/monitor_win.h" | 69 #include "ui/views/widget/monitor_win.h" |
70 #include "ui/views/win/hwnd_util.h" | 70 #include "ui/views/win/hwnd_util.h" |
71 #endif | 71 #endif |
72 | 72 |
73 using base::UserMetricsAction; | 73 using base::UserMetricsAction; |
74 using ui::DropTargetEvent; | 74 using ui::DropTargetEvent; |
75 | 75 |
76 namespace { | 76 namespace { |
77 | 77 |
78 static const int kTabStripAnimationVSlop = 40; | 78 const int kNewTabButtonHeight = 18; |
| 79 |
| 80 const int kTabStripAnimationVSlop = 40; |
| 81 |
79 // Inactive tabs in a native frame are slightly transparent. | 82 // Inactive tabs in a native frame are slightly transparent. |
80 static const uint8_t kGlassFrameInactiveTabAlpha = 200; | 83 const uint8_t kGlassFrameInactiveTabAlpha = 200; |
81 // If there are multiple tabs selected then make non-selected inactive tabs | 84 // If there are multiple tabs selected then make non-selected inactive tabs |
82 // even more transparent. | 85 // even more transparent. |
83 static const int kGlassFrameInactiveTabAlphaMultiSelection = 150; | 86 const uint8_t kGlassFrameInactiveTabAlphaMultiSelection = 150; |
84 | 87 |
85 // Alpha applied to all elements save the selected tabs. | 88 // Alpha applied to all elements save the selected tabs. |
86 static const uint8_t kInactiveTabAndNewTabButtonAlphaAsh = 230; | 89 const uint8_t kInactiveTabAndNewTabButtonAlphaAsh = 230; |
87 static const uint8_t kInactiveTabAndNewTabButtonAlpha = 255; | 90 const uint8_t kInactiveTabAndNewTabButtonAlpha = 255; |
88 | 91 |
89 // Inverse ratio of the width of a tab edge to the width of the tab. When | 92 // Inverse ratio of the width of a tab edge to the width of the tab. When |
90 // hovering over the left or right edge of a tab, the drop indicator will | 93 // hovering over the left or right edge of a tab, the drop indicator will |
91 // point between tabs. | 94 // point between tabs. |
92 static const int kTabEdgeRatioInverse = 4; | 95 const int kTabEdgeRatioInverse = 4; |
93 | 96 |
94 // Size of the drop indicator. | 97 // Size of the drop indicator. |
95 static int drop_indicator_width; | 98 int drop_indicator_width; |
96 static int drop_indicator_height; | 99 int drop_indicator_height; |
97 | 100 |
98 // Max number of stacked tabs. | 101 // Max number of stacked tabs. |
99 static const int kMaxStackedCount = 4; | 102 const int kMaxStackedCount = 4; |
100 | 103 |
101 // Padding between stacked tabs. | 104 // Padding between stacked tabs. |
102 static const int kStackedPadding = 6; | 105 const int kStackedPadding = 6; |
103 | 106 |
104 // See UpdateLayoutTypeFromMouseEvent() for a description of these. | 107 // See UpdateLayoutTypeFromMouseEvent() for a description of these. |
105 #if !defined(USE_ASH) | 108 #if !defined(USE_ASH) |
106 const int kMouseMoveTimeMS = 200; | 109 const int kMouseMoveTimeMS = 200; |
107 const int kMouseMoveCountBeforeConsiderReal = 3; | 110 const int kMouseMoveCountBeforeConsiderReal = 3; |
108 #endif | 111 #endif |
109 | 112 |
110 // Amount of time we delay before resizing after a close from a touch. | 113 // Amount of time we delay before resizing after a close from a touch. |
111 const int kTouchResizeLayoutTimeMS = 2000; | 114 const int kTouchResizeLayoutTimeMS = 2000; |
112 | 115 |
113 // Amount to adjust the clip by when the tab is stacked before the active index. | 116 // Amount to adjust the clip by when the tab is stacked before the active index. |
114 const int kStackedTabLeftClip = 20; | 117 const int kStackedTabLeftClip = 20; |
115 | 118 |
116 // Amount to adjust the clip by when the tab is stacked after the active index. | 119 // Amount to adjust the clip by when the tab is stacked after the active index. |
117 const int kStackedTabRightClip = 20; | 120 const int kStackedTabRightClip = 20; |
118 | 121 |
119 #if defined(OS_MACOSX) | 122 #if defined(OS_MACOSX) |
| 123 const int kNewTabButtonHorizontalOffset = -8; |
120 const int kPinnedToNonPinnedOffset = 2; | 124 const int kPinnedToNonPinnedOffset = 2; |
121 #else | 125 #else |
| 126 const int kNewTabButtonHorizontalOffset = -11; |
122 const int kPinnedToNonPinnedOffset = 3; | 127 const int kPinnedToNonPinnedOffset = 3; |
123 #endif | 128 #endif |
124 | 129 |
125 base::string16 GetClipboardText() { | 130 // Returns the width needed for the new tab button (and padding). |
126 if (!ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION)) | 131 int GetNewTabButtonWidth() { |
127 return base::string16(); | 132 return TabStrip::kNewTabButtonAssetWidth + kNewTabButtonHorizontalOffset; |
128 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); | |
129 CHECK(clipboard); | |
130 base::string16 clipboard_text; | |
131 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &clipboard_text); | |
132 return clipboard_text; | |
133 } | 133 } |
134 | 134 |
135 // Animation delegate used for any automatic tab movement. Hides the tab if it | 135 // Animation delegate used for any automatic tab movement. Hides the tab if it |
136 // is not fully visible within the tabstrip area, to prevent overflow clipping. | 136 // is not fully visible within the tabstrip area, to prevent overflow clipping. |
137 class TabAnimationDelegate : public gfx::AnimationDelegate { | 137 class TabAnimationDelegate : public gfx::AnimationDelegate { |
138 public: | 138 public: |
139 TabAnimationDelegate(TabStrip* tab_strip, Tab* tab); | 139 TabAnimationDelegate(TabStrip* tab_strip, Tab* tab); |
140 ~TabAnimationDelegate() override; | 140 ~TabAnimationDelegate() override; |
141 | 141 |
142 void AnimationProgressed(const gfx::Animation* animation) override; | 142 void AnimationProgressed(const gfx::Animation* animation) override; |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 void NewTabButton::OnGestureEvent(ui::GestureEvent* event) { | 338 void NewTabButton::OnGestureEvent(ui::GestureEvent* event) { |
339 // Consume all gesture events here so that the parent (Tab) does not | 339 // Consume all gesture events here so that the parent (Tab) does not |
340 // start consuming gestures. | 340 // start consuming gestures. |
341 views::ImageButton::OnGestureEvent(event); | 341 views::ImageButton::OnGestureEvent(event); |
342 event->SetHandled(); | 342 event->SetHandled(); |
343 } | 343 } |
344 | 344 |
345 bool NewTabButton::GetHitTestMask(gfx::Path* mask) const { | 345 bool NewTabButton::GetHitTestMask(gfx::Path* mask) const { |
346 DCHECK(mask); | 346 DCHECK(mask); |
347 | 347 |
348 // When the button is sized to the top of the tab strip, we want the hit | |
349 // test mask to be defined as the complete (rectangular) bounds of the | |
350 // button. | |
351 if (tab_strip_->SizeTabButtonToTopOfTabStrip()) { | 348 if (tab_strip_->SizeTabButtonToTopOfTabStrip()) { |
| 349 // When the button is sized to the top of the tab strip, we want the hit |
| 350 // test mask to be defined as the complete (rectangular) bounds of the |
| 351 // button. |
352 gfx::Rect button_bounds(GetContentsBounds()); | 352 gfx::Rect button_bounds(GetContentsBounds()); |
353 button_bounds.set_x(GetMirroredXForRect(button_bounds)); | 353 button_bounds.set_x(GetMirroredXForRect(button_bounds)); |
354 mask->addRect(RectToSkRect(button_bounds)); | 354 mask->addRect(RectToSkRect(button_bounds)); |
355 return true; | 355 } else { |
| 356 SkScalar w = SkIntToScalar(width()); |
| 357 SkScalar v_offset = SkIntToScalar(TabStrip::kNewTabButtonVerticalOffset); |
| 358 |
| 359 // These values are defined by the shape of the new tab image. Should that |
| 360 // image ever change, these values will need to be updated. They're so |
| 361 // custom it's not really worth defining constants for. |
| 362 // These values are correct for regular and USE_ASH versions of the image. |
| 363 mask->moveTo(0, v_offset + 1); |
| 364 mask->lineTo(w - 7, v_offset + 1); |
| 365 mask->lineTo(w - 4, v_offset + 4); |
| 366 mask->lineTo(w, v_offset + 16); |
| 367 mask->lineTo(w - 1, v_offset + 17); |
| 368 mask->lineTo(7, v_offset + 17); |
| 369 mask->lineTo(4, v_offset + 13); |
| 370 mask->lineTo(0, v_offset + 1); |
| 371 mask->close(); |
356 } | 372 } |
357 | 373 |
358 SkScalar w = SkIntToScalar(width()); | |
359 SkScalar v_offset = SkIntToScalar(TabStrip::kNewTabButtonVerticalOffset); | |
360 | |
361 // These values are defined by the shape of the new tab image. Should that | |
362 // image ever change, these values will need to be updated. They're so | |
363 // custom it's not really worth defining constants for. | |
364 // These values are correct for regular and USE_ASH versions of the image. | |
365 mask->moveTo(0, v_offset + 1); | |
366 mask->lineTo(w - 7, v_offset + 1); | |
367 mask->lineTo(w - 4, v_offset + 4); | |
368 mask->lineTo(w, v_offset + 16); | |
369 mask->lineTo(w - 1, v_offset + 17); | |
370 mask->lineTo(7, v_offset + 17); | |
371 mask->lineTo(4, v_offset + 13); | |
372 mask->lineTo(0, v_offset + 1); | |
373 mask->close(); | |
374 | |
375 return true; | 374 return true; |
376 } | 375 } |
377 | 376 |
378 bool NewTabButton::ShouldWindowContentsBeTransparent() const { | 377 bool NewTabButton::ShouldWindowContentsBeTransparent() const { |
379 return GetWidget() && | 378 return GetWidget() && |
380 GetWidget()->GetTopLevelWidget()->ShouldWindowContentsBeTransparent(); | 379 GetWidget()->GetTopLevelWidget()->ShouldWindowContentsBeTransparent(); |
381 } | 380 } |
382 | 381 |
383 gfx::ImageSkia NewTabButton::GetBackgroundImage( | 382 gfx::ImageSkia NewTabButton::GetBackgroundImage( |
384 views::CustomButton::ButtonState state, | 383 views::CustomButton::ButtonState state, |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 | 528 |
530 void TabStrip::RemoveTabDelegate::AnimationCanceled( | 529 void TabStrip::RemoveTabDelegate::AnimationCanceled( |
531 const gfx::Animation* animation) { | 530 const gfx::Animation* animation) { |
532 AnimationEnded(animation); | 531 AnimationEnded(animation); |
533 } | 532 } |
534 | 533 |
535 /////////////////////////////////////////////////////////////////////////////// | 534 /////////////////////////////////////////////////////////////////////////////// |
536 // TabStrip, public: | 535 // TabStrip, public: |
537 | 536 |
538 // static | 537 // static |
539 const char TabStrip::kViewClassName[] = "TabStrip"; | |
540 const int TabStrip::kNewTabButtonVerticalOffset = 7; | 538 const int TabStrip::kNewTabButtonVerticalOffset = 7; |
541 const int TabStrip::kNewTabButtonAssetWidth = 34; | 539 const int TabStrip::kNewTabButtonAssetWidth = 34; |
542 const int TabStrip::kNewTabButtonAssetHeight = 18; | |
543 #if defined(OS_MACOSX) | |
544 const int TabStrip::kNewTabButtonHorizontalOffset = -8; | |
545 #else | |
546 const int TabStrip::kNewTabButtonHorizontalOffset = -11; | |
547 #endif | |
548 | 540 |
549 TabStrip::TabStrip(TabStripController* controller) | 541 TabStrip::TabStrip(TabStripController* controller) |
550 : controller_(controller), | 542 : controller_(controller), |
551 newtab_button_(NULL), | 543 newtab_button_(NULL), |
552 current_inactive_width_(Tab::GetStandardSize().width()), | 544 current_inactive_width_(Tab::GetStandardSize().width()), |
553 current_active_width_(Tab::GetStandardSize().width()), | 545 current_active_width_(Tab::GetStandardSize().width()), |
554 available_width_for_tabs_(-1), | 546 available_width_for_tabs_(-1), |
555 in_tab_close_(false), | 547 in_tab_close_(false), |
556 animation_container_(new gfx::AnimationContainer()), | 548 animation_container_(new gfx::AnimationContainer()), |
557 bounds_animator_(this), | 549 bounds_animator_(this), |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 // If the tab is currently clipped, it shouldn't be visible. Note that we | 752 // If the tab is currently clipped, it shouldn't be visible. Note that we |
761 // allow dragged tabs to draw over the "New Tab button" region as well, | 753 // allow dragged tabs to draw over the "New Tab button" region as well, |
762 // because either the New Tab button will be hidden, or the dragged tabs will | 754 // because either the New Tab button will be hidden, or the dragged tabs will |
763 // be animating back to their normal positions and we don't want to hide them | 755 // be animating back to their normal positions and we don't want to hide them |
764 // in the New Tab button region in case they re-appear after leaving it. | 756 // in the New Tab button region in case they re-appear after leaving it. |
765 // (This prevents flickeriness.) We never draw non-dragged tabs in New Tab | 757 // (This prevents flickeriness.) We never draw non-dragged tabs in New Tab |
766 // button area, even when the button is invisible, so that they don't appear | 758 // button area, even when the button is invisible, so that they don't appear |
767 // to "pop in" when the button disappears. | 759 // to "pop in" when the button disappears. |
768 // TODO: Probably doesn't work for RTL | 760 // TODO: Probably doesn't work for RTL |
769 int right_edge = tab->bounds().right(); | 761 int right_edge = tab->bounds().right(); |
770 const int visible_width = tab->dragging() ? width() : tab_area_width(); | 762 const int visible_width = tab->dragging() ? width() : GetTabAreaWidth(); |
771 if (right_edge > visible_width) | 763 if (right_edge > visible_width) |
772 return false; | 764 return false; |
773 | 765 |
774 // Non-clipped dragging tabs should always be visible. | 766 // Non-clipped dragging tabs should always be visible. |
775 if (tab->dragging()) | 767 if (tab->dragging()) |
776 return true; | 768 return true; |
777 | 769 |
778 // Let all non-clipped closing tabs be visible. These will probably finish | 770 // Let all non-clipped closing tabs be visible. These will probably finish |
779 // closing before the user changes the active tab, so there's little reason to | 771 // closing before the user changes the active tab, so there's little reason to |
780 // try and make the more complex logic below apply. | 772 // try and make the more complex logic below apply. |
781 if (tab->closing()) | 773 if (tab->closing()) |
782 return true; | 774 return true; |
783 | 775 |
784 // Now we need to check whether the tab isn't currently clipped, but could | 776 // Now we need to check whether the tab isn't currently clipped, but could |
785 // become clipped if we changed the active tab, widening either this tab or | 777 // become clipped if we changed the active tab, widening either this tab or |
786 // the tabstrip portion before it. | 778 // the tabstrip portion before it. |
787 | 779 |
788 // Pinned tabs don't change size when activated, so any tab in the pinned tab | 780 // Pinned tabs don't change size when activated, so any tab in the pinned tab |
789 // region is safe. | 781 // region is safe. |
790 if (tab->data().pinned) | 782 if (tab->data().pinned) |
791 return true; | 783 return true; |
792 | 784 |
793 // If the active tab is on or before this tab, we're safe. | 785 // If the active tab is on or before this tab, we're safe. |
794 if (controller_->GetActiveIndex() <= GetModelIndexOfTab(tab)) | 786 if (controller_->GetActiveIndex() <= GetModelIndexOfTab(tab)) |
795 return true; | 787 return true; |
796 | 788 |
797 // We need to check what would happen if the active tab were to move to this | 789 // We need to check what would happen if the active tab were to move to this |
798 // tab or before. | 790 // tab or before. |
799 return (right_edge + current_active_width_ - current_inactive_width_) <= | 791 return (right_edge + current_active_width_ - current_inactive_width_) <= |
800 tab_area_width(); | 792 GetTabAreaWidth(); |
801 } | 793 } |
802 | 794 |
803 void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) { | 795 void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) { |
804 if (!in_tab_close_ && IsAnimating()) { | 796 if (!in_tab_close_ && IsAnimating()) { |
805 // Cancel any current animations. We do this as remove uses the current | 797 // Cancel any current animations. We do this as remove uses the current |
806 // ideal bounds and we need to know ideal bounds is in a good state. | 798 // ideal bounds and we need to know ideal bounds is in a good state. |
807 StopAnimating(true); | 799 StopAnimating(true); |
808 } | 800 } |
809 | 801 |
810 if (!GetWidget()) | 802 if (!GetWidget()) |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 // And the dragged tabs. | 1361 // And the dragged tabs. |
1370 for (size_t i = 0; i < tabs_dragging.size(); ++i) | 1362 for (size_t i = 0; i < tabs_dragging.size(); ++i) |
1371 tabs_dragging[i]->Paint(context); | 1363 tabs_dragging[i]->Paint(context); |
1372 | 1364 |
1373 // If the active tab is being dragged, it goes last. | 1365 // If the active tab is being dragged, it goes last. |
1374 if (active_tab && is_dragging) | 1366 if (active_tab && is_dragging) |
1375 active_tab->Paint(context); | 1367 active_tab->Paint(context); |
1376 } | 1368 } |
1377 | 1369 |
1378 const char* TabStrip::GetClassName() const { | 1370 const char* TabStrip::GetClassName() const { |
| 1371 static const char kViewClassName[] = "TabStrip"; |
1379 return kViewClassName; | 1372 return kViewClassName; |
1380 } | 1373 } |
1381 | 1374 |
1382 gfx::Size TabStrip::GetPreferredSize() const { | 1375 gfx::Size TabStrip::GetPreferredSize() const { |
1383 int needed_tab_width; | 1376 int needed_tab_width; |
1384 if (touch_layout_ || adjust_layout_) { | 1377 if (touch_layout_ || adjust_layout_) { |
1385 // For stacked tabs the minimum size is calculated as the size needed to | 1378 // For stacked tabs the minimum size is calculated as the size needed to |
1386 // handle showing any number of tabs. | 1379 // handle showing any number of tabs. |
1387 needed_tab_width = | 1380 needed_tab_width = |
1388 Tab::GetTouchWidth() + (2 * kStackedPadding * kMaxStackedCount); | 1381 Tab::GetTouchWidth() + (2 * kStackedPadding * kMaxStackedCount); |
(...skipping 12 matching lines...) Expand all Loading... |
1401 if (tab_count() > 1) | 1394 if (tab_count() > 1) |
1402 needed_tab_width -= (tab_count() - 1) * tab_overlap; | 1395 needed_tab_width -= (tab_count() - 1) * tab_overlap; |
1403 | 1396 |
1404 // Don't let the tabstrip shrink smaller than is necessary to show one tab, | 1397 // Don't let the tabstrip shrink smaller than is necessary to show one tab, |
1405 // and don't force it to be larger than is necessary to show 20 tabs. | 1398 // and don't force it to be larger than is necessary to show 20 tabs. |
1406 const int largest_min_tab_width = | 1399 const int largest_min_tab_width = |
1407 min_selected_width + 19 * (min_unselected_width - tab_overlap); | 1400 min_selected_width + 19 * (min_unselected_width - tab_overlap); |
1408 needed_tab_width = std::min( | 1401 needed_tab_width = std::min( |
1409 std::max(needed_tab_width, min_selected_width), largest_min_tab_width); | 1402 std::max(needed_tab_width, min_selected_width), largest_min_tab_width); |
1410 } | 1403 } |
1411 return gfx::Size(needed_tab_width + new_tab_button_width(), | 1404 return gfx::Size(needed_tab_width + GetNewTabButtonWidth(), |
1412 immersive_style_ ? Tab::GetImmersiveHeight() | 1405 immersive_style_ ? Tab::GetImmersiveHeight() |
1413 : Tab::GetMinimumInactiveSize().height()); | 1406 : Tab::GetMinimumInactiveSize().height()); |
1414 } | 1407 } |
1415 | 1408 |
1416 void TabStrip::OnDragEntered(const DropTargetEvent& event) { | 1409 void TabStrip::OnDragEntered(const DropTargetEvent& event) { |
1417 // Force animations to stop, otherwise it makes the index calculation tricky. | 1410 // Force animations to stop, otherwise it makes the index calculation tricky. |
1418 StopAnimating(true); | 1411 StopAnimating(true); |
1419 | 1412 |
1420 UpdateDropIndex(event); | 1413 UpdateDropIndex(event); |
1421 | 1414 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 return Tab::GetImmersiveHeight(); | 1505 return Tab::GetImmersiveHeight(); |
1513 } | 1506 } |
1514 | 1507 |
1515 /////////////////////////////////////////////////////////////////////////////// | 1508 /////////////////////////////////////////////////////////////////////////////// |
1516 // TabStrip, private: | 1509 // TabStrip, private: |
1517 | 1510 |
1518 void TabStrip::Init() { | 1511 void TabStrip::Init() { |
1519 set_id(VIEW_ID_TAB_STRIP); | 1512 set_id(VIEW_ID_TAB_STRIP); |
1520 // So we get enter/exit on children to switch stacked layout on and off. | 1513 // So we get enter/exit on children to switch stacked layout on and off. |
1521 set_notify_enter_exit_on_child(true); | 1514 set_notify_enter_exit_on_child(true); |
1522 newtab_button_bounds_.SetRect(0, | 1515 newtab_button_bounds_.SetRect( |
1523 0, | 1516 0, 0, kNewTabButtonAssetWidth, |
1524 kNewTabButtonAssetWidth, | 1517 kNewTabButtonHeight + kNewTabButtonVerticalOffset); |
1525 kNewTabButtonAssetHeight + | |
1526 kNewTabButtonVerticalOffset); | |
1527 newtab_button_ = new NewTabButton(this, this); | 1518 newtab_button_ = new NewTabButton(this, this); |
1528 newtab_button_->SetTooltipText( | 1519 newtab_button_->SetTooltipText( |
1529 l10n_util::GetStringUTF16(IDS_TOOLTIP_NEW_TAB)); | 1520 l10n_util::GetStringUTF16(IDS_TOOLTIP_NEW_TAB)); |
1530 newtab_button_->SetAccessibleName( | 1521 newtab_button_->SetAccessibleName( |
1531 l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)); | 1522 l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)); |
1532 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1523 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
1533 views::ImageButton::ALIGN_BOTTOM); | 1524 views::ImageButton::ALIGN_BOTTOM); |
1534 newtab_button_->SetEventTargeter( | 1525 newtab_button_->SetEventTargeter( |
1535 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(newtab_button_))); | 1526 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(newtab_button_))); |
1536 AddChildView(newtab_button_); | 1527 AddChildView(newtab_button_); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1632 } | 1623 } |
1633 | 1624 |
1634 void TabStrip::DoLayout() { | 1625 void TabStrip::DoLayout() { |
1635 last_layout_size_ = size(); | 1626 last_layout_size_ = size(); |
1636 | 1627 |
1637 StopAnimating(false); | 1628 StopAnimating(false); |
1638 | 1629 |
1639 SwapLayoutIfNecessary(); | 1630 SwapLayoutIfNecessary(); |
1640 | 1631 |
1641 if (touch_layout_) | 1632 if (touch_layout_) |
1642 touch_layout_->SetWidth(tab_area_width()); | 1633 touch_layout_->SetWidth(GetTabAreaWidth()); |
1643 | 1634 |
1644 GenerateIdealBounds(); | 1635 GenerateIdealBounds(); |
1645 | 1636 |
1646 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); | 1637 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); |
1647 SetTabVisibility(); | 1638 SetTabVisibility(); |
1648 | 1639 |
1649 SchedulePaint(); | 1640 SchedulePaint(); |
1650 | 1641 |
1651 bounds_animator_.StopAnimatingView(newtab_button_); | 1642 bounds_animator_.StopAnimatingView(newtab_button_); |
1652 newtab_button_->SetBoundsRect(newtab_button_bounds_); | 1643 newtab_button_->SetBoundsRect(newtab_button_bounds_); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 int new_x = std::max(new_bounds.x() + delta, max_x); | 1711 int new_x = std::max(new_bounds.x() + delta, max_x); |
1721 if (new_x == max_x && !tab_at(i)->data().pinned && !is_active_pinned && | 1712 if (new_x == max_x && !tab_at(i)->data().pinned && !is_active_pinned && |
1722 new_bounds.width() != active_width) | 1713 new_bounds.width() != active_width) |
1723 new_x += (active_width - new_bounds.width()); | 1714 new_x += (active_width - new_bounds.width()); |
1724 new_bounds.set_x(new_x); | 1715 new_bounds.set_x(new_x); |
1725 tabs_.set_ideal_bounds(i, new_bounds); | 1716 tabs_.set_ideal_bounds(i, new_bounds); |
1726 } | 1717 } |
1727 } else { | 1718 } else { |
1728 // Drag the tabs to the right, stacking tabs after the active tab. | 1719 // Drag the tabs to the right, stacking tabs after the active tab. |
1729 const int last_tab_width = ideal_bounds(tab_count() - 1).width(); | 1720 const int last_tab_width = ideal_bounds(tab_count() - 1).width(); |
1730 const int last_tab_x = tab_area_width() - last_tab_width; | 1721 const int last_tab_x = GetTabAreaWidth() - last_tab_width; |
1731 if (active_index == tab_count() - 1 && | 1722 if (active_index == tab_count() - 1 && |
1732 ideal_bounds(tab_count() - 1).x() == last_tab_x) | 1723 ideal_bounds(tab_count() - 1).x() == last_tab_x) |
1733 return; | 1724 return; |
1734 const int adjusted_delta = | 1725 const int adjusted_delta = |
1735 std::min(last_tab_x - | 1726 std::min(last_tab_x - |
1736 kStackedPadding * std::min(tab_count() - active_index - 1, | 1727 kStackedPadding * std::min(tab_count() - active_index - 1, |
1737 kMaxStackedCount) - | 1728 kMaxStackedCount) - |
1738 ideal_bounds(active_index).x(), | 1729 ideal_bounds(active_index).x(), |
1739 delta); | 1730 delta); |
1740 for (int last_index = tab_count() - 1, i = last_index; i >= active_index; | 1731 for (int last_index = tab_count() - 1, i = last_index; i >= active_index; |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2307 tab_at(i)->set_dragging(false); | 2298 tab_at(i)->set_dragging(false); |
2308 } | 2299 } |
2309 } | 2300 } |
2310 | 2301 |
2311 void TabStrip::GenerateIdealBounds() { | 2302 void TabStrip::GenerateIdealBounds() { |
2312 if (tab_count() == 0) | 2303 if (tab_count() == 0) |
2313 return; // Should only happen during creation/destruction, ignore. | 2304 return; // Should only happen during creation/destruction, ignore. |
2314 | 2305 |
2315 if (!touch_layout_) { | 2306 if (!touch_layout_) { |
2316 const int available_width = (available_width_for_tabs_ < 0) | 2307 const int available_width = (available_width_for_tabs_ < 0) |
2317 ? tab_area_width() | 2308 ? GetTabAreaWidth() |
2318 : available_width_for_tabs_; | 2309 : available_width_for_tabs_; |
2319 const std::vector<gfx::Rect> tabs_bounds = | 2310 const std::vector<gfx::Rect> tabs_bounds = |
2320 CalculateBounds(GetTabSizeInfo(), GetPinnedTabCount(), tab_count(), | 2311 CalculateBounds(GetTabSizeInfo(), GetPinnedTabCount(), tab_count(), |
2321 controller_->GetActiveIndex(), available_width, | 2312 controller_->GetActiveIndex(), available_width, |
2322 ¤t_active_width_, ¤t_inactive_width_); | 2313 ¤t_active_width_, ¤t_inactive_width_); |
2323 DCHECK_EQ(static_cast<size_t>(tab_count()), tabs_bounds.size()); | 2314 DCHECK_EQ(static_cast<size_t>(tab_count()), tabs_bounds.size()); |
2324 | 2315 |
2325 for (size_t i = 0; i < tabs_bounds.size(); ++i) | 2316 for (size_t i = 0; i < tabs_bounds.size(); ++i) |
2326 tabs_.set_ideal_bounds(i, tabs_bounds[i]); | 2317 tabs_.set_ideal_bounds(i, tabs_bounds[i]); |
2327 } | 2318 } |
(...skipping 16 matching lines...) Expand all Loading... |
2344 CalculateBoundsForPinnedTabs(GetTabSizeInfo(), num_pinned_tabs, tab_count(), | 2335 CalculateBoundsForPinnedTabs(GetTabSizeInfo(), num_pinned_tabs, tab_count(), |
2345 &tab_bounds); | 2336 &tab_bounds); |
2346 for (int i = 0; i < num_pinned_tabs; ++i) | 2337 for (int i = 0; i < num_pinned_tabs; ++i) |
2347 tabs_.set_ideal_bounds(i, tab_bounds[i]); | 2338 tabs_.set_ideal_bounds(i, tab_bounds[i]); |
2348 return (num_pinned_tabs < tab_count()) | 2339 return (num_pinned_tabs < tab_count()) |
2349 ? tab_bounds[num_pinned_tabs].x() | 2340 ? tab_bounds[num_pinned_tabs].x() |
2350 : tab_bounds[num_pinned_tabs - 1].right() - | 2341 : tab_bounds[num_pinned_tabs - 1].right() - |
2351 GetLayoutConstant(TABSTRIP_TAB_OVERLAP); | 2342 GetLayoutConstant(TABSTRIP_TAB_OVERLAP); |
2352 } | 2343 } |
2353 | 2344 |
| 2345 int TabStrip::GetTabAreaWidth() const { |
| 2346 return width() - GetNewTabButtonWidth(); |
| 2347 } |
| 2348 |
2354 void TabStrip::StartResizeLayoutAnimation() { | 2349 void TabStrip::StartResizeLayoutAnimation() { |
2355 PrepareForAnimation(); | 2350 PrepareForAnimation(); |
2356 GenerateIdealBounds(); | 2351 GenerateIdealBounds(); |
2357 AnimateToIdealBounds(); | 2352 AnimateToIdealBounds(); |
2358 } | 2353 } |
2359 | 2354 |
2360 void TabStrip::StartPinnedTabAnimation() { | 2355 void TabStrip::StartPinnedTabAnimation() { |
2361 in_tab_close_ = false; | 2356 in_tab_close_ = false; |
2362 available_width_for_tabs_ = -1; | 2357 available_width_for_tabs_ = -1; |
2363 | 2358 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2493 | 2488 |
2494 if (needs_touch) { | 2489 if (needs_touch) { |
2495 gfx::Size tab_size(Tab::GetMinimumActiveSize()); | 2490 gfx::Size tab_size(Tab::GetMinimumActiveSize()); |
2496 tab_size.set_width(Tab::GetTouchWidth()); | 2491 tab_size.set_width(Tab::GetTouchWidth()); |
2497 touch_layout_.reset(new StackedTabStripLayout( | 2492 touch_layout_.reset(new StackedTabStripLayout( |
2498 tab_size, | 2493 tab_size, |
2499 GetLayoutConstant(TABSTRIP_TAB_OVERLAP), | 2494 GetLayoutConstant(TABSTRIP_TAB_OVERLAP), |
2500 kStackedPadding, | 2495 kStackedPadding, |
2501 kMaxStackedCount, | 2496 kMaxStackedCount, |
2502 &tabs_)); | 2497 &tabs_)); |
2503 touch_layout_->SetWidth(tab_area_width()); | 2498 touch_layout_->SetWidth(GetTabAreaWidth()); |
2504 // This has to be after SetWidth() as SetWidth() is going to reset the | 2499 // This has to be after SetWidth() as SetWidth() is going to reset the |
2505 // bounds of the pinned tabs (since StackedTabStripLayout doesn't yet know | 2500 // bounds of the pinned tabs (since StackedTabStripLayout doesn't yet know |
2506 // how many pinned tabs there are). | 2501 // how many pinned tabs there are). |
2507 GenerateIdealBoundsForPinnedTabs(NULL); | 2502 GenerateIdealBoundsForPinnedTabs(NULL); |
2508 touch_layout_->SetXAndPinnedCount(GetStartXForNormalTabs(), | 2503 touch_layout_->SetXAndPinnedCount(GetStartXForNormalTabs(), |
2509 GetPinnedTabCount()); | 2504 GetPinnedTabCount()); |
2510 touch_layout_->SetActiveIndex(controller_->GetActiveIndex()); | 2505 touch_layout_->SetActiveIndex(controller_->GetActiveIndex()); |
2511 | 2506 |
2512 content::RecordAction(UserMetricsAction("StackedTab_EnteredStackedLayout")); | 2507 content::RecordAction(UserMetricsAction("StackedTab_EnteredStackedLayout")); |
2513 } else { | 2508 } else { |
2514 touch_layout_.reset(); | 2509 touch_layout_.reset(); |
2515 } | 2510 } |
2516 PrepareForAnimation(); | 2511 PrepareForAnimation(); |
2517 GenerateIdealBounds(); | 2512 GenerateIdealBounds(); |
2518 SetTabVisibility(); | 2513 SetTabVisibility(); |
2519 AnimateToIdealBounds(); | 2514 AnimateToIdealBounds(); |
2520 } | 2515 } |
2521 | 2516 |
2522 bool TabStrip::NeedsTouchLayout() const { | 2517 bool TabStrip::NeedsTouchLayout() const { |
2523 if (!stacked_layout_) | 2518 if (!stacked_layout_) |
2524 return false; | 2519 return false; |
2525 | 2520 |
2526 int pinned_tab_count = GetPinnedTabCount(); | 2521 int pinned_tab_count = GetPinnedTabCount(); |
2527 int normal_count = tab_count() - pinned_tab_count; | 2522 int normal_count = tab_count() - pinned_tab_count; |
2528 if (normal_count <= 1 || normal_count == pinned_tab_count) | 2523 if (normal_count <= 1 || normal_count == pinned_tab_count) |
2529 return false; | 2524 return false; |
2530 const int overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP); | 2525 const int overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP); |
2531 return (Tab::GetTouchWidth() * normal_count - overlap * (normal_count - 1)) > | 2526 return (Tab::GetTouchWidth() * normal_count - overlap * (normal_count - 1)) > |
2532 tab_area_width() - GetStartXForNormalTabs(); | 2527 GetTabAreaWidth() - GetStartXForNormalTabs(); |
2533 } | 2528 } |
2534 | 2529 |
2535 void TabStrip::SetResetToShrinkOnExit(bool value) { | 2530 void TabStrip::SetResetToShrinkOnExit(bool value) { |
2536 if (!adjust_layout_) | 2531 if (!adjust_layout_) |
2537 return; | 2532 return; |
2538 | 2533 |
2539 if (value && !stacked_layout_) | 2534 if (value && !stacked_layout_) |
2540 value = false; // We're already using shrink (not stacked) layout. | 2535 value = false; // We're already using shrink (not stacked) layout. |
2541 | 2536 |
2542 if (value == reset_to_shrink_on_exit_) | 2537 if (value == reset_to_shrink_on_exit_) |
2543 return; | 2538 return; |
2544 | 2539 |
2545 reset_to_shrink_on_exit_ = value; | 2540 reset_to_shrink_on_exit_ = value; |
2546 // Add an observer so we know when the mouse moves out of the tabstrip. | 2541 // Add an observer so we know when the mouse moves out of the tabstrip. |
2547 if (reset_to_shrink_on_exit_) | 2542 if (reset_to_shrink_on_exit_) |
2548 AddMessageLoopObserver(); | 2543 AddMessageLoopObserver(); |
2549 else | 2544 else |
2550 RemoveMessageLoopObserver(); | 2545 RemoveMessageLoopObserver(); |
2551 } | 2546 } |
2552 | 2547 |
2553 void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) { | 2548 void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) { |
2554 if (sender == newtab_button_) { | 2549 if (sender == newtab_button_) { |
2555 content::RecordAction(UserMetricsAction("NewTab_Button")); | 2550 content::RecordAction(UserMetricsAction("NewTab_Button")); |
2556 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_BUTTON, | 2551 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_BUTTON, |
2557 TabStripModel::NEW_TAB_ENUM_COUNT); | 2552 TabStripModel::NEW_TAB_ENUM_COUNT); |
2558 if (event.IsMouseEvent()) { | 2553 if (event.IsMouseEvent()) { |
2559 const ui::MouseEvent& mouse = static_cast<const ui::MouseEvent&>(event); | 2554 const ui::MouseEvent& mouse = static_cast<const ui::MouseEvent&>(event); |
2560 if (mouse.IsOnlyMiddleMouseButton()) { | 2555 if (mouse.IsOnlyMiddleMouseButton()) { |
2561 base::string16 clipboard_text = GetClipboardText(); | 2556 if (ui::Clipboard::IsSupportedClipboardType( |
2562 if (!clipboard_text.empty()) | 2557 ui::CLIPBOARD_TYPE_SELECTION)) { |
2563 controller()->CreateNewTabWithLocation(clipboard_text); | 2558 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); |
| 2559 CHECK(clipboard); |
| 2560 base::string16 clipboard_text; |
| 2561 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &clipboard_text); |
| 2562 if (!clipboard_text.empty()) |
| 2563 controller()->CreateNewTabWithLocation(clipboard_text); |
| 2564 } |
2564 return; | 2565 return; |
2565 } | 2566 } |
2566 } | 2567 } |
2567 | 2568 |
2568 controller()->CreateNewTab(); | 2569 controller()->CreateNewTab(); |
2569 if (event.type() == ui::ET_GESTURE_TAP) | 2570 if (event.type() == ui::ET_GESTURE_TAP) |
2570 TouchUMA::RecordGestureAction(TouchUMA::GESTURE_NEWTAB_TAP); | 2571 TouchUMA::RecordGestureAction(TouchUMA::GESTURE_NEWTAB_TAP); |
2571 } | 2572 } |
2572 } | 2573 } |
2573 | 2574 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2691 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); | 2692 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); |
2692 if (view) | 2693 if (view) |
2693 return view; | 2694 return view; |
2694 } | 2695 } |
2695 Tab* tab = FindTabForEvent(point); | 2696 Tab* tab = FindTabForEvent(point); |
2696 if (tab) | 2697 if (tab) |
2697 return ConvertPointToViewAndGetEventHandler(this, tab, point); | 2698 return ConvertPointToViewAndGetEventHandler(this, tab, point); |
2698 } | 2699 } |
2699 return this; | 2700 return this; |
2700 } | 2701 } |
OLD | NEW |