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

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

Issue 331343002: Misc. cleanup: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove parens 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 99
100 // See UpdateLayoutTypeFromMouseEvent() for a description of these. 100 // See UpdateLayoutTypeFromMouseEvent() for a description of these.
101 #if !defined(USE_ASH) 101 #if !defined(USE_ASH)
102 const int kMouseMoveTimeMS = 200; 102 const int kMouseMoveTimeMS = 200;
103 const int kMouseMoveCountBeforeConsiderReal = 3; 103 const int kMouseMoveCountBeforeConsiderReal = 3;
104 #endif 104 #endif
105 105
106 // Amount of time we delay before resizing after a close from a touch. 106 // Amount of time we delay before resizing after a close from a touch.
107 const int kTouchResizeLayoutTimeMS = 2000; 107 const int kTouchResizeLayoutTimeMS = 2000;
108 108
109 // Horizontal offset for the new tab button to bring it closer to the
110 // rightmost tab.
111 const int kNewTabButtonHorizontalOffset = -11;
112
113 // Vertical offset for the new tab button to bring it closer to the
114 // rightmost tab.
115 const int kNewTabButtonVerticalOffset = 7;
116
117 // Amount the left edge of a tab is offset from the rectangle of the tab's 109 // Amount the left edge of a tab is offset from the rectangle of the tab's
118 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. 110 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT.
119 // Affects the size of the "V" between adjacent tabs. 111 // Affects the size of the "V" between adjacent tabs.
120 const int kTabHorizontalOffset = -26; 112 const int kTabHorizontalOffset = -26;
121 113
122 // The size of the new tab button must be hardcoded because we need to be
123 // able to lay it out before we are able to get its image from the
124 // ui::ThemeProvider. It also makes sense to do this, because the size of the
125 // new tab button should not need to be calculated dynamically.
126 const int kNewTabButtonAssetWidth = 34;
127 const int kNewTabButtonAssetHeight = 18;
128
129 // Amount to adjust the clip by when the tab is stacked before the active index. 114 // Amount to adjust the clip by when the tab is stacked before the active index.
130 const int kStackedTabLeftClip = 20; 115 const int kStackedTabLeftClip = 20;
131 116
132 // Amount to adjust the clip by when the tab is stacked after the active index. 117 // Amount to adjust the clip by when the tab is stacked after the active index.
133 const int kStackedTabRightClip = 20; 118 const int kStackedTabRightClip = 20;
134 119
135 base::string16 GetClipboardText() { 120 base::string16 GetClipboardText() {
136 if (!ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION)) 121 if (!ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION))
137 return base::string16(); 122 return base::string16();
138 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); 123 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
139 CHECK(clipboard); 124 CHECK(clipboard);
140 base::string16 clipboard_text; 125 base::string16 clipboard_text;
141 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &clipboard_text); 126 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &clipboard_text);
142 return clipboard_text; 127 return clipboard_text;
143 } 128 }
144 129
145 // Animation delegate used when a dragged tab is released. When done sets the 130 // Animation delegate used when a dragged tab is released. When done sets the
146 // dragging state to false. 131 // dragging state to false.
147 class ResetDraggingStateDelegate 132 class ResetDraggingStateDelegate
148 : public views::BoundsAnimator::OwnedAnimationDelegate { 133 : public views::BoundsAnimator::OwnedAnimationDelegate {
149 public: 134 public:
150 explicit ResetDraggingStateDelegate(Tab* tab) : tab_(tab) { 135 explicit ResetDraggingStateDelegate(Tab* tab);
151 } 136 virtual ~ResetDraggingStateDelegate();
152 137
153 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE { 138 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
154 tab_->set_dragging(false); 139 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
155 }
156
157 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE {
158 tab_->set_dragging(false);
159 }
160 140
161 private: 141 private:
162 Tab* tab_; 142 Tab* tab_;
163 143
164 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); 144 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate);
165 }; 145 };
166 146
147 ResetDraggingStateDelegate::ResetDraggingStateDelegate(Tab* tab) : tab_(tab) {
148 }
149
150 ResetDraggingStateDelegate::~ResetDraggingStateDelegate() {
151 }
152
153 void ResetDraggingStateDelegate::AnimationEnded(
154 const gfx::Animation* animation) {
155 tab_->set_dragging(false);
156 }
157
158 void ResetDraggingStateDelegate::AnimationCanceled(
159 const gfx::Animation* animation) {
160 AnimationEnded(animation);
161 }
162
167 // If |dest| contains the point |point_in_source| the event handler from |dest| 163 // If |dest| contains the point |point_in_source| the event handler from |dest|
168 // is returned. Otherwise NULL is returned. 164 // is returned. Otherwise NULL is returned.
169 views::View* ConvertPointToViewAndGetEventHandler( 165 views::View* ConvertPointToViewAndGetEventHandler(
170 views::View* source, 166 views::View* source,
171 views::View* dest, 167 views::View* dest,
172 const gfx::Point& point_in_source) { 168 const gfx::Point& point_in_source) {
173 gfx::Point dest_point(point_in_source); 169 gfx::Point dest_point(point_in_source);
174 views::View::ConvertPointToTarget(source, dest, &dest_point); 170 views::View::ConvertPointToTarget(source, dest, &dest_point);
175 return dest->HitTestPoint(dest_point) ? 171 return dest->HitTestPoint(dest_point) ?
176 dest->GetEventHandlerForPoint(dest_point) : NULL; 172 dest->GetEventHandlerForPoint(dest_point) : NULL;
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 // The new tab background is mirrored in RTL mode, but the theme background 355 // The new tab background is mirrored in RTL mode, but the theme background
360 // should never be mirrored. Mirror it here to compensate. 356 // should never be mirrored. Mirror it here to compensate.
361 float x_scale = 1.0f; 357 float x_scale = 1.0f;
362 int x = GetMirroredX() + background_offset_.x(); 358 int x = GetMirroredX() + background_offset_.x();
363 if (base::i18n::IsRTL()) { 359 if (base::i18n::IsRTL()) {
364 x_scale = -1.0f; 360 x_scale = -1.0f;
365 // Offset by |width| such that the same region is painted as if there was no 361 // Offset by |width| such that the same region is painted as if there was no
366 // flip. 362 // flip.
367 x += width; 363 x += width;
368 } 364 }
369 canvas.TileImageInt(*background, x, kNewTabButtonVerticalOffset + offset_y, 365 canvas.TileImageInt(*background, x,
366 TabStrip::kNewTabButtonVerticalOffset + offset_y,
370 x_scale, 1.0f, 0, 0, width, height); 367 x_scale, 1.0f, 0, 0, width, height);
371 368
372 if (alpha != 255) { 369 if (alpha != 255) {
373 SkPaint paint; 370 SkPaint paint;
374 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); 371 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255));
375 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); 372 paint.setXfermodeMode(SkXfermode::kDstIn_Mode);
376 paint.setStyle(SkPaint::kFill_Style); 373 paint.setStyle(SkPaint::kFill_Style);
377 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); 374 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint);
378 } 375 }
379 376
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 virtual ~NewTabButtonTargeter() {} 423 virtual ~NewTabButtonTargeter() {}
427 424
428 private: 425 private:
429 // views::MaskedViewTargeter: 426 // views::MaskedViewTargeter:
430 virtual bool GetHitTestMask(const views::View* view, 427 virtual bool GetHitTestMask(const views::View* view,
431 gfx::Path* mask) const OVERRIDE { 428 gfx::Path* mask) const OVERRIDE {
432 DCHECK(mask); 429 DCHECK(mask);
433 DCHECK_EQ(view, masked_view()); 430 DCHECK_EQ(view, masked_view());
434 431
435 SkScalar w = SkIntToScalar(view->width()); 432 SkScalar w = SkIntToScalar(view->width());
436 SkScalar v_offset = SkIntToScalar(kNewTabButtonVerticalOffset); 433 SkScalar v_offset = SkIntToScalar(TabStrip::kNewTabButtonVerticalOffset);
437 434
438 // These values are defined by the shape of the new tab image. Should that 435 // These values are defined by the shape of the new tab image. Should that
439 // image ever change, these values will need to be updated. They're so 436 // image ever change, these values will need to be updated. They're so
440 // custom it's not really worth defining constants for. 437 // custom it's not really worth defining constants for.
441 // These values are correct for regular and USE_ASH versions of the image. 438 // These values are correct for regular and USE_ASH versions of the image.
442 mask->moveTo(0, v_offset + 1); 439 mask->moveTo(0, v_offset + 1);
443 mask->lineTo(w - 7, v_offset + 1); 440 mask->lineTo(w - 7, v_offset + 1);
444 mask->lineTo(w - 4, v_offset + 4); 441 mask->lineTo(w - 4, v_offset + 4);
445 mask->lineTo(w, v_offset + 16); 442 mask->lineTo(w, v_offset + 16);
446 mask->lineTo(w - 1, v_offset + 17); 443 mask->lineTo(w - 1, v_offset + 17);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 tab_(tab) { 485 tab_(tab) {
489 } 486 }
490 487
491 void TabStrip::RemoveTabDelegate::AnimationEnded( 488 void TabStrip::RemoveTabDelegate::AnimationEnded(
492 const gfx::Animation* animation) { 489 const gfx::Animation* animation) {
493 CompleteRemove(); 490 CompleteRemove();
494 } 491 }
495 492
496 void TabStrip::RemoveTabDelegate::AnimationCanceled( 493 void TabStrip::RemoveTabDelegate::AnimationCanceled(
497 const gfx::Animation* animation) { 494 const gfx::Animation* animation) {
498 CompleteRemove(); 495 AnimationEnded(animation);
499 } 496 }
500 497
501 void TabStrip::RemoveTabDelegate::CompleteRemove() { 498 void TabStrip::RemoveTabDelegate::CompleteRemove() {
502 DCHECK(tab_->closing()); 499 DCHECK(tab_->closing());
503 tabstrip_->RemoveAndDeleteTab(tab_); 500 tabstrip_->RemoveAndDeleteTab(tab_);
504 HighlightCloseButton(); 501 HighlightCloseButton();
505 } 502 }
506 503
507 void TabStrip::RemoveTabDelegate::HighlightCloseButton() { 504 void TabStrip::RemoveTabDelegate::HighlightCloseButton() {
508 if (tabstrip_->IsDragSessionActive() || 505 if (tabstrip_->IsDragSessionActive() ||
509 !tabstrip_->ShouldHighlightCloseButtonAfterRemove()) { 506 !tabstrip_->ShouldHighlightCloseButtonAfterRemove()) {
510 // This function is not required (and indeed may crash!) for removes 507 // This function is not required (and indeed may crash!) for removes
511 // spawned by non-mouse closes and drag-detaches. 508 // spawned by non-mouse closes and drag-detaches.
512 return; 509 return;
513 } 510 }
514 511
515 views::Widget* widget = tabstrip_->GetWidget(); 512 views::Widget* widget = tabstrip_->GetWidget();
516 // This can be null during shutdown. See http://crbug.com/42737. 513 // This can be null during shutdown. See http://crbug.com/42737.
517 if (!widget) 514 if (!widget)
518 return; 515 return;
519 516
520 widget->SynthesizeMouseMoveEvent(); 517 widget->SynthesizeMouseMoveEvent();
521 } 518 }
522 519
523 /////////////////////////////////////////////////////////////////////////////// 520 ///////////////////////////////////////////////////////////////////////////////
524 // TabStrip, public: 521 // TabStrip, public:
525 522
526 // static 523 // static
527 const char TabStrip::kViewClassName[] = "TabStrip"; 524 const char TabStrip::kViewClassName[] = "TabStrip";
528 525 const int TabStrip::kNewTabButtonHorizontalOffset = -11;
529 // static 526 const int TabStrip::kNewTabButtonVerticalOffset = 7;
530 const int TabStrip::kMiniToNonMiniGap = 3; 527 const int TabStrip::kMiniToNonMiniGap = 3;
528 const int TabStrip::kNewTabButtonAssetWidth = 34;
529 const int TabStrip::kNewTabButtonAssetHeight = 18;
531 530
532 TabStrip::TabStrip(TabStripController* controller) 531 TabStrip::TabStrip(TabStripController* controller)
533 : controller_(controller), 532 : controller_(controller),
534 newtab_button_(NULL), 533 newtab_button_(NULL),
535 current_unselected_width_(Tab::GetStandardSize().width()), 534 current_unselected_width_(Tab::GetStandardSize().width()),
536 current_selected_width_(Tab::GetStandardSize().width()), 535 current_selected_width_(Tab::GetStandardSize().width()),
537 available_width_for_tabs_(-1), 536 available_width_for_tabs_(-1),
538 in_tab_close_(false), 537 in_tab_close_(false),
539 animation_container_(new gfx::AnimationContainer()), 538 animation_container_(new gfx::AnimationContainer()),
540 bounds_animator_(this), 539 bounds_animator_(this),
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 const int active_index = controller_->GetActiveIndex(); 580 const int active_index = controller_->GetActiveIndex();
582 int active_center = 0; 581 int active_center = 0;
583 if (active_index != -1) { 582 if (active_index != -1) {
584 active_center = ideal_bounds(active_index).x() + 583 active_center = ideal_bounds(active_index).x() +
585 ideal_bounds(active_index).width() / 2; 584 ideal_bounds(active_index).width() / 2;
586 } 585 }
587 stacked_layout_ = stacked_layout; 586 stacked_layout_ = stacked_layout;
588 SetResetToShrinkOnExit(false); 587 SetResetToShrinkOnExit(false);
589 SwapLayoutIfNecessary(); 588 SwapLayoutIfNecessary();
590 // When transitioning to stacked try to keep the active tab centered. 589 // When transitioning to stacked try to keep the active tab centered.
591 if (touch_layout_.get() && active_index != -1) { 590 if (touch_layout_ && active_index != -1) {
592 touch_layout_->SetActiveTabLocation( 591 touch_layout_->SetActiveTabLocation(
593 active_center - ideal_bounds(active_index).width() / 2); 592 active_center - ideal_bounds(active_index).width() / 2);
594 AnimateToIdealBounds(); 593 AnimateToIdealBounds();
595 } 594 }
596 } 595 }
597 596
598 gfx::Rect TabStrip::GetNewTabButtonBounds() { 597 gfx::Rect TabStrip::GetNewTabButtonBounds() {
599 return newtab_button_->bounds(); 598 return newtab_button_->bounds();
600 } 599 }
601 600
(...skipping 23 matching lines...) Expand all
625 if (drag_controller_.get() && !drag_controller_->is_mutating() && 624 if (drag_controller_.get() && !drag_controller_->is_mutating() &&
626 drag_controller_->is_dragging_window()) { 625 drag_controller_->is_dragging_window()) {
627 EndDrag(END_DRAG_COMPLETE); 626 EndDrag(END_DRAG_COMPLETE);
628 } 627 }
629 Tab* tab = CreateTab(); 628 Tab* tab = CreateTab();
630 tab->SetData(data); 629 tab->SetData(data);
631 UpdateTabsClosingMap(model_index, 1); 630 UpdateTabsClosingMap(model_index, 1);
632 tabs_.Add(tab, model_index); 631 tabs_.Add(tab, model_index);
633 AddChildView(tab); 632 AddChildView(tab);
634 633
635 if (touch_layout_.get()) { 634 if (touch_layout_) {
636 GenerateIdealBoundsForMiniTabs(NULL); 635 GenerateIdealBoundsForMiniTabs(NULL);
637 int add_types = 0; 636 int add_types = 0;
638 if (data.mini) 637 if (data.mini)
639 add_types |= StackedTabStripLayout::kAddTypeMini; 638 add_types |= StackedTabStripLayout::kAddTypeMini;
640 if (is_active) 639 if (is_active)
641 add_types |= StackedTabStripLayout::kAddTypeActive; 640 add_types |= StackedTabStripLayout::kAddTypeActive;
642 touch_layout_->AddTab(model_index, add_types, GetStartXForNormalTabs()); 641 touch_layout_->AddTab(model_index, add_types, GetStartXForNormalTabs());
643 } 642 }
644 643
645 // Don't animate the first tab, it looks weird, and don't animate anything 644 // Don't animate the first tab, it looks weird, and don't animate anything
646 // if the containing window isn't visible yet. 645 // if the containing window isn't visible yet.
647 if (tab_count() > 1 && GetWidget() && GetWidget()->IsVisible()) 646 if (tab_count() > 1 && GetWidget() && GetWidget()->IsVisible())
648 StartInsertTabAnimation(model_index); 647 StartInsertTabAnimation(model_index);
649 else 648 else
650 DoLayout(); 649 DoLayout();
651 650
652 SwapLayoutIfNecessary(); 651 SwapLayoutIfNecessary();
653 652
654 FOR_EACH_OBSERVER(TabStripObserver, observers_, 653 FOR_EACH_OBSERVER(TabStripObserver, observers_,
655 TabStripAddedTabAt(this, model_index)); 654 TabStripAddedTabAt(this, model_index));
656 } 655 }
657 656
658 void TabStrip::MoveTab(int from_model_index, 657 void TabStrip::MoveTab(int from_model_index,
659 int to_model_index, 658 int to_model_index,
660 const TabRendererData& data) { 659 const TabRendererData& data) {
661 DCHECK_GT(tabs_.view_size(), 0); 660 DCHECK_GT(tabs_.view_size(), 0);
662 Tab* last_tab = tab_at(tab_count() - 1); 661 const Tab* last_tab = GetLastVisibleTab();
663 tab_at(from_model_index)->SetData(data); 662 tab_at(from_model_index)->SetData(data);
664 if (touch_layout_.get()) { 663 if (touch_layout_) {
665 tabs_.MoveViewOnly(from_model_index, to_model_index); 664 tabs_.MoveViewOnly(from_model_index, to_model_index);
666 int mini_count = 0; 665 int mini_count = 0;
667 GenerateIdealBoundsForMiniTabs(&mini_count); 666 GenerateIdealBoundsForMiniTabs(&mini_count);
668 touch_layout_->MoveTab( 667 touch_layout_->MoveTab(
669 from_model_index, to_model_index, controller_->GetActiveIndex(), 668 from_model_index, to_model_index, controller_->GetActiveIndex(),
670 GetStartXForNormalTabs(), mini_count); 669 GetStartXForNormalTabs(), mini_count);
671 } else { 670 } else {
672 tabs_.Move(from_model_index, to_model_index); 671 tabs_.Move(from_model_index, to_model_index);
673 } 672 }
674 StartMoveTabAnimation(); 673 StartMoveTabAnimation();
675 if (TabDragController::IsAttachedTo(this) && 674 if (TabDragController::IsAttachedTo(this) &&
676 (last_tab != tab_at(tab_count() - 1) || last_tab->dragging())) { 675 (last_tab != GetLastVisibleTab() || last_tab->dragging())) {
677 newtab_button_->SetVisible(false); 676 newtab_button_->SetVisible(false);
678 } 677 }
679 SwapLayoutIfNecessary(); 678 SwapLayoutIfNecessary();
680 679
681 FOR_EACH_OBSERVER(TabStripObserver, observers_, 680 FOR_EACH_OBSERVER(TabStripObserver, observers_,
682 TabStripMovedTab(this, from_model_index, to_model_index)); 681 TabStripMovedTab(this, from_model_index, to_model_index));
683 } 682 }
684 683
685 void TabStrip::RemoveTabAt(int model_index) { 684 void TabStrip::RemoveTabAt(int model_index) {
686 if (touch_layout_.get()) { 685 if (touch_layout_) {
687 Tab* tab = tab_at(model_index); 686 Tab* tab = tab_at(model_index);
688 tab->set_closing(true); 687 tab->set_closing(true);
689 int old_x = tabs_.ideal_bounds(model_index).x(); 688 int old_x = tabs_.ideal_bounds(model_index).x();
690 // We still need to paint the tab until we actually remove it. Put it in 689 // We still need to paint the tab until we actually remove it. Put it in
691 // tabs_closing_map_ so we can find it. 690 // tabs_closing_map_ so we can find it.
692 RemoveTabFromViewModel(model_index); 691 RemoveTabFromViewModel(model_index);
693 touch_layout_->RemoveTab(model_index, GenerateIdealBoundsForMiniTabs(NULL), 692 touch_layout_->RemoveTab(model_index, GenerateIdealBoundsForMiniTabs(NULL),
694 old_x); 693 old_x);
695 ScheduleRemoveTabAnimation(tab); 694 ScheduleRemoveTabAnimation(tab);
696 } else if (in_tab_close_ && model_index != GetModelCount()) { 695 } else if (in_tab_close_ && model_index != GetModelCount()) {
697 StartMouseInitiatedRemoveTabAnimation(model_index); 696 StartMouseInitiatedRemoveTabAnimation(model_index);
698 } else { 697 } else {
699 StartRemoveTabAnimation(model_index); 698 StartRemoveTabAnimation(model_index);
700 } 699 }
701 SwapLayoutIfNecessary(); 700 SwapLayoutIfNecessary();
702 701
703 FOR_EACH_OBSERVER(TabStripObserver, observers_, 702 FOR_EACH_OBSERVER(TabStripObserver, observers_,
704 TabStripRemovedTabAt(this, model_index)); 703 TabStripRemovedTabAt(this, model_index));
705 } 704 }
706 705
707 void TabStrip::SetTabData(int model_index, const TabRendererData& data) { 706 void TabStrip::SetTabData(int model_index, const TabRendererData& data) {
708 Tab* tab = tab_at(model_index); 707 Tab* tab = tab_at(model_index);
709 bool mini_state_changed = tab->data().mini != data.mini; 708 bool mini_state_changed = tab->data().mini != data.mini;
710 tab->SetData(data); 709 tab->SetData(data);
711 710
712 if (mini_state_changed) { 711 if (mini_state_changed) {
713 if (touch_layout_.get()) { 712 if (touch_layout_) {
714 int mini_tab_count = 0; 713 int mini_tab_count = 0;
715 int start_x = GenerateIdealBoundsForMiniTabs(&mini_tab_count); 714 int start_x = GenerateIdealBoundsForMiniTabs(&mini_tab_count);
716 touch_layout_->SetXAndMiniCount(start_x, mini_tab_count); 715 touch_layout_->SetXAndMiniCount(start_x, mini_tab_count);
717 } 716 }
718 if (GetWidget() && GetWidget()->IsVisible()) 717 if (GetWidget() && GetWidget()->IsVisible())
719 StartMiniTabAnimation(); 718 StartMiniTabAnimation();
720 else 719 else
721 DoLayout(); 720 DoLayout();
722 } 721 }
723 SwapLayoutIfNecessary(); 722 SwapLayoutIfNecessary();
724 } 723 }
725 724
726 void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) { 725 void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) {
727 if (!in_tab_close_ && IsAnimating()) { 726 if (!in_tab_close_ && IsAnimating()) {
728 // Cancel any current animations. We do this as remove uses the current 727 // Cancel any current animations. We do this as remove uses the current
729 // ideal bounds and we need to know ideal bounds is in a good state. 728 // ideal bounds and we need to know ideal bounds is in a good state.
730 StopAnimating(true); 729 StopAnimating(true);
731 } 730 }
732 731
733 if (!GetWidget()) 732 if (!GetWidget())
734 return; 733 return;
735 734
736 int model_count = GetModelCount(); 735 int model_count = GetModelCount();
737 if (model_index + 1 != model_count && model_count > 1) { 736 if (model_count > 1 && model_index != model_count - 1) {
738 // The user is about to close a tab other than the last tab. Set 737 // The user is about to close a tab other than the last tab. Set
739 // available_width_for_tabs_ so that if we do a layout we don't position a 738 // available_width_for_tabs_ so that if we do a layout we don't position a
740 // tab past the end of the second to last tab. We do this so that as the 739 // tab past the end of the second to last tab. We do this so that as the
741 // user closes tabs with the mouse a tab continues to fall under the mouse. 740 // user closes tabs with the mouse a tab continues to fall under the mouse.
742 Tab* last_tab = tab_at(model_count - 1); 741 Tab* last_tab = tab_at(model_count - 1);
743 Tab* tab_being_removed = tab_at(model_index); 742 Tab* tab_being_removed = tab_at(model_index);
744 available_width_for_tabs_ = last_tab->x() + last_tab->width() - 743 available_width_for_tabs_ = last_tab->x() + last_tab->width() -
745 tab_being_removed->width() - kTabHorizontalOffset; 744 tab_being_removed->width() - kTabHorizontalOffset;
746 if (model_index == 0 && tab_being_removed->data().mini && 745 if (model_index == 0 && tab_being_removed->data().mini &&
747 !tab_at(1)->data().mini) { 746 !tab_at(1)->data().mini) {
748 available_width_for_tabs_ -= kMiniToNonMiniGap; 747 available_width_for_tabs_ -= kMiniToNonMiniGap;
749 } 748 }
750 } 749 }
751 750
752 in_tab_close_ = true; 751 in_tab_close_ = true;
753 resize_layout_timer_.Stop(); 752 resize_layout_timer_.Stop();
754 if (source == CLOSE_TAB_FROM_TOUCH) { 753 if (source == CLOSE_TAB_FROM_TOUCH) {
755 StartResizeLayoutTabsFromTouchTimer(); 754 StartResizeLayoutTabsFromTouchTimer();
756 } else { 755 } else {
757 AddMessageLoopObserver(); 756 AddMessageLoopObserver();
758 } 757 }
759 } 758 }
760 759
761 void TabStrip::SetSelection(const ui::ListSelectionModel& old_selection, 760 void TabStrip::SetSelection(const ui::ListSelectionModel& old_selection,
762 const ui::ListSelectionModel& new_selection) { 761 const ui::ListSelectionModel& new_selection) {
763 if (touch_layout_.get()) { 762 if (touch_layout_) {
764 touch_layout_->SetActiveIndex(new_selection.active()); 763 touch_layout_->SetActiveIndex(new_selection.active());
765 // Only start an animation if we need to. Otherwise clicking on an 764 // Only start an animation if we need to. Otherwise clicking on an
766 // unselected tab and dragging won't work because dragging is only allowed 765 // unselected tab and dragging won't work because dragging is only allowed
767 // if not animating. 766 // if not animating.
768 if (!views::ViewModelUtils::IsAtIdealBounds(tabs_)) 767 if (!views::ViewModelUtils::IsAtIdealBounds(tabs_))
769 AnimateToIdealBounds(); 768 AnimateToIdealBounds();
770 SchedulePaint(); 769 SchedulePaint();
771 } else { 770 } else {
772 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are 771 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are
773 // a different size to the selected ones. 772 // a different size to the selected ones.
(...skipping 12 matching lines...) Expand all
786 for (size_t i = 0; i < no_longer_selected.size(); ++i) 785 for (size_t i = 0; i < no_longer_selected.size(); ++i)
787 tab_at(no_longer_selected[i])->StopMiniTabTitleAnimation(); 786 tab_at(no_longer_selected[i])->StopMiniTabTitleAnimation();
788 } 787 }
789 788
790 void TabStrip::TabTitleChangedNotLoading(int model_index) { 789 void TabStrip::TabTitleChangedNotLoading(int model_index) {
791 Tab* tab = tab_at(model_index); 790 Tab* tab = tab_at(model_index);
792 if (tab->data().mini && !tab->IsActive()) 791 if (tab->data().mini && !tab->IsActive())
793 tab->StartMiniTabTitleAnimation(); 792 tab->StartMiniTabTitleAnimation();
794 } 793 }
795 794
796 Tab* TabStrip::tab_at(int index) const {
797 return static_cast<Tab*>(tabs_.view_at(index));
798 }
799
800 int TabStrip::GetModelIndexOfTab(const Tab* tab) const { 795 int TabStrip::GetModelIndexOfTab(const Tab* tab) const {
801 return tabs_.GetIndexOfView(tab); 796 return tabs_.GetIndexOfView(tab);
802 } 797 }
803 798
804 int TabStrip::GetModelCount() const { 799 int TabStrip::GetModelCount() const {
805 return controller_->GetCount(); 800 return controller_->GetCount();
806 } 801 }
807 802
808 bool TabStrip::IsValidModelIndex(int model_index) const { 803 bool TabStrip::IsValidModelIndex(int model_index) const {
809 return controller_->IsValidIndex(model_index); 804 return controller_->IsValidIndex(model_index);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 // processed for them. 857 // processed for them.
863 return false; 858 return false;
864 } 859 }
865 860
866 void TabStrip::SetBackgroundOffset(const gfx::Point& offset) { 861 void TabStrip::SetBackgroundOffset(const gfx::Point& offset) {
867 for (int i = 0; i < tab_count(); ++i) 862 for (int i = 0; i < tab_count(); ++i)
868 tab_at(i)->set_background_offset(offset); 863 tab_at(i)->set_background_offset(offset);
869 newtab_button_->set_background_offset(offset); 864 newtab_button_->set_background_offset(offset);
870 } 865 }
871 866
872 views::View* TabStrip::newtab_button() {
873 return newtab_button_;
874 }
875
876 void TabStrip::SetImmersiveStyle(bool enable) { 867 void TabStrip::SetImmersiveStyle(bool enable) {
877 if (immersive_style_ == enable) 868 if (immersive_style_ == enable)
878 return; 869 return;
879 immersive_style_ = enable; 870 immersive_style_ = enable;
880 } 871 }
881 872
882 bool TabStrip::IsAnimating() const { 873 bool TabStrip::IsAnimating() const {
883 return bounds_animator_.IsAnimating(); 874 return bounds_animator_.IsAnimating();
884 } 875 }
885 876
(...skipping 11 matching lines...) Expand all
897 if (drop_info_.get() && drop_info_->url == url) 888 if (drop_info_.get() && drop_info_->url == url)
898 drop_info_->file_supported = supported; 889 drop_info_->file_supported = supported;
899 } 890 }
900 891
901 const ui::ListSelectionModel& TabStrip::GetSelectionModel() { 892 const ui::ListSelectionModel& TabStrip::GetSelectionModel() {
902 return controller_->GetSelectionModel(); 893 return controller_->GetSelectionModel();
903 } 894 }
904 895
905 bool TabStrip::SupportsMultipleSelection() { 896 bool TabStrip::SupportsMultipleSelection() {
906 // TODO: currently only allow single selection in touch layout mode. 897 // TODO: currently only allow single selection in touch layout mode.
907 return touch_layout_.get() == NULL; 898 return touch_layout_ == NULL;
908 } 899 }
909 900
910 void TabStrip::SelectTab(Tab* tab) { 901 void TabStrip::SelectTab(Tab* tab) {
911 int model_index = GetModelIndexOfTab(tab); 902 int model_index = GetModelIndexOfTab(tab);
912 if (IsValidModelIndex(model_index)) 903 if (IsValidModelIndex(model_index))
913 controller_->SelectTab(model_index); 904 controller_->SelectTab(model_index);
914 } 905 }
915 906
916 void TabStrip::ExtendSelectionTo(Tab* tab) { 907 void TabStrip::ExtendSelectionTo(Tab* tab) {
917 int model_index = GetModelIndexOfTab(tab); 908 int model_index = GetModelIndexOfTab(tab);
(...skipping 11 matching lines...) Expand all
929 int model_index = GetModelIndexOfTab(tab); 920 int model_index = GetModelIndexOfTab(tab);
930 if (IsValidModelIndex(model_index)) 921 if (IsValidModelIndex(model_index))
931 controller_->AddSelectionFromAnchorTo(model_index); 922 controller_->AddSelectionFromAnchorTo(model_index);
932 } 923 }
933 924
934 void TabStrip::CloseTab(Tab* tab, CloseTabSource source) { 925 void TabStrip::CloseTab(Tab* tab, CloseTabSource source) {
935 if (tab->closing()) { 926 if (tab->closing()) {
936 // If the tab is already closing, close the next tab. We do this so that the 927 // If the tab is already closing, close the next tab. We do this so that the
937 // user can rapidly close tabs by clicking the close button and not have 928 // user can rapidly close tabs by clicking the close button and not have
938 // the animations interfere with that. 929 // the animations interfere with that.
939 for (TabsClosingMap::const_iterator i(tabs_closing_map_.begin()); 930 const int closed_tab_index = FindClosingTab(tab).first->first;
940 i != tabs_closing_map_.end(); ++i) { 931 if (closed_tab_index < GetModelCount())
941 std::vector<Tab*>::const_iterator j = 932 controller_->CloseTab(closed_tab_index, source);
942 std::find(i->second.begin(), i->second.end(), tab);
943 if (j != i->second.end()) {
944 if (i->first + 1 < GetModelCount())
945 controller_->CloseTab(i->first + 1, source);
946 return;
947 }
948 }
949 // If we get here, it means a tab has been marked as closing but isn't in
950 // the set of known closing tabs.
951 NOTREACHED();
952 return; 933 return;
953 } 934 }
954 int model_index = GetModelIndexOfTab(tab); 935 int model_index = GetModelIndexOfTab(tab);
955 if (IsValidModelIndex(model_index)) 936 if (IsValidModelIndex(model_index))
956 controller_->CloseTab(model_index, source); 937 controller_->CloseTab(model_index, source);
957 } 938 }
958 939
959 void TabStrip::ShowContextMenuForTab(Tab* tab, 940 void TabStrip::ShowContextMenuForTab(Tab* tab,
960 const gfx::Point& p, 941 const gfx::Point& p,
961 ui::MenuSourceType source_type) { 942 ui::MenuSourceType source_type) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 979
999 // Do not do any dragging of tabs when using the super short immersive style. 980 // Do not do any dragging of tabs when using the super short immersive style.
1000 if (IsImmersiveStyle()) 981 if (IsImmersiveStyle())
1001 return; 982 return;
1002 983
1003 int model_index = GetModelIndexOfTab(tab); 984 int model_index = GetModelIndexOfTab(tab);
1004 if (!IsValidModelIndex(model_index)) { 985 if (!IsValidModelIndex(model_index)) {
1005 CHECK(false); 986 CHECK(false);
1006 return; 987 return;
1007 } 988 }
1008 std::vector<Tab*> tabs; 989 Tabs tabs;
1009 int size_to_selected = 0; 990 int size_to_selected = 0;
1010 int x = tab->GetMirroredXInView(event.x()); 991 int x = tab->GetMirroredXInView(event.x());
1011 int y = event.y(); 992 int y = event.y();
1012 // Build the set of selected tabs to drag and calculate the offset from the 993 // Build the set of selected tabs to drag and calculate the offset from the
1013 // first selected tab. 994 // first selected tab.
1014 for (int i = 0; i < tab_count(); ++i) { 995 for (int i = 0; i < tab_count(); ++i) {
1015 Tab* other_tab = tab_at(i); 996 Tab* other_tab = tab_at(i);
1016 if (IsTabSelected(other_tab)) { 997 if (IsTabSelected(other_tab)) {
1017 tabs.push_back(other_tab); 998 tabs.push_back(other_tab);
1018 if (other_tab == tab) { 999 if (other_tab == tab) {
(...skipping 15 matching lines...) Expand all
1034 TabDragController::DETACHABLE; 1015 TabDragController::DETACHABLE;
1035 TabDragController::MoveBehavior move_behavior = 1016 TabDragController::MoveBehavior move_behavior =
1036 TabDragController::REORDER; 1017 TabDragController::REORDER;
1037 // Use MOVE_VISIBILE_TABS in the following conditions: 1018 // Use MOVE_VISIBILE_TABS in the following conditions:
1038 // . Mouse event generated from touch and the left button is down (the right 1019 // . Mouse event generated from touch and the left button is down (the right
1039 // button corresponds to a long press, which we want to reorder). 1020 // button corresponds to a long press, which we want to reorder).
1040 // . Gesture begin and control key isn't down. 1021 // . Gesture begin and control key isn't down.
1041 // . Real mouse event and control is down. This is mostly for testing. 1022 // . Real mouse event and control is down. This is mostly for testing.
1042 DCHECK(event.type() == ui::ET_MOUSE_PRESSED || 1023 DCHECK(event.type() == ui::ET_MOUSE_PRESSED ||
1043 event.type() == ui::ET_GESTURE_BEGIN); 1024 event.type() == ui::ET_GESTURE_BEGIN);
1044 if (touch_layout_.get() && 1025 if (touch_layout_ &&
1045 ((event.type() == ui::ET_MOUSE_PRESSED && 1026 ((event.type() == ui::ET_MOUSE_PRESSED &&
1046 (((event.flags() & ui::EF_FROM_TOUCH) && 1027 (((event.flags() & ui::EF_FROM_TOUCH) &&
1047 static_cast<const ui::MouseEvent&>(event).IsLeftMouseButton()) || 1028 static_cast<const ui::MouseEvent&>(event).IsLeftMouseButton()) ||
1048 (!(event.flags() & ui::EF_FROM_TOUCH) && 1029 (!(event.flags() & ui::EF_FROM_TOUCH) &&
1049 static_cast<const ui::MouseEvent&>(event).IsControlDown()))) || 1030 static_cast<const ui::MouseEvent&>(event).IsControlDown()))) ||
1050 (event.type() == ui::ET_GESTURE_BEGIN && !event.IsControlDown()))) { 1031 (event.type() == ui::ET_GESTURE_BEGIN && !event.IsControlDown()))) {
1051 move_behavior = TabDragController::MOVE_VISIBILE_TABS; 1032 move_behavior = TabDragController::MOVE_VISIBILE_TABS;
1052 } 1033 }
1053 1034
1054 drag_controller_.reset(new TabDragController); 1035 drag_controller_.reset(new TabDragController);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 return view && view->id() == VIEW_ID_TAB ? static_cast<Tab*>(view) : NULL; 1070 return view && view->id() == VIEW_ID_TAB ? static_cast<Tab*>(view) : NULL;
1090 } 1071 }
1091 1072
1092 void TabStrip::OnMouseEventInTab(views::View* source, 1073 void TabStrip::OnMouseEventInTab(views::View* source,
1093 const ui::MouseEvent& event) { 1074 const ui::MouseEvent& event) {
1094 UpdateStackedLayoutFromMouseEvent(source, event); 1075 UpdateStackedLayoutFromMouseEvent(source, event);
1095 } 1076 }
1096 1077
1097 bool TabStrip::ShouldPaintTab(const Tab* tab, gfx::Rect* clip) { 1078 bool TabStrip::ShouldPaintTab(const Tab* tab, gfx::Rect* clip) {
1098 // Only touch layout needs to restrict the clip. 1079 // Only touch layout needs to restrict the clip.
1099 if (!(touch_layout_.get() || IsStackingDraggedTabs())) 1080 if (!touch_layout_ && !IsStackingDraggedTabs())
1100 return true; 1081 return true;
1101 1082
1102 int index = GetModelIndexOfTab(tab); 1083 int index = GetModelIndexOfTab(tab);
1103 if (index == -1) 1084 if (index == -1)
1104 return true; // Tab is closing, paint it all. 1085 return true; // Tab is closing, paint it all.
1105 1086
1106 int active_index = IsStackingDraggedTabs() ? 1087 int active_index = IsStackingDraggedTabs() ?
1107 controller_->GetActiveIndex() : touch_layout_->active_index(); 1088 controller_->GetActiveIndex() : touch_layout_->active_index();
1108 if (active_index == tab_count()) 1089 if (active_index == tab_count())
1109 active_index--; 1090 active_index--;
1110 1091
1111 if (index < active_index) { 1092 if (index < active_index) {
1112 if (tab_at(index)->x() == tab_at(index + 1)->x()) 1093 if (tab_at(index)->x() == tab_at(index + 1)->x())
1113 return false; 1094 return false;
1114 1095
1115 if (tab_at(index)->x() > tab_at(index + 1)->x()) 1096 if (tab_at(index)->x() > tab_at(index + 1)->x())
1116 return true; // Can happen during dragging. 1097 return true; // Can happen during dragging.
1117 1098
1118 clip->SetRect(0, 0, tab_at(index + 1)->x() - tab_at(index)->x() + 1099 clip->SetRect(
1119 kStackedTabLeftClip, 1100 0, 0, tab_at(index + 1)->x() - tab_at(index)->x() + kStackedTabLeftClip,
1120 tab_at(index)->height()); 1101 tab_at(index)->height());
1121 } else if (index > active_index && index > 0) { 1102 } else if (index > active_index && index > 0) {
1122 const gfx::Rect& tab_bounds(tab_at(index)->bounds()); 1103 const gfx::Rect& tab_bounds(tab_at(index)->bounds());
1123 const gfx::Rect& previous_tab_bounds(tab_at(index - 1)->bounds()); 1104 const gfx::Rect& previous_tab_bounds(tab_at(index - 1)->bounds());
1124 if (tab_bounds.x() == previous_tab_bounds.x()) 1105 if (tab_bounds.x() == previous_tab_bounds.x())
1125 return false; 1106 return false;
1126 1107
1127 if (tab_bounds.x() < previous_tab_bounds.x()) 1108 if (tab_bounds.x() < previous_tab_bounds.x())
1128 return true; // Can happen during dragging. 1109 return true; // Can happen during dragging.
1129 1110
1130 if (previous_tab_bounds.right() + kTabHorizontalOffset != tab_bounds.x()) { 1111 if (previous_tab_bounds.right() + kTabHorizontalOffset != tab_bounds.x()) {
(...skipping 29 matching lines...) Expand all
1160 return; 1141 return;
1161 DoLayout(); 1142 DoLayout();
1162 } 1143 }
1163 1144
1164 void TabStrip::PaintChildren(gfx::Canvas* canvas, 1145 void TabStrip::PaintChildren(gfx::Canvas* canvas,
1165 const views::CullSet& cull_set) { 1146 const views::CullSet& cull_set) {
1166 // The view order doesn't match the paint order (tabs_ contains the tab 1147 // The view order doesn't match the paint order (tabs_ contains the tab
1167 // ordering). Additionally we need to paint the tabs that are closing in 1148 // ordering). Additionally we need to paint the tabs that are closing in
1168 // |tabs_closing_map_|. 1149 // |tabs_closing_map_|.
1169 Tab* active_tab = NULL; 1150 Tab* active_tab = NULL;
1170 std::vector<Tab*> tabs_dragging; 1151 Tabs tabs_dragging;
1171 std::vector<Tab*> selected_tabs; 1152 Tabs selected_tabs;
1172 int selected_tab_count = 0; 1153 int selected_tab_count = 0;
1173 bool is_dragging = false; 1154 bool is_dragging = false;
1174 int active_tab_index = -1; 1155 int active_tab_index = -1;
1175 // Since |touch_layout_| is created based on number of tabs and width we use
1176 // the ideal state to determine if we should paint stacked. This minimizes
1177 // painting changes as we switch between the two.
1178 const bool stacking = stacked_layout_ || IsStackingDraggedTabs();
1179 1156
1180 const chrome::HostDesktopType host_desktop_type = 1157 const chrome::HostDesktopType host_desktop_type =
1181 chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); 1158 chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView());
1182 const int inactive_tab_alpha = 1159 const int inactive_tab_alpha =
1183 host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH ? 1160 (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) ?
1184 kInactiveTabAndNewTabButtonAlphaAsh : 1161 kInactiveTabAndNewTabButtonAlphaAsh : kInactiveTabAndNewTabButtonAlpha;
1185 kInactiveTabAndNewTabButtonAlpha;
1186 1162
1187 if (inactive_tab_alpha < 255) 1163 if (inactive_tab_alpha < 255)
1188 canvas->SaveLayerAlpha(inactive_tab_alpha); 1164 canvas->SaveLayerAlpha(inactive_tab_alpha);
1189 1165
1190 PaintClosingTabs(canvas, tab_count(), cull_set); 1166 PaintClosingTabs(canvas, tab_count(), cull_set);
1191 1167
1192 for (int i = tab_count() - 1; i >= 0; --i) { 1168 for (int i = tab_count() - 1; i >= 0; --i) {
1193 Tab* tab = tab_at(i); 1169 Tab* tab = tab_at(i);
1194 if (tab->IsSelected()) 1170 if (tab->IsSelected())
1195 selected_tab_count++; 1171 selected_tab_count++;
1196 if (tab->dragging() && !stacking) { 1172 if (tab->dragging() && !stacked_layout_) {
1197 is_dragging = true; 1173 is_dragging = true;
1198 if (tab->IsActive()) { 1174 if (tab->IsActive()) {
1199 active_tab = tab; 1175 active_tab = tab;
1200 active_tab_index = i; 1176 active_tab_index = i;
1201 } else { 1177 } else {
1202 tabs_dragging.push_back(tab); 1178 tabs_dragging.push_back(tab);
1203 } 1179 }
1204 } else if (!tab->IsActive()) { 1180 } else if (!tab->IsActive()) {
1205 if (!tab->IsSelected()) { 1181 if (!tab->IsSelected()) {
1206 if (!stacking) 1182 if (!stacked_layout_)
1207 tab->Paint(canvas, cull_set); 1183 tab->Paint(canvas, cull_set);
1208 } else { 1184 } else {
1209 selected_tabs.push_back(tab); 1185 selected_tabs.push_back(tab);
1210 } 1186 }
1211 } else { 1187 } else {
1212 active_tab = tab; 1188 active_tab = tab;
1213 active_tab_index = i; 1189 active_tab_index = i;
1214 } 1190 }
1215 PaintClosingTabs(canvas, i, cull_set); 1191 PaintClosingTabs(canvas, i, cull_set);
1216 } 1192 }
1217 1193
1218 // Draw from the left and then the right if we're in touch mode. 1194 // Draw from the left and then the right if we're in touch mode.
1219 if (stacking && active_tab_index >= 0) { 1195 if (stacked_layout_ && active_tab_index >= 0) {
1220 for (int i = 0; i < active_tab_index; ++i) { 1196 for (int i = 0; i < active_tab_index; ++i) {
1221 Tab* tab = tab_at(i); 1197 Tab* tab = tab_at(i);
1222 tab->Paint(canvas, cull_set); 1198 tab->Paint(canvas, cull_set);
1223 } 1199 }
1224 1200
1225 for (int i = tab_count() - 1; i > active_tab_index; --i) { 1201 for (int i = tab_count() - 1; i > active_tab_index; --i) {
1226 Tab* tab = tab_at(i); 1202 Tab* tab = tab_at(i);
1227 tab->Paint(canvas, cull_set); 1203 tab->Paint(canvas, cull_set);
1228 } 1204 }
1229 } 1205 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 const char* TabStrip::GetClassName() const { 1249 const char* TabStrip::GetClassName() const {
1274 return kViewClassName; 1250 return kViewClassName;
1275 } 1251 }
1276 1252
1277 gfx::Size TabStrip::GetPreferredSize() const { 1253 gfx::Size TabStrip::GetPreferredSize() const {
1278 // For stacked tabs the minimum size is calculated as the size needed to 1254 // For stacked tabs the minimum size is calculated as the size needed to
1279 // handle showing any number of tabs. Otherwise report the minimum width as 1255 // handle showing any number of tabs. Otherwise report the minimum width as
1280 // the size required for a single selected tab plus the new tab button. Don't 1256 // the size required for a single selected tab plus the new tab button. Don't
1281 // base it on the actual number of tabs because it's undesirable to have the 1257 // base it on the actual number of tabs because it's undesirable to have the
1282 // minimum window size change when a new tab is opened. 1258 // minimum window size change when a new tab is opened.
1283 int needed_width; 1259 const int needed_tab_width = (touch_layout_ || adjust_layout_) ?
1284 if (touch_layout_.get() || adjust_layout_) { 1260 (Tab::GetTouchWidth() + (2 * kStackedPadding * kMaxStackedCount)) :
1285 needed_width = Tab::GetTouchWidth() + 1261 Tab::GetMinimumSelectedSize().width();
1286 (2 * kStackedPadding * kMaxStackedCount); 1262 return gfx::Size(needed_tab_width + new_tab_button_width(), immersive_style_ ?
1287 } else { 1263 Tab::GetImmersiveHeight() : Tab::GetMinimumUnselectedSize().height());
1288 needed_width = Tab::GetMinimumSelectedSize().width();
1289 }
1290 needed_width += new_tab_button_width();
1291 if (immersive_style_)
1292 return gfx::Size(needed_width, Tab::GetImmersiveHeight());
1293 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height());
1294 } 1264 }
1295 1265
1296 void TabStrip::OnDragEntered(const DropTargetEvent& event) { 1266 void TabStrip::OnDragEntered(const DropTargetEvent& event) {
1297 // Force animations to stop, otherwise it makes the index calculation tricky. 1267 // Force animations to stop, otherwise it makes the index calculation tricky.
1298 StopAnimating(true); 1268 StopAnimating(true);
1299 1269
1300 UpdateDropIndex(event); 1270 UpdateDropIndex(event);
1301 1271
1302 GURL url; 1272 GURL url;
1303 base::string16 title; 1273 base::string16 title;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 1327
1358 void TabStrip::GetAccessibleState(ui::AXViewState* state) { 1328 void TabStrip::GetAccessibleState(ui::AXViewState* state) {
1359 state->role = ui::AX_ROLE_TAB_LIST; 1329 state->role = ui::AX_ROLE_TAB_LIST;
1360 } 1330 }
1361 1331
1362 views::View* TabStrip::GetEventHandlerForRect(const gfx::Rect& rect) { 1332 views::View* TabStrip::GetEventHandlerForRect(const gfx::Rect& rect) {
1363 if (!views::UsePointBasedTargeting(rect)) 1333 if (!views::UsePointBasedTargeting(rect))
1364 return View::GetEventHandlerForRect(rect); 1334 return View::GetEventHandlerForRect(rect);
1365 const gfx::Point point(rect.CenterPoint()); 1335 const gfx::Point point(rect.CenterPoint());
1366 1336
1367 if (!touch_layout_.get()) { 1337 if (!touch_layout_) {
1368 // Return any view that isn't a Tab or this TabStrip immediately. We don't 1338 // Return any view that isn't a Tab or this TabStrip immediately. We don't
1369 // want to interfere. 1339 // want to interfere.
1370 views::View* v = View::GetEventHandlerForRect(rect); 1340 views::View* v = View::GetEventHandlerForRect(rect);
1371 if (v && v != this && strcmp(v->GetClassName(), Tab::kViewClassName)) 1341 if (v && v != this && strcmp(v->GetClassName(), Tab::kViewClassName))
1372 return v; 1342 return v;
1373 1343
1374 views::View* tab = FindTabHitByPoint(point); 1344 views::View* tab = FindTabHitByPoint(point);
1375 if (tab) 1345 if (tab)
1376 return tab; 1346 return tab;
1377 } else { 1347 } else {
1378 if (newtab_button_->visible()) { 1348 if (newtab_button_->visible()) {
1379 views::View* view = 1349 views::View* view =
1380 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); 1350 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point);
1381 if (view) 1351 if (view)
1382 return view; 1352 return view;
1383 } 1353 }
1384 Tab* tab = FindTabForEvent(point); 1354 Tab* tab = FindTabForEvent(point);
1385 if (tab) 1355 if (tab)
1386 return ConvertPointToViewAndGetEventHandler(this, tab, point); 1356 return ConvertPointToViewAndGetEventHandler(this, tab, point);
1387 } 1357 }
1388 return this; 1358 return this;
1389 } 1359 }
1390 1360
1391 views::View* TabStrip::GetTooltipHandlerForPoint(const gfx::Point& point) { 1361 views::View* TabStrip::GetTooltipHandlerForPoint(const gfx::Point& point) {
1392 if (!HitTestPoint(point)) 1362 if (!HitTestPoint(point))
1393 return NULL; 1363 return NULL;
1394 1364
1395 if (!touch_layout_.get()) { 1365 if (!touch_layout_) {
1396 // Return any view that isn't a Tab or this TabStrip immediately. We don't 1366 // Return any view that isn't a Tab or this TabStrip immediately. We don't
1397 // want to interfere. 1367 // want to interfere.
1398 views::View* v = View::GetTooltipHandlerForPoint(point); 1368 views::View* v = View::GetTooltipHandlerForPoint(point);
1399 if (v && v != this && strcmp(v->GetClassName(), Tab::kViewClassName)) 1369 if (v && v != this && strcmp(v->GetClassName(), Tab::kViewClassName))
1400 return v; 1370 return v;
1401 1371
1402 views::View* tab = FindTabHitByPoint(point); 1372 views::View* tab = FindTabHitByPoint(point);
1403 if (tab) 1373 if (tab)
1404 return tab; 1374 return tab;
1405 } else { 1375 } else {
1406 if (newtab_button_->visible()) { 1376 if (newtab_button_->visible()) {
1407 views::View* view = 1377 views::View* view =
1408 ConvertPointToViewAndGetTooltipHandler(this, newtab_button_, point); 1378 ConvertPointToViewAndGetTooltipHandler(this, newtab_button_, point);
1409 if (view) 1379 if (view)
1410 return view; 1380 return view;
1411 } 1381 }
1412 Tab* tab = FindTabForEvent(point); 1382 Tab* tab = FindTabForEvent(point);
1413 if (tab) 1383 if (tab)
1414 return ConvertPointToViewAndGetTooltipHandler(this, tab, point); 1384 return ConvertPointToViewAndGetTooltipHandler(this, tab, point);
1415 } 1385 }
1416 return this; 1386 return this;
1417 } 1387 }
1418 1388
1419 // static 1389 // static
1420 int TabStrip::GetImmersiveHeight() { 1390 int TabStrip::GetImmersiveHeight() {
1421 return Tab::GetImmersiveHeight(); 1391 return Tab::GetImmersiveHeight();
1422 } 1392 }
1423 1393
1424 int TabStrip::GetMiniTabCount() const {
1425 int mini_count = 0;
1426 while (mini_count < tab_count() && tab_at(mini_count)->data().mini)
1427 mini_count++;
1428 return mini_count;
1429 }
1430
1431 ///////////////////////////////////////////////////////////////////////////////
1432 // TabStrip, views::ButtonListener implementation:
1433
1434 void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) {
1435 if (sender == newtab_button_) {
1436 content::RecordAction(UserMetricsAction("NewTab_Button"));
1437 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_BUTTON,
1438 TabStripModel::NEW_TAB_ENUM_COUNT);
1439 if (event.IsMouseEvent()) {
1440 const ui::MouseEvent& mouse = static_cast<const ui::MouseEvent&>(event);
1441 if (mouse.IsOnlyMiddleMouseButton()) {
1442 base::string16 clipboard_text = GetClipboardText();
1443 if (!clipboard_text.empty())
1444 controller()->CreateNewTabWithLocation(clipboard_text);
1445 return;
1446 }
1447 }
1448
1449 controller()->CreateNewTab();
1450 if (event.type() == ui::ET_GESTURE_TAP)
1451 TouchUMA::RecordGestureAction(TouchUMA::GESTURE_NEWTAB_TAP);
1452 }
1453 }
1454
1455 ///////////////////////////////////////////////////////////////////////////////
1456 // TabStrip, protected:
1457
1458 // Overridden to support automation. See automation_proxy_uitest.cc.
1459 const views::View* TabStrip::GetViewByID(int view_id) const {
1460 if (tab_count() > 0) {
1461 if (view_id == VIEW_ID_TAB_LAST) {
1462 return tab_at(tab_count() - 1);
1463 } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) {
1464 int index = view_id - VIEW_ID_TAB_0;
1465 if (index >= 0 && index < tab_count()) {
1466 return tab_at(index);
1467 } else {
1468 return NULL;
1469 }
1470 }
1471 }
1472
1473 return View::GetViewByID(view_id);
1474 }
1475
1476 bool TabStrip::OnMousePressed(const ui::MouseEvent& event) {
1477 UpdateStackedLayoutFromMouseEvent(this, event);
1478 // We can't return true here, else clicking in an empty area won't drag the
1479 // window.
1480 return false;
1481 }
1482
1483 bool TabStrip::OnMouseDragged(const ui::MouseEvent& event) {
1484 ContinueDrag(this, event);
1485 return true;
1486 }
1487
1488 void TabStrip::OnMouseReleased(const ui::MouseEvent& event) {
1489 EndDrag(END_DRAG_COMPLETE);
1490 UpdateStackedLayoutFromMouseEvent(this, event);
1491 }
1492
1493 void TabStrip::OnMouseCaptureLost() {
1494 EndDrag(END_DRAG_CAPTURE_LOST);
1495 }
1496
1497 void TabStrip::OnMouseMoved(const ui::MouseEvent& event) {
1498 UpdateStackedLayoutFromMouseEvent(this, event);
1499 }
1500
1501 void TabStrip::OnMouseEntered(const ui::MouseEvent& event) {
1502 SetResetToShrinkOnExit(true);
1503 }
1504
1505 void TabStrip::OnGestureEvent(ui::GestureEvent* event) {
1506 SetResetToShrinkOnExit(false);
1507 switch (event->type()) {
1508 case ui::ET_GESTURE_SCROLL_END:
1509 case ui::ET_SCROLL_FLING_START:
1510 case ui::ET_GESTURE_END:
1511 EndDrag(END_DRAG_COMPLETE);
1512 if (adjust_layout_) {
1513 SetStackedLayout(true);
1514 controller_->StackedLayoutMaybeChanged();
1515 }
1516 break;
1517
1518 case ui::ET_GESTURE_LONG_PRESS:
1519 if (drag_controller_.get())
1520 drag_controller_->SetMoveBehavior(TabDragController::REORDER);
1521 break;
1522
1523 case ui::ET_GESTURE_LONG_TAP: {
1524 EndDrag(END_DRAG_CANCEL);
1525 gfx::Point local_point = event->location();
1526 Tab* tab = FindTabForEvent(local_point);
1527 if (tab) {
1528 ConvertPointToScreen(this, &local_point);
1529 ShowContextMenuForTab(tab, local_point, ui::MENU_SOURCE_TOUCH);
1530 }
1531 break;
1532 }
1533
1534 case ui::ET_GESTURE_SCROLL_UPDATE:
1535 ContinueDrag(this, *event);
1536 break;
1537
1538 case ui::ET_GESTURE_BEGIN:
1539 EndDrag(END_DRAG_CANCEL);
1540 break;
1541
1542 case ui::ET_GESTURE_TAP: {
1543 const int active_index = controller_->GetActiveIndex();
1544 DCHECK_NE(-1, active_index);
1545 Tab* active_tab = tab_at(active_index);
1546 TouchUMA::GestureActionType action = TouchUMA::GESTURE_TABNOSWITCH_TAP;
1547 if (active_tab->tab_activated_with_last_gesture_begin())
1548 action = TouchUMA::GESTURE_TABSWITCH_TAP;
1549 TouchUMA::RecordGestureAction(action);
1550 break;
1551 }
1552
1553 default:
1554 break;
1555 }
1556 event->SetHandled();
1557 }
1558
1559 /////////////////////////////////////////////////////////////////////////////// 1394 ///////////////////////////////////////////////////////////////////////////////
1560 // TabStrip, private: 1395 // TabStrip, private:
1561 1396
1562 void TabStrip::Init() { 1397 void TabStrip::Init() {
1563 set_id(VIEW_ID_TAB_STRIP); 1398 set_id(VIEW_ID_TAB_STRIP);
1564 // So we get enter/exit on children to switch stacked layout on and off. 1399 // So we get enter/exit on children to switch stacked layout on and off.
1565 set_notify_enter_exit_on_child(true); 1400 set_notify_enter_exit_on_child(true);
1566 newtab_button_bounds_.SetRect(0, 1401 newtab_button_bounds_.SetRect(0,
1567 0, 1402 0,
1568 kNewTabButtonAssetWidth, 1403 kNewTabButtonAssetWidth,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1632 RemoveTabFromViewModel(model_index); 1467 RemoveTabFromViewModel(model_index);
1633 1468
1634 ScheduleRemoveTabAnimation(tab); 1469 ScheduleRemoveTabAnimation(tab);
1635 } 1470 }
1636 1471
1637 void TabStrip::ScheduleRemoveTabAnimation(Tab* tab) { 1472 void TabStrip::ScheduleRemoveTabAnimation(Tab* tab) {
1638 // Start an animation for the tabs. 1473 // Start an animation for the tabs.
1639 GenerateIdealBounds(); 1474 GenerateIdealBounds();
1640 AnimateToIdealBounds(); 1475 AnimateToIdealBounds();
1641 1476
1642 // Animate the tab being closed to 0x0. 1477 // Animate the tab being closed to zero width.
1643 gfx::Rect tab_bounds = tab->bounds(); 1478 gfx::Rect tab_bounds = tab->bounds();
1644 tab_bounds.set_width(0); 1479 tab_bounds.set_width(0);
1645 bounds_animator_.AnimateViewTo(tab, tab_bounds); 1480 bounds_animator_.AnimateViewTo(tab, tab_bounds);
1646 1481
1647 // Register delegate to do cleanup when done, BoundsAnimator takes 1482 // Register delegate to do cleanup when done, BoundsAnimator takes
1648 // ownership of RemoveTabDelegate. 1483 // ownership of RemoveTabDelegate.
1649 bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab), 1484 bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab),
1650 true); 1485 true);
1651 1486
1652 // Don't animate the new tab button when dragging tabs. Otherwise it looks 1487 // Don't animate the new tab button when dragging tabs. Otherwise it looks
(...skipping 19 matching lines...) Expand all
1672 return in_tab_close_; 1507 return in_tab_close_;
1673 } 1508 }
1674 1509
1675 void TabStrip::DoLayout() { 1510 void TabStrip::DoLayout() {
1676 last_layout_size_ = size(); 1511 last_layout_size_ = size();
1677 1512
1678 StopAnimating(false); 1513 StopAnimating(false);
1679 1514
1680 SwapLayoutIfNecessary(); 1515 SwapLayoutIfNecessary();
1681 1516
1682 if (touch_layout_.get()) 1517 if (touch_layout_)
1683 touch_layout_->SetWidth(size().width() - new_tab_button_width()); 1518 touch_layout_->SetWidth(tab_area_width());
1684 1519
1685 GenerateIdealBounds(); 1520 GenerateIdealBounds();
1686 1521
1687 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); 1522 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_);
1688 1523
1689 SchedulePaint(); 1524 SchedulePaint();
1690 1525
1691 bounds_animator_.StopAnimatingView(newtab_button_); 1526 bounds_animator_.StopAnimatingView(newtab_button_);
1692 newtab_button_->SetBoundsRect(newtab_button_bounds_); 1527 newtab_button_->SetBoundsRect(newtab_button_bounds_);
1693 } 1528 }
1694 1529
1695 void TabStrip::DragActiveTab(const std::vector<int>& initial_positions, 1530 void TabStrip::DragActiveTab(const std::vector<int>& initial_positions,
1696 int delta) { 1531 int delta) {
1697 DCHECK_EQ(tab_count(), static_cast<int>(initial_positions.size())); 1532 DCHECK_EQ(tab_count(), static_cast<int>(initial_positions.size()));
1698 if (!touch_layout_.get()) { 1533 if (!touch_layout_) {
1699 StackDraggedTabs(delta); 1534 StackDraggedTabs(delta);
1700 return; 1535 return;
1701 } 1536 }
1702 SetIdealBoundsFromPositions(initial_positions); 1537 SetIdealBoundsFromPositions(initial_positions);
1703 touch_layout_->DragActiveTab(delta); 1538 touch_layout_->DragActiveTab(delta);
1704 DoLayout(); 1539 DoLayout();
1705 } 1540 }
1706 1541
1707 void TabStrip::SetIdealBoundsFromPositions(const std::vector<int>& positions) { 1542 void TabStrip::SetIdealBoundsFromPositions(const std::vector<int>& positions) {
1708 if (static_cast<size_t>(tab_count()) != positions.size()) 1543 if (static_cast<size_t>(tab_count()) != positions.size())
1709 return; 1544 return;
1710 1545
1711 for (int i = 0; i < tab_count(); ++i) { 1546 for (int i = 0; i < tab_count(); ++i) {
1712 gfx::Rect bounds(ideal_bounds(i)); 1547 gfx::Rect bounds(ideal_bounds(i));
1713 bounds.set_x(positions[i]); 1548 bounds.set_x(positions[i]);
1714 set_ideal_bounds(i, bounds); 1549 tabs_.set_ideal_bounds(i, bounds);
1715 } 1550 }
1716 } 1551 }
1717 1552
1718 void TabStrip::StackDraggedTabs(int delta) { 1553 void TabStrip::StackDraggedTabs(int delta) {
1719 DCHECK(!touch_layout_.get()); 1554 DCHECK(!touch_layout_);
1720 GenerateIdealBounds(); 1555 GenerateIdealBounds();
1721 const int active_index = controller_->GetActiveIndex(); 1556 const int active_index = controller_->GetActiveIndex();
1722 DCHECK_NE(-1, active_index); 1557 DCHECK_NE(-1, active_index);
1723 if (delta < 0) { 1558 if (delta < 0) {
1724 // Drag the tabs to the left, stacking tabs before the active tab. 1559 // Drag the tabs to the left, stacking tabs before the active tab.
1725 const int adjusted_delta = 1560 const int adjusted_delta =
1726 std::min(ideal_bounds(active_index).x() - 1561 std::min(ideal_bounds(active_index).x() -
1727 kStackedPadding * std::min(active_index, kMaxStackedCount), 1562 kStackedPadding * std::min(active_index, kMaxStackedCount),
1728 -delta); 1563 -delta);
1729 for (int i = 0; i <= active_index; ++i) { 1564 for (int i = 0; i <= active_index; ++i) {
1730 const int min_x = std::min(i, kMaxStackedCount) * kStackedPadding; 1565 const int min_x = std::min(i, kMaxStackedCount) * kStackedPadding;
1731 gfx::Rect new_bounds(ideal_bounds(i)); 1566 gfx::Rect new_bounds(ideal_bounds(i));
1732 new_bounds.set_x(std::max(min_x, new_bounds.x() - adjusted_delta)); 1567 new_bounds.set_x(std::max(min_x, new_bounds.x() - adjusted_delta));
1733 set_ideal_bounds(i, new_bounds); 1568 tabs_.set_ideal_bounds(i, new_bounds);
1734 } 1569 }
1735 const bool is_active_mini = tab_at(active_index)->data().mini; 1570 const bool is_active_mini = tab_at(active_index)->data().mini;
1736 const int active_width = ideal_bounds(active_index).width(); 1571 const int active_width = ideal_bounds(active_index).width();
1737 for (int i = active_index + 1; i < tab_count(); ++i) { 1572 for (int i = active_index + 1; i < tab_count(); ++i) {
1738 const int max_x = ideal_bounds(active_index).x() + 1573 const int max_x = ideal_bounds(active_index).x() +
1739 (kStackedPadding * std::min(i - active_index, kMaxStackedCount)); 1574 (kStackedPadding * std::min(i - active_index, kMaxStackedCount));
1740 gfx::Rect new_bounds(ideal_bounds(i)); 1575 gfx::Rect new_bounds(ideal_bounds(i));
1741 int new_x = std::max(new_bounds.x() + delta, max_x); 1576 int new_x = std::max(new_bounds.x() + delta, max_x);
1742 if (new_x == max_x && !tab_at(i)->data().mini && !is_active_mini && 1577 if (new_x == max_x && !tab_at(i)->data().mini && !is_active_mini &&
1743 new_bounds.width() != active_width) 1578 new_bounds.width() != active_width)
1744 new_x += (active_width - new_bounds.width()); 1579 new_x += (active_width - new_bounds.width());
1745 new_bounds.set_x(new_x); 1580 new_bounds.set_x(new_x);
1746 set_ideal_bounds(i, new_bounds); 1581 tabs_.set_ideal_bounds(i, new_bounds);
1747 } 1582 }
1748 } else { 1583 } else {
1749 // Drag the tabs to the right, stacking tabs after the active tab. 1584 // Drag the tabs to the right, stacking tabs after the active tab.
1750 const int last_tab_width = ideal_bounds(tab_count() - 1).width(); 1585 const int last_tab_width = ideal_bounds(tab_count() - 1).width();
1751 const int last_tab_x = width() - new_tab_button_width() - last_tab_width; 1586 const int last_tab_x = tab_area_width() - last_tab_width;
1752 if (active_index == tab_count() - 1 && 1587 if (active_index == tab_count() - 1 &&
1753 ideal_bounds(tab_count() - 1).x() == last_tab_x) 1588 ideal_bounds(tab_count() - 1).x() == last_tab_x)
1754 return; 1589 return;
1755 const int adjusted_delta = 1590 const int adjusted_delta =
1756 std::min(last_tab_x - 1591 std::min(last_tab_x -
1757 kStackedPadding * std::min(tab_count() - active_index - 1, 1592 kStackedPadding * std::min(tab_count() - active_index - 1,
1758 kMaxStackedCount) - 1593 kMaxStackedCount) -
1759 ideal_bounds(active_index).x(), 1594 ideal_bounds(active_index).x(),
1760 delta); 1595 delta);
1761 for (int last_index = tab_count() - 1, i = last_index; i >= active_index; 1596 for (int last_index = tab_count() - 1, i = last_index; i >= active_index;
1762 --i) { 1597 --i) {
1763 const int max_x = last_tab_x - 1598 const int max_x = last_tab_x -
1764 std::min(tab_count() - i - 1, kMaxStackedCount) * kStackedPadding; 1599 std::min(tab_count() - i - 1, kMaxStackedCount) * kStackedPadding;
1765 gfx::Rect new_bounds(ideal_bounds(i)); 1600 gfx::Rect new_bounds(ideal_bounds(i));
1766 int new_x = std::min(max_x, new_bounds.x() + adjusted_delta); 1601 int new_x = std::min(max_x, new_bounds.x() + adjusted_delta);
1767 // Because of rounding not all tabs are the same width. Adjust the 1602 // Because of rounding not all tabs are the same width. Adjust the
1768 // position to accommodate this, otherwise the stacking is off. 1603 // position to accommodate this, otherwise the stacking is off.
1769 if (new_x == max_x && !tab_at(i)->data().mini && 1604 if (new_x == max_x && !tab_at(i)->data().mini &&
1770 new_bounds.width() != last_tab_width) 1605 new_bounds.width() != last_tab_width)
1771 new_x += (last_tab_width - new_bounds.width()); 1606 new_x += (last_tab_width - new_bounds.width());
1772 new_bounds.set_x(new_x); 1607 new_bounds.set_x(new_x);
1773 set_ideal_bounds(i, new_bounds); 1608 tabs_.set_ideal_bounds(i, new_bounds);
1774 } 1609 }
1775 for (int i = active_index - 1; i >= 0; --i) { 1610 for (int i = active_index - 1; i >= 0; --i) {
1776 const int min_x = ideal_bounds(active_index).x() - 1611 const int min_x = ideal_bounds(active_index).x() -
1777 std::min(active_index - i, kMaxStackedCount) * kStackedPadding; 1612 std::min(active_index - i, kMaxStackedCount) * kStackedPadding;
1778 gfx::Rect new_bounds(ideal_bounds(i)); 1613 gfx::Rect new_bounds(ideal_bounds(i));
1779 new_bounds.set_x(std::min(min_x, new_bounds.x() + delta)); 1614 new_bounds.set_x(std::min(min_x, new_bounds.x() + delta));
1780 set_ideal_bounds(i, new_bounds); 1615 tabs_.set_ideal_bounds(i, new_bounds);
1781 } 1616 }
1782 if (ideal_bounds(tab_count() - 1).right() >= newtab_button_->x()) 1617 if (ideal_bounds(tab_count() - 1).right() >= newtab_button_->x())
1783 newtab_button_->SetVisible(false); 1618 newtab_button_->SetVisible(false);
1784 } 1619 }
1785 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); 1620 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_);
1786 SchedulePaint(); 1621 SchedulePaint();
1787 } 1622 }
1788 1623
1789 bool TabStrip::IsStackingDraggedTabs() const { 1624 bool TabStrip::IsStackingDraggedTabs() const {
1790 return drag_controller_.get() && drag_controller_->started_drag() && 1625 return drag_controller_.get() && drag_controller_->started_drag() &&
1791 (drag_controller_->move_behavior() == 1626 (drag_controller_->move_behavior() ==
1792 TabDragController::MOVE_VISIBILE_TABS); 1627 TabDragController::MOVE_VISIBILE_TABS);
1793 } 1628 }
1794 1629
1795 void TabStrip::LayoutDraggedTabsAt(const std::vector<Tab*>& tabs, 1630 void TabStrip::LayoutDraggedTabsAt(const Tabs& tabs,
1796 Tab* active_tab, 1631 Tab* active_tab,
1797 const gfx::Point& location, 1632 const gfx::Point& location,
1798 bool initial_drag) { 1633 bool initial_drag) {
1799 // Immediately hide the new tab button if the last tab is being dragged. 1634 // Immediately hide the new tab button if the last tab is being dragged.
1800 if (tab_at(tab_count() - 1)->dragging()) 1635 if (GetLastVisibleTab()->dragging())
1801 newtab_button_->SetVisible(false); 1636 newtab_button_->SetVisible(false);
1802 std::vector<gfx::Rect> bounds; 1637 std::vector<gfx::Rect> bounds;
1803 CalculateBoundsForDraggedTabs(tabs, &bounds); 1638 CalculateBoundsForDraggedTabs(tabs, &bounds);
1804 DCHECK_EQ(tabs.size(), bounds.size()); 1639 DCHECK_EQ(tabs.size(), bounds.size());
1805 int active_tab_model_index = GetModelIndexOfTab(active_tab); 1640 int active_tab_model_index = GetModelIndexOfTab(active_tab);
1806 int active_tab_index = static_cast<int>( 1641 int active_tab_index = static_cast<int>(
1807 std::find(tabs.begin(), tabs.end(), active_tab) - tabs.begin()); 1642 std::find(tabs.begin(), tabs.end(), active_tab) - tabs.begin());
1808 for (size_t i = 0; i < tabs.size(); ++i) { 1643 for (size_t i = 0; i < tabs.size(); ++i) {
1809 Tab* tab = tabs[i]; 1644 Tab* tab = tabs[i];
1810 gfx::Rect new_bounds = bounds[i]; 1645 gfx::Rect new_bounds = bounds[i];
1811 new_bounds.Offset(location.x(), location.y()); 1646 new_bounds.Offset(location.x(), location.y());
1812 int consecutive_index = 1647 int consecutive_index =
1813 active_tab_model_index - (active_tab_index - static_cast<int>(i)); 1648 active_tab_model_index - (active_tab_index - static_cast<int>(i));
1814 // If this is the initial layout during a drag and the tabs aren't 1649 // If this is the initial layout during a drag and the tabs aren't
1815 // consecutive animate the view into position. Do the same if the tab is 1650 // consecutive animate the view into position. Do the same if the tab is
1816 // already animating (which means we previously caused it to animate). 1651 // already animating (which means we previously caused it to animate).
1817 if ((initial_drag && 1652 if ((initial_drag &&
1818 GetModelIndexOfTab(tabs[i]) != consecutive_index) || 1653 GetModelIndexOfTab(tabs[i]) != consecutive_index) ||
1819 bounds_animator_.IsAnimating(tabs[i])) { 1654 bounds_animator_.IsAnimating(tabs[i])) {
1820 bounds_animator_.SetTargetBounds(tabs[i], new_bounds); 1655 bounds_animator_.SetTargetBounds(tabs[i], new_bounds);
1821 } else { 1656 } else {
1822 tab->SetBoundsRect(new_bounds); 1657 tab->SetBoundsRect(new_bounds);
1823 } 1658 }
1824 } 1659 }
1825 } 1660 }
1826 1661
1827 void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<Tab*>& tabs, 1662 void TabStrip::CalculateBoundsForDraggedTabs(const Tabs& tabs,
1828 std::vector<gfx::Rect>* bounds) { 1663 std::vector<gfx::Rect>* bounds) {
1829 int x = 0; 1664 int x = 0;
1830 for (size_t i = 0; i < tabs.size(); ++i) { 1665 for (size_t i = 0; i < tabs.size(); ++i) {
1831 Tab* tab = tabs[i]; 1666 Tab* tab = tabs[i];
1832 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) 1667 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini)
1833 x += kMiniToNonMiniGap; 1668 x += kMiniToNonMiniGap;
1834 gfx::Rect new_bounds = tab->bounds(); 1669 gfx::Rect new_bounds = tab->bounds();
1835 new_bounds.set_origin(gfx::Point(x, 0)); 1670 new_bounds.set_origin(gfx::Point(x, 0));
1836 bounds->push_back(new_bounds); 1671 bounds->push_back(new_bounds);
1837 x += tab->width() + kTabHorizontalOffset; 1672 x += tab->width() + kTabHorizontalOffset;
1838 } 1673 }
1839 } 1674 }
1840 1675
1841 int TabStrip::GetSizeNeededForTabs(const std::vector<Tab*>& tabs) { 1676 int TabStrip::GetSizeNeededForTabs(const Tabs& tabs) {
1842 int width = 0; 1677 int width = 0;
1843 for (size_t i = 0; i < tabs.size(); ++i) { 1678 for (size_t i = 0; i < tabs.size(); ++i) {
1844 Tab* tab = tabs[i]; 1679 Tab* tab = tabs[i];
1845 width += tab->width(); 1680 width += tab->width();
1846 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) 1681 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini)
1847 width += kMiniToNonMiniGap; 1682 width += kMiniToNonMiniGap;
1848 } 1683 }
1849 if (tabs.size() > 0) 1684 if (tabs.size() > 0)
1850 width += kTabHorizontalOffset * static_cast<int>(tabs.size() - 1); 1685 width += kTabHorizontalOffset * static_cast<int>(tabs.size() - 1);
1851 return width; 1686 return width;
1852 } 1687 }
1853 1688
1689 int TabStrip::GetMiniTabCount() const {
1690 int mini_count = 0;
1691 while (mini_count < tab_count() && tab_at(mini_count)->data().mini)
1692 mini_count++;
1693 return mini_count;
1694 }
1695
1696 const Tab* TabStrip::GetLastVisibleTab() const {
1697 return tab_at(tab_count() - 1);
1698 }
1699
1854 void TabStrip::RemoveTabFromViewModel(int index) { 1700 void TabStrip::RemoveTabFromViewModel(int index) {
1855 // We still need to paint the tab until we actually remove it. Put it 1701 // We still need to paint the tab until we actually remove it. Put it
1856 // in tabs_closing_map_ so we can find it. 1702 // in tabs_closing_map_ so we can find it.
1857 tabs_closing_map_[index].push_back(tab_at(index)); 1703 tabs_closing_map_[index].push_back(tab_at(index));
1858 UpdateTabsClosingMap(index + 1, -1); 1704 UpdateTabsClosingMap(index + 1, -1);
1859 tabs_.Remove(index); 1705 tabs_.Remove(index);
1860 } 1706 }
1861 1707
1862 void TabStrip::RemoveAndDeleteTab(Tab* tab) { 1708 void TabStrip::RemoveAndDeleteTab(Tab* tab) {
1863 scoped_ptr<Tab> deleter(tab); 1709 scoped_ptr<Tab> deleter(tab);
1864 for (TabsClosingMap::iterator i(tabs_closing_map_.begin()); 1710 FindClosingTabResult res(FindClosingTab(tab));
1865 i != tabs_closing_map_.end(); ++i) { 1711 res.first->second.erase(res.second);
1866 std::vector<Tab*>::iterator j = 1712 if (res.first->second.empty())
1867 std::find(i->second.begin(), i->second.end(), tab); 1713 tabs_closing_map_.erase(res.first);
1868 if (j != i->second.end()) {
1869 i->second.erase(j);
1870 if (i->second.empty())
1871 tabs_closing_map_.erase(i);
1872 return;
1873 }
1874 }
1875 NOTREACHED();
1876 } 1714 }
1877 1715
1878 void TabStrip::UpdateTabsClosingMap(int index, int delta) { 1716 void TabStrip::UpdateTabsClosingMap(int index, int delta) {
1879 if (tabs_closing_map_.empty()) 1717 if (tabs_closing_map_.empty())
1880 return; 1718 return;
1881 1719
1882 if (delta == -1 && 1720 if (delta == -1 &&
1883 tabs_closing_map_.find(index - 1) != tabs_closing_map_.end() && 1721 tabs_closing_map_.find(index - 1) != tabs_closing_map_.end() &&
1884 tabs_closing_map_.find(index) != tabs_closing_map_.end()) { 1722 tabs_closing_map_.find(index) != tabs_closing_map_.end()) {
1885 const std::vector<Tab*>& tabs(tabs_closing_map_[index]); 1723 const Tabs& tabs(tabs_closing_map_[index]);
1886 tabs_closing_map_[index - 1].insert( 1724 tabs_closing_map_[index - 1].insert(
1887 tabs_closing_map_[index - 1].end(), tabs.begin(), tabs.end()); 1725 tabs_closing_map_[index - 1].end(), tabs.begin(), tabs.end());
1888 } 1726 }
1889 TabsClosingMap updated_map; 1727 TabsClosingMap updated_map;
1890 for (TabsClosingMap::iterator i(tabs_closing_map_.begin()); 1728 for (TabsClosingMap::iterator i(tabs_closing_map_.begin());
1891 i != tabs_closing_map_.end(); ++i) { 1729 i != tabs_closing_map_.end(); ++i) {
1892 if (i->first > index) 1730 if (i->first > index)
1893 updated_map[i->first + delta] = i->second; 1731 updated_map[i->first + delta] = i->second;
1894 else if (i->first < index) 1732 else if (i->first < index)
1895 updated_map[i->first] = i->second; 1733 updated_map[i->first] = i->second;
1896 } 1734 }
1897 if (delta > 0 && tabs_closing_map_.find(index) != tabs_closing_map_.end()) 1735 if (delta > 0 && tabs_closing_map_.find(index) != tabs_closing_map_.end())
1898 updated_map[index + delta] = tabs_closing_map_[index]; 1736 updated_map[index + delta] = tabs_closing_map_[index];
1899 tabs_closing_map_.swap(updated_map); 1737 tabs_closing_map_.swap(updated_map);
1900 } 1738 }
1901 1739
1902 void TabStrip::StartedDraggingTabs(const std::vector<Tab*>& tabs) { 1740 void TabStrip::StartedDraggingTabs(const Tabs& tabs) {
1903 // Let the controller know that the user started dragging tabs. 1741 // Let the controller know that the user started dragging tabs.
1904 controller()->OnStartedDraggingTabs(); 1742 controller()->OnStartedDraggingTabs();
1905 1743
1906 // Hide the new tab button immediately if we didn't originate the drag. 1744 // Hide the new tab button immediately if we didn't originate the drag.
1907 if (!drag_controller_.get()) 1745 if (!drag_controller_.get())
1908 newtab_button_->SetVisible(false); 1746 newtab_button_->SetVisible(false);
1909 1747
1910 PrepareForAnimation(); 1748 PrepareForAnimation();
1911 1749
1912 // Reset dragging state of existing tabs. 1750 // Reset dragging state of existing tabs.
(...skipping 17 matching lines...) Expand all
1930 SchedulePaint(); 1768 SchedulePaint();
1931 } 1769 }
1932 1770
1933 void TabStrip::DraggedTabsDetached() { 1771 void TabStrip::DraggedTabsDetached() {
1934 // Let the controller know that the user is not dragging this tabstrip's tabs 1772 // Let the controller know that the user is not dragging this tabstrip's tabs
1935 // anymore. 1773 // anymore.
1936 controller()->OnStoppedDraggingTabs(); 1774 controller()->OnStoppedDraggingTabs();
1937 newtab_button_->SetVisible(true); 1775 newtab_button_->SetVisible(true);
1938 } 1776 }
1939 1777
1940 void TabStrip::StoppedDraggingTabs(const std::vector<Tab*>& tabs, 1778 void TabStrip::StoppedDraggingTabs(const Tabs& tabs,
1941 const std::vector<int>& initial_positions, 1779 const std::vector<int>& initial_positions,
1942 bool move_only, 1780 bool move_only,
1943 bool completed) { 1781 bool completed) {
1944 // Let the controller know that the user stopped dragging tabs. 1782 // Let the controller know that the user stopped dragging tabs.
1945 controller()->OnStoppedDraggingTabs(); 1783 controller()->OnStoppedDraggingTabs();
1946 1784
1947 newtab_button_->SetVisible(true); 1785 newtab_button_->SetVisible(true);
1948 if (move_only && touch_layout_.get()) { 1786 if (move_only && touch_layout_) {
1949 if (completed) { 1787 if (completed)
1950 touch_layout_->SizeToFit(); 1788 touch_layout_->SizeToFit();
1951 } else { 1789 else
1952 SetIdealBoundsFromPositions(initial_positions); 1790 SetIdealBoundsFromPositions(initial_positions);
1953 }
1954 } 1791 }
1955 bool is_first_tab = true; 1792 bool is_first_tab = true;
1956 for (size_t i = 0; i < tabs.size(); ++i) 1793 for (size_t i = 0; i < tabs.size(); ++i)
1957 StoppedDraggingTab(tabs[i], &is_first_tab); 1794 StoppedDraggingTab(tabs[i], &is_first_tab);
1958 } 1795 }
1959 1796
1960 void TabStrip::StoppedDraggingTab(Tab* tab, bool* is_first_tab) { 1797 void TabStrip::StoppedDraggingTab(Tab* tab, bool* is_first_tab) {
1961 int tab_data_index = GetModelIndexOfTab(tab); 1798 int tab_data_index = GetModelIndexOfTab(tab);
1962 if (tab_data_index == -1) { 1799 if (tab_data_index == -1) {
1963 // The tab was removed before the drag completed. Don't do anything. 1800 // The tab was removed before the drag completed. Don't do anything.
(...skipping 29 matching lines...) Expand all
1993 1830
1994 void TabStrip::DestroyDragController() { 1831 void TabStrip::DestroyDragController() {
1995 newtab_button_->SetVisible(true); 1832 newtab_button_->SetVisible(true);
1996 drag_controller_.reset(); 1833 drag_controller_.reset();
1997 } 1834 }
1998 1835
1999 TabDragController* TabStrip::ReleaseDragController() { 1836 TabDragController* TabStrip::ReleaseDragController() {
2000 return drag_controller_.release(); 1837 return drag_controller_.release();
2001 } 1838 }
2002 1839
1840 TabStrip::FindClosingTabResult TabStrip::FindClosingTab(const Tab* tab) {
1841 DCHECK(tab->closing());
1842 for (TabsClosingMap::iterator i(tabs_closing_map_.begin());
1843 i != tabs_closing_map_.end(); ++i) {
1844 Tabs::iterator j = std::find(i->second.begin(), i->second.end(), tab);
1845 if (j != i->second.end())
1846 return FindClosingTabResult(i, j);
1847 }
1848 NOTREACHED();
1849 return FindClosingTabResult(tabs_closing_map_.end(), Tabs::iterator());
1850 }
1851
2003 void TabStrip::PaintClosingTabs(gfx::Canvas* canvas, 1852 void TabStrip::PaintClosingTabs(gfx::Canvas* canvas,
2004 int index, 1853 int index,
2005 const views::CullSet& cull_set) { 1854 const views::CullSet& cull_set) {
2006 if (tabs_closing_map_.find(index) == tabs_closing_map_.end()) 1855 if (tabs_closing_map_.find(index) == tabs_closing_map_.end())
2007 return; 1856 return;
2008 1857
2009 const std::vector<Tab*>& tabs = tabs_closing_map_[index]; 1858 const Tabs& tabs = tabs_closing_map_[index];
2010 for (std::vector<Tab*>::const_reverse_iterator i(tabs.rbegin()); 1859 for (Tabs::const_reverse_iterator i(tabs.rbegin()); i != tabs.rend(); ++i)
2011 i != tabs.rend(); ++i) {
2012 (*i)->Paint(canvas, cull_set); 1860 (*i)->Paint(canvas, cull_set);
2013 }
2014 } 1861 }
2015 1862
2016 void TabStrip::UpdateStackedLayoutFromMouseEvent(views::View* source, 1863 void TabStrip::UpdateStackedLayoutFromMouseEvent(views::View* source,
2017 const ui::MouseEvent& event) { 1864 const ui::MouseEvent& event) {
2018 if (!adjust_layout_) 1865 if (!adjust_layout_)
2019 return; 1866 return;
2020 1867
2021 // The following code attempts to switch to shrink (not stacked) layout when 1868 // The following code attempts to switch to shrink (not stacked) layout when
2022 // the mouse exits the tabstrip (or the mouse is pressed on a stacked tab) and 1869 // the mouse exits the tabstrip (or the mouse is pressed on a stacked tab) and
2023 // to stacked layout when a touch device is used. This is made problematic by 1870 // to stacked layout when a touch device is used. This is made problematic by
2024 // windows generating mouse move events that do not clearly indicate the move 1871 // windows generating mouse move events that do not clearly indicate the move
2025 // is the result of a touch device. This assumes a real mouse is used if 1872 // is the result of a touch device. This assumes a real mouse is used if
2026 // |kMouseMoveCountBeforeConsiderReal| mouse move events are received within 1873 // |kMouseMoveCountBeforeConsiderReal| mouse move events are received within
2027 // the time window |kMouseMoveTimeMS|. At the time we get a mouse press we 1874 // the time window |kMouseMoveTimeMS|. At the time we get a mouse press we
2028 // know whether its from a touch device or not, but we don't layout then else 1875 // know whether its from a touch device or not, but we don't layout then else
2029 // everything shifts. Instead we wait for the release. 1876 // everything shifts. Instead we wait for the release.
2030 // 1877 //
2031 // TODO(sky): revisit this when touch events are really plumbed through. 1878 // TODO(sky): revisit this when touch events are really plumbed through.
2032 1879
2033 switch (event.type()) { 1880 switch (event.type()) {
2034 case ui::ET_MOUSE_PRESSED: 1881 case ui::ET_MOUSE_PRESSED:
2035 mouse_move_count_ = 0; 1882 mouse_move_count_ = 0;
2036 last_mouse_move_time_ = base::TimeTicks(); 1883 last_mouse_move_time_ = base::TimeTicks();
2037 SetResetToShrinkOnExit((event.flags() & ui::EF_FROM_TOUCH) == 0); 1884 SetResetToShrinkOnExit((event.flags() & ui::EF_FROM_TOUCH) == 0);
2038 if (reset_to_shrink_on_exit_ && touch_layout_.get()) { 1885 if (reset_to_shrink_on_exit_ && touch_layout_) {
2039 gfx::Point tab_strip_point(event.location()); 1886 gfx::Point tab_strip_point(event.location());
2040 views::View::ConvertPointToTarget(source, this, &tab_strip_point); 1887 views::View::ConvertPointToTarget(source, this, &tab_strip_point);
2041 Tab* tab = FindTabForEvent(tab_strip_point); 1888 Tab* tab = FindTabForEvent(tab_strip_point);
2042 if (tab && touch_layout_->IsStacked(GetModelIndexOfTab(tab))) { 1889 if (tab && touch_layout_->IsStacked(GetModelIndexOfTab(tab))) {
2043 SetStackedLayout(false); 1890 SetStackedLayout(false);
2044 controller_->StackedLayoutMaybeChanged(); 1891 controller_->StackedLayoutMaybeChanged();
2045 } 1892 }
2046 } 1893 }
2047 break; 1894 break;
2048 1895
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2155 // When there are multiple tabs, we'll have one selected and some unselected 2002 // When there are multiple tabs, we'll have one selected and some unselected
2156 // tabs. If the desired width was between the minimum sizes of these types, 2003 // tabs. If the desired width was between the minimum sizes of these types,
2157 // try to shrink the tabs with the smaller minimum. For example, if we have 2004 // try to shrink the tabs with the smaller minimum. For example, if we have
2158 // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If 2005 // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If
2159 // selected tabs have a minimum width of 4 and unselected tabs have a minimum 2006 // selected tabs have a minimum width of 4 and unselected tabs have a minimum
2160 // width of 1, the above code would set *unselected_width = 2.5, 2007 // width of 1, the above code would set *unselected_width = 2.5,
2161 // *selected_width = 4, which results in a total width of 11.5. Instead, we 2008 // *selected_width = 4, which results in a total width of 11.5. Instead, we
2162 // want to set *unselected_width = 2, *selected_width = 4, for a total width 2009 // want to set *unselected_width = 2, *selected_width = 4, for a total width
2163 // of 10. 2010 // of 10.
2164 if (tab_count > 1) { 2011 if (tab_count > 1) {
2165 if ((min_unselected_width < min_selected_width) && 2012 if (desired_tab_width < min_selected_width) {
2166 (desired_tab_width < min_selected_width)) {
2167 // Unselected width = (total width - selected width) / (num_tabs - 1) 2013 // Unselected width = (total width - selected width) / (num_tabs - 1)
2168 *unselected_width = std::max(static_cast<double>( 2014 *unselected_width = std::max(static_cast<double>(
2169 available_width - total_offset - min_selected_width) / 2015 available_width - total_offset - min_selected_width) /
2170 static_cast<double>(tab_count - 1), min_unselected_width); 2016 static_cast<double>(tab_count - 1), min_unselected_width);
2171 } else if ((min_unselected_width > min_selected_width) &&
2172 (desired_tab_width < min_unselected_width)) {
2173 // Selected width = (total width - (unselected width * (num_tabs - 1)))
2174 *selected_width = std::max(available_width - total_offset -
2175 (min_unselected_width * (tab_count - 1)), min_selected_width);
2176 } 2017 }
2177 } 2018 }
2178 } 2019 }
2179 2020
2180 void TabStrip::ResizeLayoutTabs() { 2021 void TabStrip::ResizeLayoutTabs() {
2181 // We've been called back after the TabStrip has been emptied out (probably 2022 // We've been called back after the TabStrip has been emptied out (probably
2182 // just prior to the window being destroyed). We need to do nothing here or 2023 // just prior to the window being destroyed). We need to do nothing here or
2183 // else GetTabAt below will crash. 2024 // else GetTabAt below will crash.
2184 if (tab_count() == 0) 2025 if (tab_count() == 0)
2185 return; 2026 return;
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2391 void TabStrip::PrepareForAnimation() { 2232 void TabStrip::PrepareForAnimation() {
2392 if (!IsDragSessionActive() && !TabDragController::IsAttachedTo(this)) { 2233 if (!IsDragSessionActive() && !TabDragController::IsAttachedTo(this)) {
2393 for (int i = 0; i < tab_count(); ++i) 2234 for (int i = 0; i < tab_count(); ++i)
2394 tab_at(i)->set_dragging(false); 2235 tab_at(i)->set_dragging(false);
2395 } 2236 }
2396 } 2237 }
2397 2238
2398 void TabStrip::GenerateIdealBounds() { 2239 void TabStrip::GenerateIdealBounds() {
2399 int new_tab_y = 0; 2240 int new_tab_y = 0;
2400 2241
2401 if (touch_layout_.get()) { 2242 if (touch_layout_) {
2402 if (tabs_.view_size() == 0) 2243 if (tabs_.view_size() == 0)
2403 return; 2244 return;
2404 2245
2405 int new_tab_x = tabs_.ideal_bounds(tabs_.view_size() - 1).right() + 2246 int new_tab_x = tabs_.ideal_bounds(tabs_.view_size() - 1).right() +
2406 kNewTabButtonHorizontalOffset; 2247 kNewTabButtonHorizontalOffset;
2407 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); 2248 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y));
2408 return; 2249 return;
2409 } 2250 }
2410 2251
2411 double unselected, selected; 2252 GetDesiredTabWidths(tab_count(), GetMiniTabCount(),
2412 GetDesiredTabWidths(tab_count(), GetMiniTabCount(), &unselected, &selected); 2253 &current_unselected_width_, &current_selected_width_);
2413 current_unselected_width_ = unselected;
2414 current_selected_width_ = selected;
2415 2254
2416 // NOTE: This currently assumes a tab's height doesn't differ based on 2255 // NOTE: This currently assumes a tab's height doesn't differ based on
2417 // selected state or the number of tabs in the strip! 2256 // selected state or the number of tabs in the strip!
2418 int tab_height = Tab::GetStandardSize().height(); 2257 int tab_height = Tab::GetStandardSize().height();
2419 int first_non_mini_index = 0; 2258 int first_non_mini_index = 0;
2420 double tab_x = GenerateIdealBoundsForMiniTabs(&first_non_mini_index); 2259 double tab_x = GenerateIdealBoundsForMiniTabs(&first_non_mini_index);
2421 for (int i = first_non_mini_index; i < tab_count(); ++i) { 2260 for (int i = first_non_mini_index; i < tab_count(); ++i) {
2422 Tab* tab = tab_at(i); 2261 Tab* tab = tab_at(i);
2423 DCHECK(!tab->data().mini); 2262 DCHECK(!tab->data().mini);
2424 double tab_width = tab->IsActive() ? selected : unselected; 2263 double tab_width =
2264 tab->IsActive() ? current_selected_width_ : current_unselected_width_;
2425 double end_of_tab = tab_x + tab_width; 2265 double end_of_tab = tab_x + tab_width;
2426 int rounded_tab_x = Round(tab_x); 2266 int rounded_tab_x = Round(tab_x);
2427 set_ideal_bounds( 2267 tabs_.set_ideal_bounds(
2428 i, 2268 i,
2429 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, 2269 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
2430 tab_height)); 2270 tab_height));
2431 tab_x = end_of_tab + kTabHorizontalOffset; 2271 tab_x = end_of_tab + kTabHorizontalOffset;
2432 } 2272 }
2433 2273
2434 // Update bounds of new tab button. 2274 // Update bounds of new tab button.
2435 int new_tab_x; 2275 int new_tab_x;
2436 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && 2276 if ((Tab::GetStandardSize().width() - Round(current_unselected_width_)) > 1 &&
2437 !in_tab_close_) { 2277 !in_tab_close_) {
2438 // We're shrinking tabs, so we need to anchor the New Tab button to the 2278 // We're shrinking tabs, so we need to anchor the New Tab button to the
2439 // right edge of the TabStrip's bounds, rather than the right edge of the 2279 // right edge of the TabStrip's bounds, rather than the right edge of the
2440 // right-most Tab, otherwise it'll bounce when animating. 2280 // right-most Tab, otherwise it'll bounce when animating.
2441 new_tab_x = width() - newtab_button_bounds_.width(); 2281 new_tab_x = width() - newtab_button_bounds_.width();
2442 } else { 2282 } else {
2443 new_tab_x = Round(tab_x - kTabHorizontalOffset) + 2283 new_tab_x = Round(tab_x - kTabHorizontalOffset) +
2444 kNewTabButtonHorizontalOffset; 2284 kNewTabButtonHorizontalOffset;
2445 } 2285 }
2446 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); 2286 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y));
2447 } 2287 }
2448 2288
2449 int TabStrip::GenerateIdealBoundsForMiniTabs(int* first_non_mini_index) { 2289 int TabStrip::GenerateIdealBoundsForMiniTabs(int* first_non_mini_index) {
2450 int next_x = 0; 2290 int next_x = 0;
2451 int mini_width = Tab::GetMiniWidth(); 2291 int mini_width = Tab::GetMiniWidth();
2452 int tab_height = Tab::GetStandardSize().height(); 2292 int tab_height = Tab::GetStandardSize().height();
2453 int index = 0; 2293 int index = 0;
2454 for (; index < tab_count() && tab_at(index)->data().mini; ++index) { 2294 for (; index < tab_count() && tab_at(index)->data().mini; ++index) {
2455 set_ideal_bounds(index, 2295 tabs_.set_ideal_bounds(index, gfx::Rect(next_x, 0, mini_width, tab_height));
2456 gfx::Rect(next_x, 0, mini_width, tab_height));
2457 next_x += mini_width + kTabHorizontalOffset; 2296 next_x += mini_width + kTabHorizontalOffset;
2458 } 2297 }
2459 if (index > 0 && index < tab_count()) 2298 if (index > 0 && index < tab_count())
2460 next_x += kMiniToNonMiniGap; 2299 next_x += kMiniToNonMiniGap;
2461 if (first_non_mini_index) 2300 if (first_non_mini_index)
2462 *first_non_mini_index = index; 2301 *first_non_mini_index = index;
2463 return next_x; 2302 return next_x;
2464 } 2303 }
2465 2304
2466 // static
2467 int TabStrip::new_tab_button_width() {
2468 return kNewTabButtonAssetWidth + kNewTabButtonHorizontalOffset;
2469 }
2470
2471 // static
2472 int TabStrip::button_v_offset() {
2473 return kNewTabButtonVerticalOffset;
2474 }
2475
2476 int TabStrip::tab_area_width() const {
2477 return width() - new_tab_button_width();
2478 }
2479
2480 void TabStrip::StartResizeLayoutAnimation() { 2305 void TabStrip::StartResizeLayoutAnimation() {
2481 PrepareForAnimation(); 2306 PrepareForAnimation();
2482 GenerateIdealBounds(); 2307 GenerateIdealBounds();
2483 AnimateToIdealBounds(); 2308 AnimateToIdealBounds();
2484 } 2309 }
2485 2310
2486 void TabStrip::StartMiniTabAnimation() { 2311 void TabStrip::StartMiniTabAnimation() {
2487 in_tab_close_ = false; 2312 in_tab_close_ = false;
2488 available_width_for_tabs_ = -1; 2313 available_width_for_tabs_ = -1;
2489 2314
2490 PrepareForAnimation(); 2315 PrepareForAnimation();
2491 2316
2492 GenerateIdealBounds(); 2317 GenerateIdealBounds();
2493 AnimateToIdealBounds(); 2318 AnimateToIdealBounds();
2494 } 2319 }
2495 2320
2496 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { 2321 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) {
2497 // The user initiated the close. We want to persist the bounds of all the 2322 // The user initiated the close. We want to persist the bounds of all the
2498 // existing tabs, so we manually shift ideal_bounds then animate. 2323 // existing tabs, so we manually shift ideal_bounds then animate.
2499 Tab* tab_closing = tab_at(model_index); 2324 Tab* tab_closing = tab_at(model_index);
2500 int delta = tab_closing->width() + kTabHorizontalOffset; 2325 int delta = tab_closing->width() + kTabHorizontalOffset;
2501 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to 2326 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to
2502 // add the extra padding. 2327 // add the extra padding.
2503 DCHECK_NE(model_index + 1, tab_count()); 2328 DCHECK_LT(model_index, tab_count() - 1);
2504 if (tab_closing->data().mini && model_index + 1 < tab_count() && 2329 if (tab_closing->data().mini && !tab_at(model_index + 1)->data().mini)
2505 !tab_at(model_index + 1)->data().mini) {
2506 delta += kMiniToNonMiniGap; 2330 delta += kMiniToNonMiniGap;
2507 }
2508 2331
2509 for (int i = model_index + 1; i < tab_count(); ++i) { 2332 for (int i = model_index + 1; i < tab_count(); ++i) {
2510 gfx::Rect bounds = ideal_bounds(i); 2333 gfx::Rect bounds = ideal_bounds(i);
2511 bounds.set_x(bounds.x() - delta); 2334 bounds.set_x(bounds.x() - delta);
2512 set_ideal_bounds(i, bounds); 2335 tabs_.set_ideal_bounds(i, bounds);
2513 } 2336 }
2514 2337
2515 newtab_button_bounds_.set_x(newtab_button_bounds_.x() - delta); 2338 newtab_button_bounds_.set_x(newtab_button_bounds_.x() - delta);
2516 2339
2517 PrepareForAnimation(); 2340 PrepareForAnimation();
2518 2341
2519 tab_closing->set_closing(true); 2342 tab_closing->set_closing(true);
2520 2343
2521 // We still need to paint the tab until we actually remove it. Put it in 2344 // We still need to paint the tab until we actually remove it. Put it in
2522 // tabs_closing_map_ so we can find it. 2345 // tabs_closing_map_ so we can find it.
(...skipping 22 matching lines...) Expand all
2545 2368
2546 int TabStrip::GetStartXForNormalTabs() const { 2369 int TabStrip::GetStartXForNormalTabs() const {
2547 int mini_tab_count = GetMiniTabCount(); 2370 int mini_tab_count = GetMiniTabCount();
2548 if (mini_tab_count == 0) 2371 if (mini_tab_count == 0)
2549 return 0; 2372 return 0;
2550 return mini_tab_count * (Tab::GetMiniWidth() + kTabHorizontalOffset) + 2373 return mini_tab_count * (Tab::GetMiniWidth() + kTabHorizontalOffset) +
2551 kMiniToNonMiniGap; 2374 kMiniToNonMiniGap;
2552 } 2375 }
2553 2376
2554 Tab* TabStrip::FindTabForEvent(const gfx::Point& point) { 2377 Tab* TabStrip::FindTabForEvent(const gfx::Point& point) {
2555 if (touch_layout_.get()) { 2378 if (touch_layout_) {
2556 int active_tab_index = touch_layout_->active_index(); 2379 int active_tab_index = touch_layout_->active_index();
2557 if (active_tab_index != -1) { 2380 if (active_tab_index != -1) {
2558 Tab* tab = FindTabForEventFrom(point, active_tab_index, -1); 2381 Tab* tab = FindTabForEventFrom(point, active_tab_index, -1);
2559 if (!tab) 2382 if (!tab)
2560 tab = FindTabForEventFrom(point, active_tab_index + 1, 1); 2383 tab = FindTabForEventFrom(point, active_tab_index + 1, 1);
2561 return tab; 2384 return tab;
2562 } else if (tab_count()) { 2385 }
2386 if (tab_count())
2563 return FindTabForEventFrom(point, 0, 1); 2387 return FindTabForEventFrom(point, 0, 1);
2564 }
2565 } else { 2388 } else {
2566 for (int i = 0; i < tab_count(); ++i) { 2389 for (int i = 0; i < tab_count(); ++i) {
2567 if (IsPointInTab(tab_at(i), point)) 2390 if (IsPointInTab(tab_at(i), point))
2568 return tab_at(i); 2391 return tab_at(i);
2569 } 2392 }
2570 } 2393 }
2571 return NULL; 2394 return NULL;
2572 } 2395 }
2573 2396
2574 Tab* TabStrip::FindTabForEventFrom(const gfx::Point& point, 2397 Tab* TabStrip::FindTabForEventFrom(const gfx::Point& point,
(...skipping 27 matching lines...) Expand all
2602 2425
2603 std::vector<int> TabStrip::GetTabXCoordinates() { 2426 std::vector<int> TabStrip::GetTabXCoordinates() {
2604 std::vector<int> results; 2427 std::vector<int> results;
2605 for (int i = 0; i < tab_count(); ++i) 2428 for (int i = 0; i < tab_count(); ++i)
2606 results.push_back(ideal_bounds(i).x()); 2429 results.push_back(ideal_bounds(i).x());
2607 return results; 2430 return results;
2608 } 2431 }
2609 2432
2610 void TabStrip::SwapLayoutIfNecessary() { 2433 void TabStrip::SwapLayoutIfNecessary() {
2611 bool needs_touch = NeedsTouchLayout(); 2434 bool needs_touch = NeedsTouchLayout();
2612 bool using_touch = touch_layout_.get() != NULL; 2435 bool using_touch = touch_layout_ != NULL;
2613 if (needs_touch == using_touch) 2436 if (needs_touch == using_touch)
2614 return; 2437 return;
2615 2438
2616 if (needs_touch) { 2439 if (needs_touch) {
2617 gfx::Size tab_size(Tab::GetMinimumSelectedSize()); 2440 gfx::Size tab_size(Tab::GetMinimumSelectedSize());
2618 tab_size.set_width(Tab::GetTouchWidth()); 2441 tab_size.set_width(Tab::GetTouchWidth());
2619 touch_layout_.reset(new StackedTabStripLayout( 2442 touch_layout_.reset(new StackedTabStripLayout(
2620 tab_size, 2443 tab_size,
2621 kTabHorizontalOffset, 2444 kTabHorizontalOffset,
2622 kStackedPadding, 2445 kStackedPadding,
2623 kMaxStackedCount, 2446 kMaxStackedCount,
2624 &tabs_)); 2447 &tabs_));
2625 touch_layout_->SetWidth(width() - new_tab_button_width()); 2448 touch_layout_->SetWidth(tab_area_width());
2626 // This has to be after SetWidth() as SetWidth() is going to reset the 2449 // This has to be after SetWidth() as SetWidth() is going to reset the
2627 // bounds of the mini-tabs (since StackedTabStripLayout doesn't yet know how 2450 // bounds of the mini-tabs (since StackedTabStripLayout doesn't yet know how
2628 // many mini-tabs there are). 2451 // many mini-tabs there are).
2629 GenerateIdealBoundsForMiniTabs(NULL); 2452 GenerateIdealBoundsForMiniTabs(NULL);
2630 touch_layout_->SetXAndMiniCount(GetStartXForNormalTabs(), 2453 touch_layout_->SetXAndMiniCount(GetStartXForNormalTabs(),
2631 GetMiniTabCount()); 2454 GetMiniTabCount());
2632 touch_layout_->SetActiveIndex(controller_->GetActiveIndex()); 2455 touch_layout_->SetActiveIndex(controller_->GetActiveIndex());
2633 } else { 2456 } else {
2634 touch_layout_.reset(); 2457 touch_layout_.reset();
2635 } 2458 }
2636 PrepareForAnimation(); 2459 PrepareForAnimation();
2637 GenerateIdealBounds(); 2460 GenerateIdealBounds();
2638 AnimateToIdealBounds(); 2461 AnimateToIdealBounds();
2639 } 2462 }
2640 2463
2641 bool TabStrip::NeedsTouchLayout() const { 2464 bool TabStrip::NeedsTouchLayout() const {
2642 if (!stacked_layout_) 2465 if (!stacked_layout_)
2643 return false; 2466 return false;
2644 2467
2645 int mini_tab_count = GetMiniTabCount(); 2468 int mini_tab_count = GetMiniTabCount();
2646 int normal_count = tab_count() - mini_tab_count; 2469 int normal_count = tab_count() - mini_tab_count;
2647 if (normal_count <= 1 || normal_count == mini_tab_count) 2470 if (normal_count <= 1 || normal_count == mini_tab_count)
2648 return false; 2471 return false;
2649 int x = GetStartXForNormalTabs(); 2472 int x = GetStartXForNormalTabs();
2650 int available_width = width() - x - new_tab_button_width(); 2473 int available_width = tab_area_width() - x;
2651 return (Tab::GetTouchWidth() * normal_count + 2474 return (Tab::GetTouchWidth() * normal_count +
2652 kTabHorizontalOffset * (normal_count - 1)) > available_width; 2475 kTabHorizontalOffset * (normal_count - 1)) > available_width;
2653 } 2476 }
2654 2477
2655 void TabStrip::SetResetToShrinkOnExit(bool value) { 2478 void TabStrip::SetResetToShrinkOnExit(bool value) {
2656 if (!adjust_layout_) 2479 if (!adjust_layout_)
2657 return; 2480 return;
2658 2481
2659 if (value && !stacked_layout_) 2482 if (value && !stacked_layout_)
2660 value = false; // We're already using shrink (not stacked) layout. 2483 value = false; // We're already using shrink (not stacked) layout.
2661 2484
2662 if (value == reset_to_shrink_on_exit_) 2485 if (value == reset_to_shrink_on_exit_)
2663 return; 2486 return;
2664 2487
2665 reset_to_shrink_on_exit_ = value; 2488 reset_to_shrink_on_exit_ = value;
2666 // Add an observer so we know when the mouse moves out of the tabstrip. 2489 // Add an observer so we know when the mouse moves out of the tabstrip.
2667 if (reset_to_shrink_on_exit_) 2490 if (reset_to_shrink_on_exit_)
2668 AddMessageLoopObserver(); 2491 AddMessageLoopObserver();
2669 else 2492 else
2670 RemoveMessageLoopObserver(); 2493 RemoveMessageLoopObserver();
2671 } 2494 }
2495
2496 void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) {
2497 if (sender == newtab_button_) {
2498 content::RecordAction(UserMetricsAction("NewTab_Button"));
2499 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_BUTTON,
2500 TabStripModel::NEW_TAB_ENUM_COUNT);
2501 if (event.IsMouseEvent()) {
2502 const ui::MouseEvent& mouse = static_cast<const ui::MouseEvent&>(event);
2503 if (mouse.IsOnlyMiddleMouseButton()) {
2504 base::string16 clipboard_text = GetClipboardText();
2505 if (!clipboard_text.empty())
2506 controller()->CreateNewTabWithLocation(clipboard_text);
2507 return;
2508 }
2509 }
2510
2511 controller()->CreateNewTab();
2512 if (event.type() == ui::ET_GESTURE_TAP)
2513 TouchUMA::RecordGestureAction(TouchUMA::GESTURE_NEWTAB_TAP);
2514 }
2515 }
2516
2517 // Overridden to support automation. See automation_proxy_uitest.cc.
2518 const views::View* TabStrip::GetViewByID(int view_id) const {
2519 if (tab_count() > 0) {
2520 if (view_id == VIEW_ID_TAB_LAST)
2521 return tab_at(tab_count() - 1);
2522 if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) {
2523 int index = view_id - VIEW_ID_TAB_0;
2524 return (index >= 0 && index < tab_count()) ? tab_at(index) : NULL;
2525 }
2526 }
2527
2528 return View::GetViewByID(view_id);
2529 }
2530
2531 bool TabStrip::OnMousePressed(const ui::MouseEvent& event) {
2532 UpdateStackedLayoutFromMouseEvent(this, event);
2533 // We can't return true here, else clicking in an empty area won't drag the
2534 // window.
2535 return false;
2536 }
2537
2538 bool TabStrip::OnMouseDragged(const ui::MouseEvent& event) {
2539 ContinueDrag(this, event);
2540 return true;
2541 }
2542
2543 void TabStrip::OnMouseReleased(const ui::MouseEvent& event) {
2544 EndDrag(END_DRAG_COMPLETE);
2545 UpdateStackedLayoutFromMouseEvent(this, event);
2546 }
2547
2548 void TabStrip::OnMouseCaptureLost() {
2549 EndDrag(END_DRAG_CAPTURE_LOST);
2550 }
2551
2552 void TabStrip::OnMouseMoved(const ui::MouseEvent& event) {
2553 UpdateStackedLayoutFromMouseEvent(this, event);
2554 }
2555
2556 void TabStrip::OnMouseEntered(const ui::MouseEvent& event) {
2557 SetResetToShrinkOnExit(true);
2558 }
2559
2560 void TabStrip::OnGestureEvent(ui::GestureEvent* event) {
2561 SetResetToShrinkOnExit(false);
2562 switch (event->type()) {
2563 case ui::ET_GESTURE_SCROLL_END:
2564 case ui::ET_SCROLL_FLING_START:
2565 case ui::ET_GESTURE_END:
2566 EndDrag(END_DRAG_COMPLETE);
2567 if (adjust_layout_) {
2568 SetStackedLayout(true);
2569 controller_->StackedLayoutMaybeChanged();
2570 }
2571 break;
2572
2573 case ui::ET_GESTURE_LONG_PRESS:
2574 if (drag_controller_.get())
2575 drag_controller_->SetMoveBehavior(TabDragController::REORDER);
2576 break;
2577
2578 case ui::ET_GESTURE_LONG_TAP: {
2579 EndDrag(END_DRAG_CANCEL);
2580 gfx::Point local_point = event->location();
2581 Tab* tab = FindTabForEvent(local_point);
2582 if (tab) {
2583 ConvertPointToScreen(this, &local_point);
2584 ShowContextMenuForTab(tab, local_point, ui::MENU_SOURCE_TOUCH);
2585 }
2586 break;
2587 }
2588
2589 case ui::ET_GESTURE_SCROLL_UPDATE:
2590 ContinueDrag(this, *event);
2591 break;
2592
2593 case ui::ET_GESTURE_BEGIN:
2594 EndDrag(END_DRAG_CANCEL);
2595 break;
2596
2597 case ui::ET_GESTURE_TAP: {
2598 const int active_index = controller_->GetActiveIndex();
2599 DCHECK_NE(-1, active_index);
2600 Tab* active_tab = tab_at(active_index);
2601 TouchUMA::GestureActionType action = TouchUMA::GESTURE_TABNOSWITCH_TAP;
2602 if (active_tab->tab_activated_with_last_gesture_begin())
2603 action = TouchUMA::GESTURE_TABSWITCH_TAP;
2604 TouchUMA::RecordGestureAction(action);
2605 break;
2606 }
2607
2608 default:
2609 break;
2610 }
2611 event->SetHandled();
2612 }
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