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