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