Home | History | Annotate | Download | only in tabs
      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