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