blob: 577e47a7b50da46bccab819626fcb1a98a463dbf [file] [log] [blame]
// Copyright (c) 2012 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_UI_TABS_TAB_STRIP_MODEL_OBSERVER_H_
#define CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_OBSERVER_H_
#include <vector>
#include "base/macros.h"
#include "chrome/browser/ui/tabs/tab_change_type.h"
#include "ui/base/models/list_selection_model.h"
class TabStripModel;
namespace content {
class WebContents;
}
////////////////////////////////////////////////////////////////////////////////
//
// TabStripModelChange / TabStripSelectionChange
//
// The following class and structures are used to inform TabStripModelObservers
// of changes to:
// 1) selection model
// 2) activated tab
// 3) inserted/removed/moved tabs.
// These changes must be bundled together because (1) and (2) consist of indices
// into a list of tabs [determined by (3)]. All three must be kept synchronized.
//
////////////////////////////////////////////////////////////////////////////////
class TabStripModelChange {
public:
enum Type { kSelectionOnly, kInserted, kRemoved, kMoved, kReplaced };
// A WebContents was inserted at |index|. This implicitly changes the existing
// selection model by calling IncrementFrom(index).
struct Insert {
content::WebContents* contents;
int index;
};
// A WebContents was removed at |index|. This implicitly changes the existing
// selection model by calling DecrementFrom(index).
struct Remove {
content::WebContents* contents;
int index;
// The specified WebContents at |index| is being closed (and eventually
// destroyed). |tab_strip_model| is the TabStripModel that contained the
// tab.
bool will_be_deleted;
};
// A WebContents was moved from |from_index| to |to_index|. This implicitly
// changes the existing selection model by calling
// Move(from_index, to_index, 1).
struct Move {
content::WebContents* contents;
int from_index;
int to_index;
};
// The WebContents was replaced at the specified index. This is invoked when
// prerendering swaps in a prerendered WebContents.
struct Replace {
content::WebContents* old_contents;
content::WebContents* new_contents;
int index;
};
struct Delta {
union {
Insert insert;
Remove remove;
Move move;
Replace replace;
};
};
// Convenient factory methods to create |Delta| with each member.
static Delta CreateInsertDelta(content::WebContents* contents, int index);
static Delta CreateRemoveDelta(content::WebContents* contents,
int index,
bool will_be_deleted);
static Delta CreateMoveDelta(content::WebContents* contents,
int from_index,
int to_index);
static Delta CreateReplaceDelta(content::WebContents* old_contents,
content::WebContents* new_contents,
int index);
TabStripModelChange();
TabStripModelChange(Type type, const Delta& delta);
TabStripModelChange(Type type, const std::vector<Delta>& deltas);
~TabStripModelChange();
TabStripModelChange(TabStripModelChange&& other);
Type type() const { return type_; }
const std::vector<Delta>& deltas() const { return deltas_; }
private:
const Type type_ = kSelectionOnly;
const std::vector<Delta> deltas_;
DISALLOW_COPY_AND_ASSIGN(TabStripModelChange);
};
// Struct to carry changes on selection/activation.
struct TabStripSelectionChange {
TabStripSelectionChange();
TabStripSelectionChange(const TabStripSelectionChange& other);
~TabStripSelectionChange();
TabStripSelectionChange& operator=(const TabStripSelectionChange& other);
// Fill TabStripSelectionChange with given |contents| and |selection_model|.
// note that |new_contents| and |new_model| will be filled too so that
// selection_changed() and active_tab_changed() won't return true.
TabStripSelectionChange(content::WebContents* contents,
const ui::ListSelectionModel& model);
bool active_tab_changed() const { return old_contents != new_contents; }
// TODO(sangwoo.ko) Do we need something to indicate that the change
// was made implicitly?
bool selection_changed() const {
return selected_tabs_were_removed || old_model != new_model;
}
content::WebContents* old_contents = nullptr;
content::WebContents* new_contents = nullptr;
ui::ListSelectionModel old_model;
ui::ListSelectionModel new_model;
bool selected_tabs_were_removed = false;
int reason = 0;
};
////////////////////////////////////////////////////////////////////////////////
//
// 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 WebContentses.
//
// Register your TabStripModelObserver with the TabStripModel using its
// Add/RemoveObserver methods.
//
////////////////////////////////////////////////////////////////////////////////
class TabStripModelObserver {
public:
enum ChangeReason {
// Used to indicate that none of the reasons below are responsible for the
// active tab change.
CHANGE_REASON_NONE = 0,
// The active tab changed because the tab's web contents was replaced.
CHANGE_REASON_REPLACED = 1 << 0,
// The active tab changed due to a user input event.
CHANGE_REASON_USER_GESTURE = 1 << 1,
};
enum CloseAllStoppedReason {
// Used to indicate that CloseAllTab event is canceled.
kCloseAllCanceled = 0,
// Used to indicate that CloseAllTab event complete successfully.
kCloseAllCompleted = 1,
};
// |change| is a series of changes in tabtrip model. |change| consists
// of changes with same type and those changes may have caused selection or
// activation changes. |selection| is determined by comparing the state of
// TabStripModel before the |change| and after the |change| are applied.
// When only selection/activation was changed without any change about
// WebContents, |change| can be empty.
virtual void OnTabStripModelChanged(TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection);
// The specified WebContents 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 tab_change_type.h for a description of |change_type|.
virtual void TabChangedAt(content::WebContents* contents,
int index,
TabChangeType change_type);
// Invoked when the pinned state of a tab changes.
virtual void TabPinnedStateChanged(TabStripModel* tab_strip_model,
content::WebContents* 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(content::WebContents* contents,
int index);
// The TabStripModel now no longer has any tabs. The implementer may
// use this as a trigger to try and close the window containing the
// TabStripModel, for example...
virtual void TabStripEmpty();
// Sent any time an attempt is made to close all the tabs. This is not
// necessarily the result of CloseAllTabs(). For example, if the user closes
// the last tab WillCloseAllTabs() is sent. If the close does not succeed
// during the current event (say unload handlers block it) then
// CloseAllTabsStopped() is sent with reason 'CANCELED'. On the other hand if
// the close does finish then CloseAllTabsStopped() is sent with reason
// 'COMPLETED'. Also note that if the last tab is detached
// (DetachWebContentsAt()) then this is not sent.
virtual void WillCloseAllTabs(TabStripModel* tab_strip_model);
virtual void CloseAllTabsStopped(TabStripModel* tab_strip_model,
CloseAllStoppedReason reason);
// The specified tab at |index| requires the display of a UI indication to the
// user that it needs their attention. The UI indication is set iff
// |attention| is true.
virtual void SetTabNeedsAttentionAt(int index, bool attention);
protected:
TabStripModelObserver();
virtual ~TabStripModelObserver() {}
private:
DISALLOW_COPY_AND_ASSIGN(TabStripModelObserver);
};
#endif // CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_OBSERVER_H_