| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/touch/tabs/touch_tab_strip.h" | 5 #include "chrome/browser/ui/touch/tabs/touch_tab_strip.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 8 #include <cmath> |
| 9 |
| 7 #include "chrome/browser/ui/touch/tabs/touch_tab.h" | 10 #include "chrome/browser/ui/touch/tabs/touch_tab.h" |
| 8 #include "chrome/browser/ui/view_ids.h" | 11 #include "chrome/browser/ui/view_ids.h" |
| 9 #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" | 12 #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" |
| 10 #include "ui/gfx/canvas_skia.h" | 13 #include "ui/gfx/canvas_skia.h" |
| 11 #include "views/metrics.h" | 14 #include "views/metrics.h" |
| 12 #include "views/window/non_client_view.h" | 15 #include "views/window/non_client_view.h" |
| 13 #include "views/window/window.h" | 16 #include "views/window/window.h" |
| 14 | 17 |
| 15 static const int kTouchTabStripHeight = 64; | 18 static const int kTouchTabStripHeight = 64; |
| 16 static const int kTouchTabWidth = 64; | 19 static const int kTouchTabWidth = 64; |
| 17 static const int kTouchTabHeight = 64; | 20 static const int kTouchTabHeight = 64; |
| 21 static const int kScrollThreshold = 4; |
| 18 | 22 |
| 19 TouchTabStrip::TouchTabStrip(TabStripController* controller) | 23 TouchTabStrip::TouchTabStrip(TabStripController* controller) |
| 20 : BaseTabStrip(controller, BaseTabStrip::HORIZONTAL_TAB_STRIP), | 24 : BaseTabStrip(controller, BaseTabStrip::HORIZONTAL_TAB_STRIP), |
| 21 in_tab_close_(false), | 25 in_tab_close_(false), |
| 22 last_tap_time_(base::Time::FromInternalValue(0)), | 26 last_tap_time_(base::Time::FromInternalValue(0)), |
| 23 last_tapped_view_(NULL) { | 27 last_tapped_view_(NULL), |
| 28 initial_mouse_x_(0), |
| 29 initial_scroll_offset_(0), |
| 30 scroll_offset_(0), |
| 31 scrolling_(false), |
| 32 initial_tab_(NULL), |
| 33 min_scroll_offset_(0) { |
| 24 Init(); | 34 Init(); |
| 25 } | 35 } |
| 26 | 36 |
| 27 TouchTabStrip::~TouchTabStrip() { | 37 TouchTabStrip::~TouchTabStrip() { |
| 28 // The animations may reference the tabs. Shut down the animation before we | 38 // The animations may reference the tabs. Shut down the animation before we |
| 29 // delete the tabs. | 39 // delete the tabs. |
| 30 StopAnimating(false); | 40 StopAnimating(false); |
| 31 | 41 |
| 32 DestroyDragController(); | 42 DestroyDragController(); |
| 33 | 43 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 return in_tab_close_; | 131 return in_tab_close_; |
| 122 } | 132 } |
| 123 | 133 |
| 124 void TouchTabStrip::GenerateIdealBounds() { | 134 void TouchTabStrip::GenerateIdealBounds() { |
| 125 gfx::Rect bounds; | 135 gfx::Rect bounds; |
| 126 int tab_x = 0; | 136 int tab_x = 0; |
| 127 int tab_y = 0; | 137 int tab_y = 0; |
| 128 for (int i = 0; i < tab_count(); ++i) { | 138 for (int i = 0; i < tab_count(); ++i) { |
| 129 TouchTab* tab = GetTabAtTabDataIndex(i); | 139 TouchTab* tab = GetTabAtTabDataIndex(i); |
| 130 if (!tab->closing()) { | 140 if (!tab->closing()) { |
| 131 set_ideal_bounds(i, gfx::Rect(tab_x, tab_y, kTouchTabWidth, | 141 int x = tab_x + scroll_offset_; |
| 132 kTouchTabHeight)); | 142 if (tab->IsSelected()) { |
| 143 // limit the extent to which this tab can be displaced. |
| 144 x = std::min(std::max(0, x), width() - kTouchTabWidth); |
| 145 } |
| 146 set_ideal_bounds(i, gfx::Rect(x, tab_y, |
| 147 kTouchTabWidth, kTouchTabHeight)); |
| 133 // offset the next tab to the right by the width of this tab | 148 // offset the next tab to the right by the width of this tab |
| 134 tab_x += kTouchTabWidth; | 149 tab_x += kTouchTabWidth; |
| 135 } | 150 } |
| 136 } | 151 } |
| 152 min_scroll_offset_ = std::min(0, width() - tab_x); |
| 137 } | 153 } |
| 138 | 154 |
| 139 void TouchTabStrip::LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs, | 155 void TouchTabStrip::LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs, |
| 140 BaseTab* active_tab, | 156 BaseTab* active_tab, |
| 141 const gfx::Point& location, | 157 const gfx::Point& location, |
| 142 bool initial_drag) { | 158 bool initial_drag) { |
| 143 // Not needed as dragging isn't supported. | 159 // Not needed as dragging isn't supported. |
| 144 NOTIMPLEMENTED(); | 160 NOTIMPLEMENTED(); |
| 145 } | 161 } |
| 146 | 162 |
| 147 int TouchTabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { | 163 int TouchTabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { |
| 148 // Not needed as dragging isn't supported. | 164 // Not needed as dragging isn't supported. |
| 149 NOTIMPLEMENTED(); | 165 NOTIMPLEMENTED(); |
| 150 return 0; | 166 return 0; |
| 151 } | 167 } |
| 152 | 168 |
| 169 // TODO(wyck): Someday we might like to get a "scroll" interaction event by way |
| 170 // of views, triggered by the gesture manager, and/or mouse scroll wheel. |
| 171 // For now, we're just handling a single scroll with these mouse events: |
| 172 // OnMousePressed, OnMouseDragged, and OnMouseReleased. |
| 173 |
| 174 bool TouchTabStrip::OnMousePressed(const views::MouseEvent& event) { |
| 175 // When we press the mouse button, we begin a drag |
| 176 BeginScroll(event.location()); |
| 177 return true; |
| 178 } |
| 179 |
| 180 bool TouchTabStrip::OnMouseDragged(const views::MouseEvent& event) { |
| 181 ContinueScroll(event.location()); |
| 182 return true; |
| 183 } |
| 184 |
| 185 void TouchTabStrip::OnMouseReleased(const views::MouseEvent& event) { |
| 186 EndScroll(event.location()); |
| 187 } |
| 188 |
| 189 void TouchTabStrip::OnMouseCaptureLost() { |
| 190 CancelScroll(); |
| 191 } |
| 192 |
| 193 void TouchTabStrip::BeginScroll(const gfx::Point& point ) { |
| 194 initial_mouse_x_ = point.x(); |
| 195 initial_scroll_offset_ = scroll_offset_; |
| 196 initial_tab_ = static_cast<TouchTab*>(GetTabAtLocal(point)); |
| 197 } |
| 198 |
| 199 void TouchTabStrip::ContinueScroll(const gfx::Point& point) { |
| 200 int delta_x = point.x() - initial_mouse_x_; |
| 201 if (std::abs(delta_x) > kScrollThreshold) |
| 202 scrolling_ = true; |
| 203 if (scrolling_) |
| 204 ScrollTo(delta_x); |
| 205 DoLayout(); |
| 206 SchedulePaint(); |
| 207 } |
| 208 |
| 209 void TouchTabStrip::EndScroll(const gfx::Point& point) { |
| 210 int delta_x = point.x() - initial_mouse_x_; |
| 211 if (scrolling_) { |
| 212 scrolling_ = false; |
| 213 ScrollTo(delta_x); |
| 214 StopAnimating(false); |
| 215 GenerateIdealBounds(); |
| 216 AnimateToIdealBounds(); |
| 217 } else { |
| 218 TouchTab* tab = static_cast<TouchTab*>(GetTabAtLocal(point)); |
| 219 if (tab && tab == initial_tab_) |
| 220 SelectTab(tab); |
| 221 DoLayout(); |
| 222 SchedulePaint(); |
| 223 } |
| 224 initial_tab_ = NULL; |
| 225 } |
| 226 |
| 227 void TouchTabStrip::CancelScroll() { |
| 228 // Cancel the scroll by scrolling back to the initial position (deltax = 0). |
| 229 ScrollTo(0); |
| 230 StopAnimating(false); |
| 231 GenerateIdealBounds(); |
| 232 AnimateToIdealBounds(); |
| 233 } |
| 234 |
| 235 void TouchTabStrip::ScrollTo(int delta_x) { |
| 236 scroll_offset_ = initial_scroll_offset_ + delta_x; |
| 237 // Limit the scrolling here. |
| 238 // When scrolling beyond the limits of min and max offsets, the displacement |
| 239 // is adjusted to 25% of what would normally applied (divided by 4). |
| 240 // Perhaps in the future, Hooke's law could be used to model more physically |
| 241 // based spring-like behavior. |
| 242 int max_scroll_offset = 0; // Because there's never content to the left of 0. |
| 243 if (scroll_offset_ > max_scroll_offset) { |
| 244 if (scrolling_) { |
| 245 scroll_offset_ = max_scroll_offset |
| 246 + std::min((scroll_offset_ - max_scroll_offset) / 4, |
| 247 kTouchTabWidth); |
| 248 } else { |
| 249 scroll_offset_ = max_scroll_offset; |
| 250 } |
| 251 } |
| 252 if (scroll_offset_ < min_scroll_offset_) { |
| 253 if (scrolling_) { |
| 254 scroll_offset_ = min_scroll_offset_ |
| 255 + std::max((scroll_offset_ - min_scroll_offset_) / 4, |
| 256 -kTouchTabWidth); |
| 257 } else { |
| 258 scroll_offset_ = min_scroll_offset_; |
| 259 } |
| 260 } |
| 261 } |
| 262 |
| 153 TouchTab* TouchTabStrip::GetTabAtTabDataIndex(int tab_data_index) const { | 263 TouchTab* TouchTabStrip::GetTabAtTabDataIndex(int tab_data_index) const { |
| 154 return static_cast<TouchTab*>(base_tab_at_tab_index(tab_data_index)); | 264 return static_cast<TouchTab*>(base_tab_at_tab_index(tab_data_index)); |
| 155 } | 265 } |
| 156 | 266 |
| 157 //////////////////////////////////////////////////////////////////////////////// | 267 //////////////////////////////////////////////////////////////////////////////// |
| 158 // TouchTabStrip, private: | 268 // TouchTabStrip, private: |
| 159 | 269 |
| 160 void TouchTabStrip::Init() { | 270 void TouchTabStrip::Init() { |
| 161 SetID(VIEW_ID_TAB_STRIP); | 271 SetID(VIEW_ID_TAB_STRIP); |
| 162 } | 272 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 last_tapped_view_ = view; | 346 last_tapped_view_ = view; |
| 237 return TOUCH_STATUS_UNKNOWN; | 347 return TOUCH_STATUS_UNKNOWN; |
| 238 } | 348 } |
| 239 | 349 |
| 240 void TouchTabStrip::ViewHierarchyChanged(bool is_add, | 350 void TouchTabStrip::ViewHierarchyChanged(bool is_add, |
| 241 View* parent, | 351 View* parent, |
| 242 View* child) { | 352 View* child) { |
| 243 if (!is_add && last_tapped_view_ == child) | 353 if (!is_add && last_tapped_view_ == child) |
| 244 last_tapped_view_ = NULL; | 354 last_tapped_view_ = NULL; |
| 245 } | 355 } |
| OLD | NEW |