1 // Copyright (c) 2011 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_BASE_TAB_STRIP_H_ 6 #define CHROME_BROWSER_UI_VIEWS_TABS_BASE_TAB_STRIP_H_ 7 #pragma once 8 9 #include <vector> 10 11 #include "base/memory/scoped_ptr.h" 12 #include "chrome/browser/ui/views/tabs/abstract_tab_strip_view.h" 13 #include "chrome/browser/ui/views/tabs/base_tab.h" 14 #include "chrome/browser/ui/views/tabs/tab_controller.h" 15 #include "views/animation/bounds_animator.h" 16 #include "views/view.h" 17 18 class BaseTab; 19 class DraggedTabController; 20 class TabStripController; 21 22 // Base class for the view tab strip implementations. 23 class BaseTabStrip : public AbstractTabStripView, 24 public TabController { 25 public: 26 enum Type { 27 HORIZONTAL_TAB_STRIP, 28 VERTICAL_TAB_STRIP 29 }; 30 31 BaseTabStrip(TabStripController* controller, Type type); 32 virtual ~BaseTabStrip(); 33 34 Type type() const { return type_; } 35 36 // Starts highlighting the tab at the specified index. 37 virtual void StartHighlight(int model_index) = 0; 38 39 // Stops all tab higlighting. 40 virtual void StopAllHighlighting() = 0; 41 42 // Retrieves the ideal bounds for the Tab at the specified index. 43 const gfx::Rect& ideal_bounds(int tab_data_index) { 44 return tab_data_[tab_data_index].ideal_bounds; 45 } 46 47 // Creates and returns a tab that can be used for dragging. Ownership passes 48 // to the caller. 49 virtual BaseTab* CreateTabForDragging() = 0; 50 51 // Adds a tab at the specified index. 52 void AddTabAt(int model_index, const TabRendererData& data); 53 54 // Invoked from the controller when the close initiates from the TabController 55 // (the user clicked the tab close button or middle clicked the tab). This is 56 // invoked from Close. Because of unload handlers Close is not always 57 // immediately followed by RemoveTabAt. 58 virtual void PrepareForCloseAt(int model_index) {} 59 60 // Removes a tab at the specified index. 61 virtual void RemoveTabAt(int model_index) = 0; 62 63 // Selects a tab at the specified index. |old_model_index| is the selected 64 // index prior to the selection change. 65 virtual void SelectTabAt(int old_model_index, int new_model_index) = 0; 66 67 // Moves a tab. 68 virtual void MoveTab(int from_model_index, int to_model_index); 69 70 // Invoked when the title of a tab changes and the tab isn't loading. 71 virtual void TabTitleChangedNotLoading(int model_index) = 0; 72 73 // Sets the tab data at the specified model index. 74 virtual void SetTabData(int model_index, const TabRendererData& data); 75 76 // Returns the tab at the specified model index. 77 virtual BaseTab* GetBaseTabAtModelIndex(int model_index) const; 78 79 // Returns the tab at the specified tab index. 80 BaseTab* base_tab_at_tab_index(int tab_index) const { 81 return tab_data_[tab_index].tab; 82 } 83 84 // Returns the index of the specified tab in the model coordiate system, or 85 // -1 if tab is closing or not valid. 86 int GetModelIndexOfBaseTab(const BaseTab* tab) const; 87 88 // Gets the number of Tabs in the tab strip. 89 // WARNING: this is the number of tabs displayed by the tabstrip, which if 90 // an animation is ongoing is not necessarily the same as the number of tabs 91 // in the model. 92 int tab_count() const { return static_cast<int>(tab_data_.size()); } 93 94 // Cover method for TabStripController::GetCount. 95 int GetModelCount() const; 96 97 // Cover method for TabStripController::IsValidIndex. 98 bool IsValidModelIndex(int model_index) const; 99 100 // Returns the index into |tab_data_| corresponding to the index from the 101 // TabStripModel, or |tab_data_.size()| if there is no tab representing 102 // |model_index|. 103 int ModelIndexToTabIndex(int model_index) const; 104 105 TabStripController* controller() const { return controller_.get(); } 106 107 // Returns true if a drag session is currently active. 108 bool IsDragSessionActive() const; 109 110 // Returns true if a tab is being dragged into this tab strip. 111 bool IsActiveDropTarget() const; 112 113 // AbstractTabStripView implementation 114 virtual bool IsTabStripEditable() const OVERRIDE; 115 virtual bool IsTabStripCloseable() const OVERRIDE; 116 virtual void UpdateLoadingAnimations() OVERRIDE; 117 118 // TabController overrides: 119 virtual void SelectTab(BaseTab* tab) OVERRIDE; 120 virtual void ExtendSelectionTo(BaseTab* tab) OVERRIDE; 121 virtual void ToggleSelected(BaseTab* tab) OVERRIDE; 122 virtual void AddSelectionFromAnchorTo(BaseTab* tab) OVERRIDE; 123 virtual void CloseTab(BaseTab* tab) OVERRIDE; 124 virtual void ShowContextMenuForTab(BaseTab* tab, 125 const gfx::Point& p) OVERRIDE; 126 virtual bool IsActiveTab(const BaseTab* tab) const OVERRIDE; 127 virtual bool IsTabSelected(const BaseTab* tab) const OVERRIDE; 128 virtual bool IsTabPinned(const BaseTab* tab) const OVERRIDE; 129 virtual bool IsTabCloseable(const BaseTab* tab) const OVERRIDE; 130 virtual void MaybeStartDrag(BaseTab* tab, 131 const views::MouseEvent& event) OVERRIDE; 132 virtual void ContinueDrag(const views::MouseEvent& event) OVERRIDE; 133 virtual bool EndDrag(bool canceled) OVERRIDE; 134 virtual BaseTab* GetTabAt(BaseTab* tab, 135 const gfx::Point& tab_in_tab_coordinates) OVERRIDE; 136 137 // View overrides: 138 virtual void Layout() OVERRIDE; 139 140 protected: 141 // The Tabs we contain, and their last generated "good" bounds. 142 struct TabData { 143 BaseTab* tab; 144 gfx::Rect ideal_bounds; 145 }; 146 147 // View overrides. 148 virtual bool OnMouseDragged(const views::MouseEvent& event) OVERRIDE; 149 virtual void OnMouseReleased(const views::MouseEvent& event) OVERRIDE; 150 virtual void OnMouseCaptureLost() OVERRIDE; 151 152 // Creates and returns a new tab. The caller owners the returned tab. 153 virtual BaseTab* CreateTab() = 0; 154 155 // Invoked from |AddTabAt| after the newly created tab has been inserted. 156 // Subclasses should either start an animation, or layout. 157 virtual void StartInsertTabAnimation(int model_index) = 0; 158 159 // Invoked from |MoveTab| after |tab_data_| has been updated to animate the 160 // move. 161 virtual void StartMoveTabAnimation(); 162 163 // Starts the remove tab animation. 164 virtual void StartRemoveTabAnimation(int model_index); 165 166 // Starts the mini-tab animation. 167 virtual void StartMiniTabAnimation(); 168 169 // Returns whether the highlight button should be highlighted after a remove. 170 virtual bool ShouldHighlightCloseButtonAfterRemove(); 171 172 // Animates all the views to their ideal bounds. 173 // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds 174 // currently set in ideal_bounds. 175 virtual void AnimateToIdealBounds() = 0; 176 177 // Cleans up the Tab from the TabStrip. This is called from the tab animation 178 // code and is not a general-purpose method. 179 void RemoveAndDeleteTab(BaseTab* tab); 180 181 // Resets the bounds of all non-closing tabs. 182 virtual void GenerateIdealBounds() = 0; 183 184 // Invoked during drag to layout the tabs being dragged in |tabs| at 185 // |location|. If |initial_drag| is true, this is the initial layout after the 186 // user moved the mouse far enough to trigger a drag. 187 virtual void LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs, 188 BaseTab* active_tab, 189 const gfx::Point& location, 190 bool initial_drag) = 0; 191 192 // Calculates the bounds needed for each of the tabs, placing the result in 193 // |bounds|. 194 virtual void CalculateBoundsForDraggedTabs( 195 const std::vector<BaseTab*>& tabs, 196 std::vector<gfx::Rect>* bounds) = 0; 197 198 void set_ideal_bounds(int index, const gfx::Rect& bounds) { 199 tab_data_[index].ideal_bounds = bounds; 200 } 201 202 // Returns the index into |tab_data_| corresponding to the specified tab, or 203 // -1 if the tab isn't in |tab_data_|. 204 int TabIndexOfTab(BaseTab* tab) const; 205 206 // Stops any ongoing animations. If |layout| is true and an animation is 207 // ongoing this does a layout. 208 virtual void StopAnimating(bool layout); 209 210 // Destroys the active drag controller. 211 void DestroyDragController(); 212 213 // Used by DraggedTabController when the user starts or stops dragging tabs. 214 void StartedDraggingTabs(const std::vector<BaseTab*>& tabs); 215 void StoppedDraggingTabs(const std::vector<BaseTab*>& tabs); 216 217 // Returns the size needed for the specified tabs. This is invoked during drag 218 // and drop to calculate offsets and positioning. 219 virtual int GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) = 0; 220 221 // See description above field for details. 222 bool attaching_dragged_tab() const { return attaching_dragged_tab_; } 223 224 views::BoundsAnimator& bounds_animator() { return bounds_animator_; } 225 226 // Invoked prior to starting a new animation. 227 virtual void PrepareForAnimation(); 228 229 // Creates an AnimationDelegate that resets state after a remove animation 230 // completes. The caller owns the returned object. 231 ui::AnimationDelegate* CreateRemoveTabDelegate(BaseTab* tab); 232 233 // Invoked from Layout if the size changes or layout is really needed. 234 virtual void DoLayout(); 235 236 // Returns true if Tabs in this TabStrip are currently changing size or 237 // position. 238 bool IsAnimating() const; 239 240 // Get tab at a point in local view coordinates. 241 BaseTab* GetTabAtLocal(const gfx::Point& local_point); 242 243 private: 244 class RemoveTabDelegate; 245 246 friend class DraggedTabController; 247 248 // Invoked from StoppedDraggingTabs to cleanup |tab|. If |tab| is known 249 // |is_first_tab| is set to true. 250 void StoppedDraggingTab(BaseTab* tab, bool* is_first_tab); 251 252 // See description above field for details. 253 void set_attaching_dragged_tab(bool value) { attaching_dragged_tab_ = value; } 254 255 scoped_ptr<TabStripController> controller_; 256 257 const Type type_; 258 259 std::vector<TabData> tab_data_; 260 261 // The controller for a drag initiated from a Tab. Valid for the lifetime of 262 // the drag session. 263 scoped_ptr<DraggedTabController> drag_controller_; 264 265 // If true, the insert is a result of a drag attaching the tab back to the 266 // model. 267 bool attaching_dragged_tab_; 268 269 views::BoundsAnimator bounds_animator_; 270 271 // Size we last layed out at. 272 gfx::Size last_layout_size_; 273 }; 274 275 #endif // CHROME_BROWSER_UI_VIEWS_TABS_BASE_TAB_STRIP_H_ 276