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