| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_TABS_TAB_STRIP_MODEL_H_ |
| #define CHROME_BROWSER_TABS_TAB_STRIP_MODEL_H_ |
| |
| #include <vector> |
| |
| #include "base/observer_list.h" |
| #include "chrome/common/notification_registrar.h" |
| #include "chrome/common/page_transition_types.h" |
| |
| namespace gfx { |
| class Point; |
| class Rect; |
| } |
| class Browser; |
| class DockInfo; |
| class GURL; |
| class NavigationController; |
| class Profile; |
| class SiteInstance; |
| class TabContents; |
| class TabStripModelOrderController; |
| class TabStripModel; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // TabStripModelObserver |
| // |
| // Objects implement this interface when they wish to be notified of changes |
| // to the TabStripModel. |
| // |
| // Two major implementers are the TabStrip, which uses notifications sent |
| // via this interface to update the presentation of the strip, and the Browser |
| // object, which updates bookkeeping and shows/hides individual TabContentses. |
| // |
| // Register your TabStripModelObserver with the TabStripModel using its |
| // Add/RemoveObserver methods. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| class TabStripModelObserver { |
| public: |
| // Enumeration of the possible values supplied to TabChangedAt. |
| enum TabChangeType { |
| // Only the loading state changed. |
| LOADING_ONLY, |
| |
| // Only the title changed and page isn't loading. |
| TITLE_NOT_LOADING, |
| |
| // Change not characterized by LOADING_ONLY or TITLE_NOT_LOADING. |
| ALL |
| }; |
| |
| // A new TabContents was inserted into the TabStripModel at the specified |
| // index. |foreground| is whether or not it was opened in the foreground |
| // (selected). |
| virtual void TabInsertedAt(TabContents* contents, |
| int index, |
| bool foreground); |
| |
| // The specified TabContents at |index| is being closed (and eventually |
| // destroyed). |
| virtual void TabClosingAt(TabContents* contents, int index); |
| |
| // The specified TabContents at |index| is being detached, perhaps to be |
| // inserted in another TabStripModel. The implementer should take whatever |
| // action is necessary to deal with the TabContents no longer being present. |
| virtual void TabDetachedAt(TabContents* contents, int index); |
| |
| // The selected TabContents is about to change from |old_contents| at |index|. |
| // This gives observers a chance to prepare for an impending switch before it |
| // happens. |
| virtual void TabDeselectedAt(TabContents* contents, int index); |
| |
| // The selected TabContents changed from |old_contents| to |new_contents| at |
| // |index|. |user_gesture| specifies whether or not this was done by a user |
| // input event (e.g. clicking on a tab, keystroke) or as a side-effect of |
| // some other function. |
| virtual void TabSelectedAt(TabContents* old_contents, |
| TabContents* new_contents, |
| int index, |
| bool user_gesture); |
| |
| // The specified TabContents at |from_index| was moved to |to_index|. |
| virtual void TabMoved(TabContents* contents, |
| int from_index, |
| int to_index); |
| |
| // The specified TabContents at |index| changed in some way. |contents| may |
| // be an entirely different object and the old value is no longer available |
| // by the time this message is delivered. |
| // |
| // See TabChangeType for a description of |change_type|. |
| virtual void TabChangedAt(TabContents* contents, int index, |
| TabChangeType change_type); |
| |
| // The tab contents was replaced at the specified index. This is invoked when |
| // a tab becomes phantom. See description of phantom tabs in class description |
| // of TabStripModel for details. |
| virtual void TabReplacedAt(TabContents* old_contents, |
| TabContents* new_contents, int index); |
| |
| // Invoked when the pinned state of a tab changes. This is not invoked if the |
| // tab ends up moving as a result of the mini state changing. |
| // See note in TabMiniStateChanged as to how this relates to |
| // TabMiniStateChanged. |
| virtual void TabPinnedStateChanged(TabContents* contents, int index); |
| |
| // Invoked if the mini state of a tab changes. This is not invoked if the |
| // tab ends up moving as a result of the mini state changing. |
| // NOTE: this is sent when the pinned state of a non-app tab changes and is |
| // sent in addition to TabPinnedStateChanged. UI code typically need not care |
| // about TabPinnedStateChanged, but instead this. |
| virtual void TabMiniStateChanged(TabContents* contents, int index); |
| |
| // Invoked when the blocked state of a tab changes. |
| // NOTE: This is invoked when a tab becomes blocked/unblocked by a tab modal |
| // window. |
| virtual void TabBlockedStateChanged(TabContents* contents, int index); |
| |
| // The TabStripModel now no longer has any phantom tabs. The implementer may |
| // use this as a trigger to try and close the window containing the |
| // TabStripModel, for example... |
| virtual void TabStripEmpty(); |
| |
| // Sent when the tabstrip model is about to be deleted and any reference held |
| // must be dropped. |
| virtual void TabStripModelDeleted(); |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // TabStripModelDelegate |
| // |
| // A delegate interface that the TabStripModel uses to perform work that it |
| // can't do itself, such as obtain a container HWND for creating new |
| // TabContents, creating new TabStripModels for detached tabs, etc. |
| // |
| // This interface is typically implemented by the controller that instantiates |
| // the TabStripModel (in our case the Browser object). |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| class TabStripModelDelegate { |
| public: |
| // Adds what the delegate considers to be a blank tab to the model. |
| virtual TabContents* AddBlankTab(bool foreground) = 0; |
| virtual TabContents* AddBlankTabAt(int index, bool foreground) = 0; |
| |
| // Asks for a new TabStripModel to be created and the given tab contents to |
| // be added to it. Its size and position are reflected in |window_bounds|. |
| // If |dock_info|'s type is other than NONE, the newly created window should |
| // be docked as identified by |dock_info|. Returns the Browser object |
| // representing the newly created window and tab strip. This does not |
| // show the window, it's up to the caller to do so. |
| virtual Browser* CreateNewStripWithContents(TabContents* contents, |
| const gfx::Rect& window_bounds, |
| const DockInfo& dock_info) = 0; |
| |
| // Creates a new Browser object and window containing the specified |
| // |contents|, and continues a drag operation that began within the source |
| // window's tab strip. |window_bounds| are the bounds of the source window in |
| // screen coordinates, used to place the new window, and |tab_bounds| are the |
| // bounds of the dragged Tab view in the source window, in screen coordinates, |
| // used to place the new Tab in the new window. |
| virtual void ContinueDraggingDetachedTab(TabContents* contents, |
| const gfx::Rect& window_bounds, |
| const gfx::Rect& tab_bounds) = 0; |
| |
| enum { |
| TAB_MOVE_ACTION = 1, |
| TAB_TEAROFF_ACTION = 2 |
| }; |
| |
| // Determines what drag actions are possible for the specified strip. |
| virtual int GetDragActions() const = 0; |
| |
| // Creates an appropriate TabContents for the given URL. This is handled by |
| // the delegate since the TabContents may require special circumstances to |
| // exist for it to be constructed (e.g. a parent HWND). |
| // If |defer_load| is true, the navigation controller doesn't load the url. |
| // If |instance| is not null, its process is used to render the tab. |
| virtual TabContents* CreateTabContentsForURL( |
| const GURL& url, |
| const GURL& referrer, |
| Profile* profile, |
| PageTransition::Type transition, |
| bool defer_load, |
| SiteInstance* instance) const = 0; |
| |
| // Returns whether some contents can be duplicated. |
| virtual bool CanDuplicateContentsAt(int index) = 0; |
| |
| // Duplicates the contents at the provided index and places it into its own |
| // window. |
| virtual void DuplicateContentsAt(int index) = 0; |
| |
| // Called when a drag session has completed and the frame that initiated the |
| // the session should be closed. |
| virtual void CloseFrameAfterDragSession() = 0; |
| |
| // Creates an entry in the historical tab database for the specified |
| // TabContents. |
| virtual void CreateHistoricalTab(TabContents* contents) = 0; |
| |
| // Runs any unload listeners associated with the specified TabContents before |
| // it is closed. If there are unload listeners that need to be run, this |
| // function returns true and the TabStripModel will wait before closing the |
| // TabContents. If it returns false, there are no unload listeners and the |
| // TabStripModel can close the TabContents immediately. |
| virtual bool RunUnloadListenerBeforeClosing(TabContents* contents) = 0; |
| |
| // Returns true if a tab can be restored. |
| virtual bool CanRestoreTab() = 0; |
| |
| // Restores the last closed tab if CanRestoreTab would return true. |
| virtual void RestoreTab() = 0; |
| |
| // Returns whether some contents can be closed. |
| virtual bool CanCloseContentsAt(int index) = 0; |
| |
| // Returns true if we should allow "bookmark all tabs" in this window; this is |
| // true when there is more than one bookmarkable tab open. |
| virtual bool CanBookmarkAllTabs() const = 0; |
| |
| // Creates a bookmark folder containing a bookmark for all open tabs. |
| virtual void BookmarkAllTabs() = 0; |
| |
| // Returns true if any of the tabs can be closed. |
| virtual bool CanCloseTab() const; |
| |
| // Returns true if the vertical tabstrip presentation should be used. |
| virtual bool UseVerticalTabs() const = 0; |
| |
| // Toggles the use of the vertical tabstrip. |
| virtual void ToggleUseVerticalTabs() = 0; |
| |
| // Set the visiblity of the toolbar. |
| virtual void SetToolbarVisibility(bool value) = 0; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // TabStripModel |
| // |
| // A model & low level controller of a Browser Window tabstrip. Holds a vector |
| // of TabContents, and provides an API for adding, removing and shuffling |
| // them, as well as a higher level API for doing specific Browser-related |
| // tasks like adding new Tabs from just a URL, etc. |
| // |
| // Each tab may be any one of the following states: |
| // . Mini-tab. Mini tabs are locked to the left side of the tab strip and |
| // rendered differently (small tabs with only a favicon). The model makes |
| // sure all mini-tabs are at the beginning of the tab strip. For example, |
| // if a non-mini tab is added it is forced to be with non-mini tabs. Requests |
| // to move tabs outside the range of the tab type are ignored. For example, |
| // a request to move a mini-tab after non-mini-tabs is ignored. |
| // You'll notice there is no explcit api for making a tab a mini-tab, rather |
| // there are two tab types that are implicitly mini-tabs: |
| // . App. Corresponds to an extension that wants an app tab. App tabs are |
| // identified by TabContents::is_app(). |
| // . Pinned. Any tab can be pinned. A pinned tab is made phantom when closed. |
| // Non-app tabs whose pinned state is changed are moved to be with other |
| // mini-tabs or non-mini tabs. |
| // . Phantom. Only pinned tabs may be made phantom. When a tab that can be made |
| // phantom is closed the renderer is shutdown, a new |
| // TabContents/NavigationController is created that has not yet loaded the |
| // renderer and observers are notified via the TabReplacedAt method. When a |
| // phantom tab is selected the renderer is loaded and the tab is no longer |
| // phantom. |
| // Phantom tabs do not prevent the tabstrip from closing, for example if the |
| // tabstrip has one phantom and one non-phantom tab and the non-phantom tab is |
| // closed, then the tabstrip/browser are closed. |
| // |
| // A TabStripModel has one delegate that it relies on to perform certain tasks |
| // like creating new TabStripModels (probably hosted in Browser windows) when |
| // required. See TabStripDelegate above for more information. |
| // |
| // A TabStripModel also has N observers (see TabStripModelObserver above), |
| // which can be registered via Add/RemoveObserver. An Observer is notified of |
| // tab creations, removals, moves, and other interesting events. The |
| // TabStrip implements this interface to know when to create new tabs in |
| // the View, and the Browser object likewise implements to be able to update |
| // its bookkeeping when such events happen. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| class TabStripModel : public NotificationObserver { |
| public: |
| // Policy for how new tabs are inserted. |
| enum InsertionPolicy { |
| // Newly created tabs are created after the selection. This is the default. |
| INSERT_AFTER, |
| |
| // Newly created tabs are inserted before the selection. |
| INSERT_BEFORE, |
| }; |
| |
| // Used to specify what should happen when the tab is closed. |
| enum CloseTypes { |
| CLOSE_NONE = 0, |
| |
| // Indicates the tab was closed by the user. If true, |
| // TabContents::set_closed_by_user_gesture(true) is invoked. |
| CLOSE_USER_GESTURE = 1 << 0, |
| |
| // If true the history is recorded so that the tab can be reopened later. |
| // You almost always want to set this. |
| CLOSE_CREATE_HISTORICAL_TAB = 1 << 1, |
| }; |
| |
| // Constants used when adding tabs. |
| enum AddTabTypes { |
| // Used to indicate nothing special should happen to the newly inserted |
| // tab. |
| ADD_NONE = 0, |
| |
| // The tab should be selected. |
| ADD_SELECTED = 1 << 0, |
| |
| // The tab should be pinned. |
| ADD_PINNED = 1 << 1, |
| |
| // If not set the insertion index of the TabContents is left up to the Order |
| // Controller associated, so the final insertion index may differ from the |
| // specified index. Otherwise the index supplied is used. |
| ADD_FORCE_INDEX = 1 << 2, |
| |
| // If set the newly inserted tab inherits the group of the currently |
| // selected tab. If not set the tab may still inherit the group under |
| // certain situations. |
| ADD_INHERIT_GROUP = 1 << 3, |
| |
| // If set the newly inserted tab's opener is set to the currently selected |
| // tab. If not set the tab may still inherit the group/opener under certain |
| // situations. |
| // NOTE: this is ignored if ADD_INHERIT_GROUP is set. |
| ADD_INHERIT_OPENER = 1 << 4, |
| }; |
| |
| static const int kNoTab = -1; |
| |
| // Construct a TabStripModel with a delegate to help it do certain things |
| // (See TabStripModelDelegate documentation). |delegate| cannot be NULL. |
| TabStripModel(TabStripModelDelegate* delegate, Profile* profile); |
| virtual ~TabStripModel(); |
| |
| // Retrieves the TabStripModelDelegate associated with this TabStripModel. |
| TabStripModelDelegate* delegate() const { return delegate_; } |
| |
| // Add and remove observers to changes within this TabStripModel. |
| void AddObserver(TabStripModelObserver* observer); |
| void RemoveObserver(TabStripModelObserver* observer); |
| |
| // Retrieve the number of TabContentses/emptiness of the TabStripModel. |
| int count() const { return static_cast<int>(contents_data_.size()); } |
| bool empty() const { return contents_data_.empty(); } |
| |
| // Returns true if there are any non-phantom tabs. When there are no |
| // non-phantom tabs the delegate is notified by way of TabStripEmpty and the |
| // browser closes. |
| bool HasNonPhantomTabs() const; |
| |
| // Retrieve the Profile associated with this TabStripModel. |
| Profile* profile() const { return profile_; } |
| |
| // Retrieve the index of the currently selected TabContents. |
| int selected_index() const { return selected_index_; } |
| |
| // Returns true if the tabstrip is currently closing all open tabs (via a |
| // call to CloseAllTabs). As tabs close, the selection in the tabstrip |
| // changes which notifies observers, which can use this as an optimization to |
| // avoid doing meaningless or unhelpful work. |
| bool closing_all() const { return closing_all_; } |
| |
| // Access the order controller. Exposed only for unit tests. |
| TabStripModelOrderController* order_controller() const { |
| return order_controller_; |
| } |
| |
| // Sets the insertion policy. Default is INSERT_AFTER. |
| void SetInsertionPolicy(InsertionPolicy policy); |
| InsertionPolicy insertion_policy() const; |
| |
| // Returns true if |observer| is in the list of observers. This is intended |
| // for debugging. |
| bool HasObserver(TabStripModelObserver* observer); |
| |
| // Basic API ///////////////////////////////////////////////////////////////// |
| |
| // Determines if the specified index is contained within the TabStripModel. |
| bool ContainsIndex(int index) const; |
| |
| // Adds the specified TabContents in the default location. Tabs opened in the |
| // foreground inherit the group of the previously selected tab. |
| void AppendTabContents(TabContents* contents, bool foreground); |
| |
| // Adds the specified TabContents at the specified location. |add_types| is a |
| // bitmask of AddTypes; see it for details. |
| // |
| // All append/insert methods end up in this method. |
| // |
| // NOTE: adding a tab using this method does NOT query the order controller, |
| // as such the ADD_FORCE_INDEX AddType is meaningless here. The only time the |
| // |index| is changed is if using the index would result in breaking the |
| // constraint that all mini-tabs occur before non-mini-tabs. |
| // See also AddTabContents. |
| void InsertTabContentsAt(int index, |
| TabContents* contents, |
| int add_types); |
| |
| // Closes the TabContents at the specified index. This causes the TabContents |
| // to be destroyed, but it may not happen immediately (e.g. if it's a |
| // TabContents). |close_types| is a bitmask of CloseTypes. |
| // Returns true if the TabContents was closed immediately, false if it was not |
| // closed (we may be waiting for a response from an onunload handler, or |
| // waiting for the user to confirm closure). |
| bool CloseTabContentsAt(int index, uint32 close_types); |
| |
| // Replaces the entire state of a the tab at index by switching in a |
| // different NavigationController. This is used through the recently |
| // closed tabs list, which needs to replace a tab's current state |
| // and history with another set of contents and history. |
| // |
| // The old NavigationController is deallocated and this object takes |
| // ownership of the passed in controller. |
| void ReplaceNavigationControllerAt(int index, |
| NavigationController* controller); |
| |
| // Detaches the TabContents at the specified index from this strip. The |
| // TabContents is not destroyed, just removed from display. The caller is |
| // responsible for doing something with it (e.g. stuffing it into another |
| // strip). |
| TabContents* DetachTabContentsAt(int index); |
| |
| // Select the TabContents at the specified index. |user_gesture| is true if |
| // the user actually clicked on the tab or navigated to it using a keyboard |
| // command, false if the tab was selected as a by-product of some other |
| // action. |
| void SelectTabContentsAt(int index, bool user_gesture); |
| |
| // Move the TabContents at the specified index to another index. This method |
| // does NOT send Detached/Attached notifications, rather it moves the |
| // TabContents inline and sends a Moved notification instead. |
| // If |select_after_move| is false, whatever tab was selected before the move |
| // will still be selected, but it's index may have incremented or decremented |
| // one slot. |
| // NOTE: this does nothing if the move would result in app tabs and non-app |
| // tabs mixing. |
| void MoveTabContentsAt(int index, int to_position, bool select_after_move); |
| |
| // Returns the currently selected TabContents, or NULL if there is none. |
| TabContents* GetSelectedTabContents() const; |
| |
| // Returns the TabContents at the specified index, or NULL if there is none. |
| TabContents* GetTabContentsAt(int index) const; |
| |
| // Returns the index of the specified TabContents, or TabContents::kNoTab if |
| // the TabContents is not in this TabStripModel. |
| int GetIndexOfTabContents(const TabContents* contents) const; |
| |
| // Returns the index of the specified NavigationController, or -1 if it is |
| // not in this TabStripModel. |
| int GetIndexOfController(const NavigationController* controller) const; |
| |
| // Notify any observers that the TabContents at the specified index has |
| // changed in some way. See TabChangeType for details of |change_type|. |
| void UpdateTabContentsStateAt( |
| int index, |
| TabStripModelObserver::TabChangeType change_type); |
| |
| // Make sure there is an auto-generated New Tab tab in the TabStripModel. |
| // If |force_create| is true, the New Tab will be created even if the |
| // preference is set to false (used by startup). |
| void EnsureNewTabVisible(bool force_create); |
| |
| // Close all tabs at once. Code can use closing_all() above to defer |
| // operations that might otherwise by invoked by the flurry of detach/select |
| // notifications this method causes. |
| void CloseAllTabs(); |
| |
| // Returns true if there are any TabContents that are currently loading. |
| bool TabsAreLoading() const; |
| |
| // Returns the controller controller that opened the TabContents at |index|. |
| NavigationController* GetOpenerOfTabContentsAt(int index); |
| |
| // Returns the index of the next TabContents in the sequence of TabContentses |
| // spawned by the specified NavigationController after |start_index|. |
| // If |use_group| is true, the group property of the tab is used instead of |
| // the opener to find the next tab. Under some circumstances the group |
| // relationship may exist but the opener may not. |
| // NOTE: this skips phantom tabs. |
| int GetIndexOfNextTabContentsOpenedBy(const NavigationController* opener, |
| int start_index, |
| bool use_group) const; |
| |
| // Returns the index of the first TabContents in the model opened by the |
| // specified opener. |
| // NOTE: this skips phantom tabs. |
| int GetIndexOfFirstTabContentsOpenedBy(const NavigationController* opener, |
| int start_index) const; |
| |
| // Returns the index of the last TabContents in the model opened by the |
| // specified opener, starting at |start_index|. |
| // NOTE: this skips phantom tabs. |
| int GetIndexOfLastTabContentsOpenedBy(const NavigationController* opener, |
| int start_index) const; |
| |
| // Called by the Browser when a navigation is about to occur in the specified |
| // TabContents. Depending on the tab, and the transition type of the |
| // navigation, the TabStripModel may adjust its selection and grouping |
| // behavior. |
| void TabNavigating(TabContents* contents, PageTransition::Type transition); |
| |
| // Forget all Opener relationships that are stored (but _not_ group |
| // relationships!) This is to reduce unpredictable tab switching behavior |
| // in complex session states. The exact circumstances under which this method |
| // is called are left up to the implementation of the selected |
| // TabStripModelOrderController. |
| void ForgetAllOpeners(); |
| |
| // Forgets the group affiliation of the specified TabContents. This should be |
| // called when a TabContents that is part of a logical group of tabs is |
| // moved to a new logical context by the user (e.g. by typing a new URL or |
| // selecting a bookmark). This also forgets the opener, which is considered |
| // a weaker relationship than group. |
| void ForgetGroup(TabContents* contents); |
| |
| // Returns true if the group/opener relationships present for |contents| |
| // should be reset when _any_ selection change occurs in the model. |
| bool ShouldResetGroupOnSelect(TabContents* contents) const; |
| |
| // Changes the blocked state of the tab at |index|. |
| void SetTabBlocked(int index, bool blocked); |
| |
| // Changes the pinned state of the tab at |index|. See description above |
| // class for details on this. |
| void SetTabPinned(int index, bool pinned); |
| |
| // Returns true if the tab at |index| is pinned. |
| // See description above class for details on pinned tabs. |
| bool IsTabPinned(int index) const; |
| |
| // Is the tab a mini-tab? |
| // See description above class for details on this. |
| bool IsMiniTab(int index) const; |
| |
| // Is the tab at |index| an app? |
| // See description above class for details on app tabs. |
| bool IsAppTab(int index) const; |
| |
| // Returns true if the toolbar is visible for the tab at |index|. |
| bool IsToolbarVisible(int index) const; |
| |
| // Returns true if the tab is a phantom tab. A phantom tab is one where the |
| // renderer has not been loaded. |
| // See description above class for details on phantom tabs. |
| bool IsPhantomTab(int index) const; |
| |
| // Returns true if the tab at |index| is blocked by a tab modal dialog. |
| bool IsTabBlocked(int index) const; |
| |
| // Returns the index of the first tab that is not a mini-tab. This returns |
| // |count()| if all of the tabs are mini-tabs, and 0 if none of the tabs are |
| // mini-tabs. |
| int IndexOfFirstNonMiniTab() const; |
| |
| // Returns a valid index for inserting a new tab into this model. |index| is |
| // the proposed index and |mini_tab| is true if inserting a tab will become |
| // mini (pinned or app). If |mini_tab| is true, the returned index is between |
| // 0 and IndexOfFirstNonMiniTab. If |mini_tab| is false, the returned index |
| // is between IndexOfFirstNonMiniTab and count(). |
| int ConstrainInsertionIndex(int index, bool mini_tab); |
| |
| // Returns the index of the first tab that is not a phantom tab. This returns |
| // kNoTab if all of the tabs are phantom tabs. |
| int IndexOfFirstNonPhantomTab() const; |
| |
| // Returns the number of non phantom tabs in the TabStripModel. |
| int GetNonPhantomTabCount() const; |
| |
| |
| // Command level API ///////////////////////////////////////////////////////// |
| |
| // Adds a TabContents at the best position in the TabStripModel given the |
| // specified insertion index, transition, etc. |add_types| is a bitmask of |
| // AddTypes; see it for details. This method ends up calling into |
| // InsertTabContentsAt to do the actual inertion. |
| void AddTabContents(TabContents* contents, |
| int index, |
| PageTransition::Type transition, |
| int add_types); |
| |
| // Closes the selected TabContents. |
| void CloseSelectedTab(); |
| |
| // Select adjacent tabs |
| void SelectNextTab(); |
| void SelectPreviousTab(); |
| |
| // Selects the last tab in the tab strip. |
| void SelectLastTab(); |
| |
| // Swap adjacent tabs. |
| void MoveTabNext(); |
| void MoveTabPrevious(); |
| |
| // View API ////////////////////////////////////////////////////////////////// |
| |
| // The specified contents should be opened in a new tabstrip. Returns the |
| // Browser that holds it. |
| Browser* TearOffTabContents(TabContents* detached_contents, |
| const gfx::Rect& window_bounds, |
| const DockInfo& dock_info); |
| |
| // Context menu functions. |
| enum ContextMenuCommand { |
| CommandFirst = 0, |
| CommandNewTab, |
| CommandReload, |
| CommandDuplicate, |
| CommandCloseTab, |
| CommandCloseOtherTabs, |
| CommandCloseTabsToRight, |
| CommandRestoreTab, |
| CommandTogglePinned, |
| CommandToggleToolbar, |
| CommandBookmarkAllTabs, |
| CommandUseVerticalTabs, |
| CommandLast |
| }; |
| |
| // Returns true if the specified command is enabled. |
| bool IsContextMenuCommandEnabled(int context_index, |
| ContextMenuCommand command_id) const; |
| |
| // Returns true if the specified command is checked. |
| bool IsContextMenuCommandChecked(int context_index, |
| ContextMenuCommand command_id) const; |
| |
| // Performs the action associated with the specified command for the given |
| // TabStripModel index |context_index|. |
| void ExecuteContextMenuCommand(int context_index, |
| ContextMenuCommand command_id); |
| |
| // Returns a vector of indices of the tabs that will close when executing the |
| // command |id| for the tab at |index|. The returned indices are sorted in |
| // descending order. |
| std::vector<int> GetIndicesClosedByCommand(int index, |
| ContextMenuCommand id) const; |
| |
| // Overridden from notificationObserver: |
| virtual void Observe(NotificationType type, |
| const NotificationSource& source, |
| const NotificationDetails& details); |
| |
| private: |
| // We cannot be constructed without a delegate. |
| TabStripModel(); |
| |
| // Returns true if the specified TabContents is a New Tab at the end of the |
| // TabStrip. We check for this because opener relationships are _not_ |
| // forgotten for the New Tab page opened as a result of a New Tab gesture |
| // (e.g. Ctrl+T, etc) since the user may open a tab transiently to look up |
| // something related to their current activity. |
| bool IsNewTabAtEndOfTabStrip(TabContents* contents) const; |
| |
| // Closes the TabContents at the specified indices. This causes the |
| // TabContents to be destroyed, but it may not happen immediately. If the |
| // page in question has an unload event the TabContents will not be destroyed |
| // until after the event has completed, which will then call back into this |
| // method. |
| // |
| // Returns true if the TabContents were closed immediately, false if we are |
| // waiting for the result of an onunload handler. |
| bool InternalCloseTabs(const std::vector<int>& indices, uint32 close_types); |
| |
| // Invoked from InternalCloseTabs and when an extension is removed for an app |
| // tab. Notifies observers of TabClosingAt and deletes |contents|. If |
| // |create_historical_tabs| is true, CreateHistoricalTab is invoked on the |
| // delegate. |
| // |
| // The boolean parameter create_historical_tab controls whether to |
| // record these tabs and their history for reopening recently closed |
| // tabs. |
| void InternalCloseTab(TabContents* contents, |
| int index, |
| bool create_historical_tabs); |
| |
| TabContents* GetContentsAt(int index) const; |
| |
| // The actual implementation of SelectTabContentsAt. Takes the previously |
| // selected contents in |old_contents|, which may actually not be in |
| // |contents_| anymore because it may have been removed by a call to say |
| // DetachTabContentsAt... |
| void ChangeSelectedContentsFrom( |
| TabContents* old_contents, int to_index, bool user_gesture); |
| |
| // Returns the number of New Tab tabs in the TabStripModel. |
| int GetNewTabCount() const; |
| |
| // Selects either the next tab (|foward| is true), or the previous tab |
| // (|forward| is false). |
| void SelectRelativeTab(bool forward); |
| |
| // Returns the first non-phantom tab starting at |index|, skipping the tab at |
| // |ignore_index|. |
| int IndexOfNextNonPhantomTab(int index, int ignore_index); |
| |
| // Returns true if the tab at the specified index should be made phantom when |
| // the tab is closing. |
| bool ShouldMakePhantomOnClose(int index); |
| |
| // Makes the tab a phantom tab. |
| void MakePhantom(int index); |
| |
| // Does the work of MoveTabContentsAt. This has no checks to make sure the |
| // position is valid, those are done in MoveTabContentsAt. |
| void MoveTabContentsAtImpl(int index, |
| int to_position, |
| bool select_after_move); |
| |
| // Returns true if the tab represented by the specified data has an opener |
| // that matches the specified one. If |use_group| is true, then this will |
| // fall back to check the group relationship as well. |
| struct TabContentsData; |
| static bool OpenerMatches(const TabContentsData* data, |
| const NavigationController* opener, |
| bool use_group); |
| |
| // Our delegate. |
| TabStripModelDelegate* delegate_; |
| |
| // A hunk of data representing a TabContents and (optionally) the |
| // NavigationController that spawned it. This memory only sticks around while |
| // the TabContents is in the current TabStripModel, unless otherwise |
| // specified in code. |
| struct TabContentsData { |
| explicit TabContentsData(TabContents* a_contents) |
| : contents(a_contents), |
| reset_group_on_select(false), |
| pinned(false), |
| blocked(false) { |
| SetGroup(NULL); |
| } |
| |
| // Create a relationship between this TabContents and other TabContentses. |
| // Used to identify which TabContents to select next after one is closed. |
| void SetGroup(NavigationController* a_group) { |
| group = a_group; |
| opener = a_group; |
| } |
| |
| // Forget the opener relationship so that when this TabContents is closed |
| // unpredictable re-selection does not occur. |
| void ForgetOpener() { |
| opener = NULL; |
| } |
| |
| TabContents* contents; |
| // We use NavigationControllers here since they more closely model the |
| // "identity" of a Tab, TabContents can change depending on the URL loaded |
| // in the Tab. |
| // The group is used to model a set of tabs spawned from a single parent |
| // tab. This value is preserved for a given tab as long as the tab remains |
| // navigated to the link it was initially opened at or some navigation from |
| // that page (i.e. if the user types or visits a bookmark or some other |
| // navigation within that tab, the group relationship is lost). This |
| // property can safely be used to implement features that depend on a |
| // logical group of related tabs. |
| NavigationController* group; |
| // The owner models the same relationship as group, except it is more |
| // easily discarded, e.g. when the user switches to a tab not part of the |
| // same group. This property is used to determine what tab to select next |
| // when one is closed. |
| NavigationController* opener; |
| // True if our group should be reset the moment selection moves away from |
| // this Tab. This is the case for tabs opened in the foreground at the end |
| // of the TabStrip while viewing another Tab. If these tabs are closed |
| // before selection moves elsewhere, their opener is selected. But if |
| // selection shifts to _any_ tab (including their opener), the group |
| // relationship is reset to avoid confusing close sequencing. |
| bool reset_group_on_select; |
| |
| // Is the tab pinned? |
| bool pinned; |
| |
| // Is the tab interaction blocked by a modal dialog? |
| bool blocked; |
| }; |
| |
| // The TabContents data currently hosted within this TabStripModel. |
| typedef std::vector<TabContentsData*> TabContentsDataVector; |
| TabContentsDataVector contents_data_; |
| |
| // The index of the TabContents in |contents_| that is currently selected. |
| int selected_index_; |
| |
| // A profile associated with this TabStripModel, used when creating new Tabs. |
| Profile* profile_; |
| |
| // True if all tabs are currently being closed via CloseAllTabs. |
| bool closing_all_; |
| |
| // An object that determines where new Tabs should be inserted and where |
| // selection should move when a Tab is closed. |
| TabStripModelOrderController* order_controller_; |
| |
| // Our observers. |
| typedef ObserverList<TabStripModelObserver> TabStripModelObservers; |
| TabStripModelObservers observers_; |
| |
| // A scoped container for notification registries. |
| NotificationRegistrar registrar_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TabStripModel); |
| }; |
| |
| #endif // CHROME_BROWSER_TABS_TAB_STRIP_MODEL_H_ |