diff options
11 files changed, 104 insertions, 17 deletions
diff --git a/chrome/browser/ui/views/tabs/base_tab.cc b/chrome/browser/ui/views/tabs/base_tab.cc index 82cec3e..13fb340 100644 --- a/chrome/browser/ui/views/tabs/base_tab.cc +++ b/chrome/browser/ui/views/tabs/base_tab.cc @@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/utf_string_conversions.h" +#include "chrome/browser/tabs/tab_strip_selection_model.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/browser/ui/view_ids.h" @@ -288,6 +289,8 @@ bool BaseTab::OnMousePressed(const views::MouseEvent& event) { return false; if (event.IsOnlyLeftMouseButton()) { + TabStripSelectionModel original_selection; + original_selection.Copy(controller()->GetSelectionModel()); if (event.IsShiftDown() && event.IsControlDown()) { controller()->AddSelectionFromAnchorTo(this); } else if (event.IsShiftDown()) { @@ -303,7 +306,7 @@ bool BaseTab::OnMousePressed(const views::MouseEvent& event) { } else if (IsActive()) { controller()->ClickActiveTab(this); } - controller()->MaybeStartDrag(this, event); + controller()->MaybeStartDrag(this, event, original_selection); } return true; } diff --git a/chrome/browser/ui/views/tabs/base_tab_strip.cc b/chrome/browser/ui/views/tabs/base_tab_strip.cc index 85f07cb..c4136de 100644 --- a/chrome/browser/ui/views/tabs/base_tab_strip.cc +++ b/chrome/browser/ui/views/tabs/base_tab_strip.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/tabs/base_tab_strip.h" #include "base/logging.h" +#include "chrome/browser/tabs/tab_strip_selection_model.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/tabs/dragged_tab_controller.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" @@ -229,6 +230,10 @@ void BaseTabStrip::UpdateLoadingAnimations() { controller_->UpdateLoadingAnimations(); } +const TabStripSelectionModel& BaseTabStrip::GetSelectionModel() { + return controller_->GetSelectionModel(); +} + void BaseTabStrip::SelectTab(BaseTab* tab) { int model_index = GetModelIndexOfBaseTab(tab); if (IsValidModelIndex(model_index)) @@ -300,8 +305,10 @@ bool BaseTabStrip::IsTabCloseable(const BaseTab* tab) const { controller_->IsTabCloseable(model_index); } -void BaseTabStrip::MaybeStartDrag(BaseTab* tab, - const views::MouseEvent& event) { +void BaseTabStrip::MaybeStartDrag( + BaseTab* tab, + const views::MouseEvent& event, + const TabStripSelectionModel& original_selection) { // Don't accidentally start any drag operations during animations if the // mouse is down... during an animation tabs are being resized automatically, // so the View system can misinterpret this easily if the mouse is down that @@ -334,8 +341,12 @@ void BaseTabStrip::MaybeStartDrag(BaseTab* tab, } DCHECK(!tabs.empty()); DCHECK(std::find(tabs.begin(), tabs.end(), tab) != tabs.end()); - drag_controller_->Init(this, tab, tabs, gfx::Point(x, y), - tab->GetMirroredXInView(event.x())); + TabStripSelectionModel selection_model; + if (!original_selection.IsSelected(model_index)) + selection_model.Copy(original_selection); + drag_controller_->Init( + this, tab, tabs, gfx::Point(x, y), tab->GetMirroredXInView(event.x()), + selection_model); } void BaseTabStrip::ContinueDrag(const views::MouseEvent& event) { diff --git a/chrome/browser/ui/views/tabs/base_tab_strip.h b/chrome/browser/ui/views/tabs/base_tab_strip.h index 4648371..4a26aba 100644 --- a/chrome/browser/ui/views/tabs/base_tab_strip.h +++ b/chrome/browser/ui/views/tabs/base_tab_strip.h @@ -111,6 +111,7 @@ class BaseTabStrip : public AbstractTabStripView, virtual void UpdateLoadingAnimations() OVERRIDE; // TabController overrides: + virtual const TabStripSelectionModel& GetSelectionModel() OVERRIDE; virtual void SelectTab(BaseTab* tab) OVERRIDE; virtual void ExtendSelectionTo(BaseTab* tab) OVERRIDE; virtual void ToggleSelected(BaseTab* tab) OVERRIDE; @@ -122,8 +123,10 @@ class BaseTabStrip : public AbstractTabStripView, virtual bool IsTabSelected(const BaseTab* tab) const OVERRIDE; virtual bool IsTabPinned(const BaseTab* tab) const OVERRIDE; virtual bool IsTabCloseable(const BaseTab* tab) const OVERRIDE; - virtual void MaybeStartDrag(BaseTab* tab, - const views::MouseEvent& event) OVERRIDE; + virtual void MaybeStartDrag( + BaseTab* tab, + const views::MouseEvent& event, + const TabStripSelectionModel& original_selection) OVERRIDE; virtual void ContinueDrag(const views::MouseEvent& event) OVERRIDE; virtual bool EndDrag(bool canceled) OVERRIDE; virtual BaseTab* GetTabAt(BaseTab* tab, diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 0455cbd..2631515 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc @@ -181,6 +181,10 @@ bool BrowserTabStripController::IsTabPinned(BaseTab* tab) const { return IsTabPinned(tabstrip_->GetModelIndexOfBaseTab(tab)); } +const TabStripSelectionModel& BrowserTabStripController::GetSelectionModel() { + return model_->selection_model(); +} + int BrowserTabStripController::GetCount() const { return model_->count(); } diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index 7d43e42..e7e0093 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h @@ -40,6 +40,7 @@ class BrowserTabStripController : public TabStripController, bool IsTabPinned(BaseTab* tab) const; // TabStripController implementation: + virtual const TabStripSelectionModel& GetSelectionModel() OVERRIDE; virtual int GetCount() const OVERRIDE; virtual bool IsValidIndex(int model_index) const OVERRIDE; virtual bool IsActiveTab(int model_index) const; diff --git a/chrome/browser/ui/views/tabs/dragged_tab_controller.cc b/chrome/browser/ui/views/tabs/dragged_tab_controller.cc index 91204d8..97f634c 100644 --- a/chrome/browser/ui/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/ui/views/tabs/dragged_tab_controller.cc @@ -331,11 +331,13 @@ DraggedTabController::~DraggedTabController() { ResetDelegates(); } -void DraggedTabController::Init(BaseTabStrip* source_tabstrip, - BaseTab* source_tab, - const std::vector<BaseTab*>& tabs, - const gfx::Point& mouse_offset, - int source_tab_offset) { +void DraggedTabController::Init( + BaseTabStrip* source_tabstrip, + BaseTab* source_tab, + const std::vector<BaseTab*>& tabs, + const gfx::Point& mouse_offset, + int source_tab_offset, + const TabStripSelectionModel& initial_selection_model) { DCHECK(!tabs.empty()); DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); source_tabstrip_ = source_tabstrip; @@ -357,6 +359,7 @@ void DraggedTabController::Init(BaseTabStrip* source_tabstrip, static_cast<float>(source_tab->width()); } InitWindowCreatePoint(); + initial_selection_model_.Copy(initial_selection_model); } // static @@ -829,6 +832,8 @@ void DraggedTabController::Attach(BaseTabStrip* attached_tabstrip, // There is no Tab in |attached_tabstrip| that corresponds to the dragged // TabContents. We must now create one. + selection_model_before_attach_.Copy(attached_tabstrip->GetSelectionModel()); + // Remove ourselves as the delegate now that the dragged TabContents is // being inserted back into a Browser. for (size_t i = 0; i < drag_data_.size(); ++i) { @@ -922,8 +927,28 @@ void DraggedTabController::Detach() { } // If we've removed the last Tab from the TabStrip, hide the frame now. - if (attached_model->empty()) + if (attached_model->empty()) { HideFrame(); + } else if (!selection_model_before_attach_.empty() && + selection_model_before_attach_.active() >= 0 && + selection_model_before_attach_.active() < + attached_model->count()) { + // Restore the selection. + attached_model->SetSelectionFromModel(selection_model_before_attach_); + } else if (attached_tabstrip_ == source_tabstrip_ && + !initial_selection_model_.empty()) { + // First time detaching from the source tabstrip. Reset selection model to + // initial_selection_model_. Before resetting though we have to remove all + // the tabs from initial_selection_model_ as it was created with the tabs + // still there. + TabStripSelectionModel selection_model; + selection_model.Copy(initial_selection_model_); + for (DragData::const_reverse_iterator i = drag_data_.rbegin(); + i != drag_data_.rend(); ++i) { + selection_model.DecrementFrom(i->source_model_index); + } + attached_model->SetSelectionFromModel(selection_model); + } // Create the dragged view. CreateDraggedView(tab_data, drag_bounds); @@ -1076,7 +1101,12 @@ void DraggedTabController::RevertDrag() { attached_tabstrip_ = source_tabstrip_; - ResetSelection(GetModel(attached_tabstrip_)); + if (initial_selection_model_.empty()) { + ResetSelection(GetModel(attached_tabstrip_)); + } else { + GetModel(attached_tabstrip_)->SetSelectionFromModel( + initial_selection_model_); + } // If we're not attached to any TabStrip, or attached to some other TabStrip, // we need to restore the bounds of the original TabStrip's frame, in case diff --git a/chrome/browser/ui/views/tabs/dragged_tab_controller.h b/chrome/browser/ui/views/tabs/dragged_tab_controller.h index 3c0827e..910436b 100644 --- a/chrome/browser/ui/views/tabs/dragged_tab_controller.h +++ b/chrome/browser/ui/views/tabs/dragged_tab_controller.h @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "base/timer.h" +#include "chrome/browser/tabs/tab_strip_selection_model.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/browser/ui/tabs/dock_info.h" #include "content/browser/tab_contents/tab_contents_delegate.h" @@ -52,12 +53,14 @@ class DraggedTabController : public TabContentsDelegate, // pointer from the origin of the first tab in |tabs| and |source_tab_offset| // the offset from |source_tab|. |source_tab_offset| is the horizontal distant // for a horizontal tab strip, and the vertical distance for a vertical tab - // strip. + // strip. |initial_selection_model| is the selection model before the drag + // started and is only non-empty if |source_tab| was not initially selected. void Init(BaseTabStrip* source_tabstrip, BaseTab* source_tab, const std::vector<BaseTab*>& tabs, const gfx::Point& mouse_offset, - int source_tab_offset); + int source_tab_offset, + const TabStripSelectionModel& initial_selection_model); // Returns true if there is a drag underway and the drag is attached to // |tab_strip|. @@ -376,6 +379,13 @@ class DraggedTabController : public TabContentsDelegate, // True until |MoveAttached| is invoked once. bool initial_move_; + // The selection model before the drag started. See comment above Init() for + // details. + TabStripSelectionModel initial_selection_model_; + + // The selection model of |attached_tabstrip_| before the tabs were attached. + TabStripSelectionModel selection_model_before_attach_; + DISALLOW_COPY_AND_ASSIGN(DraggedTabController); }; diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc index 9ec1cb8..e5ad2cb 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc @@ -4,9 +4,16 @@ #include "chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h" +FakeBaseTabStripController::FakeBaseTabStripController() { +} + FakeBaseTabStripController::~FakeBaseTabStripController() { } +const TabStripSelectionModel& FakeBaseTabStripController::GetSelectionModel() { + return selection_model_; +} + int FakeBaseTabStripController::GetCount() const { return 0; } diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h index 2725ecb..5889a22 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h @@ -7,12 +7,15 @@ #pragma once #include "base/compiler_specific.h" +#include "chrome/browser/tabs/tab_strip_selection_model.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" class FakeBaseTabStripController : public TabStripController { public: + FakeBaseTabStripController(); virtual ~FakeBaseTabStripController(); + virtual const TabStripSelectionModel& GetSelectionModel() OVERRIDE; virtual int GetCount() const OVERRIDE; virtual bool IsValidIndex(int index) const OVERRIDE; virtual bool IsActiveTab(int index) const OVERRIDE; @@ -36,6 +39,11 @@ class FakeBaseTabStripController : public TabStripController { virtual bool IsCompatibleWith(BaseTabStrip* other) const OVERRIDE; virtual void CreateNewTab() OVERRIDE; virtual void ClickActiveTab(int index) OVERRIDE; + + private: + TabStripSelectionModel selection_model_; + + DISALLOW_COPY_AND_ASSIGN(FakeBaseTabStripController); }; #endif // CHROME_BROWSER_UI_VIEWS_TABS_FAKE_BASE_TAB_STRIP_CONTROLLER_H_ diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index 610e353..a3771d8 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h @@ -7,6 +7,7 @@ #pragma once class BaseTab; +class TabStripSelectionModel; namespace gfx { class Point; @@ -18,6 +19,8 @@ class MouseEvent; // Controller for tabs. class TabController { public: + virtual const TabStripSelectionModel& GetSelectionModel() = 0; + // Selects the tab. virtual void SelectTab(BaseTab* tab) = 0; @@ -50,7 +53,10 @@ class TabController { virtual bool IsTabCloseable(const BaseTab* tab) const = 0; // Potentially starts a drag for the specified Tab. - virtual void MaybeStartDrag(BaseTab* tab, const views::MouseEvent& event) = 0; + virtual void MaybeStartDrag( + BaseTab* tab, + const views::MouseEvent& event, + const TabStripSelectionModel& original_selection) = 0; // Continues dragging a Tab. virtual void ContinueDrag(const views::MouseEvent& event) = 0; diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index b97ca4a..5ed490c 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h @@ -9,6 +9,7 @@ class BaseTab; class BaseTabStrip; class GURL; +class TabStripSelectionModel; namespace gfx { class Point; @@ -20,6 +21,9 @@ class TabStripController { public: virtual ~TabStripController() {} + // Returns the selection model of the tabstrip. + virtual const TabStripSelectionModel& GetSelectionModel() = 0; + // Returns the number of tabs in the model. virtual int GetCount() const = 0; |