• 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 #include "ui/views/view_targeter_delegate.h"
24 
25 class NewTabButton;
26 class StackedTabStripLayout;
27 class Tab;
28 class TabDragController;
29 class TabStripController;
30 class TabStripObserver;
31 
32 namespace ui {
33 class ListSelectionModel;
34 }
35 
36 namespace views {
37 class 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 ///////////////////////////////////////////////////////////////////////////////
53 class 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.
set_adjust_layout(bool adjust_layout)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.
stacked_layout()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.
ideal_bounds(int tab_data_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|.
tab_at(int 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.
tab_count()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 
controller()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).
new_tab_button_width()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.
tab_area_width()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