diff options
author | beng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-12 22:44:06 +0000 |
---|---|---|
committer | beng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-12 22:44:06 +0000 |
commit | 3146282c2250c51569d971234fbc9756b4d7a2d4 (patch) | |
tree | 0f9f418993163cd7a67955d10e89928b28787978 /chrome/browser/views/tabs/tab_strip.h | |
parent | 5db2a6ed0d09ef82cf84ba2677ecfcdff6192c79 (diff) | |
download | chromium_src-3146282c2250c51569d971234fbc9756b4d7a2d4.zip chromium_src-3146282c2250c51569d971234fbc9756b4d7a2d4.tar.gz chromium_src-3146282c2250c51569d971234fbc9756b4d7a2d4.tar.bz2 |
Move View components of the Browser's tab strip into the browser_views project, and into the views/ subdirectory on disk.
B=2198
Review URL: http://codereview.chromium.org/3020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2140 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/tabs/tab_strip.h')
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.h | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h new file mode 100644 index 0000000..656dd12 --- /dev/null +++ b/chrome/browser/views/tabs/tab_strip.h @@ -0,0 +1,373 @@ +// Copyright (c) 2006-2008 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_VIEWS_TABS_TAB_STRIP_H__ +#define CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H__ + +#include "base/gfx/point.h" +#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/views/tabs/tab.h" +#include "chrome/views/button.h" +#include "chrome/views/hwnd_view_container.h" +#include "chrome/views/menu.h" +#include "chrome/views/view.h" + +class DraggedTabController; +class ScopedMouseCloseWidthCalculator; +class TabStripModel; + +namespace ChromeViews { +class ImageView; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// TabStrip +// +// A View that represents the TabStripModel. The TabStrip has the +// following responsibilities: +// - It implements the TabStripModelObserver interface, and acts as a +// container for Tabs, and is also responsible for creating them. +// - It takes part in Tab Drag & Drop with Tab, TabDragHelper and +// DraggedTab, focusing on tasks that require reshuffling other tabs +// in response to dragged tabs. +// +/////////////////////////////////////////////////////////////////////////////// +class TabStrip : public ChromeViews::View, + public TabStripModelObserver, + public Tab::TabDelegate, + public ChromeViews::Button::ButtonListener, + public MessageLoopForUI::Observer { + public: + TabStrip(TabStripModel* model); + virtual ~TabStrip(); + + // Returns the preferred height of this TabStrip. This is based on the + // typical height of its constituent tabs. + int GetPreferredHeight(); + + // Returns true if the associated TabStrip's delegate supports tab moving or + // detaching. Used by the Frame to determine if dragging on the Tab + // itself should move the window in cases where there's only one + // non drag-able Tab. + bool HasAvailableDragActions() const; + + // Ask the delegate to show the application menu at the provided point. + // The point is in screen coordinate system. + void ShowApplicationMenu(const gfx::Point& p); + + // Returns true if the TabStrip can accept input events. This returns false + // when the TabStrip is animating to a new state and as such the user should + // not be allowed to interact with the TabStrip. + bool CanProcessInputEvents() const; + + // Returns true if the specified point (in TabStrip coordinates) is within a + // portion of the TabStrip that should be treated as the containing Window's + // titlebar for dragging purposes. + // TODO(beng): (Cleanup) should be const, but GetViewForPoint isn't, so fie! + bool PointIsWithinWindowCaption(const CPoint& point); + + // Return true if this tab strip is compatible with the provided tab strip. + // Compatible tab strips can transfer tabs during drag and drop. + bool IsCompatibleWith(TabStrip* other); + + // Returns true if Tabs in this TabStrip are currently changing size or + // position. + bool IsAnimating() const; + + // Accessors for the model and individual Tabs. + TabStripModel* model() { return model_; } + + // Returns true if there is an active drag session. + bool IsDragSessionActive() const { return drag_controller_.get() != NULL; } + + // Aborts any active drag session. This is called from XP/VistaFrame's + // end session handler to make sure there are no drag sessions in flight that + // could prevent the frame from being closed right away. + void AbortActiveDragSession() { EndDrag(true); } + + // Destroys the active drag controller. + void DestroyDragController(); + + // Removes the drag source Tab from this TabStrip, and deletes it. + void DestroyDraggedSourceTab(Tab* tab); + + // Retrieve the ideal bounds for the Tab at the specified index. + gfx::Rect GetIdealBounds(int index); + + // ChromeViews::View overrides: + virtual void PaintChildren(ChromeCanvas* canvas); + virtual void DidChangeBounds(const CRect& previous, const CRect& current); + virtual ChromeViews::View* GetViewByID(int id) const; + virtual void Layout(); + virtual void GetPreferredSize(CSize* preferred_size); + // NOTE: the drag and drop methods are invoked from FrameView. This is done to + // allow for a drop region that extends outside the bounds of the TabStrip. + virtual void OnDragEntered(const ChromeViews::DropTargetEvent& event); + virtual int OnDragUpdated(const ChromeViews::DropTargetEvent& event); + virtual void OnDragExited(); + virtual int OnPerformDrop(const ChromeViews::DropTargetEvent& event); + virtual bool GetAccessibleRole(VARIANT* role); + virtual bool GetAccessibleName(std::wstring* name); + virtual void SetAccessibleName(const std::wstring& name); + virtual ChromeViews::View* GetViewForPoint(const CPoint& point); + virtual ChromeViews::View* GetViewForPoint(const CPoint& point, + bool can_create_floating); + + protected: + // TabStripModelObserver implementation: + virtual void TabInsertedAt(TabContents* contents, + int index, + bool foreground); + virtual void TabDetachedAt(TabContents* contents, int index); + virtual void TabSelectedAt(TabContents* old_contents, + TabContents* contents, + int index, + bool user_gesture); + virtual void TabMoved(TabContents* contents, int from_index, int to_index); + virtual void TabChangedAt(TabContents* contents, int index); + virtual void TabValidateAnimations(); + + // Tab::Delegate implementation: + virtual bool IsTabSelected(const Tab* tab) const; + virtual void SelectTab(Tab* tab); + virtual void CloseTab(Tab* tab); + virtual bool IsCommandEnabledForTab( + TabStripModel::ContextMenuCommand command_id, const Tab* tab) const; + virtual void ExecuteCommandForTab( + TabStripModel::ContextMenuCommand command_id, Tab* tab); + virtual void StartHighlightTabsForCommand( + TabStripModel::ContextMenuCommand command_id, Tab* tab); + virtual void StopHighlightTabsForCommand( + TabStripModel::ContextMenuCommand command_id, Tab* tab); + virtual void StopAllHighlighting(); + virtual void MaybeStartDrag(Tab* tab, + const ChromeViews::MouseEvent& event); + virtual void ContinueDrag(const ChromeViews::MouseEvent& event); + virtual void EndDrag(bool canceled); + + // ChromeViews::Button::ButtonListener implementation: + virtual void ButtonPressed(ChromeViews::BaseButton* sender); + + // MessageLoop::Observer implementation: + virtual void WillProcessMessage(const MSG& msg); + virtual void DidProcessMessage(const MSG& msg); + + private: + friend class DraggedTabController; + friend class InsertTabAnimation; + friend class MoveTabAnimation; + friend class RemoveTabAnimation; + friend class ResizeLayoutAnimation; + friend class SuspendAnimationsTask; + friend class TabAnimation; + + TabStrip(); + void Init(); + + // Retrieves the Tab at the specified index. Take care in using this, you may + // need to use GetTabAtAdjustForAnimation. + Tab* GetTabAt(int index) const; + + // Returns the tab at the specified index. If a remove animation is on going + // and the index is >= the index of the tab being removed, the index is + // incremented. While a remove operation is on going the indices of the model + // do not line up with the indices of the view. This method adjusts the index + // accordingly. + // + // Use this instead of GetTabAt if the index comes from the model. + Tab* GetTabAtAdjustForAnimation(int index) const; + + // Gets the number of Tabs in the collection. + int GetTabCount() const; + + // -- Tab Resize Layout ----------------------------------------------------- + + // Returns the exact (unrounded) current width of each tab. + void GetCurrentTabWidths(double* unselected_width, + double* selected_width) const; + + // Returns the exact (unrounded) desired width of each tab, based on the + // desired strip width and number of tabs. If + // |width_of_tabs_for_mouse_close_| is nonnegative we use that value in + // calculating the desired strip width; otherwise we use the current width. + void GetDesiredTabWidths(int tab_count, + double* unselected_width, + double* selected_width) const; + + // Perform an animated resize-relayout of the TabStrip immediately. + void ResizeLayoutTabs(); + + // Returns whether or not the cursor is currently in the "tab strip zone" + // which is defined as the region above the TabStrip and a bit below it. + // Note: this method cannot be const because |ConvertPointToScreen| is not. + // #@*($&(#!!! + bool IsCursorInTabStripZone(); + + // Ensure that the message loop observer used for event spying is added and + // removed appropriately so we can tell when to resize layout the tab strip. + void AddMessageLoopObserver(); + void RemoveMessageLoopObserver(); + + // Called to update the frame of the Loading animations. + void LoadingAnimationCallback(); + + // -- Link Drag & Drop ------------------------------------------------------ + + // Returns the bounds to render the drop at, in screen coordinates. Sets + // |is_beneath| to indicate whether the arrow is beneath the tab, or above + // it. + gfx::Rect GetDropBounds(int drop_index, bool drop_before, bool* is_beneath); + + // Updates the location of the drop based on the event. + void UpdateDropIndex(const ChromeViews::DropTargetEvent& event); + + // Sets the location of the drop, repainting as necessary. + void SetDropIndex(int index, bool drop_before); + + // Returns the drop effect for dropping a URL on the tab strip. This does + // not query the data in anyway, it only looks at the source operations. + int GetDropEffect(const ChromeViews::DropTargetEvent& event); + + // Returns the image to use for indicating a drop on a tab. If is_down is + // true, this returns an arrow pointing down. + static SkBitmap* GetDropArrowImage(bool is_down); + + // -- Animations ------------------------------------------------------------ + + // Generates the ideal bounds of the TabStrip when all Tabs have finished + // animating to their desired position/bounds. This is used by the standard + // Layout method and other callers like the DraggedTabController that need + // stable representations of Tab positions. + void GenerateIdealBounds(); + + // Lays out the New Tab button, assuming the right edge of the last Tab on + // the TabStrip at |last_tab_right|. + void LayoutNewTabButton(double last_tab_right, double unselected_width); + + // A generic Layout method for various classes of TabStrip animations, + // including Insert, Remove and Resize Layout cases/ + void AnimationLayout(double unselected_width); + + // Starts various types of TabStrip animations. + void StartResizeLayoutAnimation(); + void StartInsertTabAnimation(int index); + void StartRemoveTabAnimation(int index, TabContents* contents); + void StartMoveTabAnimation(int from_index, int to_index); + + // Returns true if detach or select changes in the model should be reflected + // in the TabStrip. This returns false if we're closing all tabs in the + // TabStrip and so we should prevent updating. This is not const because we + // use this as a signal to cancel any active animations. + bool CanUpdateDisplay(); + + // Notifies the TabStrip that the specified TabAnimation has completed. + // Optionally a full Layout will be performed, specified by |layout|. + class TabAnimation; + void FinishAnimation(TabAnimation* animation, bool layout); + + // Finds the index of the TabContents corresponding to |tab| in our + // associated TabStripModel, or -1 if there is none (e.g. the specified |tab| + // is being animated closed). + int GetIndexOfTab(const Tab* tab) const; + + // Calculates the available width for tabs, assuming a Tab is to be closed. + int GetAvailableWidthForTabs(Tab* last_tab) const; + + // Returns true if the specified point in TabStrip coords is within the + // hit-test region of the specified Tab. + bool IsPointInTab(Tab* tab, const CPoint& point_in_tabstrip_coords); + + // -- Member Variables ------------------------------------------------------ + + // Our model. + TabStripModel* model_; + + // A factory that is used to construct a delayed callback to the + // ResizeLayoutTabsNow method. + ScopedRunnableMethodFactory<TabStrip> resize_layout_factory_; + + // True if the TabStrip has already been added as a MessageLoop observer. + bool added_as_message_loop_observer_; + + // True if a resize layout animation should be run a short delay after the + // mouse exits the TabStrip. + // TODO(beng): (Cleanup) this would be better named "needs_resize_layout_". + bool resize_layout_scheduled_; + + // The timer used to update frames for the Loading Animation. + base::RepeatingTimer<TabStrip> loading_animation_timer_; + + // The "New Tab" button. + ChromeViews::Button* newtab_button_; + gfx::Size newtab_button_size_; + gfx::Size actual_newtab_button_size_; + + // The current widths of various types of tabs. We save these so that, as + // users close tabs while we're holding them at the same size, we can lay out + // tabs exactly and eliminate the "pixel jitter" we'd get from just leaving + // them all at their existing, rounded widths. + double current_unselected_width_; + double current_selected_width_; + + // If this value is nonnegative, it is used in GetDesiredTabWidths() to + // calculate how much space in the tab strip to use for tabs. Most of the + // time this will be -1, but while we're handling closing a tab via the mouse, + // we'll set this to the edge of the last tab before closing, so that if we + // are closing the last tab and need to resize immediately, we'll resize only + // back to this width, thus once again placing the last tab under the mouse + // cursor. + int available_width_for_tabs_; + + // Storage of strings needed for accessibility. + std::wstring accessible_name_; + + // Used during a drop session of a url. Tracks the position of the drop as + // well as a window used to highlight where the drop occurs. + struct DropInfo { + DropInfo(int index, bool drop_before, bool paint_down); + ~DropInfo(); + + // Index of the tab to drop on. If drop_before is true, the drop should + // occur between the tab at drop_index - 1 and drop_index. + // WARNING: if drop_before is true it is possible this will == tab_count, + // which indicates the drop should create a new tab at the end of the tabs. + int drop_index; + bool drop_before; + + // Direction the arrow should point in. If true, the arrow is displayed + // above the tab and points down. If false, the arrow is displayed beneath + // the tab and points up. + bool point_down; + + // Renders the drop indicator. + ChromeViews::HWNDViewContainer* arrow_window; + ChromeViews::ImageView* arrow_view; + + private: + DISALLOW_EVIL_CONSTRUCTORS(DropInfo); + }; + + // Valid for the lifetime of a drag over us. + scoped_ptr<DropInfo> drop_info_; + + // The controller for a drag initiated from a Tab. Valid for the lifetime of + // the drag session. + scoped_ptr<DraggedTabController> drag_controller_; + + // The Tabs we contain, and their last generated "good" bounds. + struct TabData { + Tab* tab; + gfx::Rect ideal_bounds; + }; + std::vector<TabData> tab_data_; + + // The currently running animation. + scoped_ptr<TabAnimation> active_animation_; + + DISALLOW_EVIL_CONSTRUCTORS(TabStrip); +}; + +#endif // CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H__ + |