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