C++程序  |  276行  |  9.95 KB

// 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_