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_STACKED_TAB_STRIP_LAYOUT_H_
      6 #define CHROME_BROWSER_UI_VIEWS_TABS_STACKED_TAB_STRIP_LAYOUT_H_
      7 
      8 #include "base/basictypes.h"
      9 #include "ui/gfx/size.h"
     10 #include "ui/views/view_model.h"
     11 
     12 namespace views {
     13 class ViewModel;
     14 }
     15 
     16 // StackedTabStripLayout is used by TabStrip in touch
     17 // mode. StackedTabStripLayout is responsible for managing the bounds of the
     18 // tabs. StackedTabStripLayout differs from the normal layout in that it stacks
     19 // tabs. Stacked tabs are tabs placed nearly on top of each other, and if enough
     20 // consecutive stacked tabs exist they are placed on top of each other. Normally
     21 // stacked tabs are placed after mini-tabs, or at the end of the tabstrip, but
     22 // during dragging tabs may be stacked before or after the active tab.
     23 class StackedTabStripLayout {
     24  public:
     25   static const int kAddTypeMini   = 1 << 0;
     26   static const int kAddTypeActive = 1 << 1;
     27 
     28   // |size| is the size for tabs, |padding| the padding between consecutive
     29   // tabs, |stacked_padding| the padding between stacked tabs,
     30   // |max_stacked_count| the maximum number of consecutive tabs that can be
     31   // stacked before they are placed on top of each other, |view_model| is the
     32   // ViewModel the bounds of the tabs are placed in.
     33   StackedTabStripLayout(const gfx::Size& size,
     34                         int padding,
     35                         int stacked_padding,
     36                         int max_stacked_count,
     37                         views::ViewModel* view_model);
     38   ~StackedTabStripLayout();
     39 
     40   // Sets the x-coordinate the normal tabs start at as well as the mini-tab
     41   // count. This is only useful if the mini-tab count or x-coordinate change.
     42   void SetXAndMiniCount(int x, int mini_tab_count);
     43 
     44   // Sets the width available for sizing the tabs to.
     45   void SetWidth(int width);
     46 
     47   int width() const { return width_; }
     48 
     49   // Sets the index of the active tab.
     50   void SetActiveIndex(int index);
     51 
     52   // Drags the active tab.
     53   void DragActiveTab(int delta);
     54 
     55   // Makes sure the tabs fill the available width. Used after a drag operation
     56   // completes.
     57   void SizeToFit();
     58 
     59   // Adds a new tab at the specified index. |add_types| is a bitmask of
     60   // kAddType*. |start_x| is the new x-coordinate non-mini tabs start at.
     61   void AddTab(int index, int add_types, int start_x);
     62 
     63   // Removes the tab at the specified index. |start_x| is the new x-coordinate
     64   // normal tabs start at, and |old_x| the old x-coordinate of the tab. It is
     65   // expected that the ViewModel hash been updated at the time this is invoked.
     66   void RemoveTab(int index, int start_x, int old_x);
     67 
     68   // Moves the tab from |from| to |to|. |new_active_index| is the index of the
     69   // currently active tab.
     70   void MoveTab(int from,
     71                int to,
     72                int new_active_index,
     73                int start_x,
     74                int mini_tab_count);
     75 
     76   // Returns the active index as used by this class. The active index dictates
     77   // stacking and what tabs are visible. As mini-tabs are never stacked,
     78   // StackedTabStripLayout forces the active index to be in the normal tabs.
     79   int active_index() const {
     80     return active_index_ < mini_tab_count_ ? mini_tab_count_ : active_index_;
     81   }
     82 
     83   int mini_tab_count() const { return mini_tab_count_; }
     84 
     85   // Returns true if the tab at index is stacked.
     86   bool IsStacked(int index) const;
     87 
     88   // Sets the location of the active tab as close to |x| as possible.
     89   void SetActiveTabLocation(int x);
     90 
     91 #if !defined(NDEBUG)
     92   std::string BoundsString() const;
     93 #endif
     94 
     95  private:
     96   friend class StackedTabStripLayoutTest;
     97 
     98   // Sets the x-coordinate normal tabs start at, width mini-tab count and
     99   // active index at once.
    100   void Reset(int x, int width, int mini_tab_count, int active_index);
    101 
    102   // Resets to an ideal layout state.
    103   void ResetToIdealState();
    104 
    105   // Makes |index| visible. This is used when a new tab is added that isn't
    106   // active.
    107   void MakeVisible(int index);
    108 
    109   // Returns the x-coordinate for the active tab constrained by the current tab
    110   // counts.
    111   int ConstrainActiveX(int x) const;
    112 
    113   // Reset the bounds of the active tab (based on ConstrainActiveX()) and resets
    114   // the bounds of the remaining tabs by way of LayoutUsingCurrent*.
    115   void SetActiveBoundsAndLayoutFromActiveTab();
    116 
    117   // Sets the bounds of the tabs after |index| relative to the position of the
    118   // tab at |index|. Each tab is placed |tab_offset()| pixels after the previous
    119   // tab, stacking as necessary.
    120   void LayoutByTabOffsetAfter(int index);
    121 
    122   // Same as LayoutByTabOffsetAfter(), but iterates toward
    123   // |mini_tab_count_|.
    124   void LayoutByTabOffsetBefore(int index);
    125 
    126   // Similar to LayoutByTabOffsetAfter(), but uses the current x-coordinate
    127   // if possible.
    128   void LayoutUsingCurrentAfter(int index);
    129   void LayoutUsingCurrentBefore(int index);
    130 
    131   void PushTabsAfter(int index, int delta);
    132   void PushTabsBefore(int index, int delta);
    133 
    134   // Does a layout for drag. Similar to LayoutUsingCurrentXXX() but does not
    135   // contrain. Used when dragging the active tab.
    136   void LayoutForDragAfter(int index);
    137   void LayoutForDragBefore(int index);
    138 
    139   // Used when the tabs are stacked at one side. The remaining tabs are stacked
    140   // against the |active_index()|. |delta| is the amount of space to resize the
    141   // the tabs by.
    142   void ExpandTabsBefore(int index, int delta);
    143   void ExpandTabsAfter(int index, int delta);
    144 
    145   // Adjusts the stacked tabs so that if there are more than
    146   // |max_stacked_count_| tabs, the set > max_stacked_count_ have an
    147   // x-coordinate of |x_|. Similarly those at the end have the same x-coordinate
    148   // and are pushed all the way to the right.
    149   void AdjustStackedTabs();
    150   void AdjustLeadingStackedTabs();
    151   void AdjustTrailingStackedTabs();
    152 
    153   // Sets the bounds of the tab at |index|.
    154   void SetIdealBoundsAt(int index, int x);
    155 
    156   // Returns the min x-coordinate for the sepcified index. This is calculated
    157   // assuming all the tabs before |index| are stacked.
    158   int GetMinX(int index) const;
    159 
    160   // Returns the max x-coordinate for the speficifed index. This is calculated
    161   // assuming all the tabs after |index| are stacked.
    162   int GetMaxX(int index) const;
    163 
    164   // Used when dragging to get the min/max coodinate.
    165   int GetMinDragX(int index) const;
    166   int GetMaxDragX(int index) const;
    167 
    168   // Returns the min x-coordinate for the tab at |index|. This is relative
    169   // to the |active_index()| and is only useful when the active tab is pushed
    170   // against the left side.
    171   int GetMinXCompressed(int index) const;
    172 
    173   // Width needed to display |count| tabs.
    174   int width_for_count(int count) const {
    175     return (count * size_.width()) + (std::max(count - 1, 0) * padding_);
    176   }
    177 
    178   // Padding needed for |count| stacked tabs.
    179   int stacked_padding_for_count(int count) const {
    180     return std::min(count, max_stacked_count_) * stacked_padding_;
    181   }
    182 
    183   // Max stacked padding.
    184   int max_stacked_width() const {
    185     return stacked_padding_ * max_stacked_count_;
    186   }
    187 
    188   int ideal_x(int index) const { return view_model_->ideal_bounds(index).x(); }
    189 
    190   // Returns true if some of the tabs need to be stacked.
    191   bool requires_stacking() const {
    192     return tab_count() != mini_tab_count_ &&
    193         x_ + width_for_count(tab_count() - mini_tab_count_) > width_;
    194   }
    195 
    196   // Number of tabs.
    197   int tab_count() const { return view_model_->view_size(); }
    198 
    199   // Number of normal (non-mini) tabs.
    200   int normal_tab_count() const { return tab_count() - mini_tab_count_; }
    201 
    202   // Distance between one tab to the next.
    203   int tab_offset() const { return size_.width() + padding_; }
    204 
    205   // Size of tabs.
    206   const gfx::Size size_;
    207 
    208   // Padding between tabs.
    209   const int padding_;
    210 
    211   // Padding between stacked tabs.
    212   const int stacked_padding_;
    213 
    214   // Max number of stacked tabs.
    215   const int max_stacked_count_;
    216 
    217   // Where bounds are placed. This is owned by TabStrip.
    218   views::ViewModel* view_model_;
    219 
    220   // x-coordinate normal tabs start at.
    221   int x_;
    222 
    223   // Available width.
    224   int width_;
    225 
    226   // Number of mini-tabs.
    227   int mini_tab_count_;
    228 
    229   // Distance from the last mini-tab to the first non-mini-tab.
    230   int mini_tab_to_non_mini_tab_;
    231 
    232   // Index of the active tab.
    233   int active_index_;
    234 
    235   // X-coordinate of the first tab. This is either |x_| if there are no
    236   // mini-tabs, or the x-coordinate of the first mini-tab.
    237   int first_tab_x_;
    238 
    239   DISALLOW_COPY_AND_ASSIGN(StackedTabStripLayout);
    240 };
    241 
    242 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_STACKED_TAB_STRIP_LAYOUT_H_
    243