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

Side by Side Diff: chrome/browser/ui/views/tabs/tab_strip.cc

Issue 339923005: Clip tabs in overflow mode. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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/tabs/tab_strip.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/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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 base::string16 GetClipboardText() { 120 base::string16 GetClipboardText() {
121 if (!ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION)) 121 if (!ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION))
122 return base::string16(); 122 return base::string16();
123 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); 123 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
124 CHECK(clipboard); 124 CHECK(clipboard);
125 base::string16 clipboard_text; 125 base::string16 clipboard_text;
126 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &clipboard_text); 126 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &clipboard_text);
127 return clipboard_text; 127 return clipboard_text;
128 } 128 }
129 129
130 // Animation delegate used for any automatic tab movement. Hides the tab if it
131 // is not fully visible within the tabstrip area, to prevent overflow clipping.
132 class TabAnimationDelegate : public gfx::AnimationDelegate {
133 public:
134 TabAnimationDelegate(TabStrip* tab_strip, Tab* tab);
135 virtual ~TabAnimationDelegate();
136
137 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
138
139 protected:
140 TabStrip* tab_strip() { return tab_strip_; }
141 Tab* tab() { return tab_; }
142
143 private:
144 TabStrip* const tab_strip_;
145 Tab* const tab_;
146
147 DISALLOW_COPY_AND_ASSIGN(TabAnimationDelegate);
148 };
149
150 TabAnimationDelegate::TabAnimationDelegate(TabStrip* tab_strip, Tab* tab)
151 : tab_strip_(tab_strip),
152 tab_(tab) {
153 }
154
155 TabAnimationDelegate::~TabAnimationDelegate() {
156 }
157
158 void TabAnimationDelegate::AnimationProgressed(
159 const gfx::Animation* animation) {
160 tab_->SetVisible(tab_strip_->ShouldTabBeVisible(tab_));
161 }
162
130 // Animation delegate used when a dragged tab is released. When done sets the 163 // Animation delegate used when a dragged tab is released. When done sets the
131 // dragging state to false. 164 // dragging state to false.
132 class ResetDraggingStateDelegate : public gfx::AnimationDelegate { 165 class ResetDraggingStateDelegate : public TabAnimationDelegate {
133 public: 166 public:
134 explicit ResetDraggingStateDelegate(Tab* tab); 167 ResetDraggingStateDelegate(TabStrip* tab_strip, Tab* tab);
135 virtual ~ResetDraggingStateDelegate(); 168 virtual ~ResetDraggingStateDelegate();
136 169
137 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; 170 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
138 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; 171 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
139 172
140 private: 173 private:
141 Tab* tab_;
142
143 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); 174 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate);
144 }; 175 };
145 176
146 ResetDraggingStateDelegate::ResetDraggingStateDelegate(Tab* tab) : tab_(tab) { 177 ResetDraggingStateDelegate::ResetDraggingStateDelegate(TabStrip* tab_strip,
178 Tab* tab)
179 : TabAnimationDelegate(tab_strip, tab) {
147 } 180 }
148 181
149 ResetDraggingStateDelegate::~ResetDraggingStateDelegate() { 182 ResetDraggingStateDelegate::~ResetDraggingStateDelegate() {
150 } 183 }
151 184
152 void ResetDraggingStateDelegate::AnimationEnded( 185 void ResetDraggingStateDelegate::AnimationEnded(
153 const gfx::Animation* animation) { 186 const gfx::Animation* animation) {
154 tab_->set_dragging(false); 187 tab()->set_dragging(false);
188 AnimationProgressed(animation); // Forces tab visibility to update.
155 } 189 }
156 190
157 void ResetDraggingStateDelegate::AnimationCanceled( 191 void ResetDraggingStateDelegate::AnimationCanceled(
158 const gfx::Animation* animation) { 192 const gfx::Animation* animation) {
159 AnimationEnded(animation); 193 AnimationEnded(animation);
160 } 194 }
161 195
162 // If |dest| contains the point |point_in_source| the event handler from |dest| 196 // If |dest| contains the point |point_in_source| the event handler from |dest|
163 // is returned. Otherwise NULL is returned. 197 // is returned. Otherwise NULL is returned.
164 views::View* ConvertPointToViewAndGetEventHandler( 198 views::View* ConvertPointToViewAndGetEventHandler(
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 } 483 }
450 484
451 DISALLOW_COPY_AND_ASSIGN(NewTabButtonTargeter); 485 DISALLOW_COPY_AND_ASSIGN(NewTabButtonTargeter);
452 }; 486 };
453 487
454 /////////////////////////////////////////////////////////////////////////////// 488 ///////////////////////////////////////////////////////////////////////////////
455 // TabStrip::RemoveTabDelegate 489 // TabStrip::RemoveTabDelegate
456 // 490 //
457 // AnimationDelegate used when removing a tab. Does the necessary cleanup when 491 // AnimationDelegate used when removing a tab. Does the necessary cleanup when
458 // done. 492 // done.
459 class TabStrip::RemoveTabDelegate : public gfx::AnimationDelegate { 493 class TabStrip::RemoveTabDelegate : public TabAnimationDelegate {
460 public: 494 public:
461 RemoveTabDelegate(TabStrip* tab_strip, Tab* tab); 495 RemoveTabDelegate(TabStrip* tab_strip, Tab* tab);
462 496
463 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; 497 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
464 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; 498 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
465 499
466 private: 500 private:
467 void CompleteRemove();
468
469 // When the animation completes, we send the Container a message to simulate
470 // a mouse moved event at the current mouse position. This tickles the Tab
471 // the mouse is currently over to show the "hot" state of the close button.
472 void HighlightCloseButton();
473
474 TabStrip* tabstrip_;
475 Tab* tab_;
476
477 DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate); 501 DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate);
478 }; 502 };
479 503
480 TabStrip::RemoveTabDelegate::RemoveTabDelegate(TabStrip* tab_strip, 504 TabStrip::RemoveTabDelegate::RemoveTabDelegate(TabStrip* tab_strip,
481 Tab* tab) 505 Tab* tab)
482 : tabstrip_(tab_strip), 506 : TabAnimationDelegate(tab_strip, tab) {
483 tab_(tab) {
484 } 507 }
485 508
486 void TabStrip::RemoveTabDelegate::AnimationEnded( 509 void TabStrip::RemoveTabDelegate::AnimationEnded(
487 const gfx::Animation* animation) { 510 const gfx::Animation* animation) {
488 CompleteRemove(); 511 DCHECK(tab()->closing());
512 tab_strip()->RemoveAndDeleteTab(tab());
513
514 // Send the Container a message to simulate a mouse moved event at the current
515 // mouse position. This tickles the Tab the mouse is currently over to show
516 // the "hot" state of the close button. Note that this is not required (and
517 // indeed may crash!) for removes spawned by non-mouse closes and
518 // drag-detaches.
519 if (!tab_strip()->IsDragSessionActive() &&
520 tab_strip()->ShouldHighlightCloseButtonAfterRemove()) {
521 // The widget can apparently be null during shutdown.
522 views::Widget* widget = tab_strip()->GetWidget();
523 if (widget)
524 widget->SynthesizeMouseMoveEvent();
525 }
489 } 526 }
490 527
491 void TabStrip::RemoveTabDelegate::AnimationCanceled( 528 void TabStrip::RemoveTabDelegate::AnimationCanceled(
492 const gfx::Animation* animation) { 529 const gfx::Animation* animation) {
493 AnimationEnded(animation); 530 AnimationEnded(animation);
494 } 531 }
495 532
496 void TabStrip::RemoveTabDelegate::CompleteRemove() {
497 DCHECK(tab_->closing());
498 tabstrip_->RemoveAndDeleteTab(tab_);
499 HighlightCloseButton();
500 }
501
502 void TabStrip::RemoveTabDelegate::HighlightCloseButton() {
503 if (tabstrip_->IsDragSessionActive() ||
504 !tabstrip_->ShouldHighlightCloseButtonAfterRemove()) {
505 // This function is not required (and indeed may crash!) for removes
506 // spawned by non-mouse closes and drag-detaches.
507 return;
508 }
509
510 views::Widget* widget = tabstrip_->GetWidget();
511 // This can be null during shutdown. See http://crbug.com/42737.
512 if (!widget)
513 return;
514
515 widget->SynthesizeMouseMoveEvent();
516 }
517
518 /////////////////////////////////////////////////////////////////////////////// 533 ///////////////////////////////////////////////////////////////////////////////
519 // TabStrip, public: 534 // TabStrip, public:
520 535
521 // static 536 // static
522 const char TabStrip::kViewClassName[] = "TabStrip"; 537 const char TabStrip::kViewClassName[] = "TabStrip";
523 const int TabStrip::kNewTabButtonHorizontalOffset = -11; 538 const int TabStrip::kNewTabButtonHorizontalOffset = -11;
524 const int TabStrip::kNewTabButtonVerticalOffset = 7; 539 const int TabStrip::kNewTabButtonVerticalOffset = 7;
525 const int TabStrip::kMiniToNonMiniGap = 3; 540 const int TabStrip::kMiniToNonMiniGap = 3;
526 const int TabStrip::kNewTabButtonAssetWidth = 34; 541 const int TabStrip::kNewTabButtonAssetWidth = 34;
527 const int TabStrip::kNewTabButtonAssetHeight = 18; 542 const int TabStrip::kNewTabButtonAssetHeight = 18;
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 touch_layout_->SetXAndMiniCount(start_x, mini_tab_count); 728 touch_layout_->SetXAndMiniCount(start_x, mini_tab_count);
714 } 729 }
715 if (GetWidget() && GetWidget()->IsVisible()) 730 if (GetWidget() && GetWidget()->IsVisible())
716 StartMiniTabAnimation(); 731 StartMiniTabAnimation();
717 else 732 else
718 DoLayout(); 733 DoLayout();
719 } 734 }
720 SwapLayoutIfNecessary(); 735 SwapLayoutIfNecessary();
721 } 736 }
722 737
738 bool TabStrip::ShouldTabBeVisible(const Tab* tab) const {
739 // When stacking tabs, all tabs should always be visible.
740 if (stacked_layout_)
sky 2014/06/17 19:41:17 touch_layout_ is more correct here.
Peter Kasting 2014/06/17 20:20:20 Why? If stacked_layout_ is true, then either we'r
sky 2014/06/17 23:53:13 No, you're right.
741 return true;
742
743 // If the tab is currently clipped, it shouldn't be visible. Note that we
744 // allow dragged tabs to draw over the "New Tab button" region as well,
745 // because either the New Tab button will be hidden, or the dragged tabs will
746 // be animating back to their normal positions and we don't want to hide them
747 // in the New Tab button region in case they re-appear after leaving it.
748 // (This prevents flickeriness.) We never draw non-dragged tabs in New Tab
749 // button area, even when the button is invisible, so that they don't appear
750 // to "pop in" when the button disappears.
751 // TODO: Probably doesn't work for RTL
752 int right_edge = tab->bounds().right();
753 const int visible_width = tab->dragging() ? width() : tab_area_width();
754 if (right_edge > visible_width)
755 return false;
756
757 // Non-clipped dragging tabs should always be visible.
758 if (tab->dragging())
759 return true;
760
761 // Let all non-clipped closing tabs be visible. These will probably finish
762 // closing before the user changes the active tab, so there's little reason to
763 // try and make the more complex logic below apply.
764 if (tab->closing())
765 return true;
766
767 // Now we need to check whether the tab isn't currently clipped, but could
768 // become clipped if we changed the active tab, widening either this tab or
769 // the tabstrip portion before it.
770
771 // Mini tabs don't change size when activated, so any tab in the mini tab
772 // region is safe.
773 const int tab_index = GetModelIndexOfTab(tab);
774 if (tab_index <= GetMiniTabCount())
sky 2014/06/17 19:41:18 I would check tab->data().mini here. The condition
Peter Kasting 2014/06/17 20:20:20 Done.
775 return true;
776
777 // If the active tab is on or before this tab, we're safe.
778 if (controller_->GetActiveIndex() <= tab_index)
779 return true;
780
781 // We need to check what would happen if the active tab were to move to this
782 // tab or before.
783 return (right_edge + current_selected_width_ - current_unselected_width_) <=
784 tab_area_width();
785 }
786
723 void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) { 787 void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) {
724 if (!in_tab_close_ && IsAnimating()) { 788 if (!in_tab_close_ && IsAnimating()) {
725 // Cancel any current animations. We do this as remove uses the current 789 // Cancel any current animations. We do this as remove uses the current
726 // ideal bounds and we need to know ideal bounds is in a good state. 790 // ideal bounds and we need to know ideal bounds is in a good state.
727 StopAnimating(true); 791 StopAnimating(true);
728 } 792 }
729 793
730 if (!GetWidget()) 794 if (!GetWidget())
731 return; 795 return;
732 796
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
1485 // strip. 1549 // strip.
1486 if (TabDragController::IsAttachedTo(this)) { 1550 if (TabDragController::IsAttachedTo(this)) {
1487 bounds_animator_.StopAnimatingView(newtab_button_); 1551 bounds_animator_.StopAnimatingView(newtab_button_);
1488 newtab_button_->SetBoundsRect(newtab_button_bounds_); 1552 newtab_button_->SetBoundsRect(newtab_button_bounds_);
1489 } 1553 }
1490 } 1554 }
1491 1555
1492 void TabStrip::AnimateToIdealBounds() { 1556 void TabStrip::AnimateToIdealBounds() {
1493 for (int i = 0; i < tab_count(); ++i) { 1557 for (int i = 0; i < tab_count(); ++i) {
1494 Tab* tab = tab_at(i); 1558 Tab* tab = tab_at(i);
1495 if (!tab->dragging()) 1559 if (!tab->dragging()) {
1496 bounds_animator_.AnimateViewTo(tab, ideal_bounds(i)); 1560 bounds_animator_.AnimateViewTo(tab, ideal_bounds(i));
1561 bounds_animator_.SetAnimationDelegate(
1562 tab, make_scoped_ptr(new TabAnimationDelegate(this, tab)));
1563 }
1497 } 1564 }
1498 1565
1499 bounds_animator_.AnimateViewTo(newtab_button_, newtab_button_bounds_); 1566 bounds_animator_.AnimateViewTo(newtab_button_, newtab_button_bounds_);
1500 } 1567 }
1501 1568
1502 bool TabStrip::ShouldHighlightCloseButtonAfterRemove() { 1569 bool TabStrip::ShouldHighlightCloseButtonAfterRemove() {
1503 return in_tab_close_; 1570 return in_tab_close_;
1504 } 1571 }
1505 1572
1506 void TabStrip::DoLayout() { 1573 void TabStrip::DoLayout() {
1507 last_layout_size_ = size(); 1574 last_layout_size_ = size();
1508 1575
1509 StopAnimating(false); 1576 StopAnimating(false);
1510 1577
1511 SwapLayoutIfNecessary(); 1578 SwapLayoutIfNecessary();
1512 1579
1513 if (touch_layout_) 1580 if (touch_layout_)
1514 touch_layout_->SetWidth(tab_area_width()); 1581 touch_layout_->SetWidth(tab_area_width());
1515 1582
1516 GenerateIdealBounds(); 1583 GenerateIdealBounds();
1517 1584
1518 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); 1585 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_);
1586 SetTabVisibility();
1519 1587
1520 SchedulePaint(); 1588 SchedulePaint();
1521 1589
1522 bounds_animator_.StopAnimatingView(newtab_button_); 1590 bounds_animator_.StopAnimatingView(newtab_button_);
1523 newtab_button_->SetBoundsRect(newtab_button_bounds_); 1591 newtab_button_->SetBoundsRect(newtab_button_bounds_);
1524 } 1592 }
1525 1593
1594 void TabStrip::SetTabVisibility() {
sky 2014/06/17 19:41:17 Can you still hit the crash you sent to me with yo
Peter Kasting 2014/06/17 20:20:20 I removed the DCHECK in ShouldTabBeVisible() that
1595 // We could probably be more efficient here by making use of the fact that the
1596 // tabstrip will always have any visible tabs, and then any invisible tabs, so
1597 // we could e.g. binary-search for the changeover point. But since we have to
1598 // iterate through all the tabs to call SetVisible() anyway, it doesn't seem
1599 // worth it.
1600 for (int i = 0; i < tab_count(); ++i) {
1601 Tab* tab = tab_at(i);
1602 tab->SetVisible(ShouldTabBeVisible(tab));
1603 }
1604 for (TabsClosingMap::const_iterator i(tabs_closing_map_.begin());
1605 i != tabs_closing_map_.end(); ++i) {
1606 for (Tabs::const_iterator j(i->second.begin()); j != i->second.end(); ++j) {
1607 Tab* tab = *j;
1608 tab->SetVisible(ShouldTabBeVisible(tab));
1609 }
1610 }
1611 }
1612
1526 void TabStrip::DragActiveTab(const std::vector<int>& initial_positions, 1613 void TabStrip::DragActiveTab(const std::vector<int>& initial_positions,
1527 int delta) { 1614 int delta) {
1528 DCHECK_EQ(tab_count(), static_cast<int>(initial_positions.size())); 1615 DCHECK_EQ(tab_count(), static_cast<int>(initial_positions.size()));
1529 if (!touch_layout_) { 1616 if (!touch_layout_) {
1530 StackDraggedTabs(delta); 1617 StackDraggedTabs(delta);
1531 return; 1618 return;
1532 } 1619 }
1533 SetIdealBoundsFromPositions(initial_positions); 1620 SetIdealBoundsFromPositions(initial_positions);
1534 touch_layout_->DragActiveTab(delta); 1621 touch_layout_->DragActiveTab(delta);
1535 DoLayout(); 1622 DoLayout();
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 // consecutive animate the view into position. Do the same if the tab is 1733 // consecutive animate the view into position. Do the same if the tab is
1647 // already animating (which means we previously caused it to animate). 1734 // already animating (which means we previously caused it to animate).
1648 if ((initial_drag && 1735 if ((initial_drag &&
1649 GetModelIndexOfTab(tabs[i]) != consecutive_index) || 1736 GetModelIndexOfTab(tabs[i]) != consecutive_index) ||
1650 bounds_animator_.IsAnimating(tabs[i])) { 1737 bounds_animator_.IsAnimating(tabs[i])) {
1651 bounds_animator_.SetTargetBounds(tabs[i], new_bounds); 1738 bounds_animator_.SetTargetBounds(tabs[i], new_bounds);
1652 } else { 1739 } else {
1653 tab->SetBoundsRect(new_bounds); 1740 tab->SetBoundsRect(new_bounds);
1654 } 1741 }
1655 } 1742 }
1743 SetTabVisibility();
1656 } 1744 }
1657 1745
1658 void TabStrip::CalculateBoundsForDraggedTabs(const Tabs& tabs, 1746 void TabStrip::CalculateBoundsForDraggedTabs(const Tabs& tabs,
1659 std::vector<gfx::Rect>* bounds) { 1747 std::vector<gfx::Rect>* bounds) {
1660 int x = 0; 1748 int x = 0;
1661 for (size_t i = 0; i < tabs.size(); ++i) { 1749 for (size_t i = 0; i < tabs.size(); ++i) {
1662 Tab* tab = tabs[i]; 1750 Tab* tab = tabs[i];
1663 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) 1751 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini)
1664 x += kMiniToNonMiniGap; 1752 x += kMiniToNonMiniGap;
1665 gfx::Rect new_bounds = tab->bounds(); 1753 gfx::Rect new_bounds = tab->bounds();
(...skipping 17 matching lines...) Expand all
1683 } 1771 }
1684 1772
1685 int TabStrip::GetMiniTabCount() const { 1773 int TabStrip::GetMiniTabCount() const {
1686 int mini_count = 0; 1774 int mini_count = 0;
1687 while (mini_count < tab_count() && tab_at(mini_count)->data().mini) 1775 while (mini_count < tab_count() && tab_at(mini_count)->data().mini)
1688 mini_count++; 1776 mini_count++;
1689 return mini_count; 1777 return mini_count;
1690 } 1778 }
1691 1779
1692 const Tab* TabStrip::GetLastVisibleTab() const { 1780 const Tab* TabStrip::GetLastVisibleTab() const {
1693 return tab_at(tab_count() - 1); 1781 for (int i = tab_count() - 1; i >= 0; --i) {
1782 const Tab* tab = tab_at(i);
1783 if (tab->visible())
1784 return tab;
1785 }
1786 NOTREACHED();
1787 return NULL;
1694 } 1788 }
1695 1789
1696 void TabStrip::RemoveTabFromViewModel(int index) { 1790 void TabStrip::RemoveTabFromViewModel(int index) {
1697 // We still need to paint the tab until we actually remove it. Put it 1791 // We still need to paint the tab until we actually remove it. Put it
1698 // in tabs_closing_map_ so we can find it. 1792 // in tabs_closing_map_ so we can find it.
1699 tabs_closing_map_[index].push_back(tab_at(index)); 1793 tabs_closing_map_[index].push_back(tab_at(index));
1700 UpdateTabsClosingMap(index + 1, -1); 1794 UpdateTabsClosingMap(index + 1, -1);
1701 tabs_.Remove(index); 1795 tabs_.Remove(index);
1702 } 1796 }
1703 1797
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1754 1848
1755 // Move the dragged tabs to their ideal bounds. 1849 // Move the dragged tabs to their ideal bounds.
1756 GenerateIdealBounds(); 1850 GenerateIdealBounds();
1757 1851
1758 // Sets the bounds of the dragged tabs. 1852 // Sets the bounds of the dragged tabs.
1759 for (size_t i = 0; i < tabs.size(); ++i) { 1853 for (size_t i = 0; i < tabs.size(); ++i) {
1760 int tab_data_index = GetModelIndexOfTab(tabs[i]); 1854 int tab_data_index = GetModelIndexOfTab(tabs[i]);
1761 DCHECK_NE(-1, tab_data_index); 1855 DCHECK_NE(-1, tab_data_index);
1762 tabs[i]->SetBoundsRect(ideal_bounds(tab_data_index)); 1856 tabs[i]->SetBoundsRect(ideal_bounds(tab_data_index));
1763 } 1857 }
1858 SetTabVisibility();
1764 SchedulePaint(); 1859 SchedulePaint();
1765 } 1860 }
1766 1861
1767 void TabStrip::DraggedTabsDetached() { 1862 void TabStrip::DraggedTabsDetached() {
1768 // Let the controller know that the user is not dragging this tabstrip's tabs 1863 // Let the controller know that the user is not dragging this tabstrip's tabs
1769 // anymore. 1864 // anymore.
1770 controller()->OnStoppedDraggingTabs(); 1865 controller()->OnStoppedDraggingTabs();
1771 newtab_button_->SetVisible(true); 1866 newtab_button_->SetVisible(true);
1772 } 1867 }
1773 1868
(...skipping 29 matching lines...) Expand all
1803 1898
1804 // Animate the view back to its correct position. 1899 // Animate the view back to its correct position.
1805 GenerateIdealBounds(); 1900 GenerateIdealBounds();
1806 AnimateToIdealBounds(); 1901 AnimateToIdealBounds();
1807 } 1902 }
1808 bounds_animator_.AnimateViewTo(tab, ideal_bounds(tab_data_index)); 1903 bounds_animator_.AnimateViewTo(tab, ideal_bounds(tab_data_index));
1809 // Install a delegate to reset the dragging state when done. We have to leave 1904 // Install a delegate to reset the dragging state when done. We have to leave
1810 // dragging true for the tab otherwise it'll draw beneath the new tab button. 1905 // dragging true for the tab otherwise it'll draw beneath the new tab button.
1811 bounds_animator_.SetAnimationDelegate( 1906 bounds_animator_.SetAnimationDelegate(
1812 tab, 1907 tab,
1813 scoped_ptr<gfx::AnimationDelegate>(new ResetDraggingStateDelegate(tab))); 1908 scoped_ptr<gfx::AnimationDelegate>(
1909 new ResetDraggingStateDelegate(this, tab)));
1814 } 1910 }
1815 1911
1816 void TabStrip::OwnDragController(TabDragController* controller) { 1912 void TabStrip::OwnDragController(TabDragController* controller) {
1817 // Typically, ReleaseDragController() and OwnDragController() calls are paired 1913 // Typically, ReleaseDragController() and OwnDragController() calls are paired
1818 // via corresponding calls to TabDragController::Detach() and 1914 // via corresponding calls to TabDragController::Detach() and
1819 // TabDragController::Attach(). There is one exception to that rule: when a 1915 // TabDragController::Attach(). There is one exception to that rule: when a
1820 // drag might start, we create a TabDragController that is owned by the 1916 // drag might start, we create a TabDragController that is owned by the
1821 // potential source tabstrip in MaybeStartDrag(). If a drag actually starts, 1917 // potential source tabstrip in MaybeStartDrag(). If a drag actually starts,
1822 // we then call Attach() on the source tabstrip, but since the source tabstrip 1918 // we then call Attach() on the source tabstrip, but since the source tabstrip
1823 // already owns the TabDragController, so we don't need to do anything. 1919 // already owns the TabDragController, so we don't need to do anything.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1951 2047
1952 *unselected_width = min_unselected_width; 2048 *unselected_width = min_unselected_width;
1953 *selected_width = min_selected_width; 2049 *selected_width = min_selected_width;
1954 2050
1955 if (tab_count == 0) { 2051 if (tab_count == 0) {
1956 // Return immediately to avoid divide-by-zero below. 2052 // Return immediately to avoid divide-by-zero below.
1957 return; 2053 return;
1958 } 2054 }
1959 2055
1960 // Determine how much space we can actually allocate to tabs. 2056 // Determine how much space we can actually allocate to tabs.
1961 int available_width; 2057 int available_width = (available_width_for_tabs_ < 0) ?
1962 if (available_width_for_tabs_ < 0) { 2058 tab_area_width() : available_width_for_tabs_;
1963 available_width = width() - new_tab_button_width();
1964 } else {
1965 // Interesting corner case: if |available_width_for_tabs_| > the result
1966 // of the calculation in the conditional arm above, the strip is in
1967 // overflow. We can either use the specified width or the true available
1968 // width here; the first preserves the consistent "leave the last tab under
1969 // the user's mouse so they can close many tabs" behavior at the cost of
1970 // prolonging the glitchy appearance of the overflow state, while the second
1971 // gets us out of overflow as soon as possible but forces the user to move
1972 // their mouse for a few tabs' worth of closing. We choose visual
1973 // imperfection over behavioral imperfection and select the first option.
1974 available_width = available_width_for_tabs_;
1975 }
1976
1977 if (mini_tab_count > 0) { 2059 if (mini_tab_count > 0) {
1978 available_width -= 2060 available_width -=
1979 mini_tab_count * (Tab::GetMiniWidth() + kTabHorizontalOffset); 2061 mini_tab_count * (Tab::GetMiniWidth() + kTabHorizontalOffset);
1980 tab_count -= mini_tab_count; 2062 tab_count -= mini_tab_count;
1981 if (tab_count == 0) { 2063 if (tab_count == 0) {
1982 *selected_width = *unselected_width = Tab::GetStandardSize().width(); 2064 *selected_width = *unselected_width = Tab::GetStandardSize().width();
1983 return; 2065 return;
1984 } 2066 }
1985 // Account for gap between the last mini-tab and first non-mini-tab. 2067 // Account for gap between the last mini-tab and first non-mini-tab.
1986 available_width -= kMiniToNonMiniGap; 2068 available_width -= kMiniToNonMiniGap;
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
2453 // many mini-tabs there are). 2535 // many mini-tabs there are).
2454 GenerateIdealBoundsForMiniTabs(NULL); 2536 GenerateIdealBoundsForMiniTabs(NULL);
2455 touch_layout_->SetXAndMiniCount(GetStartXForNormalTabs(), 2537 touch_layout_->SetXAndMiniCount(GetStartXForNormalTabs(),
2456 GetMiniTabCount()); 2538 GetMiniTabCount());
2457 touch_layout_->SetActiveIndex(controller_->GetActiveIndex()); 2539 touch_layout_->SetActiveIndex(controller_->GetActiveIndex());
2458 } else { 2540 } else {
2459 touch_layout_.reset(); 2541 touch_layout_.reset();
2460 } 2542 }
2461 PrepareForAnimation(); 2543 PrepareForAnimation();
2462 GenerateIdealBounds(); 2544 GenerateIdealBounds();
2545 SetTabVisibility();
2463 AnimateToIdealBounds(); 2546 AnimateToIdealBounds();
2464 } 2547 }
2465 2548
2466 bool TabStrip::NeedsTouchLayout() const { 2549 bool TabStrip::NeedsTouchLayout() const {
2467 if (!stacked_layout_) 2550 if (!stacked_layout_)
2468 return false; 2551 return false;
2469 2552
2470 int mini_tab_count = GetMiniTabCount(); 2553 int mini_tab_count = GetMiniTabCount();
2471 int normal_count = tab_count() - mini_tab_count; 2554 int normal_count = tab_count() - mini_tab_count;
2472 if (normal_count <= 1 || normal_count == mini_tab_count) 2555 if (normal_count <= 1 || normal_count == mini_tab_count)
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 action = TouchUMA::GESTURE_TABSWITCH_TAP; 2688 action = TouchUMA::GESTURE_TABSWITCH_TAP;
2606 TouchUMA::RecordGestureAction(action); 2689 TouchUMA::RecordGestureAction(action);
2607 break; 2690 break;
2608 } 2691 }
2609 2692
2610 default: 2693 default:
2611 break; 2694 break;
2612 } 2695 }
2613 event->SetHandled(); 2696 event->SetHandled();
2614 } 2697 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/tab_strip.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698