 Chromium Code Reviews
 Chromium Code Reviews| 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 <cmath> | |
| 
sky
2011/04/06 15:11:50
Can these be sorted?
 
wyck
2011/04/06 20:14:24
Done.
 | |
| 8 #include <algorithm> | |
| 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 DoLayout(); | |
| 183 SchedulePaint(); | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 void TouchTabStrip::OnMouseReleased(const views::MouseEvent& event, | |
| 188 bool canceled) { | |
| 189 if (canceled) { | |
| 190 // Cancel the scroll by scrolling back to the initial position (deltax = 0). | |
| 191 ScrollTo(0); | |
| 192 StopAnimating(false); | |
| 193 GenerateIdealBounds(); | |
| 194 AnimateToIdealBounds(); | |
| 195 } else { | |
| 196 EndScroll(event.location()); | |
| 197 } | |
| 198 SchedulePaint(); | |
| 199 } | |
| 200 | |
| 201 void TouchTabStrip::BeginScroll(const gfx::Point& point ) { | |
| 202 initial_mouse_x_ = point.x(); | |
| 203 initial_scroll_offset_ = scroll_offset_; | |
| 204 initial_tab_ = static_cast<TouchTab*>(GetTabAtLocal(point)); | |
| 205 } | |
| 206 | |
| 207 void TouchTabStrip::ContinueScroll(const gfx::Point& point) { | |
| 208 int delta_x = point.x() - initial_mouse_x_; | |
| 209 if (std::abs(delta_x) > kScrollThreshold) | |
| 210 scrolling_ = true; | |
| 211 if (scrolling_) | |
| 212 ScrollTo(delta_x); | |
| 213 // and layout | |
| 
sky
2011/04/06 15:11:50
This comment doesn't make sense.
 
wyck
2011/04/06 20:14:24
Right, sorry.  That was a note to myself to move t
 | |
| 214 } | |
| 215 | |
| 216 void TouchTabStrip::EndScroll(const gfx::Point& point) { | |
| 217 int delta_x = point.x() - initial_mouse_x_; | |
| 218 if (scrolling_) { | |
| 219 scrolling_ = false; | |
| 220 ScrollTo(delta_x); | |
| 221 StopAnimating(false); | |
| 222 GenerateIdealBounds(); | |
| 223 AnimateToIdealBounds(); | |
| 224 } else { | |
| 225 TouchTab* tab = static_cast<TouchTab*>(GetTabAtLocal(point)); | |
| 226 if (tab && tab == initial_tab_) | |
| 
sky
2011/04/06 15:11:50
Don't you always want to select the tab at the loc
 
wyck
2011/04/06 20:14:24
No, I was thinking it works like a button, where i
 | |
| 227 SelectTab(tab); | |
| 228 DoLayout(); | |
| 229 } | |
| 230 initial_tab_ = NULL; | |
| 231 } | |
| 232 | |
| 233 void TouchTabStrip::ScrollTo(int delta_x) { | |
| 234 scroll_offset_ = initial_scroll_offset_ + delta_x; | |
| 235 // Limit the scrolling here. | |
| 236 // When scrolling beyond the limits of min and max offsets, the displacement | |
| 237 // is adjusted to 25% of what would normally applied (divided by 4). | |
| 238 // Perhaps in the future, Hooke's law could be used to model more physically | |
| 239 // based spring-like behavior. | |
| 240 int max_scroll_offset = 0; // Because there's never content to the left of 0. | |
| 241 if (scroll_offset_ > max_scroll_offset) { | |
| 242 if (scrolling_) { | |
| 243 scroll_offset_ = max_scroll_offset | |
| 244 + std::min((scroll_offset_ - max_scroll_offset) / 4, | |
| 245 kTouchTabWidth); | |
| 246 } else { | |
| 247 scroll_offset_ = max_scroll_offset; | |
| 248 } | |
| 249 } | |
| 250 if (scroll_offset_ < min_scroll_offset_) { | |
| 251 if (scrolling_) { | |
| 252 scroll_offset_ = min_scroll_offset_ | |
| 253 + std::max((scroll_offset_ - min_scroll_offset_) / 4, | |
| 254 -kTouchTabWidth); | |
| 255 } else { | |
| 256 scroll_offset_ = min_scroll_offset_; | |
| 257 } | |
| 258 } | |
| 259 } | |
| 260 | |
| 153 TouchTab* TouchTabStrip::GetTabAtTabDataIndex(int tab_data_index) const { | 261 TouchTab* TouchTabStrip::GetTabAtTabDataIndex(int tab_data_index) const { | 
| 154 return static_cast<TouchTab*>(base_tab_at_tab_index(tab_data_index)); | 262 return static_cast<TouchTab*>(base_tab_at_tab_index(tab_data_index)); | 
| 155 } | 263 } | 
| 156 | 264 | 
| 157 //////////////////////////////////////////////////////////////////////////////// | 265 //////////////////////////////////////////////////////////////////////////////// | 
| 158 // TouchTabStrip, private: | 266 // TouchTabStrip, private: | 
| 159 | 267 | 
| 160 void TouchTabStrip::Init() { | 268 void TouchTabStrip::Init() { | 
| 161 SetID(VIEW_ID_TAB_STRIP); | 269 SetID(VIEW_ID_TAB_STRIP); | 
| 162 } | 270 } | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 last_tapped_view_ = view; | 344 last_tapped_view_ = view; | 
| 237 return TOUCH_STATUS_UNKNOWN; | 345 return TOUCH_STATUS_UNKNOWN; | 
| 238 } | 346 } | 
| 239 | 347 | 
| 240 void TouchTabStrip::ViewHierarchyChanged(bool is_add, | 348 void TouchTabStrip::ViewHierarchyChanged(bool is_add, | 
| 241 View* parent, | 349 View* parent, | 
| 242 View* child) { | 350 View* child) { | 
| 243 if (!is_add && last_tapped_view_ == child) | 351 if (!is_add && last_tapped_view_ == child) | 
| 244 last_tapped_view_ = NULL; | 352 last_tapped_view_ = NULL; | 
| 245 } | 353 } | 
| OLD | NEW |