Index: chrome/browser/ui/views/tabs/tab_strip.cc |
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc |
index d4a5e5bacbb2b103945fc986f97b6a54f9c6c774..a7b008046a0d621e9d21f7a56292c693d90fb3a2 100644 |
--- a/chrome/browser/ui/views/tabs/tab_strip.cc |
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc |
@@ -106,26 +106,11 @@ const int kMouseMoveCountBeforeConsiderReal = 3; |
// Amount of time we delay before resizing after a close from a touch. |
const int kTouchResizeLayoutTimeMS = 2000; |
-// Horizontal offset for the new tab button to bring it closer to the |
-// rightmost tab. |
-const int kNewTabButtonHorizontalOffset = -11; |
- |
-// Vertical offset for the new tab button to bring it closer to the |
-// rightmost tab. |
-const int kNewTabButtonVerticalOffset = 7; |
- |
// Amount the left edge of a tab is offset from the rectangle of the tab's |
// favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. |
// Affects the size of the "V" between adjacent tabs. |
const int kTabHorizontalOffset = -26; |
-// The size of the new tab button must be hardcoded because we need to be |
-// able to lay it out before we are able to get its image from the |
-// ui::ThemeProvider. It also makes sense to do this, because the size of the |
-// new tab button should not need to be calculated dynamically. |
-const int kNewTabButtonAssetWidth = 34; |
-const int kNewTabButtonAssetHeight = 18; |
- |
// Amount to adjust the clip by when the tab is stacked before the active index. |
const int kStackedTabLeftClip = 20; |
@@ -147,16 +132,11 @@ base::string16 GetClipboardText() { |
class ResetDraggingStateDelegate |
: public views::BoundsAnimator::OwnedAnimationDelegate { |
public: |
- explicit ResetDraggingStateDelegate(Tab* tab) : tab_(tab) { |
- } |
- |
- virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE { |
- tab_->set_dragging(false); |
- } |
+ explicit ResetDraggingStateDelegate(Tab* tab); |
+ virtual ~ResetDraggingStateDelegate(); |
- virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE { |
- tab_->set_dragging(false); |
- } |
+ virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; |
+ virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; |
private: |
Tab* tab_; |
@@ -164,6 +144,22 @@ class ResetDraggingStateDelegate |
DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); |
}; |
+ResetDraggingStateDelegate::ResetDraggingStateDelegate(Tab* tab) : tab_(tab) { |
+} |
+ |
+ResetDraggingStateDelegate::~ResetDraggingStateDelegate() { |
+} |
+ |
+void ResetDraggingStateDelegate::AnimationEnded( |
+ const gfx::Animation* animation) { |
+ tab_->set_dragging(false); |
+} |
+ |
+void ResetDraggingStateDelegate::AnimationCanceled( |
+ const gfx::Animation* animation) { |
+ AnimationEnded(animation); |
Peter Kasting
2014/06/17 03:16:18
In the future some of these delegates will do more
|
+} |
+ |
// If |dest| contains the point |point_in_source| the event handler from |dest| |
// is returned. Otherwise NULL is returned. |
views::View* ConvertPointToViewAndGetEventHandler( |
@@ -366,7 +362,8 @@ gfx::ImageSkia NewTabButton::GetBackgroundImage( |
// flip. |
x += width; |
} |
- canvas.TileImageInt(*background, x, kNewTabButtonVerticalOffset + offset_y, |
+ canvas.TileImageInt(*background, x, |
+ TabStrip::kNewTabButtonVerticalOffset + offset_y, |
x_scale, 1.0f, 0, 0, width, height); |
if (alpha != 255) { |
@@ -433,7 +430,7 @@ class NewTabButtonTargeter : public views::MaskedViewTargeter { |
DCHECK_EQ(view, masked_view()); |
SkScalar w = SkIntToScalar(view->width()); |
- SkScalar v_offset = SkIntToScalar(kNewTabButtonVerticalOffset); |
+ SkScalar v_offset = SkIntToScalar(TabStrip::kNewTabButtonVerticalOffset); |
// These values are defined by the shape of the new tab image. Should that |
// image ever change, these values will need to be updated. They're so |
@@ -495,7 +492,7 @@ void TabStrip::RemoveTabDelegate::AnimationEnded( |
void TabStrip::RemoveTabDelegate::AnimationCanceled( |
const gfx::Animation* animation) { |
- CompleteRemove(); |
+ AnimationEnded(animation); |
} |
void TabStrip::RemoveTabDelegate::CompleteRemove() { |
@@ -525,9 +522,11 @@ void TabStrip::RemoveTabDelegate::HighlightCloseButton() { |
// static |
const char TabStrip::kViewClassName[] = "TabStrip"; |
- |
-// static |
+const int TabStrip::kNewTabButtonHorizontalOffset = -11; |
+const int TabStrip::kNewTabButtonVerticalOffset = 7; |
const int TabStrip::kMiniToNonMiniGap = 3; |
+const int TabStrip::kNewTabButtonAssetWidth = 34; |
+const int TabStrip::kNewTabButtonAssetHeight = 18; |
TabStrip::TabStrip(TabStripController* controller) |
: controller_(controller), |
@@ -588,7 +587,7 @@ void TabStrip::SetStackedLayout(bool stacked_layout) { |
SetResetToShrinkOnExit(false); |
SwapLayoutIfNecessary(); |
// When transitioning to stacked try to keep the active tab centered. |
- if (touch_layout_.get() && active_index != -1) { |
+ if (touch_layout_ && active_index != -1) { |
touch_layout_->SetActiveTabLocation( |
active_center - ideal_bounds(active_index).width() / 2); |
AnimateToIdealBounds(); |
@@ -632,7 +631,7 @@ void TabStrip::AddTabAt(int model_index, |
tabs_.Add(tab, model_index); |
AddChildView(tab); |
- if (touch_layout_.get()) { |
+ if (touch_layout_) { |
GenerateIdealBoundsForMiniTabs(NULL); |
int add_types = 0; |
if (data.mini) |
@@ -659,9 +658,9 @@ void TabStrip::MoveTab(int from_model_index, |
int to_model_index, |
const TabRendererData& data) { |
DCHECK_GT(tabs_.view_size(), 0); |
- Tab* last_tab = tab_at(tab_count() - 1); |
+ const Tab* last_tab = GetLastVisibleTab(); |
tab_at(from_model_index)->SetData(data); |
- if (touch_layout_.get()) { |
+ if (touch_layout_) { |
tabs_.MoveViewOnly(from_model_index, to_model_index); |
int mini_count = 0; |
GenerateIdealBoundsForMiniTabs(&mini_count); |
@@ -673,7 +672,7 @@ void TabStrip::MoveTab(int from_model_index, |
} |
StartMoveTabAnimation(); |
if (TabDragController::IsAttachedTo(this) && |
- (last_tab != tab_at(tab_count() - 1) || last_tab->dragging())) { |
+ (last_tab != GetLastVisibleTab() || last_tab->dragging())) { |
newtab_button_->SetVisible(false); |
} |
SwapLayoutIfNecessary(); |
@@ -683,7 +682,7 @@ void TabStrip::MoveTab(int from_model_index, |
} |
void TabStrip::RemoveTabAt(int model_index) { |
- if (touch_layout_.get()) { |
+ if (touch_layout_) { |
Tab* tab = tab_at(model_index); |
tab->set_closing(true); |
int old_x = tabs_.ideal_bounds(model_index).x(); |
@@ -710,7 +709,7 @@ void TabStrip::SetTabData(int model_index, const TabRendererData& data) { |
tab->SetData(data); |
if (mini_state_changed) { |
- if (touch_layout_.get()) { |
+ if (touch_layout_) { |
int mini_tab_count = 0; |
int start_x = GenerateIdealBoundsForMiniTabs(&mini_tab_count); |
touch_layout_->SetXAndMiniCount(start_x, mini_tab_count); |
@@ -734,7 +733,7 @@ void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) { |
return; |
int model_count = GetModelCount(); |
- if (model_index + 1 != model_count && model_count > 1) { |
+ if ((model_count > 1) && (model_index != model_count - 1)) { |
Peter Kasting
2014/06/17 03:16:18
This form read a lot more clearly to me than the o
sky
2014/06/17 15:42:42
I've noticed it's mostly just you that prefers the
Peter Kasting
2014/06/17 18:11:02
I'm fine taking them out. That wasn't actually re
|
// The user is about to close a tab other than the last tab. Set |
// available_width_for_tabs_ so that if we do a layout we don't position a |
// tab past the end of the second to last tab. We do this so that as the |
@@ -760,7 +759,7 @@ void TabStrip::PrepareForCloseAt(int model_index, CloseTabSource source) { |
void TabStrip::SetSelection(const ui::ListSelectionModel& old_selection, |
const ui::ListSelectionModel& new_selection) { |
- if (touch_layout_.get()) { |
+ if (touch_layout_) { |
touch_layout_->SetActiveIndex(new_selection.active()); |
// Only start an animation if we need to. Otherwise clicking on an |
// unselected tab and dragging won't work because dragging is only allowed |
@@ -793,10 +792,6 @@ void TabStrip::TabTitleChangedNotLoading(int model_index) { |
tab->StartMiniTabTitleAnimation(); |
} |
-Tab* TabStrip::tab_at(int index) const { |
- return static_cast<Tab*>(tabs_.view_at(index)); |
-} |
- |
int TabStrip::GetModelIndexOfTab(const Tab* tab) const { |
return tabs_.GetIndexOfView(tab); |
} |
@@ -869,10 +864,6 @@ void TabStrip::SetBackgroundOffset(const gfx::Point& offset) { |
newtab_button_->set_background_offset(offset); |
} |
-views::View* TabStrip::newtab_button() { |
- return newtab_button_; |
-} |
- |
void TabStrip::SetImmersiveStyle(bool enable) { |
if (immersive_style_ == enable) |
return; |
@@ -904,7 +895,7 @@ const ui::ListSelectionModel& TabStrip::GetSelectionModel() { |
bool TabStrip::SupportsMultipleSelection() { |
// TODO: currently only allow single selection in touch layout mode. |
- return touch_layout_.get() == NULL; |
+ return touch_layout_ == NULL; |
} |
void TabStrip::SelectTab(Tab* tab) { |
@@ -936,19 +927,9 @@ void TabStrip::CloseTab(Tab* tab, CloseTabSource source) { |
// If the tab is already closing, close the next tab. We do this so that the |
// user can rapidly close tabs by clicking the close button and not have |
// the animations interfere with that. |
- for (TabsClosingMap::const_iterator i(tabs_closing_map_.begin()); |
- i != tabs_closing_map_.end(); ++i) { |
- std::vector<Tab*>::const_iterator j = |
- std::find(i->second.begin(), i->second.end(), tab); |
- if (j != i->second.end()) { |
- if (i->first + 1 < GetModelCount()) |
- controller_->CloseTab(i->first + 1, source); |
- return; |
- } |
- } |
- // If we get here, it means a tab has been marked as closing but isn't in |
- // the set of known closing tabs. |
- NOTREACHED(); |
+ const int closed_tab_index = FindClosingTab(tab).first->first; |
+ if (closed_tab_index < GetModelCount()) |
+ controller_->CloseTab(closed_tab_index, source); |
return; |
} |
int model_index = GetModelIndexOfTab(tab); |
@@ -1005,7 +986,7 @@ void TabStrip::MaybeStartDrag( |
CHECK(false); |
return; |
} |
- std::vector<Tab*> tabs; |
+ Tabs tabs; |
int size_to_selected = 0; |
int x = tab->GetMirroredXInView(event.x()); |
int y = event.y(); |
@@ -1041,7 +1022,7 @@ void TabStrip::MaybeStartDrag( |
// . Real mouse event and control is down. This is mostly for testing. |
DCHECK(event.type() == ui::ET_MOUSE_PRESSED || |
event.type() == ui::ET_GESTURE_BEGIN); |
- if (touch_layout_.get() && |
+ if (touch_layout_ && |
((event.type() == ui::ET_MOUSE_PRESSED && |
(((event.flags() & ui::EF_FROM_TOUCH) && |
static_cast<const ui::MouseEvent&>(event).IsLeftMouseButton()) || |
@@ -1096,7 +1077,7 @@ void TabStrip::OnMouseEventInTab(views::View* source, |
bool TabStrip::ShouldPaintTab(const Tab* tab, gfx::Rect* clip) { |
// Only touch layout needs to restrict the clip. |
- if (!(touch_layout_.get() || IsStackingDraggedTabs())) |
+ if (!touch_layout_ && !IsStackingDraggedTabs()) |
return true; |
int index = GetModelIndexOfTab(tab); |
@@ -1115,9 +1096,9 @@ bool TabStrip::ShouldPaintTab(const Tab* tab, gfx::Rect* clip) { |
if (tab_at(index)->x() > tab_at(index + 1)->x()) |
return true; // Can happen during dragging. |
- clip->SetRect(0, 0, tab_at(index + 1)->x() - tab_at(index)->x() + |
- kStackedTabLeftClip, |
- tab_at(index)->height()); |
+ clip->SetRect( |
+ 0, 0, tab_at(index + 1)->x() - tab_at(index)->x() + kStackedTabLeftClip, |
+ tab_at(index)->height()); |
} else if (index > active_index && index > 0) { |
const gfx::Rect& tab_bounds(tab_at(index)->bounds()); |
const gfx::Rect& previous_tab_bounds(tab_at(index - 1)->bounds()); |
@@ -1167,22 +1148,17 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas, |
// ordering). Additionally we need to paint the tabs that are closing in |
// |tabs_closing_map_|. |
Tab* active_tab = NULL; |
- std::vector<Tab*> tabs_dragging; |
- std::vector<Tab*> selected_tabs; |
+ Tabs tabs_dragging; |
+ Tabs selected_tabs; |
int selected_tab_count = 0; |
bool is_dragging = false; |
int active_tab_index = -1; |
- // Since |touch_layout_| is created based on number of tabs and width we use |
- // the ideal state to determine if we should paint stacked. This minimizes |
- // painting changes as we switch between the two. |
- const bool stacking = stacked_layout_ || IsStackingDraggedTabs(); |
Peter Kasting
2014/06/17 03:16:18
Eliminating this relies on your comment over IM th
|
const chrome::HostDesktopType host_desktop_type = |
chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); |
const int inactive_tab_alpha = |
- host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH ? |
- kInactiveTabAndNewTabButtonAlphaAsh : |
- kInactiveTabAndNewTabButtonAlpha; |
+ (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) ? |
+ kInactiveTabAndNewTabButtonAlphaAsh : kInactiveTabAndNewTabButtonAlpha; |
if (inactive_tab_alpha < 255) |
canvas->SaveLayerAlpha(inactive_tab_alpha); |
@@ -1193,7 +1169,7 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas, |
Tab* tab = tab_at(i); |
if (tab->IsSelected()) |
selected_tab_count++; |
- if (tab->dragging() && !stacking) { |
+ if (tab->dragging() && !stacked_layout_) { |
is_dragging = true; |
if (tab->IsActive()) { |
active_tab = tab; |
@@ -1203,7 +1179,7 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas, |
} |
} else if (!tab->IsActive()) { |
if (!tab->IsSelected()) { |
- if (!stacking) |
+ if (!stacked_layout_) |
tab->Paint(canvas, cull_set); |
} else { |
selected_tabs.push_back(tab); |
@@ -1216,7 +1192,7 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas, |
} |
// Draw from the left and then the right if we're in touch mode. |
- if (stacking && active_tab_index >= 0) { |
+ if (stacked_layout_ && active_tab_index >= 0) { |
for (int i = 0; i < active_tab_index; ++i) { |
Tab* tab = tab_at(i); |
tab->Paint(canvas, cull_set); |
@@ -1280,17 +1256,11 @@ gfx::Size TabStrip::GetPreferredSize() const { |
// the size required for a single selected tab plus the new tab button. Don't |
// base it on the actual number of tabs because it's undesirable to have the |
// minimum window size change when a new tab is opened. |
- int needed_width; |
- if (touch_layout_.get() || adjust_layout_) { |
- needed_width = Tab::GetTouchWidth() + |
- (2 * kStackedPadding * kMaxStackedCount); |
- } else { |
- needed_width = Tab::GetMinimumSelectedSize().width(); |
- } |
- needed_width += new_tab_button_width(); |
- if (immersive_style_) |
- return gfx::Size(needed_width, Tab::GetImmersiveHeight()); |
- return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); |
+ const int needed_tab_width = (touch_layout_ || adjust_layout_) ? |
+ (Tab::GetTouchWidth() + (2 * kStackedPadding * kMaxStackedCount)) : |
+ Tab::GetMinimumSelectedSize().width(); |
+ return gfx::Size(needed_tab_width + new_tab_button_width(), immersive_style_ ? |
+ Tab::GetImmersiveHeight() : Tab::GetMinimumUnselectedSize().height()); |
} |
void TabStrip::OnDragEntered(const DropTargetEvent& event) { |
@@ -1364,7 +1334,7 @@ views::View* TabStrip::GetEventHandlerForRect(const gfx::Rect& rect) { |
return View::GetEventHandlerForRect(rect); |
const gfx::Point point(rect.CenterPoint()); |
- if (!touch_layout_.get()) { |
+ if (!touch_layout_) { |
// Return any view that isn't a Tab or this TabStrip immediately. We don't |
// want to interfere. |
views::View* v = View::GetEventHandlerForRect(rect); |
@@ -1392,7 +1362,7 @@ views::View* TabStrip::GetTooltipHandlerForPoint(const gfx::Point& point) { |
if (!HitTestPoint(point)) |
return NULL; |
- if (!touch_layout_.get()) { |
+ if (!touch_layout_) { |
// Return any view that isn't a Tab or this TabStrip immediately. We don't |
// want to interfere. |
views::View* v = View::GetTooltipHandlerForPoint(point); |
@@ -1421,141 +1391,6 @@ int TabStrip::GetImmersiveHeight() { |
return Tab::GetImmersiveHeight(); |
} |
-int TabStrip::GetMiniTabCount() const { |
- int mini_count = 0; |
- while (mini_count < tab_count() && tab_at(mini_count)->data().mini) |
- mini_count++; |
- return mini_count; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// TabStrip, views::ButtonListener implementation: |
- |
-void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) { |
- if (sender == newtab_button_) { |
- content::RecordAction(UserMetricsAction("NewTab_Button")); |
- UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_BUTTON, |
- TabStripModel::NEW_TAB_ENUM_COUNT); |
- if (event.IsMouseEvent()) { |
- const ui::MouseEvent& mouse = static_cast<const ui::MouseEvent&>(event); |
- if (mouse.IsOnlyMiddleMouseButton()) { |
- base::string16 clipboard_text = GetClipboardText(); |
- if (!clipboard_text.empty()) |
- controller()->CreateNewTabWithLocation(clipboard_text); |
- return; |
- } |
- } |
- |
- controller()->CreateNewTab(); |
- if (event.type() == ui::ET_GESTURE_TAP) |
- TouchUMA::RecordGestureAction(TouchUMA::GESTURE_NEWTAB_TAP); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// TabStrip, protected: |
- |
-// Overridden to support automation. See automation_proxy_uitest.cc. |
-const views::View* TabStrip::GetViewByID(int view_id) const { |
- if (tab_count() > 0) { |
- if (view_id == VIEW_ID_TAB_LAST) { |
- return tab_at(tab_count() - 1); |
- } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) { |
- int index = view_id - VIEW_ID_TAB_0; |
- if (index >= 0 && index < tab_count()) { |
- return tab_at(index); |
- } else { |
- return NULL; |
- } |
- } |
- } |
- |
- return View::GetViewByID(view_id); |
-} |
- |
-bool TabStrip::OnMousePressed(const ui::MouseEvent& event) { |
- UpdateStackedLayoutFromMouseEvent(this, event); |
- // We can't return true here, else clicking in an empty area won't drag the |
- // window. |
- return false; |
-} |
- |
-bool TabStrip::OnMouseDragged(const ui::MouseEvent& event) { |
- ContinueDrag(this, event); |
- return true; |
-} |
- |
-void TabStrip::OnMouseReleased(const ui::MouseEvent& event) { |
- EndDrag(END_DRAG_COMPLETE); |
- UpdateStackedLayoutFromMouseEvent(this, event); |
-} |
- |
-void TabStrip::OnMouseCaptureLost() { |
- EndDrag(END_DRAG_CAPTURE_LOST); |
-} |
- |
-void TabStrip::OnMouseMoved(const ui::MouseEvent& event) { |
- UpdateStackedLayoutFromMouseEvent(this, event); |
-} |
- |
-void TabStrip::OnMouseEntered(const ui::MouseEvent& event) { |
- SetResetToShrinkOnExit(true); |
-} |
- |
-void TabStrip::OnGestureEvent(ui::GestureEvent* event) { |
- SetResetToShrinkOnExit(false); |
- switch (event->type()) { |
- case ui::ET_GESTURE_SCROLL_END: |
- case ui::ET_SCROLL_FLING_START: |
- case ui::ET_GESTURE_END: |
- EndDrag(END_DRAG_COMPLETE); |
- if (adjust_layout_) { |
- SetStackedLayout(true); |
- controller_->StackedLayoutMaybeChanged(); |
- } |
- break; |
- |
- case ui::ET_GESTURE_LONG_PRESS: |
- if (drag_controller_.get()) |
- drag_controller_->SetMoveBehavior(TabDragController::REORDER); |
- break; |
- |
- case ui::ET_GESTURE_LONG_TAP: { |
- EndDrag(END_DRAG_CANCEL); |
- gfx::Point local_point = event->location(); |
- Tab* tab = FindTabForEvent(local_point); |
- if (tab) { |
- ConvertPointToScreen(this, &local_point); |
- ShowContextMenuForTab(tab, local_point, ui::MENU_SOURCE_TOUCH); |
- } |
- break; |
- } |
- |
- case ui::ET_GESTURE_SCROLL_UPDATE: |
- ContinueDrag(this, *event); |
- break; |
- |
- case ui::ET_GESTURE_BEGIN: |
- EndDrag(END_DRAG_CANCEL); |
- break; |
- |
- case ui::ET_GESTURE_TAP: { |
- const int active_index = controller_->GetActiveIndex(); |
- DCHECK_NE(-1, active_index); |
- Tab* active_tab = tab_at(active_index); |
- TouchUMA::GestureActionType action = TouchUMA::GESTURE_TABNOSWITCH_TAP; |
- if (active_tab->tab_activated_with_last_gesture_begin()) |
- action = TouchUMA::GESTURE_TABSWITCH_TAP; |
- TouchUMA::RecordGestureAction(action); |
- break; |
- } |
- |
- default: |
- break; |
- } |
- event->SetHandled(); |
-} |
- |
/////////////////////////////////////////////////////////////////////////////// |
// TabStrip, private: |
@@ -1639,7 +1474,7 @@ void TabStrip::ScheduleRemoveTabAnimation(Tab* tab) { |
GenerateIdealBounds(); |
AnimateToIdealBounds(); |
- // Animate the tab being closed to 0x0. |
+ // Animate the tab being closed to zero width. |
gfx::Rect tab_bounds = tab->bounds(); |
tab_bounds.set_width(0); |
bounds_animator_.AnimateViewTo(tab, tab_bounds); |
@@ -1679,8 +1514,8 @@ void TabStrip::DoLayout() { |
SwapLayoutIfNecessary(); |
- if (touch_layout_.get()) |
- touch_layout_->SetWidth(size().width() - new_tab_button_width()); |
+ if (touch_layout_) |
+ touch_layout_->SetWidth(tab_area_width()); |
GenerateIdealBounds(); |
@@ -1695,7 +1530,7 @@ void TabStrip::DoLayout() { |
void TabStrip::DragActiveTab(const std::vector<int>& initial_positions, |
int delta) { |
DCHECK_EQ(tab_count(), static_cast<int>(initial_positions.size())); |
- if (!touch_layout_.get()) { |
+ if (!touch_layout_) { |
StackDraggedTabs(delta); |
return; |
} |
@@ -1711,12 +1546,12 @@ void TabStrip::SetIdealBoundsFromPositions(const std::vector<int>& positions) { |
for (int i = 0; i < tab_count(); ++i) { |
gfx::Rect bounds(ideal_bounds(i)); |
bounds.set_x(positions[i]); |
- set_ideal_bounds(i, bounds); |
+ tabs_.set_ideal_bounds(i, bounds); |
} |
} |
void TabStrip::StackDraggedTabs(int delta) { |
- DCHECK(!touch_layout_.get()); |
+ DCHECK(!touch_layout_); |
GenerateIdealBounds(); |
const int active_index = controller_->GetActiveIndex(); |
DCHECK_NE(-1, active_index); |
@@ -1730,7 +1565,7 @@ void TabStrip::StackDraggedTabs(int delta) { |
const int min_x = std::min(i, kMaxStackedCount) * kStackedPadding; |
gfx::Rect new_bounds(ideal_bounds(i)); |
new_bounds.set_x(std::max(min_x, new_bounds.x() - adjusted_delta)); |
- set_ideal_bounds(i, new_bounds); |
+ tabs_.set_ideal_bounds(i, new_bounds); |
} |
const bool is_active_mini = tab_at(active_index)->data().mini; |
const int active_width = ideal_bounds(active_index).width(); |
@@ -1743,12 +1578,12 @@ void TabStrip::StackDraggedTabs(int delta) { |
new_bounds.width() != active_width) |
new_x += (active_width - new_bounds.width()); |
new_bounds.set_x(new_x); |
- set_ideal_bounds(i, new_bounds); |
+ tabs_.set_ideal_bounds(i, new_bounds); |
} |
} else { |
// Drag the tabs to the right, stacking tabs after the active tab. |
const int last_tab_width = ideal_bounds(tab_count() - 1).width(); |
- const int last_tab_x = width() - new_tab_button_width() - last_tab_width; |
+ const int last_tab_x = tab_area_width() - last_tab_width; |
if (active_index == tab_count() - 1 && |
ideal_bounds(tab_count() - 1).x() == last_tab_x) |
return; |
@@ -1770,14 +1605,14 @@ void TabStrip::StackDraggedTabs(int delta) { |
new_bounds.width() != last_tab_width) |
new_x += (last_tab_width - new_bounds.width()); |
new_bounds.set_x(new_x); |
- set_ideal_bounds(i, new_bounds); |
+ tabs_.set_ideal_bounds(i, new_bounds); |
} |
for (int i = active_index - 1; i >= 0; --i) { |
const int min_x = ideal_bounds(active_index).x() - |
std::min(active_index - i, kMaxStackedCount) * kStackedPadding; |
gfx::Rect new_bounds(ideal_bounds(i)); |
new_bounds.set_x(std::min(min_x, new_bounds.x() + delta)); |
- set_ideal_bounds(i, new_bounds); |
+ tabs_.set_ideal_bounds(i, new_bounds); |
} |
if (ideal_bounds(tab_count() - 1).right() >= newtab_button_->x()) |
newtab_button_->SetVisible(false); |
@@ -1792,12 +1627,12 @@ bool TabStrip::IsStackingDraggedTabs() const { |
TabDragController::MOVE_VISIBILE_TABS); |
} |
-void TabStrip::LayoutDraggedTabsAt(const std::vector<Tab*>& tabs, |
+void TabStrip::LayoutDraggedTabsAt(const Tabs& tabs, |
Tab* active_tab, |
const gfx::Point& location, |
bool initial_drag) { |
// Immediately hide the new tab button if the last tab is being dragged. |
- if (tab_at(tab_count() - 1)->dragging()) |
+ if (GetLastVisibleTab()->dragging()) |
newtab_button_->SetVisible(false); |
std::vector<gfx::Rect> bounds; |
CalculateBoundsForDraggedTabs(tabs, &bounds); |
@@ -1824,7 +1659,7 @@ void TabStrip::LayoutDraggedTabsAt(const std::vector<Tab*>& tabs, |
} |
} |
-void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<Tab*>& tabs, |
+void TabStrip::CalculateBoundsForDraggedTabs(const Tabs& tabs, |
std::vector<gfx::Rect>* bounds) { |
int x = 0; |
for (size_t i = 0; i < tabs.size(); ++i) { |
@@ -1838,7 +1673,7 @@ void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<Tab*>& tabs, |
} |
} |
-int TabStrip::GetSizeNeededForTabs(const std::vector<Tab*>& tabs) { |
+int TabStrip::GetSizeNeededForTabs(const Tabs& tabs) { |
int width = 0; |
for (size_t i = 0; i < tabs.size(); ++i) { |
Tab* tab = tabs[i]; |
@@ -1851,6 +1686,17 @@ int TabStrip::GetSizeNeededForTabs(const std::vector<Tab*>& tabs) { |
return width; |
} |
+int TabStrip::GetMiniTabCount() const { |
+ int mini_count = 0; |
+ while (mini_count < tab_count() && tab_at(mini_count)->data().mini) |
+ mini_count++; |
+ return mini_count; |
+} |
+ |
+const Tab* TabStrip::GetLastVisibleTab() const { |
+ return tab_at(tab_count() - 1); |
+} |
+ |
void TabStrip::RemoveTabFromViewModel(int index) { |
// We still need to paint the tab until we actually remove it. Put it |
// in tabs_closing_map_ so we can find it. |
@@ -1861,18 +1707,10 @@ void TabStrip::RemoveTabFromViewModel(int index) { |
void TabStrip::RemoveAndDeleteTab(Tab* tab) { |
scoped_ptr<Tab> deleter(tab); |
- for (TabsClosingMap::iterator i(tabs_closing_map_.begin()); |
- i != tabs_closing_map_.end(); ++i) { |
- std::vector<Tab*>::iterator j = |
- std::find(i->second.begin(), i->second.end(), tab); |
- if (j != i->second.end()) { |
- i->second.erase(j); |
- if (i->second.empty()) |
- tabs_closing_map_.erase(i); |
- return; |
- } |
- } |
- NOTREACHED(); |
+ FindClosingTabResult res(FindClosingTab(tab)); |
+ res.first->second.erase(res.second); |
+ if (res.first->second.empty()) |
+ tabs_closing_map_.erase(res.first); |
} |
void TabStrip::UpdateTabsClosingMap(int index, int delta) { |
@@ -1882,7 +1720,7 @@ void TabStrip::UpdateTabsClosingMap(int index, int delta) { |
if (delta == -1 && |
tabs_closing_map_.find(index - 1) != tabs_closing_map_.end() && |
tabs_closing_map_.find(index) != tabs_closing_map_.end()) { |
- const std::vector<Tab*>& tabs(tabs_closing_map_[index]); |
+ const Tabs& tabs(tabs_closing_map_[index]); |
tabs_closing_map_[index - 1].insert( |
tabs_closing_map_[index - 1].end(), tabs.begin(), tabs.end()); |
} |
@@ -1899,7 +1737,7 @@ void TabStrip::UpdateTabsClosingMap(int index, int delta) { |
tabs_closing_map_.swap(updated_map); |
} |
-void TabStrip::StartedDraggingTabs(const std::vector<Tab*>& tabs) { |
+void TabStrip::StartedDraggingTabs(const Tabs& tabs) { |
// Let the controller know that the user started dragging tabs. |
controller()->OnStartedDraggingTabs(); |
@@ -1937,7 +1775,7 @@ void TabStrip::DraggedTabsDetached() { |
newtab_button_->SetVisible(true); |
} |
-void TabStrip::StoppedDraggingTabs(const std::vector<Tab*>& tabs, |
+void TabStrip::StoppedDraggingTabs(const Tabs& tabs, |
const std::vector<int>& initial_positions, |
bool move_only, |
bool completed) { |
@@ -1945,12 +1783,11 @@ void TabStrip::StoppedDraggingTabs(const std::vector<Tab*>& tabs, |
controller()->OnStoppedDraggingTabs(); |
newtab_button_->SetVisible(true); |
- if (move_only && touch_layout_.get()) { |
- if (completed) { |
+ if (move_only && touch_layout_) { |
+ if (completed) |
touch_layout_->SizeToFit(); |
- } else { |
+ else |
SetIdealBoundsFromPositions(initial_positions); |
- } |
} |
bool is_first_tab = true; |
for (size_t i = 0; i < tabs.size(); ++i) |
@@ -2000,17 +1837,27 @@ TabDragController* TabStrip::ReleaseDragController() { |
return drag_controller_.release(); |
} |
+TabStrip::FindClosingTabResult TabStrip::FindClosingTab(const Tab* tab) { |
+ DCHECK(tab->closing()); |
+ for (TabsClosingMap::iterator i(tabs_closing_map_.begin()); |
+ i != tabs_closing_map_.end(); ++i) { |
+ Tabs::iterator j = std::find(i->second.begin(), i->second.end(), tab); |
+ if (j != i->second.end()) |
+ return FindClosingTabResult(i, j); |
+ } |
+ NOTREACHED(); |
+ return FindClosingTabResult(tabs_closing_map_.end(), Tabs::iterator()); |
+} |
+ |
void TabStrip::PaintClosingTabs(gfx::Canvas* canvas, |
int index, |
const views::CullSet& cull_set) { |
if (tabs_closing_map_.find(index) == tabs_closing_map_.end()) |
return; |
- const std::vector<Tab*>& tabs = tabs_closing_map_[index]; |
- for (std::vector<Tab*>::const_reverse_iterator i(tabs.rbegin()); |
- i != tabs.rend(); ++i) { |
+ const Tabs& tabs = tabs_closing_map_[index]; |
+ for (Tabs::const_reverse_iterator i(tabs.rbegin()); i != tabs.rend(); ++i) |
(*i)->Paint(canvas, cull_set); |
- } |
} |
void TabStrip::UpdateStackedLayoutFromMouseEvent(views::View* source, |
@@ -2035,7 +1882,7 @@ void TabStrip::UpdateStackedLayoutFromMouseEvent(views::View* source, |
mouse_move_count_ = 0; |
last_mouse_move_time_ = base::TimeTicks(); |
SetResetToShrinkOnExit((event.flags() & ui::EF_FROM_TOUCH) == 0); |
- if (reset_to_shrink_on_exit_ && touch_layout_.get()) { |
+ if (reset_to_shrink_on_exit_ && touch_layout_) { |
gfx::Point tab_strip_point(event.location()); |
views::View::ConvertPointToTarget(source, this, &tab_strip_point); |
Tab* tab = FindTabForEvent(tab_strip_point); |
@@ -2162,17 +2009,11 @@ void TabStrip::GetDesiredTabWidths(int tab_count, |
// want to set *unselected_width = 2, *selected_width = 4, for a total width |
// of 10. |
if (tab_count > 1) { |
- if ((min_unselected_width < min_selected_width) && |
- (desired_tab_width < min_selected_width)) { |
+ if (desired_tab_width < min_selected_width) { |
// Unselected width = (total width - selected width) / (num_tabs - 1) |
*unselected_width = std::max(static_cast<double>( |
available_width - total_offset - min_selected_width) / |
static_cast<double>(tab_count - 1), min_unselected_width); |
- } else if ((min_unselected_width > min_selected_width) && |
- (desired_tab_width < min_unselected_width)) { |
- // Selected width = (total width - (unselected width * (num_tabs - 1))) |
- *selected_width = std::max(available_width - total_offset - |
- (min_unselected_width * (tab_count - 1)), min_selected_width); |
} |
} |
} |
@@ -2398,7 +2239,7 @@ void TabStrip::PrepareForAnimation() { |
void TabStrip::GenerateIdealBounds() { |
int new_tab_y = 0; |
- if (touch_layout_.get()) { |
+ if (touch_layout_) { |
if (tabs_.view_size() == 0) |
return; |
@@ -2408,10 +2249,8 @@ void TabStrip::GenerateIdealBounds() { |
return; |
} |
- double unselected, selected; |
- GetDesiredTabWidths(tab_count(), GetMiniTabCount(), &unselected, &selected); |
- current_unselected_width_ = unselected; |
- current_selected_width_ = selected; |
+ GetDesiredTabWidths(tab_count(), GetMiniTabCount(), |
+ ¤t_unselected_width_, ¤t_selected_width_); |
// NOTE: This currently assumes a tab's height doesn't differ based on |
// selected state or the number of tabs in the strip! |
@@ -2421,10 +2260,11 @@ void TabStrip::GenerateIdealBounds() { |
for (int i = first_non_mini_index; i < tab_count(); ++i) { |
Tab* tab = tab_at(i); |
DCHECK(!tab->data().mini); |
- double tab_width = tab->IsActive() ? selected : unselected; |
+ double tab_width = |
+ tab->IsActive() ? current_selected_width_ : current_unselected_width_; |
double end_of_tab = tab_x + tab_width; |
int rounded_tab_x = Round(tab_x); |
- set_ideal_bounds( |
+ tabs_.set_ideal_bounds( |
i, |
gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, |
tab_height)); |
@@ -2433,7 +2273,7 @@ void TabStrip::GenerateIdealBounds() { |
// Update bounds of new tab button. |
int new_tab_x; |
- if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && |
+ if ((Tab::GetStandardSize().width() - Round(current_unselected_width_)) > 1 && |
!in_tab_close_) { |
// We're shrinking tabs, so we need to anchor the New Tab button to the |
// right edge of the TabStrip's bounds, rather than the right edge of the |
@@ -2452,8 +2292,7 @@ int TabStrip::GenerateIdealBoundsForMiniTabs(int* first_non_mini_index) { |
int tab_height = Tab::GetStandardSize().height(); |
int index = 0; |
for (; index < tab_count() && tab_at(index)->data().mini; ++index) { |
- set_ideal_bounds(index, |
- gfx::Rect(next_x, 0, mini_width, tab_height)); |
+ tabs_.set_ideal_bounds(index, gfx::Rect(next_x, 0, mini_width, tab_height)); |
next_x += mini_width + kTabHorizontalOffset; |
} |
if (index > 0 && index < tab_count()) |
@@ -2463,20 +2302,6 @@ int TabStrip::GenerateIdealBoundsForMiniTabs(int* first_non_mini_index) { |
return next_x; |
} |
-// static |
-int TabStrip::new_tab_button_width() { |
- return kNewTabButtonAssetWidth + kNewTabButtonHorizontalOffset; |
-} |
- |
-// static |
-int TabStrip::button_v_offset() { |
- return kNewTabButtonVerticalOffset; |
-} |
- |
-int TabStrip::tab_area_width() const { |
- return width() - new_tab_button_width(); |
-} |
- |
void TabStrip::StartResizeLayoutAnimation() { |
PrepareForAnimation(); |
GenerateIdealBounds(); |
@@ -2500,16 +2325,14 @@ void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { |
int delta = tab_closing->width() + kTabHorizontalOffset; |
// If the tab being closed is a mini-tab next to a non-mini-tab, be sure to |
// add the extra padding. |
- DCHECK_NE(model_index + 1, tab_count()); |
- if (tab_closing->data().mini && model_index + 1 < tab_count() && |
- !tab_at(model_index + 1)->data().mini) { |
+ DCHECK_LT(model_index, tab_count() - 1); |
+ if (tab_closing->data().mini && !tab_at(model_index + 1)->data().mini) |
delta += kMiniToNonMiniGap; |
- } |
for (int i = model_index + 1; i < tab_count(); ++i) { |
gfx::Rect bounds = ideal_bounds(i); |
bounds.set_x(bounds.x() - delta); |
- set_ideal_bounds(i, bounds); |
+ tabs_.set_ideal_bounds(i, bounds); |
} |
newtab_button_bounds_.set_x(newtab_button_bounds_.x() - delta); |
@@ -2552,16 +2375,16 @@ int TabStrip::GetStartXForNormalTabs() const { |
} |
Tab* TabStrip::FindTabForEvent(const gfx::Point& point) { |
- if (touch_layout_.get()) { |
+ if (touch_layout_) { |
int active_tab_index = touch_layout_->active_index(); |
if (active_tab_index != -1) { |
Tab* tab = FindTabForEventFrom(point, active_tab_index, -1); |
if (!tab) |
tab = FindTabForEventFrom(point, active_tab_index + 1, 1); |
return tab; |
- } else if (tab_count()) { |
- return FindTabForEventFrom(point, 0, 1); |
} |
+ if (tab_count()) |
+ return FindTabForEventFrom(point, 0, 1); |
} else { |
for (int i = 0; i < tab_count(); ++i) { |
if (IsPointInTab(tab_at(i), point)) |
@@ -2609,7 +2432,7 @@ std::vector<int> TabStrip::GetTabXCoordinates() { |
void TabStrip::SwapLayoutIfNecessary() { |
bool needs_touch = NeedsTouchLayout(); |
- bool using_touch = touch_layout_.get() != NULL; |
+ bool using_touch = touch_layout_ != NULL; |
if (needs_touch == using_touch) |
return; |
@@ -2622,7 +2445,7 @@ void TabStrip::SwapLayoutIfNecessary() { |
kStackedPadding, |
kMaxStackedCount, |
&tabs_)); |
- touch_layout_->SetWidth(width() - new_tab_button_width()); |
+ touch_layout_->SetWidth(tab_area_width()); |
// This has to be after SetWidth() as SetWidth() is going to reset the |
// bounds of the mini-tabs (since StackedTabStripLayout doesn't yet know how |
// many mini-tabs there are). |
@@ -2647,7 +2470,7 @@ bool TabStrip::NeedsTouchLayout() const { |
if (normal_count <= 1 || normal_count == mini_tab_count) |
return false; |
int x = GetStartXForNormalTabs(); |
- int available_width = width() - x - new_tab_button_width(); |
+ int available_width = tab_area_width() - x; |
return (Tab::GetTouchWidth() * normal_count + |
kTabHorizontalOffset * (normal_count - 1)) > available_width; |
} |
@@ -2669,3 +2492,121 @@ void TabStrip::SetResetToShrinkOnExit(bool value) { |
else |
RemoveMessageLoopObserver(); |
} |
+ |
+void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) { |
+ if (sender == newtab_button_) { |
+ content::RecordAction(UserMetricsAction("NewTab_Button")); |
+ UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_BUTTON, |
+ TabStripModel::NEW_TAB_ENUM_COUNT); |
+ if (event.IsMouseEvent()) { |
+ const ui::MouseEvent& mouse = static_cast<const ui::MouseEvent&>(event); |
+ if (mouse.IsOnlyMiddleMouseButton()) { |
+ base::string16 clipboard_text = GetClipboardText(); |
+ if (!clipboard_text.empty()) |
+ controller()->CreateNewTabWithLocation(clipboard_text); |
+ return; |
+ } |
+ } |
+ |
+ controller()->CreateNewTab(); |
+ if (event.type() == ui::ET_GESTURE_TAP) |
+ TouchUMA::RecordGestureAction(TouchUMA::GESTURE_NEWTAB_TAP); |
+ } |
+} |
+ |
+// Overridden to support automation. See automation_proxy_uitest.cc. |
+const views::View* TabStrip::GetViewByID(int view_id) const { |
+ if (tab_count() > 0) { |
+ if (view_id == VIEW_ID_TAB_LAST) |
+ return tab_at(tab_count() - 1); |
+ if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) { |
+ int index = view_id - VIEW_ID_TAB_0; |
+ return (index >= 0 && index < tab_count()) ? tab_at(index) : NULL; |
+ } |
+ } |
+ |
+ return View::GetViewByID(view_id); |
+} |
+ |
+bool TabStrip::OnMousePressed(const ui::MouseEvent& event) { |
+ UpdateStackedLayoutFromMouseEvent(this, event); |
+ // We can't return true here, else clicking in an empty area won't drag the |
+ // window. |
+ return false; |
+} |
+ |
+bool TabStrip::OnMouseDragged(const ui::MouseEvent& event) { |
+ ContinueDrag(this, event); |
+ return true; |
+} |
+ |
+void TabStrip::OnMouseReleased(const ui::MouseEvent& event) { |
+ EndDrag(END_DRAG_COMPLETE); |
+ UpdateStackedLayoutFromMouseEvent(this, event); |
+} |
+ |
+void TabStrip::OnMouseCaptureLost() { |
+ EndDrag(END_DRAG_CAPTURE_LOST); |
+} |
+ |
+void TabStrip::OnMouseMoved(const ui::MouseEvent& event) { |
+ UpdateStackedLayoutFromMouseEvent(this, event); |
+} |
+ |
+void TabStrip::OnMouseEntered(const ui::MouseEvent& event) { |
+ SetResetToShrinkOnExit(true); |
+} |
+ |
+void TabStrip::OnGestureEvent(ui::GestureEvent* event) { |
+ SetResetToShrinkOnExit(false); |
+ switch (event->type()) { |
+ case ui::ET_GESTURE_SCROLL_END: |
+ case ui::ET_SCROLL_FLING_START: |
+ case ui::ET_GESTURE_END: |
+ EndDrag(END_DRAG_COMPLETE); |
+ if (adjust_layout_) { |
+ SetStackedLayout(true); |
+ controller_->StackedLayoutMaybeChanged(); |
+ } |
+ break; |
+ |
+ case ui::ET_GESTURE_LONG_PRESS: |
+ if (drag_controller_.get()) |
+ drag_controller_->SetMoveBehavior(TabDragController::REORDER); |
+ break; |
+ |
+ case ui::ET_GESTURE_LONG_TAP: { |
+ EndDrag(END_DRAG_CANCEL); |
+ gfx::Point local_point = event->location(); |
+ Tab* tab = FindTabForEvent(local_point); |
+ if (tab) { |
+ ConvertPointToScreen(this, &local_point); |
+ ShowContextMenuForTab(tab, local_point, ui::MENU_SOURCE_TOUCH); |
+ } |
+ break; |
+ } |
+ |
+ case ui::ET_GESTURE_SCROLL_UPDATE: |
+ ContinueDrag(this, *event); |
+ break; |
+ |
+ case ui::ET_GESTURE_BEGIN: |
+ EndDrag(END_DRAG_CANCEL); |
+ break; |
+ |
+ case ui::ET_GESTURE_TAP: { |
+ const int active_index = controller_->GetActiveIndex(); |
+ DCHECK_NE(-1, active_index); |
+ Tab* active_tab = tab_at(active_index); |
+ TouchUMA::GestureActionType action = TouchUMA::GESTURE_TABNOSWITCH_TAP; |
+ if (active_tab->tab_activated_with_last_gesture_begin()) |
+ action = TouchUMA::GESTURE_TABSWITCH_TAP; |
+ TouchUMA::RecordGestureAction(action); |
+ break; |
+ } |
+ |
+ default: |
+ break; |
+ } |
+ event->SetHandled(); |
+} |