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