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