1 // Copyright (c) 2012 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. 4 5 #ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_ 6 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_ 7 8 #include <vector> 9 10 #include "base/compiler_specific.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/timer/timer.h" 13 #include "chrome/browser/ui/tabs/tab_strip_layout_type.h" 14 #include "chrome/browser/ui/views/tabs/tab.h" 15 #include "chrome/browser/ui/views/tabs/tab_controller.h" 16 #include "ui/gfx/animation/animation_container.h" 17 #include "ui/gfx/point.h" 18 #include "ui/gfx/rect.h" 19 #include "ui/views/animation/bounds_animator.h" 20 #include "ui/views/controls/button/image_button.h" 21 #include "ui/views/mouse_watcher.h" 22 #include "ui/views/view.h" 23 #include "ui/views/view_model.h" 24 25 class NewTabButton; 26 class StackedTabStripLayout; 27 class Tab; 28 class TabDragController; 29 class TabStripController; 30 class TabStripObserver; 31 32 namespace ui { 33 class ListSelectionModel; 34 } 35 36 namespace views { 37 class ImageView; 38 } 39 40 /////////////////////////////////////////////////////////////////////////////// 41 // 42 // TabStrip 43 // 44 // A View that represents the TabStripModel. The TabStrip has the 45 // following responsibilities: 46 // - It implements the TabStripModelObserver interface, and acts as a 47 // container for Tabs, and is also responsible for creating them. 48 // - It takes part in Tab Drag & Drop with Tab, TabDragHelper and 49 // DraggedTab, focusing on tasks that require reshuffling other tabs 50 // in response to dragged tabs. 51 // 52 /////////////////////////////////////////////////////////////////////////////// 53 class TabStrip : public views::View, 54 public views::ButtonListener, 55 public views::MouseWatcherListener, 56 public TabController { 57 public: 58 static const char kViewClassName[]; 59 60 explicit TabStrip(TabStripController* controller); 61 virtual ~TabStrip(); 62 63 // Add and remove observers to changes within this TabStrip. 64 void AddObserver(TabStripObserver* observer); 65 void RemoveObserver(TabStripObserver* observer); 66 67 // Sets the layout type. If |adjust_layout| is true the layout type changes 68 // based on whether the user uses a mouse or touch device with the tabstrip. 69 // If |adjust_layout| is false the layout is fixed to |layout_type|. 70 void SetLayoutType(TabStripLayoutType layout_type, bool adjust_layout); 71 TabStripLayoutType layout_type() const { return layout_type_; } 72 73 // Returns the bounds of the new tab button. 74 gfx::Rect GetNewTabButtonBounds(); 75 76 // Returns true if the new tab button should be sized to the top of the tab 77 // strip. 78 bool SizeTabButtonToTopOfTabStrip(); 79 80 // Starts highlighting the tab at the specified index. 81 void StartHighlight(int model_index); 82 83 // Stops all tab higlighting. 84 void StopAllHighlighting(); 85 86 // Adds a tab at the specified index. 87 void AddTabAt(int model_index, const TabRendererData& data, bool is_active); 88 89 // Moves a tab. 90 void MoveTab(int from_model_index, 91 int to_model_index, 92 const TabRendererData& data); 93 94 // Removes a tab at the specified index. 95 void RemoveTabAt(int model_index); 96 97 // Sets the tab data at the specified model index. 98 void SetTabData(int model_index, const TabRendererData& data); 99 100 // Invoked from the controller when the close initiates from the TabController 101 // (the user clicked the tab close button or middle clicked the tab). This is 102 // invoked from Close. Because of unload handlers Close is not always 103 // immediately followed by RemoveTabAt. 104 void PrepareForCloseAt(int model_index, CloseTabSource source); 105 106 // Invoked when the selection changes from |old_selection| to 107 // |new_selection|. 108 void SetSelection(const ui::ListSelectionModel& old_selection, 109 const ui::ListSelectionModel& new_selection); 110 111 // Invoked when the title of a tab changes and the tab isn't loading. 112 void TabTitleChangedNotLoading(int model_index); 113 114 // Retrieves the ideal bounds for the Tab at the specified index. 115 const gfx::Rect& ideal_bounds(int tab_data_index) { 116 return tabs_.ideal_bounds(tab_data_index); 117 } 118 119 // Returns the Tab at |index|. 120 Tab* tab_at(int index) const; 121 122 // Returns the index of the specified tab in the model coordinate system, or 123 // -1 if tab is closing or not valid. 124 int GetModelIndexOfTab(const Tab* tab) const; 125 126 // Gets the number of Tabs in the tab strip. 127 int tab_count() const { return tabs_.view_size(); } 128 129 // Cover method for TabStripController::GetCount. 130 int GetModelCount() const; 131 132 // Cover method for TabStripController::IsValidIndex. 133 bool IsValidModelIndex(int model_index) const; 134 135 TabStripController* controller() const { return controller_.get(); } 136 137 // Creates and returns a tab that can be used for dragging. Ownership passes 138 // to the caller. 139 Tab* CreateTabForDragging(); 140 141 // Returns true if a drag session is currently active. 142 bool IsDragSessionActive() const; 143 144 // Returns true if a tab is being dragged into this tab strip. 145 bool IsActiveDropTarget() const; 146 147 // Returns true if the tab strip is editable. Returns false if the tab strip 148 // is being dragged or animated to prevent extensions from messing things up 149 // while that's happening. 150 bool IsTabStripEditable() const; 151 152 // Returns false when there is a drag operation in progress so that the frame 153 // doesn't close. 154 bool IsTabStripCloseable() const; 155 156 // Updates the loading animations displayed by tabs in the tabstrip to the 157 // next frame. 158 void UpdateLoadingAnimations(); 159 160 // Returns true if the specified point (in TabStrip coordinates) is in the 161 // window caption area of the browser window. 162 bool IsPositionInWindowCaption(const gfx::Point& point); 163 164 // Returns true if the specified rect (in TabStrip coordinates) intersects 165 // the window caption area of the browser window. 166 bool IsRectInWindowCaption(const gfx::Rect& rect); 167 168 // Set the background offset used by inactive tabs to match the frame image. 169 void SetBackgroundOffset(const gfx::Point& offset); 170 171 // Returns the new tab button. This is never NULL. 172 views::View* newtab_button(); 173 174 // Sets a painting style with miniature "tab indicator" rectangles at the top. 175 void SetImmersiveStyle(bool enable); 176 177 // Returns true if Tabs in this TabStrip are currently changing size or 178 // position. 179 bool IsAnimating() const; 180 181 // Stops any ongoing animations. If |layout| is true and an animation is 182 // ongoing this does a layout. 183 void StopAnimating(bool layout); 184 185 // Called to indicate whether the given URL is a supported file. 186 void FileSupported(const GURL& url, bool supported); 187 188 // TabController overrides: 189 virtual const ui::ListSelectionModel& GetSelectionModel() OVERRIDE; 190 virtual bool SupportsMultipleSelection() OVERRIDE; 191 virtual void SelectTab(Tab* tab) OVERRIDE; 192 virtual void ExtendSelectionTo(Tab* tab) OVERRIDE; 193 virtual void ToggleSelected(Tab* tab) OVERRIDE; 194 virtual void AddSelectionFromAnchorTo(Tab* tab) OVERRIDE; 195 virtual void CloseTab(Tab* tab, CloseTabSource source) OVERRIDE; 196 virtual void ShowContextMenuForTab(Tab* tab, 197 const gfx::Point& p, 198 ui::MenuSourceType source_type) OVERRIDE; 199 virtual bool IsActiveTab(const Tab* tab) const OVERRIDE; 200 virtual bool IsTabSelected(const Tab* tab) const OVERRIDE; 201 virtual bool IsTabPinned(const Tab* tab) const OVERRIDE; 202 virtual void MaybeStartDrag( 203 Tab* tab, 204 const ui::LocatedEvent& event, 205 const ui::ListSelectionModel& original_selection) OVERRIDE; 206 virtual void ContinueDrag(views::View* view, 207 const ui::LocatedEvent& event) OVERRIDE; 208 virtual bool EndDrag(EndDragReason reason) OVERRIDE; 209 virtual Tab* GetTabAt(Tab* tab, 210 const gfx::Point& tab_in_tab_coordinates) OVERRIDE; 211 virtual void OnMouseEventInTab(views::View* source, 212 const ui::MouseEvent& event) OVERRIDE; 213 virtual bool ShouldPaintTab(const Tab* tab, gfx::Rect* clip) OVERRIDE; 214 virtual bool IsImmersiveStyle() const OVERRIDE; 215 216 // MouseWatcherListener overrides: 217 virtual void MouseMovedOutOfHost() OVERRIDE; 218 219 // views::View overrides: 220 virtual void Layout() OVERRIDE; 221 virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE; 222 virtual const char* GetClassName() const OVERRIDE; 223 virtual gfx::Size GetPreferredSize() OVERRIDE; 224 // NOTE: the drag and drop methods are invoked from FrameView. This is done 225 // to allow for a drop region that extends outside the bounds of the TabStrip. 226 virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE; 227 virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE; 228 virtual void OnDragExited() OVERRIDE; 229 virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE; 230 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; 231 virtual views::View* GetEventHandlerForRect(const gfx::Rect& rect) OVERRIDE; 232 virtual views::View* GetTooltipHandlerForPoint( 233 const gfx::Point& point) OVERRIDE; 234 235 // Returns preferred height in immersive style. 236 static int GetImmersiveHeight(); 237 238 protected: 239 // Horizontal gap between mini and non-mini-tabs. 240 static const int kMiniToNonMiniGap; 241 242 void set_ideal_bounds(int index, const gfx::Rect& bounds) { 243 tabs_.set_ideal_bounds(index, bounds); 244 } 245 246 // Returns the number of mini-tabs. 247 int GetMiniTabCount() const; 248 249 // views::ButtonListener implementation: 250 virtual void ButtonPressed(views::Button* sender, 251 const ui::Event& event) OVERRIDE; 252 253 // View overrides. 254 virtual const views::View* GetViewByID(int id) const OVERRIDE; 255 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 256 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; 257 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 258 virtual void OnMouseCaptureLost() OVERRIDE; 259 virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE; 260 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; 261 262 // ui::EventHandler overrides. 263 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 264 265 private: 266 typedef std::map<int, std::vector<Tab*> > TabsClosingMap; 267 268 class RemoveTabDelegate; 269 270 friend class TabDragController; 271 friend class TabDragControllerTest; 272 FRIEND_TEST_ALL_PREFIXES(TabDragControllerTest, GestureEndShouldEndDragTest); 273 friend class TabStripTest; 274 FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabHitTestMaskWhenStacked); 275 FRIEND_TEST_ALL_PREFIXES(TabStripTest, ClippedTabCloseButton); 276 277 // Used during a drop session of a url. Tracks the position of the drop as 278 // well as a window used to highlight where the drop occurs. 279 struct DropInfo { 280 DropInfo(int drop_index, 281 bool drop_before, 282 bool point_down, 283 views::Widget* context); 284 ~DropInfo(); 285 286 // Index of the tab to drop on. If drop_before is true, the drop should 287 // occur between the tab at drop_index - 1 and drop_index. 288 // WARNING: if drop_before is true it is possible this will == tab_count, 289 // which indicates the drop should create a new tab at the end of the tabs. 290 int drop_index; 291 bool drop_before; 292 293 // Direction the arrow should point in. If true, the arrow is displayed 294 // above the tab and points down. If false, the arrow is displayed beneath 295 // the tab and points up. 296 bool point_down; 297 298 // Renders the drop indicator. 299 views::Widget* arrow_window; 300 views::ImageView* arrow_view; 301 302 // The URL for the drop event. 303 GURL url; 304 305 // Whether the MIME type of the file pointed to by |url| is supported. 306 bool file_supported; 307 308 private: 309 DISALLOW_COPY_AND_ASSIGN(DropInfo); 310 }; 311 312 void Init(); 313 314 // Creates and returns a new tab. The caller owners the returned tab. 315 Tab* CreateTab(); 316 317 // Invoked from |AddTabAt| after the newly created tab has been inserted. 318 void StartInsertTabAnimation(int model_index); 319 320 // Invoked from |MoveTab| after |tab_data_| has been updated to animate the 321 // move. 322 void StartMoveTabAnimation(); 323 324 // Starts the remove tab animation. 325 void StartRemoveTabAnimation(int model_index); 326 327 // Schedules the animations and bounds changes necessary for a remove tab 328 // animation. 329 void ScheduleRemoveTabAnimation(Tab* tab); 330 331 // Animates all the views to their ideal bounds. 332 // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds 333 // currently set in ideal_bounds. 334 void AnimateToIdealBounds(); 335 336 // Returns whether the highlight button should be highlighted after a remove. 337 bool ShouldHighlightCloseButtonAfterRemove(); 338 339 // Invoked from Layout if the size changes or layout is really needed. 340 void DoLayout(); 341 342 // Drags the active tab by |delta|. |initial_positions| is the x-coordinates 343 // of the tabs when the drag started. 344 void DragActiveTab(const std::vector<int>& initial_positions, int delta); 345 346 // Sets the ideal bounds x-coordinates to |positions|. 347 void SetIdealBoundsFromPositions(const std::vector<int>& positions); 348 349 // Stacks the dragged tabs. This is used if the drag operation is 350 // MOVE_VISIBILE_TABS and the tabs don't fill the tabstrip. When this happens 351 // the active tab follows the mouse and the other tabs stack around it. 352 void StackDraggedTabs(int delta); 353 354 // Returns true if dragging has resulted in temporarily stacking the tabs. 355 bool IsStackingDraggedTabs() const; 356 357 // Invoked during drag to layout the tabs being dragged in |tabs| at 358 // |location|. If |initial_drag| is true, this is the initial layout after the 359 // user moved the mouse far enough to trigger a drag. 360 void LayoutDraggedTabsAt(const std::vector<Tab*>& tabs, 361 Tab* active_tab, 362 const gfx::Point& location, 363 bool initial_drag); 364 365 // Calculates the bounds needed for each of the tabs, placing the result in 366 // |bounds|. 367 void CalculateBoundsForDraggedTabs(const std::vector<Tab*>& tabs, 368 std::vector<gfx::Rect>* bounds); 369 370 // Returns the size needed for the specified tabs. This is invoked during drag 371 // and drop to calculate offsets and positioning. 372 int GetSizeNeededForTabs(const std::vector<Tab*>& tabs); 373 374 // Adds the tab at |index| to |tabs_closing_map_| and removes the tab from 375 // |tabs_|. 376 void RemoveTabFromViewModel(int index); 377 378 // Cleans up the Tab from the TabStrip. This is called from the tab animation 379 // code and is not a general-purpose method. 380 void RemoveAndDeleteTab(Tab* tab); 381 382 // Adjusts the indices of all tabs in |tabs_closing_map_| whose index is 383 // >= |index| to have a new index of |index + delta|. 384 void UpdateTabsClosingMap(int index, int delta); 385 386 // Used by TabDragController when the user starts or stops dragging tabs. 387 void StartedDraggingTabs(const std::vector<Tab*>& tabs); 388 389 // Invoked when TabDragController detaches a set of tabs. 390 void DraggedTabsDetached(); 391 392 // Used by TabDragController when the user stops dragging tabs. |move_only| is 393 // true if the move behavior is TabDragController::MOVE_VISIBILE_TABS. 394 // |completed| is true if the drag operation completed successfully, false if 395 // it was reverted. 396 void StoppedDraggingTabs(const std::vector<Tab*>& tabs, 397 const std::vector<int>& initial_positions, 398 bool move_only, 399 bool completed); 400 401 // Invoked from StoppedDraggingTabs to cleanup |tab|. If |tab| is known 402 // |is_first_tab| is set to true. 403 void StoppedDraggingTab(Tab* tab, bool* is_first_tab); 404 405 // Takes ownership of |controller|. 406 void OwnDragController(TabDragController* controller); 407 408 // Destroys the current TabDragController. This cancel the existing drag 409 // operation. 410 void DestroyDragController(); 411 412 // Releases ownership of the current TabDragController. 413 TabDragController* ReleaseDragController(); 414 415 // Paints all the tabs in |tabs_closing_map_[index]|. 416 void PaintClosingTabs(gfx::Canvas* canvas, int index); 417 418 // Invoked when a mouse event occurs over |source|. Potentially switches the 419 // layout type. 420 void UpdateLayoutTypeFromMouseEvent(views::View* source, 421 const ui::MouseEvent& event); 422 423 // -- Tab Resize Layout ----------------------------------------------------- 424 425 // Returns the exact (unrounded) current width of each tab. 426 void GetCurrentTabWidths(double* unselected_width, 427 double* selected_width) const; 428 429 // Returns the exact (unrounded) desired width of each tab, based on the 430 // desired strip width and number of tabs. If 431 // |width_of_tabs_for_mouse_close_| is nonnegative we use that value in 432 // calculating the desired strip width; otherwise we use the current width. 433 // |mini_tab_count| gives the number of mini-tabs and |tab_count| the number 434 // of mini and non-mini-tabs. 435 void GetDesiredTabWidths(int tab_count, 436 int mini_tab_count, 437 double* unselected_width, 438 double* selected_width) const; 439 440 // Perform an animated resize-relayout of the TabStrip immediately. 441 void ResizeLayoutTabs(); 442 443 // Invokes ResizeLayoutTabs() as long as we're not in a drag session. If we 444 // are in a drag session this restarts the timer. 445 void ResizeLayoutTabsFromTouch(); 446 447 // Restarts |resize_layout_timer_|. 448 void StartResizeLayoutTabsFromTouchTimer(); 449 450 // Sets the bounds of the tabs to |tab_bounds|. 451 void SetTabBoundsForDrag(const std::vector<gfx::Rect>& tab_bounds); 452 453 // Ensure that the message loop observer used for event spying is added and 454 // removed appropriately so we can tell when to resize layout the tab strip. 455 void AddMessageLoopObserver(); 456 void RemoveMessageLoopObserver(); 457 458 // -- Link Drag & Drop ------------------------------------------------------ 459 460 // Returns the bounds to render the drop at, in screen coordinates. Sets 461 // |is_beneath| to indicate whether the arrow is beneath the tab, or above 462 // it. 463 gfx::Rect GetDropBounds(int drop_index, bool drop_before, bool* is_beneath); 464 465 // Updates the location of the drop based on the event. 466 void UpdateDropIndex(const ui::DropTargetEvent& event); 467 468 // Sets the location of the drop, repainting as necessary. 469 void SetDropIndex(int tab_data_index, bool drop_before); 470 471 // Returns the drop effect for dropping a URL on the tab strip. This does 472 // not query the data in anyway, it only looks at the source operations. 473 int GetDropEffect(const ui::DropTargetEvent& event); 474 475 // Returns the image to use for indicating a drop on a tab. If is_down is 476 // true, this returns an arrow pointing down. 477 static gfx::ImageSkia* GetDropArrowImage(bool is_down); 478 479 // -- Animations ------------------------------------------------------------ 480 481 // Invoked prior to starting a new animation. 482 void PrepareForAnimation(); 483 484 // Generates the ideal bounds for each of the tabs as well as the new tab 485 // button. 486 void GenerateIdealBounds(); 487 488 // Generates the ideal bounds for the mini tabs. Returns the index to position 489 // the first non-mini tab and sets |first_non_mini_index| to the index of the 490 // first non-mini tab. 491 int GenerateIdealBoundsForMiniTabs(int* first_non_mini_index); 492 493 // Returns the width needed for the new tab button (and padding). 494 static int new_tab_button_width(); 495 496 // Returns the vertical offset of the tab strip button. This offset applies 497 // only to restored windows. 498 static int button_v_offset(); 499 500 // Returns the width of the area that contains tabs. This does not include 501 // the width of the new tab button. 502 int tab_area_width() const; 503 504 // Starts various types of TabStrip animations. 505 void StartResizeLayoutAnimation(); 506 void StartMiniTabAnimation(); 507 void StartMouseInitiatedRemoveTabAnimation(int model_index); 508 509 // Returns true if the specified point in TabStrip coords is within the 510 // hit-test region of the specified Tab. 511 bool IsPointInTab(Tab* tab, const gfx::Point& point_in_tabstrip_coords); 512 513 // -- Touch Layout ---------------------------------------------------------- 514 515 // Returns the position normal tabs start at. 516 int GetStartXForNormalTabs() const; 517 518 // Returns the tab to use for event handling. This uses FindTabForEventFrom() 519 // to do the actual searching. 520 Tab* FindTabForEvent(const gfx::Point& point); 521 522 // Returns the tab to use for event handling starting at index |start| and 523 // iterating by |delta|. 524 Tab* FindTabForEventFrom(const gfx::Point& point, int start, int delta); 525 526 // For a given point, finds a tab that is hit by the point. If the point hits 527 // an area on which two tabs are overlapping, the tab is selected as follows: 528 // - If one of the tabs is active, select it. 529 // - Select the left one. 530 // If no tabs are hit, returns NULL. 531 views::View* FindTabHitByPoint(const gfx::Point& point); 532 533 // Returns the x-coordinates of the tabs. 534 std::vector<int> GetTabXCoordinates(); 535 536 // Creates/Destroys |touch_layout_| as necessary. 537 void SwapLayoutIfNecessary(); 538 539 // Returns true if |touch_layout_| is needed. 540 bool NeedsTouchLayout() const; 541 542 // Sets the value of |reset_to_shrink_on_exit_|. If true |mouse_watcher_| is 543 // used to track when the mouse truly exits the tabstrip and the layout type 544 // is reset. 545 void SetResetToShrinkOnExit(bool value); 546 547 // Should the layout dynamically adjust? 548 bool GetAdjustLayout() const; 549 550 // -- Member Variables ------------------------------------------------------ 551 552 // There is a one-to-one mapping between each of the tabs in the 553 // TabStripController (TabStripModel) and |tabs_|. Because we animate tab 554 // removal there exists a period of time where a tab is displayed but not in 555 // the model. When this occurs the tab is removed from |tabs_| and placed in 556 // |tabs_closing_map_|. When the animation completes the tab is removed from 557 // |tabs_closing_map_|. The painting code ensures both sets of tabs are 558 // painted, and the event handling code ensures only tabs in |tabs_| are used. 559 views::ViewModel tabs_; 560 TabsClosingMap tabs_closing_map_; 561 562 scoped_ptr<TabStripController> controller_; 563 564 // The "New Tab" button. 565 NewTabButton* newtab_button_; 566 567 // Ideal bounds of the new tab button. 568 gfx::Rect newtab_button_bounds_; 569 570 // The current widths of various types of tabs. We save these so that, as 571 // users close tabs while we're holding them at the same size, we can lay out 572 // tabs exactly and eliminate the "pixel jitter" we'd get from just leaving 573 // them all at their existing, rounded widths. 574 double current_unselected_width_; 575 double current_selected_width_; 576 577 // If this value is nonnegative, it is used in GetDesiredTabWidths() to 578 // calculate how much space in the tab strip to use for tabs. Most of the 579 // time this will be -1, but while we're handling closing a tab via the mouse, 580 // we'll set this to the edge of the last tab before closing, so that if we 581 // are closing the last tab and need to resize immediately, we'll resize only 582 // back to this width, thus once again placing the last tab under the mouse 583 // cursor. 584 int available_width_for_tabs_; 585 586 // True if PrepareForCloseAt has been invoked. When true remove animations 587 // preserve current tab bounds. 588 bool in_tab_close_; 589 590 // Valid for the lifetime of a drag over us. 591 scoped_ptr<DropInfo> drop_info_; 592 593 // To ensure all tabs pulse at the same time they share the same animation 594 // container. This is that animation container. 595 scoped_refptr<gfx::AnimationContainer> animation_container_; 596 597 // MouseWatcher is used for two things: 598 // . When a tab is closed to reset the layout. 599 // . When a mouse is used and the layout dynamically adjusts and is currently 600 // TAB_STRIP_LAYOUT_STACKED. 601 scoped_ptr<views::MouseWatcher> mouse_watcher_; 602 603 // The controller for a drag initiated from a Tab. Valid for the lifetime of 604 // the drag session. 605 scoped_ptr<TabDragController> drag_controller_; 606 607 views::BoundsAnimator bounds_animator_; 608 609 // Size we last layed out at. 610 gfx::Size last_layout_size_; 611 612 TabStripLayoutType layout_type_; 613 614 // See description above SetLayoutType(). 615 bool adjust_layout_; 616 617 // Only used while in touch mode. 618 scoped_ptr<StackedTabStripLayout> touch_layout_; 619 620 // If true the layout type is set to TAB_STRIP_LAYOUT_SHRINK when the mouse 621 // exits the tabstrip (as determined using MouseWatcher). 622 bool reset_to_shrink_on_exit_; 623 624 // Location of the mouse at the time of the last move. 625 gfx::Point last_mouse_move_location_; 626 627 // Time of the last mouse move event. 628 base::TimeTicks last_mouse_move_time_; 629 630 // Number of mouse moves. 631 int mouse_move_count_; 632 633 // Timer used when a tab is closed and we need to relayout. Only used when a 634 // tab close comes from a touch device. 635 base::OneShotTimer<TabStrip> resize_layout_timer_; 636 637 // True if tabs are painted as rectangular light-bars. 638 bool immersive_style_; 639 640 // Our observers. 641 typedef ObserverList<TabStripObserver> TabStripObservers; 642 TabStripObservers observers_; 643 644 DISALLOW_COPY_AND_ASSIGN(TabStrip); 645 }; 646 647 #endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_ 648