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