Home | History | Annotate | Download | only in tabs
      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.
     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.
     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.
    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|.
    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.
    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 
    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).
    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.
    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