OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/views/tabs/base_tab_strip.h" | 5 #include "chrome/browser/views/tabs/base_tab_strip.h" |
6 | 6 |
| 7 #include "base/logging.h" |
| 8 #include "chrome/browser/views/tabs/dragged_tab_controller.h" |
7 #include "chrome/browser/views/tabs/tab_strip_controller.h" | 9 #include "chrome/browser/views/tabs/tab_strip_controller.h" |
| 10 #include "views/widget/root_view.h" |
| 11 #include "views/window/window.h" |
8 | 12 |
9 BaseTabStrip::BaseTabStrip(TabStripController* controller) | 13 BaseTabStrip::BaseTabStrip(TabStripController* controller, Type type) |
10 : controller_(controller) { | 14 : controller_(controller), |
| 15 type_(type), |
| 16 attaching_dragged_tab_(false) { |
11 } | 17 } |
12 | 18 |
13 BaseTabStrip::~BaseTabStrip() { | 19 BaseTabStrip::~BaseTabStrip() { |
14 } | 20 } |
15 | 21 |
16 void BaseTabStrip::UpdateLoadingAnimations() { | 22 void BaseTabStrip::UpdateLoadingAnimations() { |
17 controller_->UpdateLoadingAnimations(); | 23 controller_->UpdateLoadingAnimations(); |
18 } | 24 } |
19 | 25 |
20 BaseTabRenderer* BaseTabStrip::GetSelectedBaseTab() const { | 26 BaseTabRenderer* BaseTabStrip::GetSelectedBaseTab() const { |
21 return GetBaseTabAtModelIndex(controller_->GetSelectedIndex()); | 27 return GetBaseTabAtModelIndex(controller_->GetSelectedIndex()); |
22 } | 28 } |
23 | 29 |
| 30 void BaseTabStrip::AddTabAt(int model_index, |
| 31 bool foreground, |
| 32 const TabRendererData& data) { |
| 33 BaseTabRenderer* tab = CreateTab(); |
| 34 tab->SetData(data); |
| 35 |
| 36 TabData d = { tab, gfx::Rect() }; |
| 37 tab_data_.insert(tab_data_.begin() + ModelIndexToTabIndex(model_index), d); |
| 38 |
| 39 AddChildView(tab); |
| 40 |
| 41 // Don't animate the first tab, it looks weird, and don't animate anything |
| 42 // if the containing window isn't visible yet. |
| 43 if (tab_count() > 1 && GetWindow() && GetWindow()->IsVisible()) |
| 44 StartInsertTabAnimation(model_index, foreground); |
| 45 else |
| 46 Layout(); |
| 47 } |
| 48 |
| 49 void BaseTabStrip::MoveTab(int from_model_index, int to_model_index) { |
| 50 int from_tab_data_index = ModelIndexToTabIndex(from_model_index); |
| 51 |
| 52 BaseTabRenderer* tab = tab_data_[from_tab_data_index].tab; |
| 53 tab_data_.erase(tab_data_.begin() + from_tab_data_index); |
| 54 |
| 55 TabData data = {tab, gfx::Rect()}; |
| 56 |
| 57 int to_tab_data_index = ModelIndexToTabIndex(to_model_index); |
| 58 |
| 59 tab_data_.insert(tab_data_.begin() + to_tab_data_index, data); |
| 60 |
| 61 StartMoveTabAnimation(); |
| 62 } |
| 63 |
| 64 BaseTabRenderer* BaseTabStrip::GetBaseTabAtModelIndex(int model_index) const { |
| 65 return base_tab_at_tab_index(ModelIndexToTabIndex(model_index)); |
| 66 } |
| 67 |
| 68 int BaseTabStrip::GetModelIndexOfBaseTab(const BaseTabRenderer* tab) const { |
| 69 for (int i = 0, model_index = 0; i < tab_count(); ++i) { |
| 70 BaseTabRenderer* current_tab = base_tab_at_tab_index(i); |
| 71 if (!current_tab->closing()) { |
| 72 if (current_tab == tab) |
| 73 return model_index; |
| 74 model_index++; |
| 75 } |
| 76 } |
| 77 return -1; |
| 78 } |
| 79 |
24 int BaseTabStrip::GetModelCount() const { | 80 int BaseTabStrip::GetModelCount() const { |
25 return controller_->GetCount(); | 81 return controller_->GetCount(); |
26 } | 82 } |
27 | 83 |
28 bool BaseTabStrip::IsValidModelIndex(int model_index) const { | 84 bool BaseTabStrip::IsValidModelIndex(int model_index) const { |
29 return controller_->IsValidIndex(model_index); | 85 return controller_->IsValidIndex(model_index); |
30 } | 86 } |
31 | 87 |
| 88 int BaseTabStrip::ModelIndexToTabIndex(int model_index) const { |
| 89 int current_model_index = 0; |
| 90 for (int i = 0; i < tab_count(); ++i) { |
| 91 if (!base_tab_at_tab_index(i)->closing()) { |
| 92 if (current_model_index == model_index) |
| 93 return i; |
| 94 current_model_index++; |
| 95 } |
| 96 } |
| 97 return static_cast<int>(tab_data_.size()); |
| 98 } |
| 99 |
| 100 bool BaseTabStrip::IsDragSessionActive() const { |
| 101 return drag_controller_.get() != NULL; |
| 102 } |
| 103 |
32 void BaseTabStrip::SelectTab(BaseTabRenderer* tab) { | 104 void BaseTabStrip::SelectTab(BaseTabRenderer* tab) { |
33 int model_index = GetModelIndexOfBaseTab(tab); | 105 int model_index = GetModelIndexOfBaseTab(tab); |
34 if (IsValidModelIndex(model_index)) | 106 if (IsValidModelIndex(model_index)) |
35 controller_->SelectTab(model_index); | 107 controller_->SelectTab(model_index); |
36 } | 108 } |
37 | 109 |
38 void BaseTabStrip::CloseTab(BaseTabRenderer* tab) { | 110 void BaseTabStrip::CloseTab(BaseTabRenderer* tab) { |
39 int model_index = GetModelIndexOfBaseTab(tab); | 111 int model_index = GetModelIndexOfBaseTab(tab); |
40 if (IsValidModelIndex(model_index)) | 112 if (IsValidModelIndex(model_index)) |
41 controller_->CloseTab(model_index); | 113 controller_->CloseTab(model_index); |
42 } | 114 } |
43 | 115 |
44 void BaseTabStrip::ShowContextMenu(BaseTabRenderer* tab, const gfx::Point& p) { | 116 void BaseTabStrip::ShowContextMenu(BaseTabRenderer* tab, const gfx::Point& p) { |
45 controller_->ShowContextMenu(tab, p); | 117 controller_->ShowContextMenu(tab, p); |
46 } | 118 } |
47 | 119 |
48 bool BaseTabStrip::IsTabSelected(const BaseTabRenderer* tab) const { | 120 bool BaseTabStrip::IsTabSelected(const BaseTabRenderer* tab) const { |
49 int model_index = GetModelIndexOfBaseTab(tab); | 121 int model_index = GetModelIndexOfBaseTab(tab); |
50 return IsValidModelIndex(model_index) && | 122 return IsValidModelIndex(model_index) && |
51 controller_->IsTabSelected(model_index); | 123 controller_->IsTabSelected(model_index); |
52 } | 124 } |
53 | 125 |
54 bool BaseTabStrip::IsTabPinned(const BaseTabRenderer* tab) const { | 126 bool BaseTabStrip::IsTabPinned(const BaseTabRenderer* tab) const { |
| 127 if (tab->closing()) |
| 128 return false; |
| 129 |
55 int model_index = GetModelIndexOfBaseTab(tab); | 130 int model_index = GetModelIndexOfBaseTab(tab); |
56 return IsValidModelIndex(model_index) && | 131 return IsValidModelIndex(model_index) && |
57 controller_->IsTabPinned(model_index); | 132 controller_->IsTabPinned(model_index); |
58 } | 133 } |
| 134 |
| 135 void BaseTabStrip::MaybeStartDrag(BaseTabRenderer* tab, |
| 136 const views::MouseEvent& event) { |
| 137 // Don't accidentally start any drag operations during animations if the |
| 138 // mouse is down... during an animation tabs are being resized automatically, |
| 139 // so the View system can misinterpret this easily if the mouse is down that |
| 140 // the user is dragging. |
| 141 if (IsAnimating() || tab->closing() || |
| 142 controller_->HasAvailableDragActions() == 0) { |
| 143 return; |
| 144 } |
| 145 int model_index = GetModelIndexOfBaseTab(tab); |
| 146 if (!IsValidModelIndex(model_index)) { |
| 147 CHECK(false); |
| 148 return; |
| 149 } |
| 150 drag_controller_.reset(new DraggedTabController(tab, this)); |
| 151 drag_controller_->CaptureDragInfo(tab, event.location()); |
| 152 } |
| 153 |
| 154 void BaseTabStrip::ContinueDrag(const views::MouseEvent& event) { |
| 155 // We can get called even if |MaybeStartDrag| wasn't called in the event of |
| 156 // a TabStrip animation when the mouse button is down. In this case we should |
| 157 // _not_ continue the drag because it can lead to weird bugs. |
| 158 if (drag_controller_.get()) { |
| 159 bool started_drag = drag_controller_->started_drag(); |
| 160 drag_controller_->Drag(); |
| 161 if (drag_controller_->started_drag() && !started_drag) { |
| 162 // The drag just started. Redirect mouse events to us to that the tab that |
| 163 // originated the drag can be safely deleted. |
| 164 GetRootView()->SetMouseHandler(this); |
| 165 } |
| 166 } |
| 167 } |
| 168 |
| 169 bool BaseTabStrip::EndDrag(bool canceled) { |
| 170 if (!drag_controller_.get()) |
| 171 return false; |
| 172 bool started_drag = drag_controller_->started_drag(); |
| 173 drag_controller_->EndDrag(canceled); |
| 174 return started_drag; |
| 175 } |
| 176 |
| 177 void BaseTabStrip::Layout() { |
| 178 StopAnimating(false); |
| 179 |
| 180 GenerateIdealBounds(); |
| 181 |
| 182 for (int i = 0; i < tab_count(); ++i) |
| 183 tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds); |
| 184 |
| 185 SchedulePaint(); |
| 186 } |
| 187 |
| 188 bool BaseTabStrip::OnMouseDragged(const views::MouseEvent& event) { |
| 189 if (drag_controller_.get()) |
| 190 drag_controller_->Drag(); |
| 191 return true; |
| 192 } |
| 193 |
| 194 void BaseTabStrip::OnMouseReleased(const views::MouseEvent& event, |
| 195 bool canceled) { |
| 196 EndDrag(canceled); |
| 197 } |
| 198 |
| 199 void BaseTabStrip::RemoveAndDeleteTab(BaseTabRenderer* tab) { |
| 200 int tab_data_index = TabIndexOfTab(tab); |
| 201 |
| 202 DCHECK(tab_data_index != -1); |
| 203 |
| 204 // Remove the Tab from the TabStrip's list... |
| 205 tab_data_.erase(tab_data_.begin() + tab_data_index); |
| 206 |
| 207 delete tab; |
| 208 } |
| 209 |
| 210 int BaseTabStrip::TabIndexOfTab(BaseTabRenderer* tab) const { |
| 211 for (int i = 0; i < tab_count(); ++i) { |
| 212 if (base_tab_at_tab_index(i) == tab) |
| 213 return i; |
| 214 } |
| 215 return -1; |
| 216 } |
| 217 |
| 218 void BaseTabStrip::DestroyDragController() { |
| 219 if (IsDragSessionActive()) |
| 220 drag_controller_.reset(NULL); |
| 221 } |
OLD | NEW |