Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: chrome/browser/views/tabs/tab_strip.cc

Issue 2124003: More TabStrip refactoring. (Closed)
Patch Set: Merge with trunk Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/views/tabs/tab_strip.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/tab_strip.h" 5 #include "chrome/browser/views/tabs/tab_strip.h"
6 6
7 #include "app/animation_container.h" 7 #include "app/animation_container.h"
8 #include "app/drag_drop_types.h" 8 #include "app/drag_drop_types.h"
9 #include "app/l10n_util.h" 9 #include "app/l10n_util.h"
10 #include "app/resource_bundle.h" 10 #include "app/resource_bundle.h"
11 #include "app/slide_animation.h" 11 #include "app/slide_animation.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/stl_util-inl.h" 13 #include "base/stl_util-inl.h"
14 #include "chrome/browser/browser.h" 14 #include "chrome/browser/browser.h"
15 #include "chrome/browser/browser_theme_provider.h" 15 #include "chrome/browser/browser_theme_provider.h"
16 #include "chrome/browser/defaults.h" 16 #include "chrome/browser/defaults.h"
17 #include "chrome/browser/view_ids.h" 17 #include "chrome/browser/view_ids.h"
18 #include "chrome/browser/views/tabs/dragged_tab_controller.h"
19 #include "chrome/browser/views/tabs/tab.h" 18 #include "chrome/browser/views/tabs/tab.h"
20 #include "chrome/browser/views/tabs/tab_strip_controller.h" 19 #include "chrome/browser/views/tabs/tab_strip_controller.h"
21 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
22 #include "gfx/canvas.h" 21 #include "gfx/canvas.h"
23 #include "gfx/path.h" 22 #include "gfx/path.h"
24 #include "gfx/size.h" 23 #include "gfx/size.h"
25 #include "grit/generated_resources.h" 24 #include "grit/generated_resources.h"
26 #include "grit/theme_resources.h" 25 #include "grit/theme_resources.h"
27 #include "views/controls/image_view.h" 26 #include "views/controls/image_view.h"
28 #include "views/widget/default_theme_provider.h" 27 #include "views/widget/default_theme_provider.h"
29 #include "views/widget/root_view.h"
30 #include "views/window/non_client_view.h" 28 #include "views/window/non_client_view.h"
31 #include "views/window/window.h" 29 #include "views/window/window.h"
32 30
33 #if defined(OS_WIN) 31 #if defined(OS_WIN)
34 #include "app/win_util.h" 32 #include "app/win_util.h"
35 #include "views/widget/widget_win.h" 33 #include "views/widget/widget_win.h"
36 #elif defined(OS_LINUX) 34 #elif defined(OS_LINUX)
37 #include "views/widget/widget_gtk.h" 35 #include "views/widget/widget_gtk.h"
38 #endif 36 #endif
39 37
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 Tab* tab_; 103 Tab* tab_;
106 104
107 DISALLOW_COPY_AND_ASSIGN(NewTabAlphaDelegate); 105 DISALLOW_COPY_AND_ASSIGN(NewTabAlphaDelegate);
108 }; 106 };
109 107
110 // Animation delegate used when a dragged tab is released. When done sets the 108 // Animation delegate used when a dragged tab is released. When done sets the
111 // dragging state to false. 109 // dragging state to false.
112 class ResetDraggingStateDelegate 110 class ResetDraggingStateDelegate
113 : public views::BoundsAnimator::OwnedAnimationDelegate { 111 : public views::BoundsAnimator::OwnedAnimationDelegate {
114 public: 112 public:
115 explicit ResetDraggingStateDelegate(Tab* tab) : tab_(tab) { 113 explicit ResetDraggingStateDelegate(BaseTabRenderer* tab) : tab_(tab) {
116 } 114 }
117 115
118 virtual void AnimationEnded(const Animation* animation) { 116 virtual void AnimationEnded(const Animation* animation) {
119 tab_->set_dragging(false); 117 tab_->set_dragging(false);
120 } 118 }
121 119
122 virtual void AnimationCanceled(const Animation* animation) { 120 virtual void AnimationCanceled(const Animation* animation) {
123 tab_->set_dragging(false); 121 tab_->set_dragging(false);
124 } 122 }
125 123
126 private: 124 private:
127 Tab* tab_; 125 BaseTabRenderer* tab_;
128 126
129 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); 127 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate);
130 }; 128 };
131 129
132 /////////////////////////////////////////////////////////////////////////////// 130 ///////////////////////////////////////////////////////////////////////////////
133 // NewTabButton 131 // NewTabButton
134 // 132 //
135 // A subclass of button that hit-tests to the shape of the new tab button. 133 // A subclass of button that hit-tests to the shape of the new tab button.
136 134
137 class NewTabButton : public views::ImageButton { 135 class NewTabButton : public views::ImageButton {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 CompleteRemove(); 197 CompleteRemove();
200 } 198 }
201 199
202 private: 200 private:
203 void CompleteRemove() { 201 void CompleteRemove() {
204 if (!tab_->closing()) { 202 if (!tab_->closing()) {
205 // The tab was added back yet we weren't canceled. This shouldn't happen. 203 // The tab was added back yet we weren't canceled. This shouldn't happen.
206 NOTREACHED(); 204 NOTREACHED();
207 return; 205 return;
208 } 206 }
209 tabstrip_->RemoveTab(tab_); 207 tabstrip_->RemoveAndDeleteTab(tab_);
210 HighlightCloseButton(); 208 HighlightCloseButton();
211 } 209 }
212 210
213 // When the animation completes, we send the Container a message to simulate 211 // When the animation completes, we send the Container a message to simulate
214 // a mouse moved event at the current mouse position. This tickles the Tab 212 // a mouse moved event at the current mouse position. This tickles the Tab
215 // the mouse is currently over to show the "hot" state of the close button. 213 // the mouse is currently over to show the "hot" state of the close button.
216 void HighlightCloseButton() { 214 void HighlightCloseButton() {
217 if (tabstrip_->available_width_for_tabs_ == -1 || 215 if (tabstrip_->available_width_for_tabs_ == -1 ||
218 tabstrip_->IsDragSessionActive()) { 216 tabstrip_->IsDragSessionActive()) {
219 // This function is not required (and indeed may crash!) for removes 217 // This function is not required (and indeed may crash!) for removes
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 /////////////////////////////////////////////////////////////////////////////// 249 ///////////////////////////////////////////////////////////////////////////////
252 // TabStrip, public: 250 // TabStrip, public:
253 251
254 // static 252 // static
255 const int TabStrip::mini_to_non_mini_gap_ = 3; 253 const int TabStrip::mini_to_non_mini_gap_ = 3;
256 254
257 // static 255 // static
258 const int TabStrip::extra_gap_for_nano_ = 10; 256 const int TabStrip::extra_gap_for_nano_ = 10;
259 257
260 TabStrip::TabStrip(TabStripController* controller) 258 TabStrip::TabStrip(TabStripController* controller)
261 : BaseTabStrip(controller), 259 : BaseTabStrip(controller, BaseTabStrip::HORIZONTAL_TAB_STRIP),
262 resize_layout_factory_(this), 260 resize_layout_factory_(this),
263 added_as_message_loop_observer_(false), 261 added_as_message_loop_observer_(false),
264 needs_resize_layout_(false), 262 needs_resize_layout_(false),
265 current_unselected_width_(Tab::GetStandardSize().width()), 263 current_unselected_width_(Tab::GetStandardSize().width()),
266 current_selected_width_(Tab::GetStandardSize().width()), 264 current_selected_width_(Tab::GetStandardSize().width()),
267 available_width_for_tabs_(-1), 265 available_width_for_tabs_(-1),
268 animation_container_(new AnimationContainer()), 266 animation_container_(new AnimationContainer()),
269 ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)), 267 ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)),
270 animation_type_(ANIMATION_DEFAULT), 268 animation_type_(ANIMATION_DEFAULT),
271 new_tab_button_enabled_(true), 269 new_tab_button_enabled_(true),
272 cancelling_animation_(false), 270 cancelling_animation_(false) {
273 attaching_dragged_tab_(false) {
274 Init(); 271 Init();
275 } 272 }
276 273
277 TabStrip::~TabStrip() { 274 TabStrip::~TabStrip() {
278 // The animations may reference the tabs. Shut down the animation before we 275 // The animations may reference the tabs. Shut down the animation before we
279 // delete the tabs. 276 // delete the tabs.
280 StopAnimating(false); 277 StopAnimating(false);
281 278
282 // TODO(beng): remove this if it doesn't work to fix the TabSelectedAt bug. 279 DestroyDragController();
283 drag_controller_.reset(NULL);
284 280
285 // Make sure we unhook ourselves as a message loop observer so that we don't 281 // Make sure we unhook ourselves as a message loop observer so that we don't
286 // crash in the case where the user closes the window after closing a tab 282 // crash in the case where the user closes the window after closing a tab
287 // but before moving the mouse. 283 // but before moving the mouse.
288 RemoveMessageLoopObserver(); 284 RemoveMessageLoopObserver();
289 285
290 // The children (tabs) may callback to us from their destructor. Delete them 286 // The children (tabs) may callback to us from their destructor. Delete them
291 // so that if they call back we aren't in a weird state. 287 // so that if they call back we aren't in a weird state.
292 RemoveAllChildViews(true); 288 RemoveAllChildViews(true);
293 } 289 }
294 290
295 void TabStrip::DestroyDragController() {
296 if (IsDragSessionActive())
297 drag_controller_.reset(NULL);
298 }
299
300 gfx::Rect TabStrip::GetIdealBounds(int tab_data_index) {
301 DCHECK_GE(tab_data_index, 0);
302 DCHECK_LT(tab_data_index, GetTabCount());
303 return tab_data_[tab_data_index].ideal_bounds;
304 }
305
306 void TabStrip::InitTabStripButtons() { 291 void TabStrip::InitTabStripButtons() {
307 newtab_button_ = new NewTabButton(this); 292 newtab_button_ = new NewTabButton(this);
308 if (browser_defaults::kSizeTabButtonToTopOfTabStrip) { 293 if (browser_defaults::kSizeTabButtonToTopOfTabStrip) {
309 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, 294 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
310 views::ImageButton::ALIGN_BOTTOM); 295 views::ImageButton::ALIGN_BOTTOM);
311 } 296 }
312 LoadNewTabButtonImage(); 297 LoadNewTabButtonImage();
313 newtab_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_NEWTAB)); 298 newtab_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_NEWTAB));
314 AddChildView(newtab_button_); 299 AddChildView(newtab_button_);
315 } 300 }
316 301
317 gfx::Rect TabStrip::GetNewTabButtonBounds() { 302 gfx::Rect TabStrip::GetNewTabButtonBounds() {
318 return newtab_button_->bounds(); 303 return newtab_button_->bounds();
319 } 304 }
320 305
321 //////////////////////////////////////////////////////////////////////////////// 306 ////////////////////////////////////////////////////////////////////////////////
322 // TabStrip, BaseTabStrip implementation: 307 // TabStrip, BaseTabStrip implementation:
323 308
324 int TabStrip::GetPreferredHeight() { 309 int TabStrip::GetPreferredHeight() {
325 return GetPreferredSize().height(); 310 return GetPreferredSize().height();
326 } 311 }
327 312
328 void TabStrip::SetBackgroundOffset(const gfx::Point& offset) { 313 void TabStrip::SetBackgroundOffset(const gfx::Point& offset) {
329 int tab_count = GetTabCount(); 314 for (int i = 0; i < tab_count(); ++i)
330 for (int i = 0; i < tab_count; ++i)
331 GetTabAtTabDataIndex(i)->SetBackgroundOffset(offset); 315 GetTabAtTabDataIndex(i)->SetBackgroundOffset(offset);
332 } 316 }
333 317
334 bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) { 318 bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) {
335 views::View* v = GetViewForPoint(point); 319 views::View* v = GetViewForPoint(point);
336 320
337 // If there is no control at this location, claim the hit was in the title 321 // If there is no control at this location, claim the hit was in the title
338 // bar to get a move action. 322 // bar to get a move action.
339 if (v == this) 323 if (v == this)
340 return true; 324 return true;
(...skipping 10 matching lines...) Expand all
351 335
352 // All other regions, including the new Tab button, should be considered part 336 // All other regions, including the new Tab button, should be considered part
353 // of the containing Window's client area so that regular events can be 337 // of the containing Window's client area so that regular events can be
354 // processed for them. 338 // processed for them.
355 return false; 339 return false;
356 } 340 }
357 341
358 void TabStrip::SetDraggedTabBounds(int tab_index, const gfx::Rect& tab_bounds) { 342 void TabStrip::SetDraggedTabBounds(int tab_index, const gfx::Rect& tab_bounds) {
359 } 343 }
360 344
361 bool TabStrip::IsDragSessionActive() const {
362 return drag_controller_.get() != NULL;
363 }
364
365 bool TabStrip::IsAnimating() const { 345 bool TabStrip::IsAnimating() const {
366 return bounds_animator_.IsAnimating() || new_tab_timer_.IsRunning(); 346 return bounds_animator_.IsAnimating() || new_tab_timer_.IsRunning();
367 } 347 }
368 348
369 TabStrip* TabStrip::AsTabStrip() { 349 TabStrip* TabStrip::AsTabStrip() {
370 return this; 350 return this;
371 } 351 }
372 352
373 void TabStrip::AddTabAt(int model_index,
374 bool foreground,
375 const TabRendererData& data) {
376 Tab* tab = CreateTab();
377 tab->SetAnimationContainer(animation_container_.get());
378 tab->SetData(data);
379
380 TabData d = { tab, gfx::Rect() };
381 tab_data_.insert(tab_data_.begin() +
382 ModelIndexToTabDataIndex(model_index), d);
383
384 AddChildView(tab);
385
386 // Don't animate the first tab, it looks weird, and don't animate anything
387 // if the containing window isn't visible yet.
388 if (GetTabCount() > 1 && GetWindow() && GetWindow()->IsVisible()) {
389 if (!IsDragSessionActive() && !attaching_dragged_tab_ &&
390 ShouldStartIntertTabAnimationAtEnd(model_index, foreground)) {
391 StartInsertTabAnimationAtEnd();
392 } else {
393 StartInsertTabAnimation(model_index);
394 }
395 } else {
396 Layout();
397 }
398 }
399
400 void TabStrip::RemoveTabAt(int model_index, bool initiated_close) { 353 void TabStrip::RemoveTabAt(int model_index, bool initiated_close) {
401 if (initiated_close) { 354 if (initiated_close) {
402 int model_count = GetModelCount(); 355 int model_count = GetModelCount();
403 if (model_index != model_count && model_count > 0) { 356 if (model_index != model_count && model_count > 0) {
404 Tab* last_tab = GetTabAtModelIndex(model_count - 1); 357 Tab* last_tab = GetTabAtModelIndex(model_count - 1);
405 // Limit the width available to the TabStrip for laying out Tabs, so that 358 // Limit the width available to the TabStrip for laying out Tabs, so that
406 // Tabs are not resized until a later time (when the mouse pointer leaves 359 // Tabs are not resized until a later time (when the mouse pointer leaves
407 // the TabStrip). 360 // the TabStrip).
408 available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab); 361 available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
409 needs_resize_layout_ = true; 362 needs_resize_layout_ = true;
410 AddMessageLoopObserver(); 363 AddMessageLoopObserver();
411 } else if (model_count) { 364 } else if (model_count) {
412 Tab* last_tab = GetTabAtModelIndex(model_count); 365 Tab* last_tab = GetTabAtModelIndex(model_count);
413 // Limit the width available to the TabStrip for laying out Tabs, so that 366 // Limit the width available to the TabStrip for laying out Tabs, so that
414 // Tabs are not resized until a later time (when the mouse pointer leaves 367 // Tabs are not resized until a later time (when the mouse pointer leaves
415 // the TabStrip). 368 // the TabStrip).
416 available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab); 369 available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
417 needs_resize_layout_ = true; 370 needs_resize_layout_ = true;
418 AddMessageLoopObserver(); 371 AddMessageLoopObserver();
419 } 372 }
420 } 373 }
421
422 StartRemoveTabAnimation(model_index); 374 StartRemoveTabAnimation(model_index);
423 } 375 }
424 376
425 void TabStrip::SelectTabAt(int old_model_index, int new_model_index) { 377 void TabStrip::SelectTabAt(int old_model_index, int new_model_index) {
426 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are 378 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are
427 // a different size to the selected ones. 379 // a different size to the selected ones.
428 bool tiny_tabs = current_unselected_width_ != current_selected_width_; 380 bool tiny_tabs = current_unselected_width_ != current_selected_width_;
429 if (!IsAnimating() && (!needs_resize_layout_ || tiny_tabs)) { 381 if (!IsAnimating() && (!needs_resize_layout_ || tiny_tabs)) {
430 Layout(); 382 Layout();
431 } else { 383 } else {
432 SchedulePaint(); 384 SchedulePaint();
433 } 385 }
434 386
435 if (old_model_index >= 0) { 387 if (old_model_index >= 0) {
436 GetTabAtTabDataIndex(ModelIndexToTabDataIndex(old_model_index))-> 388 GetTabAtTabDataIndex(ModelIndexToTabIndex(old_model_index))->
437 StopMiniTabTitleAnimation(); 389 StopMiniTabTitleAnimation();
438 } 390 }
439 } 391 }
440 392
441 void TabStrip::MoveTab(int from_model_index, int to_model_index) {
442 StartMoveTabAnimation(from_model_index, to_model_index);
443 }
444
445 void TabStrip::TabTitleChangedNotLoading(int model_index) { 393 void TabStrip::TabTitleChangedNotLoading(int model_index) {
446 Tab* tab = GetTabAtModelIndex(model_index); 394 Tab* tab = GetTabAtModelIndex(model_index);
447 if (tab->data().mini && !tab->IsSelected()) 395 if (tab->data().mini && !tab->IsSelected())
448 tab->StartMiniTabTitleAnimation(); 396 tab->StartMiniTabTitleAnimation();
449 } 397 }
450 398
451 void TabStrip::SetTabData(int model_index, const TabRendererData& data) { 399 void TabStrip::SetTabData(int model_index, const TabRendererData& data) {
452 Tab* tab = GetTabAtModelIndex(model_index); 400 Tab* tab = GetTabAtModelIndex(model_index);
453 bool mini_state_changed = tab->data().mini != data.mini; 401 bool mini_state_changed = tab->data().mini != data.mini;
454 tab->SetData(data); 402 tab->SetData(data);
455 tab->SchedulePaint(); 403 tab->SchedulePaint();
456 404
457 if (mini_state_changed) { 405 if (mini_state_changed) {
458 if (GetWindow() && GetWindow()->IsVisible()) 406 if (GetWindow() && GetWindow()->IsVisible())
459 StartMiniTabAnimation(); 407 StartMiniTabAnimation();
460 else 408 else
461 Layout(); 409 Layout();
462 } 410 }
463 } 411 }
464 412
465 void TabStrip::StartHighlight(int model_index) { 413 void TabStrip::StartHighlight(int model_index) {
466 GetTabAtModelIndex(model_index)->StartPulse(); 414 GetTabAtModelIndex(model_index)->StartPulse();
467 } 415 }
468 416
469 void TabStrip::StopAllHighlighting() { 417 void TabStrip::StopAllHighlighting() {
470 for (int i = 0; i < GetTabCount(); ++i) 418 for (int i = 0; i < tab_count(); ++i)
471 GetTabAtTabDataIndex(i)->StopPulse(); 419 GetTabAtTabDataIndex(i)->StopPulse();
472 } 420 }
473 421
474 BaseTabRenderer* TabStrip::GetBaseTabAtModelIndex(int model_index) const {
475 return GetTabAtModelIndex(model_index);
476 }
477
478 BaseTabRenderer* TabStrip::GetBaseTabAtTabIndex(int tab_index) const {
479 return GetTabAtTabDataIndex(tab_index);
480 }
481
482 int TabStrip::GetModelIndexOfBaseTab(const BaseTabRenderer* tab) const {
483 return GetModelIndexOfTab(static_cast<const Tab*>(tab));
484 }
485
486 BaseTabRenderer* TabStrip::CreateTabForDragging() { 422 BaseTabRenderer* TabStrip::CreateTabForDragging() {
487 Tab* tab = new Tab(NULL); 423 Tab* tab = new Tab(NULL);
488 // Make sure the dragged tab shares our theme provider. We need to explicitly 424 // Make sure the dragged tab shares our theme provider. We need to explicitly
489 // do this as during dragging there isn't a theme provider. 425 // do this as during dragging there isn't a theme provider.
490 tab->SetThemeProvider(GetThemeProvider()); 426 tab->SetThemeProvider(GetThemeProvider());
491 return tab; 427 return tab;
492 } 428 }
493 429
494 /////////////////////////////////////////////////////////////////////////////// 430 ///////////////////////////////////////////////////////////////////////////////
495 // TabStrip, views::View overrides: 431 // TabStrip, views::View overrides:
496 432
497 void TabStrip::PaintChildren(gfx::Canvas* canvas) { 433 void TabStrip::PaintChildren(gfx::Canvas* canvas) {
498 // Tabs are painted in reverse order, so they stack to the left. 434 // Tabs are painted in reverse order, so they stack to the left.
499 int tab_count = GetTabCount();
500
501 // Phantom tabs appear behind all other tabs and are rendered first. To make 435 // Phantom tabs appear behind all other tabs and are rendered first. To make
502 // them slightly transparent we render them to a different layer. 436 // them slightly transparent we render them to a different layer.
503 if (HasPhantomTabs()) { 437 if (HasPhantomTabs()) {
504 SkRect bounds; 438 SkRect bounds;
505 bounds.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height())); 439 bounds.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height()));
506 canvas->saveLayerAlpha(&bounds, kPhantomTabAlpha, 440 canvas->saveLayerAlpha(&bounds, kPhantomTabAlpha,
507 SkCanvas::kARGB_ClipLayer_SaveFlag); 441 SkCanvas::kARGB_ClipLayer_SaveFlag);
508 canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); 442 canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
509 for (int i = tab_count - 1; i >= 0; --i) { 443 for (int i = tab_count() - 1; i >= 0; --i) {
510 Tab* tab = GetTabAtTabDataIndex(i); 444 Tab* tab = GetTabAtTabDataIndex(i);
511 if (tab->data().phantom) 445 if (tab->data().phantom)
512 tab->ProcessPaint(canvas); 446 tab->ProcessPaint(canvas);
513 } 447 }
514 canvas->restore(); 448 canvas->restore();
515 449
516 canvas->saveLayerAlpha(&bounds, kPhantomTabIconAlpha, 450 canvas->saveLayerAlpha(&bounds, kPhantomTabIconAlpha,
517 SkCanvas::kARGB_ClipLayer_SaveFlag); 451 SkCanvas::kARGB_ClipLayer_SaveFlag);
518 canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); 452 canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
519 for (int i = tab_count - 1; i >= 0; --i) { 453 for (int i = tab_count() - 1; i >= 0; --i) {
520 Tab* tab = GetTabAtTabDataIndex(i); 454 Tab* tab = GetTabAtTabDataIndex(i);
521 if (tab->data().phantom) { 455 if (tab->data().phantom) {
522 canvas->save(); 456 canvas->save();
523 canvas->ClipRectInt(tab->MirroredX(), tab->y(), tab->width(), 457 canvas->ClipRectInt(tab->MirroredX(), tab->y(), tab->width(),
524 tab->height()); 458 tab->height());
525 canvas->TranslateInt(tab->MirroredX(), tab->y()); 459 canvas->TranslateInt(tab->MirroredX(), tab->y());
526 tab->PaintIcon(canvas); 460 tab->PaintIcon(canvas);
527 canvas->restore(); 461 canvas->restore();
528 } 462 }
529 } 463 }
530 canvas->restore(); 464 canvas->restore();
531 } 465 }
532 466
533 Tab* selected_tab = NULL; 467 Tab* selected_tab = NULL;
534 468
535 Tab* dragging_tab = NULL; 469 Tab* dragging_tab = NULL;
536 470
537 int model_count = GetModelCount(); 471 int model_count = GetModelCount();
538 472
539 for (int i = tab_count - 1; i >= 0; --i) { 473 for (int i = tab_count() - 1; i >= 0; --i) {
540 Tab* tab = GetTabAtTabDataIndex(i); 474 Tab* tab = GetTabAtTabDataIndex(i);
541 // We must ask the _Tab's_ model, not ourselves, because in some situations 475 // We must ask the _Tab's_ model, not ourselves, because in some situations
542 // the model will be different to this object, e.g. when a Tab is being 476 // the model will be different to this object, e.g. when a Tab is being
543 // removed after its TabContents has been destroyed. 477 // removed after its TabContents has been destroyed.
544 if (!tab->data().phantom) { 478 if (!tab->data().phantom) {
545 if (tab->dragging()) { 479 if (tab->dragging()) {
546 dragging_tab = tab; 480 dragging_tab = tab;
547 } else if (!tab->IsSelected()) { 481 } else if (!tab->IsSelected()) {
548 if (tab->render_unselected() && model_count > 1) { 482 if (tab->render_unselected() && model_count > 1) {
549 // See comment above kNetTabAnimationSelectedOffset as to why we do 483 // See comment above kNetTabAnimationSelectedOffset as to why we do
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 newtab_button_->ProcessPaint(canvas); 525 newtab_button_->ProcessPaint(canvas);
592 } 526 }
593 527
594 // And the dragged tab. 528 // And the dragged tab.
595 if (dragging_tab) 529 if (dragging_tab)
596 dragging_tab->ProcessPaint(canvas); 530 dragging_tab->ProcessPaint(canvas);
597 } 531 }
598 532
599 // Overridden to support automation. See automation_proxy_uitest.cc. 533 // Overridden to support automation. See automation_proxy_uitest.cc.
600 views::View* TabStrip::GetViewByID(int view_id) const { 534 views::View* TabStrip::GetViewByID(int view_id) const {
601 if (GetTabCount() > 0) { 535 if (tab_count() > 0) {
602 if (view_id == VIEW_ID_TAB_LAST) { 536 if (view_id == VIEW_ID_TAB_LAST) {
603 return GetTabAtTabDataIndex(GetTabCount() - 1); 537 return GetTabAtTabDataIndex(tab_count() - 1);
604 } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) { 538 } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) {
605 int index = view_id - VIEW_ID_TAB_0; 539 int index = view_id - VIEW_ID_TAB_0;
606 if (index >= 0 && index < GetTabCount()) { 540 if (index >= 0 && index < tab_count()) {
607 return GetTabAtTabDataIndex(index); 541 return GetTabAtTabDataIndex(index);
608 } else { 542 } else {
609 return NULL; 543 return NULL;
610 } 544 }
611 } 545 }
612 } 546 }
613 547
614 return View::GetViewByID(view_id); 548 return View::GetViewByID(view_id);
615 } 549 }
616 550
617 void TabStrip::Layout() { 551 void TabStrip::Layout() {
618 // Called from: 552 BaseTabStrip::Layout();
619 // - window resize
620 StopAnimating(false);
621
622 GenerateIdealBounds();
623
624 for (int i = 0, tab_count = GetTabCount(); i < tab_count; ++i)
625 tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds);
626 553
627 if (new_tab_button_enabled_) { 554 if (new_tab_button_enabled_) {
628 newtab_button_->SetBounds(newtab_button_bounds_); 555 newtab_button_->SetBounds(newtab_button_bounds_);
629 newtab_button_->SetVisible(true); 556 newtab_button_->SetVisible(true);
630 } else { 557 } else {
631 newtab_button_->SetVisible(false); 558 newtab_button_->SetVisible(false);
632 } 559 }
633
634 SchedulePaint();
635 } 560 }
636 561
637 gfx::Size TabStrip::GetPreferredSize() { 562 gfx::Size TabStrip::GetPreferredSize() {
638 return gfx::Size(0, Tab::GetMinimumUnselectedSize().height()); 563 return gfx::Size(0, Tab::GetMinimumUnselectedSize().height());
639 } 564 }
640 565
641 void TabStrip::OnDragEntered(const DropTargetEvent& event) { 566 void TabStrip::OnDragEntered(const DropTargetEvent& event) {
642 // Force animations to stop, otherwise it makes the index calculation tricky. 567 // Force animations to stop, otherwise it makes the index calculation tricky.
643 StopAnimating(true); 568 StopAnimating(true);
644 569
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 // Return any view that isn't a Tab or this TabStrip immediately. We don't 610 // Return any view that isn't a Tab or this TabStrip immediately. We don't
686 // want to interfere. 611 // want to interfere.
687 views::View* v = View::GetViewForPoint(point); 612 views::View* v = View::GetViewForPoint(point);
688 if (v && v != this && v->GetClassName() != Tab::kTabClassName) 613 if (v && v != this && v->GetClassName() != Tab::kTabClassName)
689 return v; 614 return v;
690 615
691 // The display order doesn't necessarily match the child list order, so we 616 // The display order doesn't necessarily match the child list order, so we
692 // walk the display list hit-testing Tabs. Since the selected tab always 617 // walk the display list hit-testing Tabs. Since the selected tab always
693 // renders on top of adjacent tabs, it needs to be hit-tested before any 618 // renders on top of adjacent tabs, it needs to be hit-tested before any
694 // left-adjacent Tab, so we look ahead for it as we walk. 619 // left-adjacent Tab, so we look ahead for it as we walk.
695 int tab_count = GetTabCount(); 620 for (int i = 0; i < tab_count(); ++i) {
696 for (int i = 0; i < tab_count; ++i) { 621 Tab* next_tab = i < (tab_count() - 1) ? GetTabAtTabDataIndex(i + 1) : NULL;
697 Tab* next_tab = i < (tab_count - 1) ? GetTabAtTabDataIndex(i + 1) : NULL;
698 if (next_tab && next_tab->IsSelected() && IsPointInTab(next_tab, point)) 622 if (next_tab && next_tab->IsSelected() && IsPointInTab(next_tab, point))
699 return next_tab; 623 return next_tab;
700 Tab* tab = GetTabAtTabDataIndex(i); 624 Tab* tab = GetTabAtTabDataIndex(i);
701 if (IsPointInTab(tab, point)) 625 if (IsPointInTab(tab, point))
702 return tab; 626 return tab;
703 } 627 }
704 628
705 // No need to do any floating view stuff, we don't use them in the TabStrip. 629 // No need to do any floating view stuff, we don't use them in the TabStrip.
706 return this; 630 return this;
707 } 631 }
708 632
709 void TabStrip::ThemeChanged() { 633 void TabStrip::ThemeChanged() {
710 LoadNewTabButtonImage(); 634 LoadNewTabButtonImage();
711 } 635 }
712 636
713 void TabStrip::OnBoundsAnimatorDone(views::BoundsAnimator* animator) { 637 void TabStrip::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
714 AnimationType last_type = animation_type_; 638 AnimationType last_type = animation_type_;
715 639
716 ResetAnimationState(false); 640 ResetAnimationState(false);
717 641
718 if (!cancelling_animation_ && last_type == ANIMATION_NEW_TAB_2) 642 if (!cancelling_animation_ && last_type == ANIMATION_NEW_TAB_2)
719 NewTabAnimation2Done(); 643 NewTabAnimation2Done();
720 } 644 }
721 645
722 Tab* TabStrip::CreateTab() { 646 Tab* TabStrip::CreateTab() {
723 return new Tab(this); 647 Tab* tab = new Tab(this);
648 tab->SetAnimationContainer(animation_container_.get());
649 return tab;
650 }
651
652 void TabStrip::StartInsertTabAnimation(int model_index, bool foreground) {
653 if (!IsDragSessionActive() && !attaching_dragged_tab() &&
654 ShouldStartIntertTabAnimationAtEnd(model_index, foreground)) {
655 StartInsertTabAnimationAtEnd();
656 } else {
657 StartInsertTabAnimationImpl(model_index);
658 }
659 }
660
661 void TabStrip::StartMoveTabAnimation() {
662 ResetAnimationState(true);
663
664 GenerateIdealBounds();
665 AnimateToIdealBounds();
666 }
667
668 void TabStrip::StartedDraggingTab(BaseTabRenderer* tab) {
669 tab->set_dragging(true);
670
671 // Stop any animations on the tab.
672 bounds_animator_.StopAnimatingView(tab);
673
674 // Move the tab to its ideal bounds.
675 GenerateIdealBounds();
676 int tab_data_index = TabIndexOfTab(tab);
677 DCHECK(tab_data_index != -1);
678 tab->SetBounds(ideal_bounds(tab_data_index));
679 SchedulePaint();
680 }
681
682 void TabStrip::StoppedDraggingTab(BaseTabRenderer* tab) {
683 int tab_data_index = TabIndexOfTab(tab);
684 if (tab_data_index == -1) {
685 // The tab was removed before the drag completed. Don't do anything.
686 return;
687 }
688
689 // Animate the view back to its correct position.
690 ResetAnimationState(true);
691 GenerateIdealBounds();
692 AnimateToIdealBounds();
693 bounds_animator_.AnimateViewTo(tab, ideal_bounds(TabIndexOfTab(tab)));
694
695 // Install a delegate to reset the dragging state when done. We have to leave
696 // dragging true for the tab otherwise it'll draw beneath the new tab button.
697 bounds_animator_.SetAnimationDelegate(tab,
698 new ResetDraggingStateDelegate(tab),
699 true);
724 } 700 }
725 701
726 void TabStrip::ViewHierarchyChanged(bool is_add, 702 void TabStrip::ViewHierarchyChanged(bool is_add,
727 views::View* parent, 703 views::View* parent,
728 views::View* child) { 704 views::View* child) {
729 if (is_add && child == this) 705 if (is_add && child == this)
730 InitTabStripButtons(); 706 InitTabStripButtons();
731 } 707 }
732 708
733 bool TabStrip::OnMouseDragged(const views::MouseEvent& event) {
734 if (drag_controller_.get())
735 drag_controller_->Drag();
736 return true;
737 }
738
739 void TabStrip::OnMouseReleased(const views::MouseEvent& event,
740 bool canceled) {
741 EndDrag(canceled);
742 }
743
744 /////////////////////////////////////////////////////////////////////////////// 709 ///////////////////////////////////////////////////////////////////////////////
745 // TabStrip, Tab::Delegate implementation: 710 // TabStrip, Tab::Delegate implementation:
746 711
747 bool TabStrip::IsTabSelected(const BaseTabRenderer* btr) const { 712 bool TabStrip::IsTabSelected(const BaseTabRenderer* btr) const {
748 const Tab* tab = static_cast<const Tab*>(btr); 713 const Tab* tab = static_cast<const Tab*>(btr);
749 if (tab->closing() || tab->render_unselected()) 714 if (tab->closing() || tab->render_unselected())
750 return false; 715 return false;
751 716
752 return BaseTabStrip::IsTabSelected(btr); 717 return BaseTabStrip::IsTabSelected(btr);
753 } 718 }
754 719
755 bool TabStrip::IsTabPinned(const BaseTabRenderer* btr) const {
756 const Tab* tab = static_cast<const Tab*>(btr);
757 if (tab->closing())
758 return false;
759
760 return BaseTabStrip::IsTabPinned(tab);
761 }
762
763 void TabStrip::MaybeStartDrag(BaseTabRenderer* btr,
764 const views::MouseEvent& event) {
765 Tab* tab = static_cast<Tab*>(btr);
766 // Don't accidentally start any drag operations during animations if the
767 // mouse is down... during an animation tabs are being resized automatically,
768 // so the View system can misinterpret this easily if the mouse is down that
769 // the user is dragging.
770 if (IsAnimating() || tab->closing() || !HasAvailableDragActions())
771 return;
772 int model_index = GetModelIndexOfTab(tab);
773 if (!IsValidModelIndex(model_index)) {
774 CHECK(false);
775 return;
776 }
777 drag_controller_.reset(new DraggedTabController(tab, this));
778 drag_controller_->CaptureDragInfo(tab, event.location());
779 }
780
781 void TabStrip::ContinueDrag(const views::MouseEvent& event) {
782 // We can get called even if |MaybeStartDrag| wasn't called in the event of
783 // a TabStrip animation when the mouse button is down. In this case we should
784 // _not_ continue the drag because it can lead to weird bugs.
785 if (drag_controller_.get()) {
786 bool started_drag = drag_controller_->started_drag();
787 drag_controller_->Drag();
788 if (drag_controller_->started_drag() && !started_drag) {
789 // The drag just started. Redirect mouse events to us to that the tab that
790 // originated the drag can be safely deleted.
791 GetRootView()->SetMouseHandler(this);
792 }
793 }
794 }
795
796 bool TabStrip::EndDrag(bool canceled) {
797 if (!drag_controller_.get())
798 return false;
799 bool started_drag = drag_controller_->started_drag();
800 drag_controller_->EndDrag(canceled);
801 return started_drag;
802 }
803
804 bool TabStrip::HasAvailableDragActions() const {
805 return controller()->HasAvailableDragActions() != 0;
806 }
807
808 /////////////////////////////////////////////////////////////////////////////// 720 ///////////////////////////////////////////////////////////////////////////////
809 // TabStrip, views::BaseButton::ButtonListener implementation: 721 // TabStrip, views::BaseButton::ButtonListener implementation:
810 722
811 void TabStrip::ButtonPressed(views::Button* sender, const views::Event& event) { 723 void TabStrip::ButtonPressed(views::Button* sender, const views::Event& event) {
812 if (sender == newtab_button_) 724 if (sender == newtab_button_)
813 controller()->CreateNewTab(); 725 controller()->CreateNewTab();
814 } 726 }
815 727
816 /////////////////////////////////////////////////////////////////////////////// 728 ///////////////////////////////////////////////////////////////////////////////
817 // TabStrip, MessageLoop::Observer implementation: 729 // TabStrip, MessageLoop::Observer implementation:
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_P)); 821 tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_P));
910 newtab_button_->SetImage(views::CustomButton::BS_HOT, 822 newtab_button_->SetImage(views::CustomButton::BS_HOT,
911 tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_H)); 823 tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_H));
912 newtab_button_->SetBackground(color, background, 824 newtab_button_->SetBackground(color, background,
913 tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_MASK)); 825 tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_MASK));
914 if (in_test) 826 if (in_test)
915 delete tp; 827 delete tp;
916 } 828 }
917 829
918 Tab* TabStrip::GetTabAtTabDataIndex(int tab_data_index) const { 830 Tab* TabStrip::GetTabAtTabDataIndex(int tab_data_index) const {
919 DCHECK_GE(tab_data_index, 0); 831 return static_cast<Tab*>(base_tab_at_tab_index(tab_data_index));
920 DCHECK_LT(tab_data_index, GetTabCount());
921 return tab_data_[tab_data_index].tab;
922 } 832 }
923 833
924 Tab* TabStrip::GetTabAtModelIndex(int model_index) const { 834 Tab* TabStrip::GetTabAtModelIndex(int model_index) const {
925 return GetTabAtTabDataIndex(ModelIndexToTabDataIndex(model_index)); 835 return GetTabAtTabDataIndex(ModelIndexToTabIndex(model_index));
926 }
927
928 int TabStrip::GetTabCount() const {
929 return static_cast<int>(tab_data_.size());
930 } 836 }
931 837
932 void TabStrip::GetCurrentTabWidths(double* unselected_width, 838 void TabStrip::GetCurrentTabWidths(double* unselected_width,
933 double* selected_width) const { 839 double* selected_width) const {
934 *unselected_width = current_unselected_width_; 840 *unselected_width = current_unselected_width_;
935 *selected_width = current_selected_width_; 841 *selected_width = current_selected_width_;
936 } 842 }
937 843
938 void TabStrip::GetDesiredTabWidths(int tab_count, 844 void TabStrip::GetDesiredTabWidths(int tab_count,
939 int mini_tab_count, 845 int mini_tab_count,
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 *selected_width = std::max(available_width - total_offset - 923 *selected_width = std::max(available_width - total_offset -
1018 (min_unselected_width * (tab_count - 1)), min_selected_width); 924 (min_unselected_width * (tab_count - 1)), min_selected_width);
1019 } 925 }
1020 } 926 }
1021 } 927 }
1022 928
1023 void TabStrip::ResizeLayoutTabs() { 929 void TabStrip::ResizeLayoutTabs() {
1024 // We've been called back after the TabStrip has been emptied out (probably 930 // We've been called back after the TabStrip has been emptied out (probably
1025 // just prior to the window being destroyed). We need to do nothing here or 931 // just prior to the window being destroyed). We need to do nothing here or
1026 // else GetTabAt below will crash. 932 // else GetTabAt below will crash.
1027 if (GetTabCount() == 0) 933 if (tab_count() == 0)
1028 return; 934 return;
1029 935
1030 resize_layout_factory_.RevokeAll(); 936 resize_layout_factory_.RevokeAll();
1031 937
1032 // It is critically important that this is unhooked here, otherwise we will 938 // It is critically important that this is unhooked here, otherwise we will
1033 // keep spying on messages forever. 939 // keep spying on messages forever.
1034 RemoveMessageLoopObserver(); 940 RemoveMessageLoopObserver();
1035 941
1036 available_width_for_tabs_ = -1; 942 available_width_for_tabs_ = -1;
1037 int mini_tab_count = GetMiniTabCount(); 943 int mini_tab_count = GetMiniTabCount();
1038 if (mini_tab_count == GetTabCount()) { 944 if (mini_tab_count == tab_count()) {
1039 // Only mini-tabs, we know the tab widths won't have changed (all 945 // Only mini-tabs, we know the tab widths won't have changed (all
1040 // mini-tabs have the same width), so there is nothing to do. 946 // mini-tabs have the same width), so there is nothing to do.
1041 return; 947 return;
1042 } 948 }
1043 Tab* first_tab = GetTabAtTabDataIndex(mini_tab_count); 949 Tab* first_tab = GetTabAtTabDataIndex(mini_tab_count);
1044 double unselected, selected; 950 double unselected, selected;
1045 GetDesiredTabWidths(GetTabCount(), mini_tab_count, GetNanoTabCount(), 951 GetDesiredTabWidths(tab_count(), mini_tab_count, GetNanoTabCount(),
1046 &unselected, &selected); 952 &unselected, &selected);
1047 int w = Round(first_tab->IsSelected() ? selected : selected); 953 int w = Round(first_tab->IsSelected() ? selected : selected);
1048 954
1049 // We only want to run the animation if we're not already at the desired 955 // We only want to run the animation if we're not already at the desired
1050 // size. 956 // size.
1051 if (abs(first_tab->width() - w) > 1) 957 if (abs(first_tab->width() - w) > 1)
1052 StartResizeLayoutAnimation(); 958 StartResizeLayoutAnimation();
1053 } 959 }
1054 960
1055 bool TabStrip::IsCursorInTabStripZone() const { 961 bool TabStrip::IsCursorInTabStripZone() const {
(...skipping 30 matching lines...) Expand all
1086 MessageLoopForUI::current()->RemoveObserver(this); 992 MessageLoopForUI::current()->RemoveObserver(this);
1087 added_as_message_loop_observer_ = false; 993 added_as_message_loop_observer_ = false;
1088 } 994 }
1089 } 995 }
1090 996
1091 gfx::Rect TabStrip::GetDropBounds(int drop_index, 997 gfx::Rect TabStrip::GetDropBounds(int drop_index,
1092 bool drop_before, 998 bool drop_before,
1093 bool* is_beneath) { 999 bool* is_beneath) {
1094 DCHECK(drop_index != -1); 1000 DCHECK(drop_index != -1);
1095 int center_x; 1001 int center_x;
1096 if (drop_index < GetTabCount()) { 1002 if (drop_index < tab_count()) {
1097 Tab* tab = GetTabAtTabDataIndex(drop_index); 1003 Tab* tab = GetTabAtTabDataIndex(drop_index);
1098 if (drop_before) 1004 if (drop_before)
1099 center_x = tab->x() - (kTabHOffset / 2); 1005 center_x = tab->x() - (kTabHOffset / 2);
1100 else 1006 else
1101 center_x = tab->x() + (tab->width() / 2); 1007 center_x = tab->x() + (tab->width() / 2);
1102 } else { 1008 } else {
1103 Tab* last_tab = GetTabAtTabDataIndex(drop_index - 1); 1009 Tab* last_tab = GetTabAtTabDataIndex(drop_index - 1);
1104 center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2); 1010 center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2);
1105 } 1011 }
1106 1012
(...skipping 21 matching lines...) Expand all
1128 1034
1129 return drop_bounds; 1035 return drop_bounds;
1130 } 1036 }
1131 1037
1132 void TabStrip::UpdateDropIndex(const DropTargetEvent& event) { 1038 void TabStrip::UpdateDropIndex(const DropTargetEvent& event) {
1133 // If the UI layout is right-to-left, we need to mirror the mouse 1039 // If the UI layout is right-to-left, we need to mirror the mouse
1134 // coordinates since we calculate the drop index based on the 1040 // coordinates since we calculate the drop index based on the
1135 // original (and therefore non-mirrored) positions of the tabs. 1041 // original (and therefore non-mirrored) positions of the tabs.
1136 const int x = MirroredXCoordinateInsideView(event.x()); 1042 const int x = MirroredXCoordinateInsideView(event.x());
1137 // We don't allow replacing the urls of mini-tabs. 1043 // We don't allow replacing the urls of mini-tabs.
1138 for (int i = GetMiniTabCount(); i < GetTabCount(); ++i) { 1044 for (int i = GetMiniTabCount(); i < tab_count(); ++i) {
1139 Tab* tab = GetTabAtTabDataIndex(i); 1045 Tab* tab = GetTabAtTabDataIndex(i);
1140 const int tab_max_x = tab->x() + tab->width(); 1046 const int tab_max_x = tab->x() + tab->width();
1141 const int hot_width = tab->width() / 3; 1047 const int hot_width = tab->width() / 3;
1142 if (x < tab_max_x) { 1048 if (x < tab_max_x) {
1143 if (x < tab->x() + hot_width) 1049 if (x < tab->x() + hot_width)
1144 SetDropIndex(i, true); 1050 SetDropIndex(i, true);
1145 else if (x >= tab_max_x - hot_width) 1051 else if (x >= tab_max_x - hot_width)
1146 SetDropIndex(i + 1, true); 1052 SetDropIndex(i + 1, true);
1147 else 1053 else
1148 SetDropIndex(i, false); 1054 SetDropIndex(i, false);
1149 return; 1055 return;
1150 } 1056 }
1151 } 1057 }
1152 1058
1153 // The drop isn't over a tab, add it to the end. 1059 // The drop isn't over a tab, add it to the end.
1154 SetDropIndex(GetTabCount(), true); 1060 SetDropIndex(tab_count(), true);
1155 } 1061 }
1156 1062
1157 void TabStrip::SetDropIndex(int tab_data_index, bool drop_before) { 1063 void TabStrip::SetDropIndex(int tab_data_index, bool drop_before) {
1158 if (tab_data_index == -1) { 1064 if (tab_data_index == -1) {
1159 if (drop_info_.get()) 1065 if (drop_info_.get())
1160 drop_info_.reset(NULL); 1066 drop_info_.reset(NULL);
1161 return; 1067 return;
1162 } 1068 }
1163 1069
1164 if (drop_info_.get() && drop_info_->drop_index == tab_data_index && 1070 if (drop_info_.get() && drop_info_->drop_index == tab_data_index &&
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 arrow_window->Close(); 1148 arrow_window->Close();
1243 } 1149 }
1244 1150
1245 /////////////////////////////////////////////////////////////////////////////// 1151 ///////////////////////////////////////////////////////////////////////////////
1246 1152
1247 // Called from: 1153 // Called from:
1248 // - BasicLayout 1154 // - BasicLayout
1249 // - Tab insertion/removal 1155 // - Tab insertion/removal
1250 // - Tab reorder 1156 // - Tab reorder
1251 void TabStrip::GenerateIdealBounds() { 1157 void TabStrip::GenerateIdealBounds() {
1252 int tab_count = GetTabCount();
1253 int non_closing_tab_count = 0; 1158 int non_closing_tab_count = 0;
1254 int mini_tab_count = 0; 1159 int mini_tab_count = 0;
1255 int nano_tab_count = 0; 1160 int nano_tab_count = 0;
1256 for (int i = 0; i < tab_count; ++i) { 1161 for (int i = 0; i < tab_count(); ++i) {
1257 if (!tab_data_[i].tab->closing()) { 1162 BaseTabRenderer* tab = base_tab_at_tab_index(i);
1163 if (!tab->closing()) {
1258 ++non_closing_tab_count; 1164 ++non_closing_tab_count;
1259 if (tab_data_[i].tab->data().mini) 1165 if (tab->data().mini)
1260 mini_tab_count++; 1166 mini_tab_count++;
1261 if (tab_data_[i].tab->data().app) 1167 if (tab->data().app)
1262 nano_tab_count++; 1168 nano_tab_count++;
1263 } 1169 }
1264 } 1170 }
1265 1171
1266 double unselected, selected; 1172 double unselected, selected;
1267 GetDesiredTabWidths(non_closing_tab_count, mini_tab_count, nano_tab_count, 1173 GetDesiredTabWidths(non_closing_tab_count, mini_tab_count, nano_tab_count,
1268 &unselected, &selected); 1174 &unselected, &selected);
1269 1175
1270 current_unselected_width_ = unselected; 1176 current_unselected_width_ = unselected;
1271 current_selected_width_ = selected; 1177 current_selected_width_ = selected;
1272 1178
1273 // NOTE: This currently assumes a tab's height doesn't differ based on 1179 // NOTE: This currently assumes a tab's height doesn't differ based on
1274 // selected state or the number of tabs in the strip! 1180 // selected state or the number of tabs in the strip!
1275 int tab_height = Tab::GetStandardSize().height(); 1181 int tab_height = Tab::GetStandardSize().height();
1276 double tab_x = 0; 1182 double tab_x = 0;
1277 bool last_was_mini = false; 1183 bool last_was_mini = false;
1278 for (int i = 0; i < tab_count; ++i) { 1184 for (int i = 0; i < tab_count(); ++i) {
1279 if (!tab_data_[i].tab->closing()) {
1280 Tab* tab = GetTabAtTabDataIndex(i); 1185 Tab* tab = GetTabAtTabDataIndex(i);
1186 if (!tab->closing()) {
1281 double tab_width = unselected; 1187 double tab_width = unselected;
1282 if (tab->data().mini) { 1188 if (tab->data().mini) {
1283 tab_width = Tab::GetMiniWidth(); 1189 tab_width = Tab::GetMiniWidth();
1284 } else { 1190 } else {
1285 if (last_was_mini) { 1191 if (last_was_mini) {
1286 // Give a bigger gap between mini and non-mini tabs. 1192 // Give a bigger gap between mini and non-mini tabs.
1287 tab_x += mini_to_non_mini_gap_; 1193 tab_x += mini_to_non_mini_gap_;
1288 if (nano_tab_count > 0) 1194 if (nano_tab_count > 0)
1289 tab_x += extra_gap_for_nano_; 1195 tab_x += extra_gap_for_nano_;
1290 } 1196 }
1291 if (tab->IsSelected()) 1197 if (tab->IsSelected())
1292 tab_width = selected; 1198 tab_width = selected;
1293 } 1199 }
1294 double end_of_tab = tab_x + tab_width; 1200 double end_of_tab = tab_x + tab_width;
1295 int rounded_tab_x = Round(tab_x); 1201 int rounded_tab_x = Round(tab_x);
1296 tab_data_[i].ideal_bounds = 1202 set_ideal_bounds(i,
1297 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, 1203 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
1298 tab_height); 1204 tab_height));
1299 tab_x = end_of_tab + kTabHOffset; 1205 tab_x = end_of_tab + kTabHOffset;
1300 last_was_mini = tab->data().mini; 1206 last_was_mini = tab->data().mini;
1301 } 1207 }
1302 } 1208 }
1303 1209
1304 // Update bounds of new tab button. 1210 // Update bounds of new tab button.
1305 int new_tab_x; 1211 int new_tab_x;
1306 int new_tab_y = browser_defaults::kSizeTabButtonToTopOfTabStrip ? 1212 int new_tab_y = browser_defaults::kSizeTabButtonToTopOfTabStrip ?
1307 0 : kNewTabButtonVOffset; 1213 0 : kNewTabButtonVOffset;
1308 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && 1214 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 &&
1309 available_width_for_tabs_ == -1) { 1215 available_width_for_tabs_ == -1) {
1310 // We're shrinking tabs, so we need to anchor the New Tab button to the 1216 // We're shrinking tabs, so we need to anchor the New Tab button to the
1311 // right edge of the TabStrip's bounds, rather than the right edge of the 1217 // right edge of the TabStrip's bounds, rather than the right edge of the
1312 // right-most Tab, otherwise it'll bounce when animating. 1218 // right-most Tab, otherwise it'll bounce when animating.
1313 new_tab_x = width() - newtab_button_bounds_.width(); 1219 new_tab_x = width() - newtab_button_bounds_.width();
1314 } else { 1220 } else {
1315 new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; 1221 new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset;
1316 } 1222 }
1317 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); 1223 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y));
1318 } 1224 }
1319 1225
1320 void TabStrip::NewTabAnimation1Done() { 1226 void TabStrip::NewTabAnimation1Done() {
1321 int tab_data_index = static_cast<int>(tab_data_.size() - 1); 1227 int tab_data_index = tab_count() - 1;
1322 Tab* tab = GetTabAtTabDataIndex(tab_data_index); 1228 Tab* tab = GetTabAtTabDataIndex(tab_data_index);
1323 1229
1324 gfx::Rect old_tab_bounds = tab->bounds(); 1230 gfx::Rect old_tab_bounds = tab->bounds();
1325 1231
1326 GenerateIdealBounds(); 1232 GenerateIdealBounds();
1327 1233
1328 gfx::Rect& end_bounds = tab_data_[tab_data_index].ideal_bounds; 1234 gfx::Rect end_bounds = ideal_bounds(tab_data_index);
1329 end_bounds.Offset(kNewTabOvershoot, 0); 1235 end_bounds.Offset(kNewTabOvershoot, 0);
1236 set_ideal_bounds(tab_data_index, end_bounds);
1330 1237
1331 int x = old_tab_bounds.right() - end_bounds.width(); 1238 int x = old_tab_bounds.right() - end_bounds.width();
1332 int w = end_bounds.width(); 1239 int w = end_bounds.width();
1333 if (x < 0) { 1240 if (x < 0) {
1334 w += x; 1241 w += x;
1335 x = 0; 1242 x = 0;
1336 } 1243 }
1337 tab->SetBounds(x, old_tab_bounds.y(), w, end_bounds.height()); 1244 tab->SetBounds(x, old_tab_bounds.y(), w, end_bounds.height());
1338 1245
1339 AnimateToIdealBounds(); 1246 AnimateToIdealBounds();
(...skipping 13 matching lines...) Expand all
1353 1260
1354 GenerateIdealBounds(); 1261 GenerateIdealBounds();
1355 1262
1356 AnimateToIdealBounds(); 1263 AnimateToIdealBounds();
1357 1264
1358 SlideAnimation* animation = new SlideAnimation(NULL); 1265 SlideAnimation* animation = new SlideAnimation(NULL);
1359 animation->SetSlideDuration(kNewTab3DurationMs); 1266 animation->SetSlideDuration(kNewTab3DurationMs);
1360 animation->SetTweenType(Tween::EASE_IN_OUT); 1267 animation->SetTweenType(Tween::EASE_IN_OUT);
1361 1268
1362 // BoundsAnimator takes ownership of animation. 1269 // BoundsAnimator takes ownership of animation.
1363 bounds_animator_.SetAnimationForView(tab_data_.back().tab, animation); 1270 bounds_animator_.SetAnimationForView(
1271 GetTabAtTabDataIndex(tab_count() - 1), animation);
1364 } 1272 }
1365 1273
1366 void TabStrip::AnimateToIdealBounds() { 1274 void TabStrip::AnimateToIdealBounds() {
1367 for (size_t i = 0; i < tab_data_.size(); ++i) { 1275 for (int i = 0; i < tab_count(); ++i) {
1368 if (!tab_data_[i].tab->closing() && !tab_data_[i].tab->dragging()) { 1276 Tab* tab = GetTabAtTabDataIndex(i);
1369 bounds_animator_.AnimateViewTo(tab_data_[i].tab, 1277 if (!tab->closing() && !tab->dragging())
1370 tab_data_[i].ideal_bounds); 1278 bounds_animator_.AnimateViewTo(tab, ideal_bounds(i));
1371 }
1372 } 1279 }
1373 1280
1374 if (animation_type_ != ANIMATION_NEW_TAB_3) { 1281 if (animation_type_ != ANIMATION_NEW_TAB_3) {
1375 bounds_animator_.AnimateViewTo(newtab_button_, newtab_button_bounds_); 1282 bounds_animator_.AnimateViewTo(newtab_button_, newtab_button_bounds_);
1376 } 1283 }
1377 } 1284 }
1378 1285
1379 bool TabStrip::ShouldStartIntertTabAnimationAtEnd(int model_index, 1286 bool TabStrip::ShouldStartIntertTabAnimationAtEnd(int model_index,
1380 bool foreground) { 1287 bool foreground) {
1381 return foreground && (model_index + 1 == GetModelCount()) && 1288 return foreground && (model_index + 1 == GetModelCount()) &&
1382 controller()->IsNewTabPage(model_index); 1289 controller()->IsNewTabPage(model_index);
1383 } 1290 }
1384 1291
1385 void TabStrip::StartResizeLayoutAnimation() { 1292 void TabStrip::StartResizeLayoutAnimation() {
1386 ResetAnimationState(true); 1293 ResetAnimationState(true);
1387 GenerateIdealBounds(); 1294 GenerateIdealBounds();
1388 AnimateToIdealBounds(); 1295 AnimateToIdealBounds();
1389 } 1296 }
1390 1297
1391 void TabStrip::StartInsertTabAnimationAtEnd() { 1298 void TabStrip::StartInsertTabAnimationAtEnd() {
1392 ResetAnimationState(true); 1299 ResetAnimationState(true);
1393 1300
1394 // The TabStrip can now use its entire width to lay out Tabs. 1301 // The TabStrip can now use its entire width to lay out Tabs.
1395 available_width_for_tabs_ = -1; 1302 available_width_for_tabs_ = -1;
1396 1303
1397 animation_type_ = ANIMATION_NEW_TAB_1; 1304 animation_type_ = ANIMATION_NEW_TAB_1;
1398 1305
1399 GenerateIdealBounds(); 1306 GenerateIdealBounds();
1400 1307
1401 int tab_data_index = ModelIndexToTabDataIndex(GetModelCount() - 1); 1308 int tab_data_index = ModelIndexToTabIndex(GetModelCount() - 1);
1402 Tab* tab = tab_data_[tab_data_index].tab; 1309 Tab* tab = GetTabAtTabDataIndex(tab_data_index);
1403 tab->SizeToNewTabButtonImages(); 1310 tab->SizeToNewTabButtonImages();
1404 tab->SetBounds(newtab_button_->x() + 1311 tab->SetBounds(newtab_button_->x() +
1405 (newtab_button_->width() - tab->width()) / 2, 1312 (newtab_button_->width() - tab->width()) / 2,
1406 tab_data_[tab_data_index].ideal_bounds.y(), 1313 ideal_bounds(tab_data_index).y(),
1407 tab->width(), tab->height()); 1314 tab->width(), tab->height());
1408 tab->set_render_as_new_tab(true); 1315 tab->set_render_as_new_tab(true);
1409 1316
1410 new_tab_timer_.Start(base::TimeDelta::FromMilliseconds(kNewTabDurationMs), 1317 new_tab_timer_.Start(base::TimeDelta::FromMilliseconds(kNewTabDurationMs),
1411 this, &TabStrip::NewTabAnimation1Done); 1318 this, &TabStrip::NewTabAnimation1Done);
1412 } 1319 }
1413 1320
1414 void TabStrip::StartInsertTabAnimation(int model_index) { 1321 void TabStrip::StartInsertTabAnimationImpl(int model_index) {
1415 ResetAnimationState(true); 1322 ResetAnimationState(true);
1416 1323
1417 // The TabStrip can now use its entire width to lay out Tabs. 1324 // The TabStrip can now use its entire width to lay out Tabs.
1418 available_width_for_tabs_ = -1; 1325 available_width_for_tabs_ = -1;
1419 1326
1420 GenerateIdealBounds(); 1327 GenerateIdealBounds();
1421 1328
1422 int tab_data_index = ModelIndexToTabDataIndex(model_index); 1329 int tab_data_index = ModelIndexToTabIndex(model_index);
1423 Tab* tab = tab_data_[tab_data_index].tab; 1330 BaseTabRenderer* tab = base_tab_at_tab_index(tab_data_index);
1424 if (model_index == 0) { 1331 if (model_index == 0) {
1425 tab->SetBounds(0, tab_data_[tab_data_index].ideal_bounds.y(), 0, 1332 tab->SetBounds(0, ideal_bounds(tab_data_index).y(), 0,
1426 tab_data_[tab_data_index].ideal_bounds.height()); 1333 ideal_bounds(tab_data_index).height());
1427 } else { 1334 } else {
1428 Tab* last_tab = tab_data_[tab_data_index - 1].tab; 1335 BaseTabRenderer* last_tab = base_tab_at_tab_index(tab_data_index - 1);
1429 tab->SetBounds(last_tab->bounds().right() + kTabHOffset, 1336 tab->SetBounds(last_tab->bounds().right() + kTabHOffset,
1430 tab_data_[tab_data_index].ideal_bounds.y(), 0, 1337 ideal_bounds(tab_data_index).y(), 0,
1431 tab_data_[tab_data_index].ideal_bounds.height()); 1338 ideal_bounds(tab_data_index).height());
1432 } 1339 }
1433 1340
1434 AnimateToIdealBounds(); 1341 AnimateToIdealBounds();
1435 } 1342 }
1436 1343
1437 void TabStrip::StartRemoveTabAnimation(int model_index) { 1344 void TabStrip::StartRemoveTabAnimation(int model_index) {
1438 ResetAnimationState(true); 1345 ResetAnimationState(true);
1439 1346
1440 // Mark the tab as closing. 1347 // Mark the tab as closing.
1441 int tab_data_index = ModelIndexToTabDataIndex(model_index); 1348 Tab* tab = GetTabAtModelIndex(model_index);
1442 Tab* tab = tab_data_[tab_data_index].tab;
1443 tab->set_closing(true); 1349 tab->set_closing(true);
1444 1350
1445 // Start an animation for the tabs. 1351 // Start an animation for the tabs.
1446 GenerateIdealBounds(); 1352 GenerateIdealBounds();
1447 AnimateToIdealBounds(); 1353 AnimateToIdealBounds();
1448 1354
1449 // Animate the tab being closed to 0x0. 1355 // Animate the tab being closed to 0x0.
1450 gfx::Rect tab_bounds = tab->bounds(); 1356 gfx::Rect tab_bounds = tab->bounds();
1451 tab_bounds.set_width(0); 1357 tab_bounds.set_width(0);
1452 bounds_animator_.AnimateViewTo(tab, tab_bounds); 1358 bounds_animator_.AnimateViewTo(tab, tab_bounds);
1453 1359
1454 // Register delegate to do cleanup when done, BoundsAnimator takes 1360 // Register delegate to do cleanup when done, BoundsAnimator takes
1455 // ownership of RemoveTabDelegate. 1361 // ownership of RemoveTabDelegate.
1456 bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab), 1362 bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab),
1457 true); 1363 true);
1458 } 1364 }
1459 1365
1460 void TabStrip::StartMoveTabAnimation(int from_model_index,
1461 int to_model_index) {
1462 ResetAnimationState(true);
1463
1464 int from_tab_data_index = ModelIndexToTabDataIndex(from_model_index);
1465
1466 Tab* tab = tab_data_[from_tab_data_index].tab;
1467 tab_data_.erase(tab_data_.begin() + from_tab_data_index);
1468
1469 TabData data = {tab, gfx::Rect()};
1470
1471 int to_tab_data_index = ModelIndexToTabDataIndex(to_model_index);
1472
1473 tab_data_.insert(tab_data_.begin() + to_tab_data_index, data);
1474
1475 GenerateIdealBounds();
1476 AnimateToIdealBounds();
1477 }
1478
1479 void TabStrip::StartMiniTabAnimation() { 1366 void TabStrip::StartMiniTabAnimation() {
1480 ResetAnimationState(true); 1367 ResetAnimationState(true);
1481 1368
1482 GenerateIdealBounds(); 1369 GenerateIdealBounds();
1483 AnimateToIdealBounds(); 1370 AnimateToIdealBounds();
1484 } 1371 }
1485 1372
1486 void TabStrip::StopAnimating(bool layout) { 1373 void TabStrip::StopAnimating(bool layout) {
1487 if (!IsAnimating()) 1374 if (!IsAnimating())
1488 return; 1375 return;
(...skipping 19 matching lines...) Expand all
1508 void TabStrip::ResetAnimationState(bool stop_new_tab_timer) { 1395 void TabStrip::ResetAnimationState(bool stop_new_tab_timer) {
1509 if (animation_type_ == ANIMATION_NEW_TAB_2) 1396 if (animation_type_ == ANIMATION_NEW_TAB_2)
1510 newtab_button_->SchedulePaint(); 1397 newtab_button_->SchedulePaint();
1511 1398
1512 if (stop_new_tab_timer) 1399 if (stop_new_tab_timer)
1513 new_tab_timer_.Stop(); 1400 new_tab_timer_.Stop();
1514 1401
1515 animation_type_ = ANIMATION_DEFAULT; 1402 animation_type_ = ANIMATION_DEFAULT;
1516 1403
1517 // Reset the animation state of each tab. 1404 // Reset the animation state of each tab.
1518 for (int i = 0, count = GetTabCount(); i < count; ++i) { 1405 for (int i = 0; i < tab_count(); ++i) {
1519 Tab* tab = GetTabAtTabDataIndex(i); 1406 Tab* tab = GetTabAtTabDataIndex(i);
1520 tab->set_render_as_new_tab(false); 1407 tab->set_render_as_new_tab(false);
1521 tab->set_render_unselected(false); 1408 tab->set_render_unselected(false);
1522 tab->set_alpha(1); 1409 tab->set_alpha(1);
1523 } 1410 }
1524 } 1411 }
1525 1412
1526 int TabStrip::GetMiniTabCount() const { 1413 int TabStrip::GetMiniTabCount() const {
1527 int mini_count = 0; 1414 int mini_count = 0;
1528 for (size_t i = 0; i < tab_data_.size(); ++i) { 1415 for (int i = 0; i < tab_count(); ++i) {
1529 if (tab_data_[i].tab->data().mini) 1416 if (base_tab_at_tab_index(i)->data().mini)
1530 mini_count++; 1417 mini_count++;
1531 else 1418 else
1532 return mini_count; 1419 return mini_count;
1533 } 1420 }
1534 return mini_count; 1421 return mini_count;
1535 } 1422 }
1536 1423
1537 int TabStrip::GetNanoTabCount() const { 1424 int TabStrip::GetNanoTabCount() const {
1538 int nano_count = 0; 1425 int nano_count = 0;
1539 for (size_t i = 0; i < tab_data_.size(); ++i) { 1426 for (int i = 0; i < tab_count(); ++i) {
1540 if (tab_data_[i].tab->data().app) 1427 if (base_tab_at_tab_index(i)->data().app)
1541 nano_count++; 1428 nano_count++;
1542 else 1429 else
1543 return nano_count; 1430 return nano_count;
1544 } 1431 }
1545 return nano_count; 1432 return nano_count;
1546 } 1433 }
1547 1434
1548 int TabStrip::GetAvailableWidthForTabs(Tab* last_tab) const { 1435 int TabStrip::GetAvailableWidthForTabs(Tab* last_tab) const {
1549 return last_tab->x() + last_tab->width(); 1436 return last_tab->x() + last_tab->width();
1550 } 1437 }
1551 1438
1552 bool TabStrip::IsPointInTab(Tab* tab, 1439 bool TabStrip::IsPointInTab(Tab* tab,
1553 const gfx::Point& point_in_tabstrip_coords) { 1440 const gfx::Point& point_in_tabstrip_coords) {
1554 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); 1441 gfx::Point point_in_tab_coords(point_in_tabstrip_coords);
1555 View::ConvertPointToView(this, tab, &point_in_tab_coords); 1442 View::ConvertPointToView(this, tab, &point_in_tab_coords);
1556 return tab->HitTest(point_in_tab_coords); 1443 return tab->HitTest(point_in_tab_coords);
1557 } 1444 }
1558 1445
1559 void TabStrip::RemoveTab(Tab* tab) {
1560 int tab_data_index = TabDataIndexOfTab(tab);
1561
1562 DCHECK(tab_data_index != -1);
1563
1564 // Remove the Tab from the TabStrip's list...
1565 tab_data_.erase(tab_data_.begin() + tab_data_index);
1566
1567 delete tab;
1568 }
1569
1570 void TabStrip::HandleGlobalMouseMoveEvent() { 1446 void TabStrip::HandleGlobalMouseMoveEvent() {
1571 if (!IsCursorInTabStripZone()) { 1447 if (!IsCursorInTabStripZone()) {
1572 // Mouse moved outside the tab slop zone, start a timer to do a resize 1448 // Mouse moved outside the tab slop zone, start a timer to do a resize
1573 // layout after a short while... 1449 // layout after a short while...
1574 if (resize_layout_factory_.empty()) { 1450 if (resize_layout_factory_.empty()) {
1575 MessageLoop::current()->PostDelayedTask(FROM_HERE, 1451 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1576 resize_layout_factory_.NewRunnableMethod( 1452 resize_layout_factory_.NewRunnableMethod(
1577 &TabStrip::ResizeLayoutTabs), 1453 &TabStrip::ResizeLayoutTabs),
1578 kResizeTabsTimeMs); 1454 kResizeTabsTimeMs);
1579 } 1455 }
1580 } else { 1456 } else {
1581 // Mouse moved quickly out of the tab strip and then into it again, so 1457 // Mouse moved quickly out of the tab strip and then into it again, so
1582 // cancel the timer so that the strip doesn't move when the mouse moves 1458 // cancel the timer so that the strip doesn't move when the mouse moves
1583 // back over it. 1459 // back over it.
1584 resize_layout_factory_.RevokeAll(); 1460 resize_layout_factory_.RevokeAll();
1585 } 1461 }
1586 } 1462 }
1587 1463
1588 bool TabStrip::HasPhantomTabs() const { 1464 bool TabStrip::HasPhantomTabs() const {
1589 for (int i = 0; i < GetTabCount(); ++i) { 1465 for (int i = 0; i < tab_count(); ++i) {
1590 if (GetTabAtTabDataIndex(i)->data().phantom) 1466 if (GetTabAtTabDataIndex(i)->data().phantom)
1591 return true; 1467 return true;
1592 } 1468 }
1593 return false; 1469 return false;
1594 } 1470 }
1595
1596 int TabStrip::GetModelIndexOfTab(const Tab* tab) const {
1597 for (int i = 0, model_index = 0; i < GetTabCount(); ++i) {
1598 Tab* current_tab = GetTabAtTabDataIndex(i);
1599 if (!current_tab->closing()) {
1600 if (current_tab == tab)
1601 return model_index;
1602 model_index++;
1603 }
1604 }
1605 return -1;
1606 }
1607
1608 int TabStrip::ModelIndexToTabDataIndex(int model_index) const {
1609 int current_model_index = 0;
1610 for (size_t i = 0; i < tab_data_.size(); ++i) {
1611 if (!tab_data_[i].tab->closing()) {
1612 if (current_model_index == model_index)
1613 return i;
1614 current_model_index++;
1615 }
1616 }
1617 return tab_data_.size();
1618 }
1619
1620 int TabStrip::TabDataIndexOfTab(Tab* tab) const {
1621 for (size_t i = 0; i < tab_data_.size(); ++i) {
1622 if (tab_data_[i].tab == tab)
1623 return i;
1624 }
1625 return -1;
1626 }
1627
1628 void TabStrip::StartedDraggingTab(Tab* tab) {
1629 tab->set_dragging(true);
1630
1631 // Stop any animations on the tab.
1632 bounds_animator_.StopAnimatingView(tab);
1633
1634 // Move the tab to its ideal bounds.
1635 GenerateIdealBounds();
1636 int tab_data_index = TabDataIndexOfTab(tab);
1637 DCHECK(tab_data_index != -1);
1638 tab->SetBounds(tab_data_[tab_data_index].ideal_bounds);
1639 SchedulePaint();
1640 }
1641
1642 void TabStrip::StoppedDraggingTab(Tab* tab) {
1643 int tab_data_index = TabDataIndexOfTab(tab);
1644 if (tab_data_index == -1) {
1645 // The tab was removed before the drag completed. Don't do anything.
1646 return;
1647 }
1648
1649 // Animate the view back to its correct position.
1650 ResetAnimationState(true);
1651 GenerateIdealBounds();
1652 AnimateToIdealBounds();
1653 bounds_animator_.AnimateViewTo(
1654 tab,
1655 tab_data_[TabDataIndexOfTab(tab)].ideal_bounds);
1656
1657 // Install a delegate to reset the dragging state when done. We have to leave
1658 // dragging true for the tab otherwise it'll draw beneath the new tab button.
1659 bounds_animator_.SetAnimationDelegate(tab,
1660 new ResetDraggingStateDelegate(tab),
1661 true);
1662 }
OLDNEW
« no previous file with comments | « chrome/browser/views/tabs/tab_strip.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698