// Copyright (c) 2011 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_VIEWS_TABS_BASE_TAB_STRIP_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_BASE_TAB_STRIP_H_
#pragma once
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/views/tabs/abstract_tab_strip_view.h"
#include "chrome/browser/ui/views/tabs/base_tab.h"
#include "chrome/browser/ui/views/tabs/tab_controller.h"
#include "views/animation/bounds_animator.h"
#include "views/view.h"
class BaseTab;
class DraggedTabController;
class TabStripController;
// Base class for the view tab strip implementations.
class BaseTabStrip : public AbstractTabStripView,
public TabController {
public:
enum Type {
HORIZONTAL_TAB_STRIP,
VERTICAL_TAB_STRIP
};
BaseTabStrip(TabStripController* controller, Type type);
virtual ~BaseTabStrip();
Type type() const { return type_; }
// Starts highlighting the tab at the specified index.
virtual void StartHighlight(int model_index) = 0;
// Stops all tab higlighting.
virtual void StopAllHighlighting() = 0;
// Retrieves the ideal bounds for the Tab at the specified index.
const gfx::Rect& ideal_bounds(int tab_data_index) {
return tab_data_[tab_data_index].ideal_bounds;
}
// Creates and returns a tab that can be used for dragging. Ownership passes
// to the caller.
virtual BaseTab* CreateTabForDragging() = 0;
// Adds a tab at the specified index.
void AddTabAt(int model_index, const TabRendererData& data);
// Invoked from the controller when the close initiates from the TabController
// (the user clicked the tab close button or middle clicked the tab). This is
// invoked from Close. Because of unload handlers Close is not always
// immediately followed by RemoveTabAt.
virtual void PrepareForCloseAt(int model_index) {}
// Removes a tab at the specified index.
virtual void RemoveTabAt(int model_index) = 0;
// Selects a tab at the specified index. |old_model_index| is the selected
// index prior to the selection change.
virtual void SelectTabAt(int old_model_index, int new_model_index) = 0;
// Moves a tab.
virtual void MoveTab(int from_model_index, int to_model_index);
// Invoked when the title of a tab changes and the tab isn't loading.
virtual void TabTitleChangedNotLoading(int model_index) = 0;
// Sets the tab data at the specified model index.
virtual void SetTabData(int model_index, const TabRendererData& data);
// Returns the tab at the specified model index.
virtual BaseTab* GetBaseTabAtModelIndex(int model_index) const;
// Returns the tab at the specified tab index.
BaseTab* base_tab_at_tab_index(int tab_index) const {
return tab_data_[tab_index].tab;
}
// Returns the index of the specified tab in the model coordiate system, or
// -1 if tab is closing or not valid.
int GetModelIndexOfBaseTab(const BaseTab* tab) const;
// Gets the number of Tabs in the tab strip.
// WARNING: this is the number of tabs displayed by the tabstrip, which if
// an animation is ongoing is not necessarily the same as the number of tabs
// in the model.
int tab_count() const { return static_cast<int>(tab_data_.size()); }
// Cover method for TabStripController::GetCount.
int GetModelCount() const;
// Cover method for TabStripController::IsValidIndex.
bool IsValidModelIndex(int model_index) const;
// Returns the index into |tab_data_| corresponding to the index from the
// TabStripModel, or |tab_data_.size()| if there is no tab representing
// |model_index|.
int ModelIndexToTabIndex(int model_index) const;
TabStripController* controller() const { return controller_.get(); }
// Returns true if a drag session is currently active.
bool IsDragSessionActive() const;
// Returns true if a tab is being dragged into this tab strip.
bool IsActiveDropTarget() const;
// AbstractTabStripView implementation
virtual bool IsTabStripEditable() const OVERRIDE;
virtual bool IsTabStripCloseable() const OVERRIDE;
virtual void UpdateLoadingAnimations() OVERRIDE;
// TabController overrides:
virtual void SelectTab(BaseTab* tab) OVERRIDE;
virtual void ExtendSelectionTo(BaseTab* tab) OVERRIDE;
virtual void ToggleSelected(BaseTab* tab) OVERRIDE;
virtual void AddSelectionFromAnchorTo(BaseTab* tab) OVERRIDE;
virtual void CloseTab(BaseTab* tab) OVERRIDE;
virtual void ShowContextMenuForTab(BaseTab* tab,
const gfx::Point& p) OVERRIDE;
virtual bool IsActiveTab(const BaseTab* tab) const OVERRIDE;
virtual bool IsTabSelected(const BaseTab* tab) const OVERRIDE;
virtual bool IsTabPinned(const BaseTab* tab) const OVERRIDE;
virtual bool IsTabCloseable(const BaseTab* tab) const OVERRIDE;
virtual void MaybeStartDrag(BaseTab* tab,
const views::MouseEvent& event) OVERRIDE;
virtual void ContinueDrag(const views::MouseEvent& event) OVERRIDE;
virtual bool EndDrag(bool canceled) OVERRIDE;
virtual BaseTab* GetTabAt(BaseTab* tab,
const gfx::Point& tab_in_tab_coordinates) OVERRIDE;
// View overrides:
virtual void Layout() OVERRIDE;
protected:
// The Tabs we contain, and their last generated "good" bounds.
struct TabData {
BaseTab* tab;
gfx::Rect ideal_bounds;
};
// View overrides.
virtual bool OnMouseDragged(const views::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const views::MouseEvent& event) OVERRIDE;
virtual void OnMouseCaptureLost() OVERRIDE;
// Creates and returns a new tab. The caller owners the returned tab.
virtual BaseTab* CreateTab() = 0;
// Invoked from |AddTabAt| after the newly created tab has been inserted.
// Subclasses should either start an animation, or layout.
virtual void StartInsertTabAnimation(int model_index) = 0;
// Invoked from |MoveTab| after |tab_data_| has been updated to animate the
// move.
virtual void StartMoveTabAnimation();
// Starts the remove tab animation.
virtual void StartRemoveTabAnimation(int model_index);
// Starts the mini-tab animation.
virtual void StartMiniTabAnimation();
// Returns whether the highlight button should be highlighted after a remove.
virtual bool ShouldHighlightCloseButtonAfterRemove();
// Animates all the views to their ideal bounds.
// NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds
// currently set in ideal_bounds.
virtual void AnimateToIdealBounds() = 0;
// Cleans up the Tab from the TabStrip. This is called from the tab animation
// code and is not a general-purpose method.
void RemoveAndDeleteTab(BaseTab* tab);
// Resets the bounds of all non-closing tabs.
virtual void GenerateIdealBounds() = 0;
// Invoked during drag to layout the tabs being dragged in |tabs| at
// |location|. If |initial_drag| is true, this is the initial layout after the
// user moved the mouse far enough to trigger a drag.
virtual void LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs,
BaseTab* active_tab,
const gfx::Point& location,
bool initial_drag) = 0;
// Calculates the bounds needed for each of the tabs, placing the result in
// |bounds|.
virtual void CalculateBoundsForDraggedTabs(
const std::vector<BaseTab*>& tabs,
std::vector<gfx::Rect>* bounds) = 0;
void set_ideal_bounds(int index, const gfx::Rect& bounds) {
tab_data_[index].ideal_bounds = bounds;
}
// Returns the index into |tab_data_| corresponding to the specified tab, or
// -1 if the tab isn't in |tab_data_|.
int TabIndexOfTab(BaseTab* tab) const;
// Stops any ongoing animations. If |layout| is true and an animation is
// ongoing this does a layout.
virtual void StopAnimating(bool layout);
// Destroys the active drag controller.
void DestroyDragController();
// Used by DraggedTabController when the user starts or stops dragging tabs.
void StartedDraggingTabs(const std::vector<BaseTab*>& tabs);
void StoppedDraggingTabs(const std::vector<BaseTab*>& tabs);
// Returns the size needed for the specified tabs. This is invoked during drag
// and drop to calculate offsets and positioning.
virtual int GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) = 0;
// See description above field for details.
bool attaching_dragged_tab() const { return attaching_dragged_tab_; }
views::BoundsAnimator& bounds_animator() { return bounds_animator_; }
// Invoked prior to starting a new animation.
virtual void PrepareForAnimation();
// Creates an AnimationDelegate that resets state after a remove animation
// completes. The caller owns the returned object.
ui::AnimationDelegate* CreateRemoveTabDelegate(BaseTab* tab);
// Invoked from Layout if the size changes or layout is really needed.
virtual void DoLayout();
// Returns true if Tabs in this TabStrip are currently changing size or
// position.
bool IsAnimating() const;
// Get tab at a point in local view coordinates.
BaseTab* GetTabAtLocal(const gfx::Point& local_point);
private:
class RemoveTabDelegate;
friend class DraggedTabController;
// Invoked from StoppedDraggingTabs to cleanup |tab|. If |tab| is known
// |is_first_tab| is set to true.
void StoppedDraggingTab(BaseTab* tab, bool* is_first_tab);
// See description above field for details.
void set_attaching_dragged_tab(bool value) { attaching_dragged_tab_ = value; }
scoped_ptr<TabStripController> controller_;
const Type type_;
std::vector<TabData> tab_data_;
// The controller for a drag initiated from a Tab. Valid for the lifetime of
// the drag session.
scoped_ptr<DraggedTabController> drag_controller_;
// If true, the insert is a result of a drag attaching the tab back to the
// model.
bool attaching_dragged_tab_;
views::BoundsAnimator bounds_animator_;
// Size we last layed out at.
gfx::Size last_layout_size_;
};
#endif // CHROME_BROWSER_UI_VIEWS_TABS_BASE_TAB_STRIP_H_