diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-24 20:58:36 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-24 20:58:36 +0000 |
commit | c242e46421bb2c71aaa39ac687279a204f5d7d3b (patch) | |
tree | 6f307bf4d7d53d3bc776758705d584213e35ebda /chrome/browser/views | |
parent | bb4bc30596a168f80f2c651971c23999690b9cae (diff) | |
download | chromium_src-c242e46421bb2c71aaa39ac687279a204f5d7d3b.zip chromium_src-c242e46421bb2c71aaa39ac687279a204f5d7d3b.tar.gz chromium_src-c242e46421bb2c71aaa39ac687279a204f5d7d3b.tar.bz2 |
More side tabs tweaks:
. gets dragging of side tabs to work.
. gets icons to render correctly.
. adds animation support.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/2100013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48080 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views')
-rw-r--r-- | chrome/browser/views/frame/browser_view_layout.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/frame/glass_browser_frame_view.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/frame/opaque_browser_frame_view.cc | 3 | ||||
-rw-r--r-- | chrome/browser/views/tabs/base_tab_strip.cc | 188 | ||||
-rw-r--r-- | chrome/browser/views/tabs/base_tab_strip.h | 31 | ||||
-rw-r--r-- | chrome/browser/views/tabs/dragged_tab_controller.cc | 200 | ||||
-rw-r--r-- | chrome/browser/views/tabs/dragged_tab_controller.h | 20 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab.cc | 100 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab.h | 6 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab_strip.cc | 67 | ||||
-rw-r--r-- | chrome/browser/views/tabs/side_tab_strip.h | 8 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.cc | 195 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.h | 19 |
13 files changed, 488 insertions, 355 deletions
diff --git a/chrome/browser/views/frame/browser_view_layout.cc b/chrome/browser/views/frame/browser_view_layout.cc index d0427d0..91c0646 100644 --- a/chrome/browser/views/frame/browser_view_layout.cc +++ b/chrome/browser/views/frame/browser_view_layout.cc @@ -32,7 +32,7 @@ const int kTabShadowSize = 2; const int kToolbarTabStripVerticalOverlap = 3; // The horizontal overlap between the SideTabStrip the other contents of the // BrowserView. -const int kBrowserViewTabStripHorizontalOverlap = 4; +const int kBrowserViewTabStripHorizontalOverlap = 2; // An offset distance between certain toolbars and the toolbar that preceded // them in layout. const int kSeparationLineHeight = 1; diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc index 6838a3e..2d48a06 100644 --- a/chrome/browser/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/views/frame/glass_browser_frame_view.cc @@ -80,8 +80,8 @@ gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip( BaseTabStrip* tabstrip) const { if (browser_view_->UseVerticalTabs()) { gfx::Size ps = tabstrip->GetPreferredSize(); - return gfx::Rect(0, NonClientTopBorderHeight(), ps.width(), - browser_view_->height()); + return gfx::Rect(NonClientBorderThickness(), NonClientTopBorderHeight(), + ps.width(), browser_view_->height()); } int minimize_button_offset = frame_->GetMinimizeButtonOffset(); int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc index 6380fda..497c220 100644 --- a/chrome/browser/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc @@ -200,7 +200,8 @@ gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( int y = CaptionButtonY() + minimize_button_->GetPreferredSize().height() + 2; gfx::Size ps = tabstrip->GetPreferredSize(); - return gfx::Rect(0, y, ps.width(), browser_view_->height()); + return gfx::Rect(NonClientBorderThickness(), y, ps.width(), + browser_view_->height()); } int tabstrip_y = NonClientTopBorderHeight(); diff --git a/chrome/browser/views/tabs/base_tab_strip.cc b/chrome/browser/views/tabs/base_tab_strip.cc index da59c28..8e3023f 100644 --- a/chrome/browser/views/tabs/base_tab_strip.cc +++ b/chrome/browser/views/tabs/base_tab_strip.cc @@ -10,10 +10,117 @@ #include "views/widget/root_view.h" #include "views/window/window.h" +#if defined(OS_WIN) +#include "app/win_util.h" +#include "views/widget/widget_win.h" +#endif + +namespace { + +// Animation delegate used when a dragged tab is released. When done sets the +// dragging state to false. +class ResetDraggingStateDelegate + : public views::BoundsAnimator::OwnedAnimationDelegate { + public: + explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { + } + + virtual void AnimationEnded(const Animation* animation) { + tab_->set_dragging(false); + } + + virtual void AnimationCanceled(const Animation* animation) { + tab_->set_dragging(false); + } + + private: + BaseTab* tab_; + + DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); +}; + +} // namespace + +// AnimationDelegate used when removing a tab. Does the necessary cleanup when +// done. +class BaseTabStrip::RemoveTabDelegate + : public views::BoundsAnimator::OwnedAnimationDelegate { + public: + RemoveTabDelegate(BaseTabStrip* tab_strip, BaseTab* tab) + : tabstrip_(tab_strip), + tab_(tab) { + } + + virtual void AnimationEnded(const Animation* animation) { + CompleteRemove(); + } + + virtual void AnimationCanceled(const Animation* animation) { + // We can be canceled for two interesting reasons: + // . The tab we reference was dragged back into the tab strip. In this case + // we don't want to remove the tab (closing is false). + // . The drag was completed before the animation completed + // (DestroyDraggedSourceTab). In this case we need to remove the tab + // (closing is true). + if (tab_->closing()) + CompleteRemove(); + } + + private: + void CompleteRemove() { + if (!tab_->closing()) { + // The tab was added back yet we weren't canceled. This shouldn't happen. + NOTREACHED(); + return; + } + tabstrip_->RemoveAndDeleteTab(tab_); + HighlightCloseButton(); + } + + // When the animation completes, we send the Container a message to simulate + // a mouse moved event at the current mouse position. This tickles the Tab + // the mouse is currently over to show the "hot" state of the close button. + void HighlightCloseButton() { + if (tabstrip_->IsDragSessionActive() || + !tabstrip_->ShouldHighlightCloseButtonAfterRemove()) { + // This function is not required (and indeed may crash!) for removes + // spawned by non-mouse closes and drag-detaches. + return; + } + +#if defined(OS_WIN) + views::Widget* widget = tabstrip_->GetWidget(); + // This can be null during shutdown. See http://crbug.com/42737. + if (!widget) + return; + // Force the close button (that slides under the mouse) to highlight by + // saying the mouse just moved, but sending the same coordinates. + DWORD pos = GetMessagePos(); + POINT cursor_point = {GET_X_LPARAM(pos), GET_Y_LPARAM(pos)}; + MapWindowPoints(NULL, widget->GetNativeView(), &cursor_point, 1); + + static_cast<views::WidgetWin*>(widget)->ResetLastMouseMoveFlag(); + // Return to message loop - otherwise we may disrupt some operation that's + // in progress. + SendMessage(widget->GetNativeView(), WM_MOUSEMOVE, 0, + MAKELPARAM(cursor_point.x, cursor_point.y)); +#else + NOTIMPLEMENTED(); +#endif + } + + BaseTabStrip* tabstrip_; + BaseTab* tab_; + + DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate); +}; + BaseTabStrip::BaseTabStrip(TabStripController* controller, Type type) : controller_(controller), type_(type), - attaching_dragged_tab_(false) { + attaching_dragged_tab_(false), + ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)) { + bounds_animator_.set_observer(this); } BaseTabStrip::~BaseTabStrip() { @@ -23,6 +130,10 @@ void BaseTabStrip::UpdateLoadingAnimations() { controller_->UpdateLoadingAnimations(); } +bool BaseTabStrip::IsAnimating() const { + return bounds_animator_.IsAnimating(); +} + BaseTab* BaseTabStrip::GetSelectedBaseTab() const { return GetBaseTabAtModelIndex(controller_->GetSelectedIndex()); } @@ -196,6 +307,31 @@ void BaseTabStrip::OnMouseReleased(const views::MouseEvent& event, EndDrag(canceled); } +void BaseTabStrip::StartRemoveTabAnimation(int model_index) { + PrepareForAnimation(); + + // Mark the tab as closing. + BaseTab* tab = GetBaseTabAtModelIndex(model_index); + tab->set_closing(true); + + // Start an animation for the tabs. + GenerateIdealBounds(); + AnimateToIdealBounds(); + + // Animate the tab being closed to 0x0. + gfx::Rect tab_bounds = tab->bounds(); + if (type() == HORIZONTAL_TAB_STRIP) + tab_bounds.set_width(0); + else + tab_bounds.set_height(0); + bounds_animator_.AnimateViewTo(tab, tab_bounds); + + // Register delegate to do cleanup when done, BoundsAnimator takes + // ownership of RemoveTabDelegate. + bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab), + true); +} + void BaseTabStrip::RemoveAndDeleteTab(BaseTab* tab) { int tab_data_index = TabIndexOfTab(tab); @@ -219,3 +355,53 @@ void BaseTabStrip::DestroyDragController() { if (IsDragSessionActive()) drag_controller_.reset(NULL); } + +void BaseTabStrip::StartedDraggingTab(BaseTab* tab) { + PrepareForAnimation(); + + // Reset the dragging state of all other tabs. We do this as the painting code + // only handles one tab being dragged at a time. If another tab is marked as + // dragging, it should also be closing. + for (int i = 0; i < tab_count(); ++i) + base_tab_at_tab_index(i)->set_dragging(false); + + tab->set_dragging(true); + + // Stop any animations on the tab. + bounds_animator_.StopAnimatingView(tab); + + // Move the tab to its ideal bounds. + GenerateIdealBounds(); + int tab_data_index = TabIndexOfTab(tab); + DCHECK(tab_data_index != -1); + tab->SetBounds(ideal_bounds(tab_data_index)); + SchedulePaint(); +} + +void BaseTabStrip::StoppedDraggingTab(BaseTab* tab) { + int tab_data_index = TabIndexOfTab(tab); + if (tab_data_index == -1) { + // The tab was removed before the drag completed. Don't do anything. + return; + } + + PrepareForAnimation(); + + // Animate the view back to its correct position. + GenerateIdealBounds(); + AnimateToIdealBounds(); + bounds_animator_.AnimateViewTo(tab, ideal_bounds(TabIndexOfTab(tab))); + + // Install a delegate to reset the dragging state when done. We have to leave + // dragging true for the tab otherwise it'll draw beneath the new tab button. + bounds_animator_.SetAnimationDelegate(tab, + new ResetDraggingStateDelegate(tab), + true); +} + +void BaseTabStrip::PrepareForAnimation() { + if (!IsDragSessionActive()) { + for (int i = 0; i < tab_count(); ++i) + base_tab_at_tab_index(i)->set_dragging(false); + } +} diff --git a/chrome/browser/views/tabs/base_tab_strip.h b/chrome/browser/views/tabs/base_tab_strip.h index c10a924..e30657c 100644 --- a/chrome/browser/views/tabs/base_tab_strip.h +++ b/chrome/browser/views/tabs/base_tab_strip.h @@ -10,6 +10,7 @@ #include "base/scoped_ptr.h" #include "chrome/browser/views/tabs/base_tab.h" #include "chrome/browser/views/tabs/tab_controller.h" +#include "views/animation/bounds_animator.h" #include "views/view.h" class BaseTab; @@ -20,6 +21,7 @@ class ThemeProvider; // Base class for the view tab strip implementations. class BaseTabStrip : public views::View, + public views::BoundsAnimatorObserver, public TabController { public: enum Type { @@ -54,7 +56,7 @@ class BaseTabStrip : public views::View, // Returns true if Tabs in this TabStrip are currently changing size or // position. - virtual bool IsAnimating() const = 0; + virtual bool IsAnimating() const; // Returns this object as a TabStrip if it is one. virtual TabStrip* AsTabStrip() = 0; @@ -154,6 +156,9 @@ class BaseTabStrip : public views::View, gfx::Rect ideal_bounds; }; + // BoundsAnimator::Observer overrides: + virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) {} + // View overrides. virtual bool OnMouseDragged(const views::MouseEvent& event); virtual void OnMouseReleased(const views::MouseEvent& event, @@ -170,6 +175,17 @@ class BaseTabStrip : public views::View, // move. virtual void StartMoveTabAnimation() = 0; + // Starts the remove tab animation. + virtual void StartRemoveTabAnimation(int model_index); + + // Returns whether the highlight button should be highlighted after a remove. + virtual bool ShouldHighlightCloseButtonAfterRemove() { return true; } + + // 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); @@ -193,13 +209,20 @@ class BaseTabStrip : public views::View, void DestroyDragController(); // Used by DraggedTabController when the user starts or stops dragging a tab. - virtual void StartedDraggingTab(BaseTab* tab) = 0; - virtual void StoppedDraggingTab(BaseTab* tab) = 0; + void StartedDraggingTab(BaseTab* tab); + void StoppedDraggingTab(BaseTab* tab); // 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(); + private: + class RemoveTabDelegate; + friend class DraggedTabController; // See description above field for details. @@ -218,6 +241,8 @@ class BaseTabStrip : public views::View, // 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_; }; #endif // CHROME_BROWSER_VIEWS_TABS_BASE_TAB_STRIP_H_ diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index e09abe0..bb97cd6 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -25,6 +25,8 @@ #include "chrome/browser/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/views/tabs/dragged_tab_view.h" #include "chrome/browser/views/tabs/native_view_photobooth.h" +#include "chrome/browser/views/tabs/side_tab.h" +#include "chrome/browser/views/tabs/side_tab_strip.h" #include "chrome/browser/views/tabs/tab.h" #include "chrome/browser/views/tabs/tab_strip.h" #include "chrome/common/notification_service.h" @@ -47,6 +49,10 @@ static const int kHorizontalMoveThreshold = 16; // Pixels. +// Distance in pixels the user must move the mouse before we consider moving +// an attached vertical tab. +static const int kVerticalMoveThreshold = 8; + namespace { // Delay, in ms, during dragging before we bring a window to front. @@ -188,6 +194,13 @@ gfx::Point ConvertScreenPointToTabStripPoint(BaseTabStrip* tabstrip, screen_point.y() - tabstrip_topleft.y()); } +// Returns the the x-coordinate of |point| if the type of tabstrip is horizontal +// otherwise returns the y-coordinate. +int MajorAxisValue(const gfx::Point& point, BaseTabStrip* tabstrip) { + return (tabstrip->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) ? + point.x() : point.y(); +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -324,7 +337,7 @@ DraggedTabController::DraggedTabController(BaseTab* source_tab, offset_to_width_ratio_(0), old_focused_view_(NULL), in_destructor_(false), - last_move_screen_x_(0), + last_move_screen_loc_(0), mini_(source_tab->data().mini), pinned_(source_tabstrip->IsTabPinned(source_tab)), started_drag_(false) { @@ -532,6 +545,15 @@ gfx::Point DraggedTabController::GetWindowCreatePoint() const { void DraggedTabController::UpdateDockInfo(const gfx::Point& screen_point) { // Update the DockInfo for the current mouse coordinates. DockInfo dock_info = GetDockInfoAtPoint(screen_point); + if (source_tabstrip_->type() == BaseTabStrip::VERTICAL_TAB_STRIP && + ((dock_info.type() == DockInfo::LEFT_OF_WINDOW && + !base::i18n::IsRTL()) || + (dock_info.type() == DockInfo::RIGHT_OF_WINDOW && + base::i18n::IsRTL()))) { + // For side tabs it's way to easy to trigger to docking along the left/right + // edge, so we disable it. + dock_info = DockInfo(); + } if (!dock_info.equals(dock_info_)) { // DockInfo for current position differs. if (dock_info_.type() != DockInfo::NONE && @@ -658,55 +680,40 @@ void DraggedTabController::MoveAttachedTab(const gfx::Point& screen_point) { TabStripModel* attached_model = GetModel(attached_tabstrip_); int from_index = attached_model->GetIndexOfTabContents(dragged_contents_); + int threshold = kVerticalMoveThreshold; if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - MoveAttachedTabHorizontalTabStrip(screen_point, attached_model, - dragged_view_point, from_index); - } else { - MoveAttachedTabVerticalTabStrip(screen_point, attached_model, - dragged_view_point, from_index); + TabStrip* tab_strip = static_cast<TabStrip*>(attached_tabstrip_); + + // Determine the horizontal move threshold. This is dependent on the width + // of tabs. The smaller the tabs compared to the standard size, the smaller + // the threshold. + double unselected, selected; + tab_strip->GetCurrentTabWidths(&unselected, &selected); + double ratio = unselected / Tab::GetStandardSize().width(); + threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); } - attached_tab_->SchedulePaint(); - attached_tab_->SetX(dragged_view_point.x()); - attached_tab_->SetY(dragged_view_point.y()); - attached_tab_->SchedulePaint(); -} - -void DraggedTabController::MoveAttachedTabHorizontalTabStrip( - const gfx::Point& screen_point, - TabStripModel* model, - const gfx::Point& dragged_view_point, - int from_index) { - TabStrip* tab_strip = static_cast<TabStrip*>(attached_tabstrip_); - // Determine the horizontal move threshold. This is dependent on the width - // of tabs. The smaller the tabs compared to the standard size, the smaller - // the threshold. - double unselected, selected; - tab_strip->GetCurrentTabWidths(&unselected, &selected); - double ratio = unselected / Tab::GetStandardSize().width(); - int threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); // Update the model, moving the TabContents from one index to another. Do this // only if we have moved a minimum distance since the last reorder (to prevent // jitter). - if (abs(screen_point.x() - last_move_screen_x_) > threshold) { + if (abs(MajorAxisValue(screen_point, attached_tabstrip_) - + last_move_screen_loc_) > threshold) { gfx::Point dragged_view_screen_point(dragged_view_point); - views::View::ConvertPointToScreen(tab_strip, &dragged_view_screen_point); + views::View::ConvertPointToScreen(attached_tabstrip_, + &dragged_view_screen_point); gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_screen_point); int to_index = GetInsertionIndexForDraggedBounds(bounds, true); to_index = NormalizeIndexToAttachedTabStrip(to_index); if (from_index != to_index) { - last_move_screen_x_ = screen_point.x(); - model->MoveTabContentsAt(from_index, to_index, true); + last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip_); + attached_model->MoveTabContentsAt(from_index, to_index, true); } } -} -void DraggedTabController::MoveAttachedTabVerticalTabStrip( - const gfx::Point& screen_point, - TabStripModel* model, - const gfx::Point& dragged_view_point, - int from_index) { - // TODO(sky): implement me. + attached_tab_->SchedulePaint(); + attached_tab_->SetX(dragged_view_point.x()); + attached_tab_->SetY(dragged_view_point.y()); + attached_tab_->SchedulePaint(); } void DraggedTabController::MoveDetachedTab(const gfx::Point& screen_point) { @@ -769,20 +776,33 @@ BaseTabStrip* DraggedTabController::GetTabStripForPoint( BaseTabStrip* DraggedTabController::GetTabStripIfItContains( BaseTabStrip* tabstrip, const gfx::Point& screen_point) const { - // TODO(sky): this likely needs to be adjusted for vertical tabs. static const int kVerticalDetachMagnetism = 15; + static const int kHorizontalDetachMagnetism = 15; // Make sure the specified screen point is actually within the bounds of the // specified tabstrip... gfx::Rect tabstrip_bounds = GetViewScreenBounds(tabstrip); - if (screen_point.x() < tabstrip_bounds.right() && - screen_point.x() >= tabstrip_bounds.x()) { - // TODO(beng): make this be relative to the start position of the mouse for - // the source TabStrip. - int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism; - int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism; - if (screen_point.y() >= lower_threshold && - screen_point.y() <= upper_threshold) { - return tabstrip; + if (tabstrip->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { + if (screen_point.x() < tabstrip_bounds.right() && + screen_point.x() >= tabstrip_bounds.x()) { + // TODO(beng): make this be relative to the start position of the mouse + // for the source TabStrip. + int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism; + int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism; + if (screen_point.y() >= lower_threshold && + screen_point.y() <= upper_threshold) { + return tabstrip; + } + } + } else { + if (screen_point.y() < tabstrip_bounds.bottom() && + screen_point.y() >= tabstrip_bounds.y()) { + int upper_threshold = tabstrip_bounds.right() + + kHorizontalDetachMagnetism; + int lower_threshold = tabstrip_bounds.x() - kHorizontalDetachMagnetism; + if (screen_point.x() >= lower_threshold && + screen_point.x() <= upper_threshold) { + return tabstrip; + } } } return NULL; @@ -818,7 +838,7 @@ void DraggedTabController::Attach(BaseTabStrip* attached_tabstrip, // Inserting counts as a move. We don't want the tabs to jitter when the // user moves the tab immediately after attaching it. - last_move_screen_x_ = screen_point.x(); + last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip); // Figure out where to insert the tab based on the bounds of the dragged // representation and the ideal bounds of the other Tabs already in the @@ -837,11 +857,12 @@ void DraggedTabController::Attach(BaseTabStrip* attached_tabstrip, attached_tab_ = tab; attached_tabstrip_->StartedDraggingTab(tab); - // TODO(sky): this needs to adjust based on orientation of the tab strip. - // The size of the dragged tab may have changed. Adjust the x offset so that - // ratio of mouse_offset_ to original width is maintained. - mouse_offset_.set_x(static_cast<int>(offset_to_width_ratio_ * - static_cast<int>(tab->width()))); + if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { + // The size of the dragged tab may have changed. Adjust the x offset so that + // ratio of mouse_offset_ to original width is maintained. + mouse_offset_.set_x(static_cast<int>(offset_to_width_ratio_ * + static_cast<int>(tab->width()))); + } // Move the corresponding window to the front. attached_tabstrip_->GetWindow()->Activate(); @@ -857,6 +878,8 @@ void DraggedTabController::Detach() { TabStripModel* attached_model = GetModel(attached_tabstrip_); int index = attached_model->GetIndexOfTabContents(dragged_contents_); DCHECK(index != -1); + // Hide the tab so that the user doesn't see it animate closed. + attached_tab_->SetVisible(false); attached_model->DetachTabContentsAt(index); // If we've removed the last Tab from the TabStrip, hide the frame now. @@ -885,8 +908,8 @@ void DraggedTabController::Detach() { int DraggedTabController::GetInsertionIndexForDraggedBounds( const gfx::Rect& dragged_bounds, bool is_tab_attached) const { - // TODO(sky): this needs to adjust based on orientation of the tab strip. int right_tab_x = 0; + int bottom_tab_y = 0; // If the UI layout of the tab strip is right-to-left, we need to mirror the // bounds of the dragged tab before performing the drag/drop related @@ -904,27 +927,45 @@ int DraggedTabController::GetInsertionIndexForDraggedBounds( int index = -1; for (int i = 0; i < attached_tabstrip_->tab_count(); ++i) { const gfx::Rect& ideal_bounds = attached_tabstrip_->ideal_bounds(i); - gfx::Rect left_half = ideal_bounds; - left_half.set_width(left_half.width() / 2); - gfx::Rect right_half = ideal_bounds; - right_half.set_width(ideal_bounds.width() - left_half.width()); - right_half.set_x(left_half.right()); - right_tab_x = right_half.right(); - if (adjusted_bounds.x() >= right_half.x() && - adjusted_bounds.x() < right_half.right()) { - index = i + 1; - break; - } else if (adjusted_bounds.x() >= left_half.x() && - adjusted_bounds.x() < left_half.right()) { - index = i; - break; + if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { + gfx::Rect left_half = ideal_bounds; + left_half.set_width(left_half.width() / 2); + gfx::Rect right_half = ideal_bounds; + right_half.set_width(ideal_bounds.width() - left_half.width()); + right_half.set_x(left_half.right()); + right_tab_x = right_half.right(); + if (adjusted_bounds.x() >= right_half.x() && + adjusted_bounds.x() < right_half.right()) { + index = i + 1; + break; + } else if (adjusted_bounds.x() >= left_half.x() && + adjusted_bounds.x() < left_half.right()) { + index = i; + break; + } + } else { + // Vertical tab strip. + int max_y = ideal_bounds.bottom(); + int mid_y = ideal_bounds.y() + ideal_bounds.height() / 2; + bottom_tab_y = max_y; + if (adjusted_bounds.y() < mid_y) { + index = i; + break; + } else if (adjusted_bounds.y() >= mid_y && adjusted_bounds.y() < max_y) { + index = i + 1; + break; + } } } if (index == -1) { - if (adjusted_bounds.right() > right_tab_x) + if ((attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP && + adjusted_bounds.right() > right_tab_x) || + (attached_tabstrip_->type() == BaseTabStrip::VERTICAL_TAB_STRIP && + adjusted_bounds.y() >= bottom_tab_y)) { index = GetModel(attached_tabstrip_)->count(); - else + } else { index = 0; + } } index = GetModel(attached_tabstrip_)->ConstrainInsertionIndex(index, mini_); @@ -939,12 +980,13 @@ gfx::Rect DraggedTabController::GetDraggedViewTabStripBounds( const gfx::Point& screen_point) { gfx::Point client_point = ConvertScreenPointToTabStripPoint(attached_tabstrip_, screen_point); + // attached_tab_ is NULL when inserting into a new tabstrip. if (attached_tab_) { return gfx::Rect(client_point.x(), client_point.y(), attached_tab_->width(), attached_tab_->height()); } + if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - // attached_tab_ is NULL when inserting into a new tabstrip. double sel_width, unselected_width; static_cast<TabStrip*>(attached_tabstrip_)->GetCurrentTabWidths( &sel_width, &unselected_width); @@ -952,9 +994,10 @@ gfx::Rect DraggedTabController::GetDraggedViewTabStripBounds( static_cast<int>(sel_width), Tab::GetStandardSize().height()); } - // TODO(sky): this needs to adjust based on orientation of the tab strip. + return gfx::Rect(client_point.x(), client_point.y(), - 0, Tab::GetStandardSize().height()); + attached_tabstrip_->width(), + SideTab::GetPreferredHeight()); } gfx::Point DraggedTabController::GetAttachedTabDragPoint( @@ -972,10 +1015,15 @@ gfx::Point DraggedTabController::GetAttachedTabDragPoint( const gfx::Size& tab_size = attached_tab_->bounds().size(); - int max_x = attached_tabstrip_->bounds().right() - tab_size.width(); - // TODO(sky): this needs to adjust based on orientation of the tab strip. - x = std::min(std::max(x, 0), max_x); - y = 0; + if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { + int max_x = attached_tabstrip_->bounds().right() - tab_size.width(); + x = std::min(std::max(x, 0), max_x); + y = 0; + } else { + x = SideTabStrip::kTabStripInset; + int max_y = attached_tabstrip_->bounds().bottom() - tab_size.height(); + y = std::min(std::max(y, SideTabStrip::kTabStripInset), max_y); + } return gfx::Point(x, y); } diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h index c1e62df..280c3af 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.h +++ b/chrome/browser/views/tabs/dragged_tab_controller.h @@ -153,20 +153,6 @@ class DraggedTabController : public TabContentsDelegate, // Handles dragging a tab while the tab is attached. void MoveAttachedTab(const gfx::Point& screen_point); - // Adjusts the model as necessary for a move when the attached tab strip is - // horizontal. - void MoveAttachedTabHorizontalTabStrip(const gfx::Point& screen_point, - TabStripModel* model, - const gfx::Point& dragged_view_point, - int from_index); - - // Adjusts the model as necessary for a move when the attached tab strip is - // vertical. - void MoveAttachedTabVerticalTabStrip(const gfx::Point& screen_point, - TabStripModel* model, - const gfx::Point& dragged_view_point, - int from_index); - // Handles dragging while the tab is detached. void MoveDetachedTab(const gfx::Point& screen_point); @@ -313,9 +299,9 @@ class DraggedTabController : public TabContentsDelegate, bool in_destructor_; - // The horizontal position of the mouse cursor in screen coordinates at the - // time of the last re-order event. - int last_move_screen_x_; + // The position along the major axis of the mouse cursor in screen coordinates + // at the time of the last re-order event. + int last_move_screen_loc_; DockInfo dock_info_; diff --git a/chrome/browser/views/tabs/side_tab.cc b/chrome/browser/views/tabs/side_tab.cc index 58da29d..d456a5d 100644 --- a/chrome/browser/views/tabs/side_tab.cc +++ b/chrome/browser/views/tabs/side_tab.cc @@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/utf_string_conversions.h" #include "gfx/canvas.h" +#include "gfx/favicon_size.h" #include "gfx/path.h" #include "gfx/skia_util.h" #include "grit/app_resources.h" @@ -17,12 +18,15 @@ namespace { const int kVerticalTabHeight = 27; -const int kIconSize = 16; -const int kIconTitleSpacing = 4; const int kTitleCloseSpacing = 4; -const SkScalar kRoundRectRadius = 5; +const SkScalar kRoundRectRadius = 4; const SkColor kTabBackgroundColor = SK_ColorWHITE; -const SkAlpha kBackgroundTabAlpha = 170; + +// Padding between the edge and the icon. +const int kIconLeftPadding = 5; + +// Location the title starts at. +const int kTitleX = kIconLeftPadding + kFavIconSize + 5; }; //////////////////////////////////////////////////////////////////////////////// @@ -35,83 +39,67 @@ SideTab::SideTab(TabController* controller) SideTab::~SideTab() { } +// static +int SideTab::GetPreferredHeight() { + return 27; +} + //////////////////////////////////////////////////////////////////////////////// // SideTab, views::View overrides: void SideTab::Layout() { - int icon_y; - int icon_x = icon_y = (height() - kIconSize) / 2; - // TODO(sky): big mini icons. - icon_bounds_.SetRect(icon_x, icon_y, kIconSize, kIconSize); + if (ShouldShowIcon()) { + int icon_x = kIconLeftPadding; + int icon_y = (height() - kFavIconSize) / 2; + int icon_size = + !data().favicon.empty() ? data().favicon.width() : kFavIconSize; + if (icon_size != kFavIconSize) { + icon_x -= (icon_size - kFavIconSize) / 2; + icon_y -= (icon_size - kFavIconSize) / 2; + } + icon_bounds_.SetRect(icon_x, icon_y, icon_size, icon_size); + } else { + icon_bounds_ = gfx::Rect(); + } gfx::Size ps = close_button()->GetPreferredSize(); int close_y = (height() - ps.height()) / 2; close_button()->SetBounds( - std::max(0, width() - ps.width() - close_y), + std::max(0, width() - ps.width() - + (GetPreferredHeight() - ps.height()) / 2), close_y, ps.width(), ps.height()); int title_y = (height() - font_height()) / 2; - int title_x = icon_bounds_.right() + kIconTitleSpacing; title_bounds_.SetRect( - title_x, + kTitleX, title_y, - std::max(0, close_button()->x() - kTitleCloseSpacing - title_x), + std::max(0, close_button()->x() - kTitleCloseSpacing - kTitleX), font_height()); } void SideTab::Paint(gfx::Canvas* canvas) { - SkPaint paint; - paint.setColor(kTabBackgroundColor); - paint.setAntiAlias(true); - gfx::Path tab_shape; - FillTabShapePath(&tab_shape); - canvas->drawPath(tab_shape, paint); - - PaintIcon(canvas, icon_bounds_.x(), icon_bounds_.y()); - PaintTitle(canvas, SK_ColorBLACK); - - if (!IsSelected() && GetThemeProvider()->ShouldUseNativeFrame()) { - // Make sure un-selected tabs are somewhat transparent. + if (IsSelected() || !controller()) { SkPaint paint; - - SkAlpha opacity = kBackgroundTabAlpha; - if (hover_animation() && hover_animation()->is_animating()) { - opacity = - static_cast<SkAlpha>(hover_animation()->GetCurrentValue() * 255); - } - - paint.setColor(SkColorSetARGB(kBackgroundTabAlpha, 255, 255, 255)); - paint.setXfermodeMode(SkXfermode::kDstIn_Mode); - paint.setStyle(SkPaint::kFill_Style); + paint.setColor(kTabBackgroundColor); paint.setAntiAlias(true); - canvas->FillRectInt(0, 0, width(), height(), paint); + SkRect border_rect = { SkIntToScalar(0), SkIntToScalar(0), + SkIntToScalar(width()), SkIntToScalar(height()) }; + canvas->drawRoundRect(border_rect, SkIntToScalar(kRoundRectRadius), + SkIntToScalar(kRoundRectRadius), paint); } + + if (ShouldShowIcon()) + PaintIcon(canvas, icon_bounds_.x(), icon_bounds_.y()); + + PaintTitle(canvas, SK_ColorBLACK); } gfx::Size SideTab::GetPreferredSize() { - return gfx::Size(0, 27); + return gfx::Size(0, GetPreferredHeight()); } -//////////////////////////////////////////////////////////////////////////////// -// SideTab, private: - -#define CUBIC_ARC_FACTOR ((SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3) - -void SideTab::FillTabShapePath(gfx::Path* path) { - SkScalar s = SkScalarMul(kRoundRectRadius, CUBIC_ARC_FACTOR); - path->moveTo(SkIntToScalar(kRoundRectRadius), 0); - path->cubicTo(SkIntToScalar(kRoundRectRadius) - s, 0, 0, - SkIntToScalar(kRoundRectRadius) - s, 0, - SkIntToScalar(kRoundRectRadius)); - path->lineTo(0, SkIntToScalar(height() - kRoundRectRadius)); - path->cubicTo(0, SkIntToScalar(height() - kRoundRectRadius) + s, - SkIntToScalar(kRoundRectRadius) - s, SkIntToScalar(height()), - SkIntToScalar(kRoundRectRadius), - SkIntToScalar(height())); - path->lineTo(SkIntToScalar(width()), SkIntToScalar(height())); - path->lineTo(SkIntToScalar(width()), 0); - path->lineTo(SkIntToScalar(kRoundRectRadius), 0); - path->close(); +bool SideTab::ShouldShowIcon() const { + return data().mini || data().show_icon; } diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h index 48918e2..d3b4236 100644 --- a/chrome/browser/views/tabs/side_tab.h +++ b/chrome/browser/views/tabs/side_tab.h @@ -17,6 +17,9 @@ class SideTab : public BaseTab { explicit SideTab(TabController* controller); virtual ~SideTab(); + // Returns the preferred height of side tabs. + static int GetPreferredHeight(); + // views::View Overrides: virtual void Layout(); virtual void Paint(gfx::Canvas* canvas); @@ -26,7 +29,8 @@ class SideTab : public BaseTab { virtual const gfx::Rect& title_bounds() const { return title_bounds_; } private: - void FillTabShapePath(gfx::Path* path); + // Returns true if the icon should be shown. + bool ShouldShowIcon() const; gfx::Rect icon_bounds_; gfx::Rect title_bounds_; diff --git a/chrome/browser/views/tabs/side_tab_strip.cc b/chrome/browser/views/tabs/side_tab_strip.cc index 216d103..ee779c5 100644 --- a/chrome/browser/views/tabs/side_tab_strip.cc +++ b/chrome/browser/views/tabs/side_tab_strip.cc @@ -6,19 +6,24 @@ #include "chrome/browser/views/tabs/side_tab.h" #include "chrome/browser/view_ids.h" +#include "views/background.h" namespace { const int kVerticalTabSpacing = 2; const int kTabStripWidth = 140; -const int kTabStripInset = 3; +const SkColor kBackgroundColor = SkColorSetARGB(255, 209, 220, 248); } +// static +const int SideTabStrip::kTabStripInset = 3; + //////////////////////////////////////////////////////////////////////////////// // SideTabStrip, public: SideTabStrip::SideTabStrip(TabStripController* controller) : BaseTabStrip(controller, BaseTabStrip::VERTICAL_TAB_STRIP) { SetID(VIEW_ID_TAB_STRIP); + set_background(views::Background::CreateSolidBackground(kBackgroundColor)); } SideTabStrip::~SideTabStrip() { @@ -43,10 +48,6 @@ void SideTabStrip::SetDraggedTabBounds(int tab_index, const gfx::Rect& tab_bounds) { } -bool SideTabStrip::IsAnimating() const { - return false; -} - TabStrip* SideTabStrip::AsTabStrip() { return NULL; } @@ -66,8 +67,7 @@ BaseTab* SideTabStrip::CreateTabForDragging() { } void SideTabStrip::RemoveTabAt(int model_index, bool initiated_close) { - RemoveAndDeleteTab(GetBaseTabAtModelIndex(model_index)); - Layout(); + StartRemoveTabAnimation(model_index); } void SideTabStrip::SelectTabAt(int old_model_index, int new_model_index) { @@ -87,6 +87,22 @@ gfx::Size SideTabStrip::GetPreferredSize() { return gfx::Size(kTabStripWidth, 0); } +void SideTabStrip::PaintChildren(gfx::Canvas* canvas) { + // Make sure the dragged tab appears on top of all others by paint it last. + BaseTab* dragging_tab = NULL; + + for (int i = tab_count() - 1; i >= 0; --i) { + BaseTab* tab = base_tab_at_tab_index(i); + if (tab->dragging()) + dragging_tab = tab; + else + tab->ProcessPaint(canvas); + } + + if (dragging_tab) + dragging_tab->ProcessPaint(canvas); +} + BaseTab* SideTabStrip::CreateTab() { return new SideTab(this); } @@ -108,12 +124,45 @@ void SideTabStrip::GenerateIdealBounds() { } void SideTabStrip::StartInsertTabAnimation(int model_index, bool foreground) { - Layout(); + PrepareForAnimation(); + + GenerateIdealBounds(); + + int tab_data_index = ModelIndexToTabIndex(model_index); + BaseTab* tab = base_tab_at_tab_index(tab_data_index); + if (model_index == 0) { + tab->SetBounds(ideal_bounds(tab_data_index).x(), 0, + ideal_bounds(tab_data_index).width(), 0); + } else { + BaseTab* last_tab = base_tab_at_tab_index(tab_data_index - 1); + tab->SetBounds(last_tab->x(), last_tab->bounds().bottom(), + ideal_bounds(tab_data_index).width(), 0); + } + + AnimateToIdealBounds(); } void SideTabStrip::StartMoveTabAnimation() { - Layout(); + PrepareForAnimation(); + + GenerateIdealBounds(); + AnimateToIdealBounds(); } void SideTabStrip::StopAnimating(bool layout) { + if (!IsAnimating()) + return; + + bounds_animator().Cancel(); + + if (layout) + Layout(); +} + +void SideTabStrip::AnimateToIdealBounds() { + for (int i = 0; i < tab_count(); ++i) { + BaseTab* tab = base_tab_at_tab_index(i); + if (!tab->closing() && !tab->dragging()) + bounds_animator().AnimateViewTo(tab, ideal_bounds(i)); + } } diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h index fb23a4f..d958674 100644 --- a/chrome/browser/views/tabs/side_tab_strip.h +++ b/chrome/browser/views/tabs/side_tab_strip.h @@ -11,6 +11,9 @@ struct TabRendererData; class SideTabStrip : public BaseTabStrip { public: + // The tabs are inset by this much along all axis. + static const int kTabStripInset; + explicit SideTabStrip(TabStripController* controller); virtual ~SideTabStrip(); @@ -20,7 +23,6 @@ class SideTabStrip : public BaseTabStrip { virtual bool IsPositionInWindowCaption(const gfx::Point& point); virtual void SetDraggedTabBounds(int tab_index, const gfx::Rect& tab_bounds); - virtual bool IsAnimating() const; virtual TabStrip* AsTabStrip(); virtual void StartHighlight(int model_index); @@ -33,6 +35,7 @@ class SideTabStrip : public BaseTabStrip { // views::View overrides: virtual gfx::Size GetPreferredSize(); + virtual void PaintChildren(gfx::Canvas* canvas); protected: // BaseTabStrip overrides: @@ -41,8 +44,7 @@ class SideTabStrip : public BaseTabStrip { virtual void StartInsertTabAnimation(int model_index, bool foreground); virtual void StartMoveTabAnimation(); virtual void StopAnimating(bool layout); - virtual void StartedDraggingTab(BaseTab* tab) {} - virtual void StoppedDraggingTab(BaseTab* tab) {} + virtual void AnimateToIdealBounds(); private: DISALLOW_COPY_AND_ASSIGN(SideTabStrip); diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index 2c1af2a..fbd860e 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -105,28 +105,6 @@ class NewTabAlphaDelegate DISALLOW_COPY_AND_ASSIGN(NewTabAlphaDelegate); }; -// Animation delegate used when a dragged tab is released. When done sets the -// dragging state to false. -class ResetDraggingStateDelegate - : public views::BoundsAnimator::OwnedAnimationDelegate { - public: - explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { - } - - virtual void AnimationEnded(const Animation* animation) { - tab_->set_dragging(false); - } - - virtual void AnimationCanceled(const Animation* animation) { - tab_->set_dragging(false); - } - - private: - BaseTab* tab_; - - DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); -}; - /////////////////////////////////////////////////////////////////////////////// // NewTabButton // @@ -172,80 +150,6 @@ class NewTabButton : public views::ImageButton { } // namespace -// AnimationDelegate used when removing a tab. Does the necessary cleanup when -// done. -class TabStrip::RemoveTabDelegate - : public views::BoundsAnimator::OwnedAnimationDelegate { - public: - RemoveTabDelegate(TabStrip* tab_strip, Tab* tab) - : tabstrip_(tab_strip), - tab_(tab) { - } - - virtual void AnimationEnded(const Animation* animation) { - CompleteRemove(); - } - - virtual void AnimationCanceled(const Animation* animation) { - // We can be canceled for two interesting reasons: - // . The tab we reference was dragged back into the tab strip. In this case - // we don't want to remove the tab (closing is false). - // . The drag was completed before the animation completed - // (DestroyDraggedSourceTab). In this case we need to remove the tab - // (closing is true). - if (tab_->closing()) - CompleteRemove(); - } - - private: - void CompleteRemove() { - if (!tab_->closing()) { - // The tab was added back yet we weren't canceled. This shouldn't happen. - NOTREACHED(); - return; - } - tabstrip_->RemoveAndDeleteTab(tab_); - HighlightCloseButton(); - } - - // When the animation completes, we send the Container a message to simulate - // a mouse moved event at the current mouse position. This tickles the Tab - // the mouse is currently over to show the "hot" state of the close button. - void HighlightCloseButton() { - if (tabstrip_->available_width_for_tabs_ == -1 || - tabstrip_->IsDragSessionActive()) { - // This function is not required (and indeed may crash!) for removes - // spawned by non-mouse closes and drag-detaches. - return; - } - -#if defined(OS_WIN) - views::Widget* widget = tabstrip_->GetWidget(); - // This can be null during shutdown. See http://crbug.com/42737. - if (!widget) - return; - // Force the close button (that slides under the mouse) to highlight by - // saying the mouse just moved, but sending the same coordinates. - DWORD pos = GetMessagePos(); - POINT cursor_point = {GET_X_LPARAM(pos), GET_Y_LPARAM(pos)}; - MapWindowPoints(NULL, widget->GetNativeView(), &cursor_point, 1); - - static_cast<views::WidgetWin*>(widget)->ResetLastMouseMoveFlag(); - // Return to message loop - otherwise we may disrupt some operation that's - // in progress. - SendMessage(widget->GetNativeView(), WM_MOUSEMOVE, 0, - MAKELPARAM(cursor_point.x, cursor_point.y)); -#else - NOTIMPLEMENTED(); -#endif - } - - TabStrip* tabstrip_; - Tab* tab_; - - DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate); -}; - /////////////////////////////////////////////////////////////////////////////// // TabStrip, public: @@ -264,7 +168,6 @@ TabStrip::TabStrip(TabStripController* controller) current_selected_width_(Tab::GetStandardSize().width()), available_width_for_tabs_(-1), animation_container_(new AnimationContainer()), - ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)), animation_type_(ANIMATION_DEFAULT), new_tab_button_enabled_(true), cancelling_animation_(false) { @@ -343,7 +246,7 @@ void TabStrip::SetDraggedTabBounds(int tab_index, const gfx::Rect& tab_bounds) { } bool TabStrip::IsAnimating() const { - return bounds_animator_.IsAnimating() || new_tab_timer_.IsRunning(); + return BaseTabStrip::IsAnimating() || new_tab_timer_.IsRunning(); } TabStrip* TabStrip::AsTabStrip() { @@ -659,44 +562,31 @@ void TabStrip::StartInsertTabAnimation(int model_index, bool foreground) { } void TabStrip::StartMoveTabAnimation() { - ResetAnimationState(true); + PrepareForAnimation(); GenerateIdealBounds(); AnimateToIdealBounds(); } -void TabStrip::StartedDraggingTab(BaseTab* tab) { - tab->set_dragging(true); - - // Stop any animations on the tab. - bounds_animator_.StopAnimatingView(tab); +void TabStrip::AnimateToIdealBounds() { + for (int i = 0; i < tab_count(); ++i) { + Tab* tab = GetTabAtTabDataIndex(i); + if (!tab->closing() && !tab->dragging()) + bounds_animator().AnimateViewTo(tab, ideal_bounds(i)); + } - // Move the tab to its ideal bounds. - GenerateIdealBounds(); - int tab_data_index = TabIndexOfTab(tab); - DCHECK(tab_data_index != -1); - tab->SetBounds(ideal_bounds(tab_data_index)); - SchedulePaint(); + if (animation_type_ != ANIMATION_NEW_TAB_3) { + bounds_animator().AnimateViewTo(newtab_button_, newtab_button_bounds_); + } } -void TabStrip::StoppedDraggingTab(BaseTab* tab) { - int tab_data_index = TabIndexOfTab(tab); - if (tab_data_index == -1) { - // The tab was removed before the drag completed. Don't do anything. - return; - } +bool TabStrip::ShouldHighlightCloseButtonAfterRemove() { + return available_width_for_tabs_ != -1; +} - // Animate the view back to its correct position. +void TabStrip::PrepareForAnimation() { + BaseTabStrip::PrepareForAnimation(); ResetAnimationState(true); - GenerateIdealBounds(); - AnimateToIdealBounds(); - bounds_animator_.AnimateViewTo(tab, ideal_bounds(TabIndexOfTab(tab))); - - // Install a delegate to reset the dragging state when done. We have to leave - // dragging true for the tab otherwise it'll draw beneath the new tab button. - bounds_animator_.SetAnimationDelegate(tab, - new ResetDraggingStateDelegate(tab), - true); } void TabStrip::ViewHierarchyChanged(bool is_add, @@ -797,7 +687,6 @@ void TabStrip::Init() { drop_indicator_width = drop_image->width(); drop_indicator_height = drop_image->height(); } - bounds_animator_.set_observer(this); } void TabStrip::LoadNewTabButtonImage() { @@ -1251,8 +1140,8 @@ void TabStrip::NewTabAnimation1Done() { tab->set_alpha(0); // BoundsAnimator takes ownership of NewTabAlphaDelegate. - bounds_animator_.SetAnimationDelegate(tab, new NewTabAlphaDelegate(tab), - true); + bounds_animator().SetAnimationDelegate(tab, new NewTabAlphaDelegate(tab), + true); } void TabStrip::NewTabAnimation2Done() { @@ -1267,22 +1156,10 @@ void TabStrip::NewTabAnimation2Done() { animation->SetTweenType(Tween::EASE_IN_OUT); // BoundsAnimator takes ownership of animation. - bounds_animator_.SetAnimationForView( + bounds_animator().SetAnimationForView( GetTabAtTabDataIndex(tab_count() - 1), animation); } -void TabStrip::AnimateToIdealBounds() { - for (int i = 0; i < tab_count(); ++i) { - Tab* tab = GetTabAtTabDataIndex(i); - if (!tab->closing() && !tab->dragging()) - bounds_animator_.AnimateViewTo(tab, ideal_bounds(i)); - } - - if (animation_type_ != ANIMATION_NEW_TAB_3) { - bounds_animator_.AnimateViewTo(newtab_button_, newtab_button_bounds_); - } -} - bool TabStrip::ShouldStartIntertTabAnimationAtEnd(int model_index, bool foreground) { return foreground && (model_index + 1 == GetModelCount()) && @@ -1290,13 +1167,13 @@ bool TabStrip::ShouldStartIntertTabAnimationAtEnd(int model_index, } void TabStrip::StartResizeLayoutAnimation() { - ResetAnimationState(true); + PrepareForAnimation(); GenerateIdealBounds(); AnimateToIdealBounds(); } void TabStrip::StartInsertTabAnimationAtEnd() { - ResetAnimationState(true); + PrepareForAnimation(); // The TabStrip can now use its entire width to lay out Tabs. available_width_for_tabs_ = -1; @@ -1319,7 +1196,7 @@ void TabStrip::StartInsertTabAnimationAtEnd() { } void TabStrip::StartInsertTabAnimationImpl(int model_index) { - ResetAnimationState(true); + PrepareForAnimation(); // The TabStrip can now use its entire width to lay out Tabs. available_width_for_tabs_ = -1; @@ -1341,30 +1218,8 @@ void TabStrip::StartInsertTabAnimationImpl(int model_index) { AnimateToIdealBounds(); } -void TabStrip::StartRemoveTabAnimation(int model_index) { - ResetAnimationState(true); - - // Mark the tab as closing. - Tab* tab = GetTabAtModelIndex(model_index); - tab->set_closing(true); - - // Start an animation for the tabs. - GenerateIdealBounds(); - AnimateToIdealBounds(); - - // Animate the tab being closed to 0x0. - gfx::Rect tab_bounds = tab->bounds(); - tab_bounds.set_width(0); - bounds_animator_.AnimateViewTo(tab, tab_bounds); - - // Register delegate to do cleanup when done, BoundsAnimator takes - // ownership of RemoveTabDelegate. - bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab), - true); -} - void TabStrip::StartMiniTabAnimation() { - ResetAnimationState(true); + PrepareForAnimation(); GenerateIdealBounds(); AnimateToIdealBounds(); @@ -1376,11 +1231,11 @@ void TabStrip::StopAnimating(bool layout) { new_tab_timer_.Stop(); - if (bounds_animator_.IsAnimating()) { + if (bounds_animator().IsAnimating()) { // Cancelling the animation triggers OnBoundsAnimatorDone, which invokes // ResetAnimationState. cancelling_animation_ = true; - bounds_animator_.Cancel(); + bounds_animator().Cancel(); cancelling_animation_ = false; } else { ResetAnimationState(false); diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h index 7486f46..33f132d 100644 --- a/chrome/browser/views/tabs/tab_strip.h +++ b/chrome/browser/views/tabs/tab_strip.h @@ -12,7 +12,6 @@ #include "chrome/browser/views/tabs/base_tab_strip.h" #include "gfx/point.h" #include "gfx/rect.h" -#include "views/animation/bounds_animator.h" #include "views/controls/button/image_button.h" class Tab; @@ -41,8 +40,7 @@ class WidgetWin; /////////////////////////////////////////////////////////////////////////////// class TabStrip : public BaseTabStrip, public views::ButtonListener, - public MessageLoopForUI::Observer, - public views::BoundsAnimatorObserver { + public MessageLoopForUI::Observer { public: explicit TabStrip(TabStripController* controller); virtual ~TabStrip(); @@ -102,8 +100,9 @@ class TabStrip : public BaseTabStrip, virtual BaseTab* CreateTab(); virtual void StartInsertTabAnimation(int model_index, bool foreground); virtual void StartMoveTabAnimation(); - virtual void StartedDraggingTab(BaseTab* tab); - virtual void StoppedDraggingTab(BaseTab* tab); + virtual void AnimateToIdealBounds(); + virtual bool ShouldHighlightCloseButtonAfterRemove(); + virtual void PrepareForAnimation(); // views::View implementation: virtual void ViewHierarchyChanged(bool is_add, @@ -133,8 +132,6 @@ class TabStrip : public BaseTabStrip, static const int extra_gap_for_nano_; private: - class RemoveTabDelegate; - friend class DraggedTabController; // AnimationType used for tracking animations that require additional @@ -280,11 +277,6 @@ class TabStrip : public BaseTabStrip, void NewTabAnimation1Done(); void NewTabAnimation2Done(); - // Animates all the views to their ideal bounds. - // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds - // currently set in ideal_bounds. - void AnimateToIdealBounds(); - // Returns true if a new tab inserted at specified index should start the // new tab animation. See description above AnimationType for details on // this animation. @@ -294,7 +286,6 @@ class TabStrip : public BaseTabStrip, void StartResizeLayoutAnimation(); void StartInsertTabAnimationAtEnd(); void StartInsertTabAnimationImpl(int model_index); - void StartRemoveTabAnimation(int model_index); void StartMoveTabAnimation(int from_model_index, int to_model_index); void StartMiniTabAnimation(); @@ -371,8 +362,6 @@ class TabStrip : public BaseTabStrip, // container. This is that animation container. scoped_refptr<AnimationContainer> animation_container_; - views::BoundsAnimator bounds_animator_; - // Used for stage 1 of new tab animation. base::OneShotTimer<TabStrip> new_tab_timer_; |