Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / views / ash / tab_scrubber.cc
blob716e7cff7e9e85e637468ecf9529adc7c1fba274
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/ash/tab_scrubber.h"
7 #include "ash/shell.h"
8 #include "ash/wm/window_util.h"
9 #include "base/metrics/histogram.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_finder.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/browser/ui/views/frame/browser_view.h"
15 #include "chrome/browser/ui/views/tabs/tab.h"
16 #include "chrome/browser/ui/views/tabs/tab_strip.h"
17 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/notification_source.h"
19 #include "ui/aura/window.h"
20 #include "ui/events/event.h"
21 #include "ui/events/event_utils.h"
22 #include "ui/events/gesture_detection/gesture_configuration.h"
23 #include "ui/views/controls/glow_hover_controller.h"
25 namespace {
26 const int64 kActivationDelayMS = 200;
29 // static
30 TabScrubber* TabScrubber::GetInstance() {
31 static TabScrubber* instance = NULL;
32 if (!instance)
33 instance = new TabScrubber();
34 return instance;
37 // static
38 gfx::Point TabScrubber::GetStartPoint(
39 TabStrip* tab_strip,
40 int index,
41 TabScrubber::Direction direction) {
42 int initial_tab_offset = Tab::GetMiniWidth() / 2;
43 gfx::Rect tab_bounds = tab_strip->tab_at(index)->bounds();
44 float x = direction == LEFT ?
45 tab_bounds.x() + initial_tab_offset :
46 tab_bounds.right() - initial_tab_offset;
47 return gfx::Point(x, tab_bounds.CenterPoint().y());
50 bool TabScrubber::IsActivationPending() {
51 return activate_timer_.IsRunning();
54 TabScrubber::TabScrubber()
55 : scrubbing_(false),
56 browser_(NULL),
57 swipe_x_(-1),
58 swipe_y_(-1),
59 swipe_direction_(LEFT),
60 highlighted_tab_(-1),
61 activate_timer_(true, false),
62 activation_delay_(kActivationDelayMS),
63 use_default_activation_delay_(true),
64 weak_ptr_factory_(this) {
65 ash::Shell::GetInstance()->AddPreTargetHandler(this);
66 registrar_.Add(
67 this,
68 chrome::NOTIFICATION_BROWSER_CLOSED,
69 content::NotificationService::AllSources());
72 TabScrubber::~TabScrubber() {
73 // Note: The weak_ptr_factory_ should invalidate its weak pointers before
74 // any other members are destroyed.
75 weak_ptr_factory_.InvalidateWeakPtrs();
78 void TabScrubber::OnScrollEvent(ui::ScrollEvent* event) {
79 if (event->type() == ui::ET_SCROLL_FLING_CANCEL ||
80 event->type() == ui::ET_SCROLL_FLING_START) {
81 FinishScrub(true);
82 immersive_reveal_lock_.reset();
83 return;
86 if (event->finger_count() != 3)
87 return;
89 Browser* browser = GetActiveBrowser();
90 if (!browser || (scrubbing_ && browser_ && browser != browser_) ||
91 (highlighted_tab_ != -1 &&
92 highlighted_tab_ >= browser->tab_strip_model()->count())) {
93 FinishScrub(false);
94 return;
97 BrowserView* browser_view =
98 BrowserView::GetBrowserViewForNativeWindow(
99 browser->window()->GetNativeWindow());
100 TabStrip* tab_strip = browser_view->tabstrip();
102 if (tab_strip->IsAnimating()) {
103 FinishScrub(false);
104 return;
107 // We are handling the event.
108 event->StopPropagation();
110 float x_offset = event->x_offset();
111 int last_tab_index = highlighted_tab_ == -1 ?
112 browser->tab_strip_model()->active_index() : highlighted_tab_;
113 if (!scrubbing_) {
114 swipe_direction_ = (x_offset < 0) ? LEFT : RIGHT;
115 const gfx::Point start_point =
116 GetStartPoint(tab_strip,
117 browser->tab_strip_model()->active_index(),
118 swipe_direction_);
119 browser_ = browser;
120 scrubbing_ = true;
122 swipe_x_ = start_point.x();
123 swipe_y_ = start_point.y();
124 ImmersiveModeController* immersive_controller =
125 browser_view->immersive_mode_controller();
126 if (immersive_controller->IsEnabled()) {
127 immersive_reveal_lock_.reset(immersive_controller->GetRevealedLock(
128 ImmersiveModeController::ANIMATE_REVEAL_YES));
130 tab_strip->AddObserver(this);
131 } else if (highlighted_tab_ == -1) {
132 Direction direction = (x_offset < 0) ? LEFT : RIGHT;
133 if (direction != swipe_direction_) {
134 const gfx::Point start_point =
135 GetStartPoint(tab_strip,
136 browser->tab_strip_model()->active_index(),
137 direction);
138 swipe_x_ = start_point.x();
139 swipe_y_ = start_point.y();
140 swipe_direction_ = direction;
144 swipe_x_ += x_offset;
145 Tab* first_tab = tab_strip->tab_at(0);
146 int first_tab_center = first_tab->bounds().CenterPoint().x();
147 Tab* last_tab = tab_strip->tab_at(tab_strip->tab_count() - 1);
148 int last_tab_tab_center = last_tab->bounds().CenterPoint().x();
149 if (swipe_x_ < first_tab_center)
150 swipe_x_ = first_tab_center;
151 if (swipe_x_ > last_tab_tab_center)
152 swipe_x_ = last_tab_tab_center;
154 Tab* initial_tab = tab_strip->tab_at(last_tab_index);
155 gfx::Point tab_point(swipe_x_, swipe_y_);
156 views::View::ConvertPointToTarget(tab_strip, initial_tab, &tab_point);
157 Tab* new_tab = tab_strip->GetTabAt(initial_tab, tab_point);
158 if (!new_tab)
159 return;
161 int new_index = tab_strip->GetModelIndexOfTab(new_tab);
162 if (highlighted_tab_ == -1 &&
163 new_index == browser->tab_strip_model()->active_index())
164 return;
166 if (new_index != highlighted_tab_) {
167 if (activate_timer_.IsRunning()) {
168 activate_timer_.Reset();
169 } else {
170 int delay = use_default_activation_delay_
171 ? ui::GestureConfiguration::GetInstance()
172 ->tab_scrub_activation_delay_in_ms()
173 : activation_delay_;
174 if (delay >= 0) {
175 activate_timer_.Start(FROM_HERE,
176 base::TimeDelta::FromMilliseconds(delay),
177 base::Bind(&TabScrubber::FinishScrub,
178 weak_ptr_factory_.GetWeakPtr(),
179 true));
182 if (highlighted_tab_ != -1) {
183 Tab* tab = tab_strip->tab_at(highlighted_tab_);
184 tab->hover_controller()->HideImmediately();
186 if (new_index == browser->tab_strip_model()->active_index()) {
187 highlighted_tab_ = -1;
188 } else {
189 highlighted_tab_ = new_index;
190 new_tab->hover_controller()->Show(views::GlowHoverController::PRONOUNCED);
193 if (highlighted_tab_ != -1) {
194 gfx::Point hover_point(swipe_x_, swipe_y_);
195 views::View::ConvertPointToTarget(tab_strip, new_tab, &hover_point);
196 new_tab->hover_controller()->SetLocation(hover_point);
200 void TabScrubber::Observe(int type,
201 const content::NotificationSource& source,
202 const content::NotificationDetails& details) {
203 if (content::Source<Browser>(source).ptr() == browser_) {
204 activate_timer_.Stop();
205 swipe_x_ = -1;
206 swipe_y_ = -1;
207 scrubbing_ = false;
208 highlighted_tab_ = -1;
209 browser_ = NULL;
213 void TabScrubber::TabStripAddedTabAt(TabStrip* tab_strip, int index) {
214 if (highlighted_tab_ == -1)
215 return;
217 if (index < highlighted_tab_)
218 ++highlighted_tab_;
221 void TabScrubber::TabStripMovedTab(TabStrip* tab_strip,
222 int from_index,
223 int to_index) {
224 if (highlighted_tab_ == -1)
225 return;
227 if (from_index == highlighted_tab_)
228 highlighted_tab_ = to_index;
229 else if (from_index < highlighted_tab_&& highlighted_tab_<= to_index)
230 --highlighted_tab_;
231 else if (from_index > highlighted_tab_ && highlighted_tab_ >= to_index)
232 ++highlighted_tab_;
235 void TabScrubber::TabStripRemovedTabAt(TabStrip* tab_strip, int index) {
236 if (highlighted_tab_ == -1)
237 return;
238 if (index == highlighted_tab_) {
239 FinishScrub(false);
240 return;
242 if (index < highlighted_tab_)
243 --highlighted_tab_;
246 void TabScrubber::TabStripDeleted(TabStrip* tab_strip) {
247 if (highlighted_tab_ == -1)
248 return;
251 Browser* TabScrubber::GetActiveBrowser() {
252 aura::Window* active_window = ash::wm::GetActiveWindow();
253 if (!active_window)
254 return NULL;
256 Browser* browser = chrome::FindBrowserWithWindow(active_window);
257 if (!browser || browser->type() != Browser::TYPE_TABBED)
258 return NULL;
260 return browser;
263 void TabScrubber::FinishScrub(bool activate) {
264 activate_timer_.Stop();
266 if (browser_ && browser_->window()) {
267 BrowserView* browser_view =
268 BrowserView::GetBrowserViewForNativeWindow(
269 browser_->window()->GetNativeWindow());
270 TabStrip* tab_strip = browser_view->tabstrip();
271 if (activate && highlighted_tab_ != -1) {
272 Tab* tab = tab_strip->tab_at(highlighted_tab_);
273 tab->hover_controller()->HideImmediately();
274 int distance =
275 std::abs(
276 highlighted_tab_ - browser_->tab_strip_model()->active_index());
277 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.ScrubDistance", distance, 0, 20, 21);
278 browser_->tab_strip_model()->ActivateTabAt(highlighted_tab_, true);
280 tab_strip->RemoveObserver(this);
282 swipe_x_ = -1;
283 swipe_y_ = -1;
284 scrubbing_ = false;
285 highlighted_tab_ = -1;