172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/base_tab_strip.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/view_ids.h" 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/tabs/dragged_tab_controller.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/tabs/tab_strip_controller.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget_win.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Animation delegate used when a dragged tab is released. When done sets the 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// dragging state to false. 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ResetDraggingStateDelegate 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public views::BoundsAnimator::OwnedAnimationDelegate { 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationEnded(const ui::Animation* animation) { 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_->set_dragging(false); 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationCanceled(const ui::Animation* animation) { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_->set_dragging(false); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab_; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AnimationDelegate used when removing a tab. Does the necessary cleanup when 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// done. 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BaseTabStrip::RemoveTabDelegate 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public views::BoundsAnimator::OwnedAnimationDelegate { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemoveTabDelegate(BaseTabStrip* tab_strip, BaseTab* tab) 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : tabstrip_(tab_strip), 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_(tab) { 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationEnded(const ui::Animation* animation) { 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompleteRemove(); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationCanceled(const ui::Animation* animation) { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can be canceled for two interesting reasons: 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // . The tab we reference was dragged back into the tab strip. In this case 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we don't want to remove the tab (closing is false). 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // . The drag was completed before the animation completed 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (DestroyDraggedSourceTab). In this case we need to remove the tab 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (closing is true). 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_->closing()) 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompleteRemove(); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CompleteRemove() { 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tab_->closing()) { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab was added back yet we weren't canceled. This shouldn't happen. 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tabstrip_->RemoveAndDeleteTab(tab_); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HighlightCloseButton(); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the animation completes, we send the Container a message to simulate 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a mouse moved event at the current mouse position. This tickles the Tab 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the mouse is currently over to show the "hot" state of the close button. 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void HighlightCloseButton() { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tabstrip_->IsDragSessionActive() || 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !tabstrip_->ShouldHighlightCloseButtonAfterRemove()) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This function is not required (and indeed may crash!) for removes 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // spawned by non-mouse closes and drag-detaches. 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Widget* widget = tabstrip_->GetWidget(); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This can be null during shutdown. See http://crbug.com/42737. 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!widget) 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force the close button (that slides under the mouse) to highlight by 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // saying the mouse just moved, but sending the same coordinates. 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD pos = GetMessagePos(); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT cursor_point = {GET_X_LPARAM(pos), GET_Y_LPARAM(pos)}; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MapWindowPoints(NULL, widget->GetNativeView(), &cursor_point, 1); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<views::WidgetWin*>(widget)->ResetLastMouseMoveFlag(); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return to message loop - otherwise we may disrupt some operation that's 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in progress. 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendMessage(widget->GetNativeView(), WM_MOUSEMOVE, 0, 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(cursor_point.x, cursor_point.y)); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTabStrip* tabstrip_; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab_; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTabStrip::BaseTabStrip(TabStripController* controller, Type type) 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : controller_(controller), 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch type_(type), 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attaching_dragged_tab_(false), 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)) { 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTabStrip::~BaseTabStrip() { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::AddTabAt(int model_index, const TabRendererData& data) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = CreateTab(); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->SetData(data); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabData d = { tab, gfx::Rect() }; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_data_.insert(tab_data_.begin() + ModelIndexToTabIndex(model_index), d); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(tab); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't animate the first tab, it looks weird, and don't animate anything 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if the containing window isn't visible yet. 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_count() > 1 && GetWindow() && GetWindow()->IsVisible()) 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartInsertTabAnimation(model_index); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DoLayout(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::MoveTab(int from_model_index, int to_model_index) { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int from_tab_data_index = ModelIndexToTabIndex(from_model_index); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = tab_data_[from_tab_data_index].tab; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_data_.erase(tab_data_.begin() + from_tab_data_index); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabData data = {tab, gfx::Rect()}; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int to_tab_data_index = ModelIndexToTabIndex(to_model_index); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_data_.insert(tab_data_.begin() + to_tab_data_index, data); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartMoveTabAnimation(); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::SetTabData(int model_index, const TabRendererData& data) { 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = GetBaseTabAtModelIndex(model_index); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool mini_state_changed = tab->data().mini != data.mini; 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->SetData(data); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mini_state_changed) { 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (GetWindow() && GetWindow()->IsVisible()) 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartMiniTabAnimation(); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DoLayout(); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTab* BaseTabStrip::GetBaseTabAtModelIndex(int model_index) const { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return base_tab_at_tab_index(ModelIndexToTabIndex(model_index)); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BaseTabStrip::GetModelIndexOfBaseTab(const BaseTab* tab) const { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0, model_index = 0; i < tab_count(); ++i) { 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* current_tab = base_tab_at_tab_index(i); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!current_tab->closing()) { 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_tab == tab) 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return model_index; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_index++; 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (current_tab == tab) { 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return -1; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BaseTabStrip::GetModelCount() const { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return controller_->GetCount(); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseTabStrip::IsValidModelIndex(int model_index) const { 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return controller_->IsValidIndex(model_index); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BaseTabStrip::ModelIndexToTabIndex(int model_index) const { 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int current_model_index = 0; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_count(); ++i) { 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!base_tab_at_tab_index(i)->closing()) { 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_model_index == model_index) 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i; 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_model_index++; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return static_cast<int>(tab_data_.size()); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseTabStrip::IsDragSessionActive() const { 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return drag_controller_.get() != NULL; 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool BaseTabStrip::IsActiveDropTarget() const { 21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (int i = 0; i < tab_count(); ++i) { 21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen BaseTab* tab = base_tab_at_tab_index(i); 21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (tab->dragging()) 21621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 21821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 21921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 22021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool BaseTabStrip::IsTabStripEditable() const { 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return !IsDragSessionActive() && !IsActiveDropTarget(); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool BaseTabStrip::IsTabStripCloseable() const { 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return !IsDragSessionActive(); 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::UpdateLoadingAnimations() { 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen controller_->UpdateLoadingAnimations(); 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::SelectTab(BaseTab* tab) { 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int model_index = GetModelIndexOfBaseTab(tab); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsValidModelIndex(model_index)) 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->SelectTab(model_index); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::ExtendSelectionTo(BaseTab* tab) { 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int model_index = GetModelIndexOfBaseTab(tab); 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsValidModelIndex(model_index)) 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen controller_->ExtendSelectionTo(model_index); 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::ToggleSelected(BaseTab* tab) { 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int model_index = GetModelIndexOfBaseTab(tab); 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsValidModelIndex(model_index)) 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen controller_->ToggleSelected(model_index); 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::AddSelectionFromAnchorTo(BaseTab* tab) { 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int model_index = GetModelIndexOfBaseTab(tab); 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsValidModelIndex(model_index)) 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen controller_->AddSelectionFromAnchorTo(model_index); 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::CloseTab(BaseTab* tab) { 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find the closest model index. We do this so that the user can rapdily close 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tabs and have the close click close the next tab. 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int model_index = 0; 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_count(); ++i) { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* current_tab = base_tab_at_tab_index(i); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_tab == tab) 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!current_tab->closing()) 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_index++; 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsValidModelIndex(model_index)) 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->CloseTab(model_index); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid BaseTabStrip::ShowContextMenuForTab(BaseTab* tab, const gfx::Point& p) { 274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen controller_->ShowContextMenuForTab(tab, p); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool BaseTabStrip::IsActiveTab(const BaseTab* tab) const { 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int model_index = GetModelIndexOfBaseTab(tab); 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return IsValidModelIndex(model_index) && 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen controller_->IsActiveTab(model_index); 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseTabStrip::IsTabSelected(const BaseTab* tab) const { 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int model_index = GetModelIndexOfBaseTab(tab); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IsValidModelIndex(model_index) && 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->IsTabSelected(model_index); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseTabStrip::IsTabPinned(const BaseTab* tab) const { 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab->closing()) 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int model_index = GetModelIndexOfBaseTab(tab); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IsValidModelIndex(model_index) && 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->IsTabPinned(model_index); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseTabStrip::IsTabCloseable(const BaseTab* tab) const { 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int model_index = GetModelIndexOfBaseTab(tab); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !IsValidModelIndex(model_index) || 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->IsTabCloseable(model_index); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::MaybeStartDrag(BaseTab* tab, 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const views::MouseEvent& event) { 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't accidentally start any drag operations during animations if the 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // mouse is down... during an animation tabs are being resized automatically, 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so the View system can misinterpret this easily if the mouse is down that 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the user is dragging. 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsAnimating() || tab->closing() || 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->HasAvailableDragActions() == 0) { 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int model_index = GetModelIndexOfBaseTab(tab); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsValidModelIndex(model_index)) { 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(false); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_controller_.reset(new DraggedTabController()); 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> tabs; 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int size_to_selected = 0; 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int x = tab->GetMirroredXInView(event.x()); 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int y = event.y(); 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Build the set of selected tabs to drag and calculate the offset from the 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // first selected tab. 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < tab_count(); ++i) { 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTab* other_tab = base_tab_at_tab_index(i); 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsTabSelected(other_tab) && !other_tab->closing()) { 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs.push_back(other_tab); 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (other_tab == tab) { 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_to_selected = GetSizeNeededForTabs(tabs); 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (type() == HORIZONTAL_TAB_STRIP) 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen x = size_to_selected - tab->width() + x; 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen y = size_to_selected - tab->height() + y; 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!tabs.empty()); 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(std::find(tabs.begin(), tabs.end(), tab) != tabs.end()); 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_controller_->Init(this, tab, tabs, gfx::Point(x, y), 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab->GetMirroredXInView(event.x())); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::ContinueDrag(const views::MouseEvent& event) { 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can get called even if |MaybeStartDrag| wasn't called in the event of 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a TabStrip animation when the mouse button is down. In this case we should 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // _not_ continue the drag because it can lead to weird bugs. 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_controller_.get()) { 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool started_drag = drag_controller_->started_drag(); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_controller_->Drag(); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_controller_->started_drag() && !started_drag) { 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The drag just started. Redirect mouse events to us to that the tab that 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // originated the drag can be safely deleted. 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetRootView()->SetMouseHandler(this); 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseTabStrip::EndDrag(bool canceled) { 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!drag_controller_.get()) 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool started_drag = drag_controller_->started_drag(); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_controller_->EndDrag(canceled); 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return started_drag; 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTab* BaseTabStrip::GetTabAt(BaseTab* tab, 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Point& tab_in_tab_coordinates) { 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point local_point = tab_in_tab_coordinates; 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConvertPointToView(tab, this, &local_point); 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetTabAtLocal(local_point); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::Layout() { 376731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Only do a layout if our size changed. 377731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (last_layout_size_ == size()) 378731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 379731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DoLayout(); 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseTabStrip::OnMouseDragged(const views::MouseEvent& event) { 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_controller_.get()) 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_controller_->Drag(); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::OnMouseReleased(const views::MouseEvent& event) { 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EndDrag(false); 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::OnMouseCaptureLost() { 393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EndDrag(true); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BaseTabStrip::StartMoveTabAnimation() { 39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PrepareForAnimation(); 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GenerateIdealBounds(); 39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen AnimateToIdealBounds(); 40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::StartRemoveTabAnimation(int model_index) { 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrepareForAnimation(); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Mark the tab as closing. 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = GetBaseTabAtModelIndex(model_index); 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->set_closing(true); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start an animation for the tabs. 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GenerateIdealBounds(); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimateToIdealBounds(); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Animate the tab being closed to 0x0. 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect tab_bounds = tab->bounds(); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type() == HORIZONTAL_TAB_STRIP) 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_bounds.set_width(0); 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_bounds.set_height(0); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds_animator_.AnimateViewTo(tab, tab_bounds); 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register delegate to do cleanup when done, BoundsAnimator takes 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ownership of RemoveTabDelegate. 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab), 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true); 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::StartMiniTabAnimation() { 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrepareForAnimation(); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GenerateIdealBounds(); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimateToIdealBounds(); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool BaseTabStrip::ShouldHighlightCloseButtonAfterRemove() { 435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::RemoveAndDeleteTab(BaseTab* tab) { 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_data_index = TabIndexOfTab(tab); 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(tab_data_index != -1); 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove the Tab from the TabStrip's list... 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_data_.erase(tab_data_.begin() + tab_data_index); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete tab; 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BaseTabStrip::TabIndexOfTab(BaseTab* tab) const { 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_count(); ++i) { 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (base_tab_at_tab_index(i) == tab) 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i; 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BaseTabStrip::StopAnimating(bool layout) { 45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!IsAnimating()) 45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 46072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bounds_animator().Cancel(); 46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (layout) 46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DoLayout(); 46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 46672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::DestroyDragController() { 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsDragSessionActive()) 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_controller_.reset(NULL); 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::StartedDraggingTabs(const std::vector<BaseTab*>& tabs) { 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrepareForAnimation(); 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Reset dragging state of existing tabs. 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_count(); ++i) 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base_tab_at_tab_index(i)->set_dragging(false); 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < tabs.size(); ++i) { 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs[i]->set_dragging(true); 481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bounds_animator_.StopAnimatingView(tabs[i]); 482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Move the dragged tabs to their ideal bounds. 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GenerateIdealBounds(); 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Sets the bounds of the dragged tabs. 488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < tabs.size(); ++i) { 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int tab_data_index = TabIndexOfTab(tabs[i]); 490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(tab_data_index != -1); 491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs[i]->SetBoundsRect(ideal_bounds(tab_data_index)); 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SchedulePaint(); 494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::StoppedDraggingTabs(const std::vector<BaseTab*>& tabs) { 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool is_first_tab = true; 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < tabs.size(); ++i) 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StoppedDraggingTab(tabs[i], &is_first_tab); 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseTabStrip::PrepareForAnimation() { 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsDragSessionActive() && !DraggedTabController::IsAttachedTo(this)) { 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_count(); ++i) 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base_tab_at_tab_index(i)->set_dragging(false); 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenui::AnimationDelegate* BaseTabStrip::CreateRemoveTabDelegate(BaseTab* tab) { 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new RemoveTabDelegate(this, tab); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 512731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 513731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid BaseTabStrip::DoLayout() { 514731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick last_layout_size_ = size(); 515731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 516731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick StopAnimating(false); 517731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 518731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GenerateIdealBounds(); 519731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 520731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (int i = 0; i < tab_count(); ++i) 52172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen tab_data_[i].tab->SetBoundsRect(tab_data_[i].ideal_bounds); 522731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 523731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SchedulePaint(); 524731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool BaseTabStrip::IsAnimating() const { 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return bounds_animator_.IsAnimating(); 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBaseTab* BaseTabStrip::GetTabAtLocal(const gfx::Point& local_point) { 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::View* view = GetEventHandlerForPoint(local_point); 532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!view) 533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; // No tab contains the point. 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Walk up the view hierarchy until we find a tab, or the TabStrip. 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (view && view != this && view->GetID() != VIEW_ID_TAB) 537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen view = view->parent(); 538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return view && view->GetID() == VIEW_ID_TAB ? 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<BaseTab*>(view) : NULL; 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseTabStrip::StoppedDraggingTab(BaseTab* tab, bool* is_first_tab) { 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int tab_data_index = TabIndexOfTab(tab); 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (tab_data_index == -1) { 546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The tab was removed before the drag completed. Don't do anything. 547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (*is_first_tab) { 551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *is_first_tab = false; 552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PrepareForAnimation(); 553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Animate the view back to its correct position. 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GenerateIdealBounds(); 556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AnimateToIdealBounds(); 557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bounds_animator_.AnimateViewTo(tab, ideal_bounds(TabIndexOfTab(tab))); 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Install a delegate to reset the dragging state when done. We have to leave 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // dragging true for the tab otherwise it'll draw beneath the new tab button. 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bounds_animator_.SetAnimationDelegate( 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab, new ResetDraggingStateDelegate(tab), true); 563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 564