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