summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-24 20:58:36 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-24 20:58:36 +0000
commitc242e46421bb2c71aaa39ac687279a204f5d7d3b (patch)
tree6f307bf4d7d53d3bc776758705d584213e35ebda /chrome/browser/views
parentbb4bc30596a168f80f2c651971c23999690b9cae (diff)
downloadchromium_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.cc2
-rw-r--r--chrome/browser/views/frame/glass_browser_frame_view.cc4
-rw-r--r--chrome/browser/views/frame/opaque_browser_frame_view.cc3
-rw-r--r--chrome/browser/views/tabs/base_tab_strip.cc188
-rw-r--r--chrome/browser/views/tabs/base_tab_strip.h31
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.cc200
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.h20
-rw-r--r--chrome/browser/views/tabs/side_tab.cc100
-rw-r--r--chrome/browser/views/tabs/side_tab.h6
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.cc67
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.h8
-rw-r--r--chrome/browser/views/tabs/tab_strip.cc195
-rw-r--r--chrome/browser/views/tabs/tab_strip.h19
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_;