summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-13 21:34:24 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-13 21:34:24 +0000
commitd69a820b742aeeb6ba6d6521eb4d328b27ead35f (patch)
tree8b1b84f1eb0860e5825ff47c6dbe72f42b6ae2bb
parentbb7edffa557429eb8653f26458ec499621c76dc2 (diff)
downloadchromium_src-d69a820b742aeeb6ba6d6521eb4d328b27ead35f.zip
chromium_src-d69a820b742aeeb6ba6d6521eb4d328b27ead35f.tar.gz
chromium_src-d69a820b742aeeb6ba6d6521eb4d328b27ead35f.tar.bz2
app_list: Update over-scroll animation.
- Remove over-scroll animation on app icons; - Add an over-scroll animation on bubble widget itself by shifting 48px in the scroll direction and snap back after over-scroll; BUG=none. TEST=Verify bubble moves with touch when over-scroll happens and snaps back afterwards. R=sky@chromium.org Review URL: https://chromiumcodereview.appspot.com/10915265 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@156639 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/wm/app_list_controller.cc57
-rw-r--r--ash/wm/app_list_controller.h16
-rw-r--r--ui/app_list/apps_grid_view.cc20
-rw-r--r--ui/app_list/pagination_model.cc4
-rw-r--r--ui/app_list/pagination_model.h3
5 files changed, 84 insertions, 16 deletions
diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc
index 5ae14a9..8f6ebcb 100644
--- a/ash/wm/app_list_controller.cc
+++ b/ash/wm/app_list_controller.cc
@@ -33,6 +33,12 @@ const int kAnimationDurationMs = 200;
// Offset in pixels to animation away/towards the launcher.
const int kAnimationOffset = 8;
+// Duration for snap back animation after over-scroll in milliseconds.
+const int kSnapBackAnimationDurationMs = 100;
+
+// The maximum shift in pixels when over-scroll happens.
+const int kMaxOverScrollShift = 48;
+
ui::Layer* GetLayer(views::Widget* widget) {
return widget->GetNativeView()->layer();
}
@@ -85,8 +91,10 @@ gfx::Rect OffsetTowardsShelf(const gfx::Rect& rect) {
AppListController::AppListController()
: pagination_model_(new app_list::PaginationModel),
is_visible_(false),
- view_(NULL) {
+ view_(NULL),
+ should_snap_back_(false) {
Shell::GetInstance()->AddShellObserver(this);
+ pagination_model_->AddObserver(this);
}
AppListController::~AppListController() {
@@ -96,6 +104,7 @@ AppListController::~AppListController() {
view_->GetWidget()->CloseNow();
Shell::GetInstance()->RemoveShellObserver(this);
+ pagination_model_->RemoveObserver(this);
}
void AppListController::SetVisible(bool visible) {
@@ -181,6 +190,7 @@ void AppListController::ScheduleAnimation() {
gfx::Rect target_bounds;
if (is_visible_) {
target_bounds = layer->bounds();
+ view_bounds_ = target_bounds;
layer->SetBounds(OffsetTowardsShelf(layer->bounds()));
} else {
target_bounds = OffsetTowardsShelf(layer->bounds());
@@ -220,8 +230,10 @@ void AppListController::ProcessLocatedEvent(aura::Window* target,
}
void AppListController::UpdateBounds() {
- if (view_ && is_visible_)
+ if (view_ && is_visible_) {
view_->UpdateBounds();
+ view_bounds_ = view_->GetWidget()->GetNativeView()->bounds();
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -306,5 +318,46 @@ void AppListController::OnLauncherIconPositionsChanged() {
UpdateBounds();
}
+////////////////////////////////////////////////////////////////////////////////
+// AppListController, PaginationModelObserver implementation:
+
+void AppListController::TotalPagesChanged() {
+}
+
+void AppListController::SelectedPageChanged(int old_selected,
+ int new_selected) {
+}
+
+void AppListController::TransitionChanged() {
+ // |view_| could be NULL when app list is closed with a running transition.
+ if (!view_)
+ return;
+
+ const app_list::PaginationModel::Transition& transition =
+ pagination_model_->transition();
+ if (pagination_model_->is_valid_page(transition.target_page))
+ return;
+
+ if (pagination_model_->scrolling()) {
+ const int current_page = pagination_model_->selected_page();
+ const int dir = transition.target_page > current_page ? -1 : 1;
+
+ const double progress = 1.0 - pow(1.0 - transition.progress, 4);
+ const int shift = kMaxOverScrollShift * progress * dir;
+
+ gfx::Rect shifted(view_bounds_);
+ shifted.set_x(shifted.x() + shift);
+ view_->GetWidget()->SetBounds(shifted);
+ should_snap_back_ = true;
+ } else if (should_snap_back_) {
+ should_snap_back_ = false;
+ ui::Layer* layer = GetLayer(view_->GetWidget());
+ ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
+ animation.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kSnapBackAnimationDurationMs));
+ layer->SetBounds(view_bounds_);
+ }
+}
+
} // namespace internal
} // namespace ash
diff --git a/ash/wm/app_list_controller.h b/ash/wm/app_list_controller.h
index a360c28..a841609 100644
--- a/ash/wm/app_list_controller.h
+++ b/ash/wm/app_list_controller.h
@@ -10,10 +10,12 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/timer.h"
+#include "ui/app_list/pagination_model_observer.h"
#include "ui/aura/event_filter.h"
#include "ui/aura/focus_change_observer.h"
#include "ui/aura/root_window_observer.h"
#include "ui/compositor/layer_animation_observer.h"
+#include "ui/gfx/rect.h"
#include "ui/views/widget/widget_observer.h"
namespace app_list {
@@ -38,7 +40,8 @@ class AppListController : public aura::EventFilter,
public ui::ImplicitAnimationObserver,
public views::WidgetObserver,
public ShellObserver,
- public LauncherIconObserver {
+ public LauncherIconObserver,
+ public app_list::PaginationModelObserver {
public:
AppListController();
virtual ~AppListController();
@@ -104,6 +107,11 @@ class AppListController : public aura::EventFilter,
// LauncherIconObserver overrides:
virtual void OnLauncherIconPositionsChanged() OVERRIDE;
+ // app_list::PaginationModelObserver overrides:
+ virtual void TotalPagesChanged() OVERRIDE;
+ virtual void SelectedPageChanged(int old_selected, int new_selected) OVERRIDE;
+ virtual void TransitionChanged() OVERRIDE;
+
scoped_ptr<app_list::PaginationModel> pagination_model_;
// Whether we should show or hide app list widget.
@@ -112,6 +120,12 @@ class AppListController : public aura::EventFilter,
// The AppListView this class manages, owned by its widget.
app_list::AppListView* view_;
+ // Cached bounds of |view_| for snapping back animation after over-scroll.
+ gfx::Rect view_bounds_;
+
+ // Whether should schedule snap back animation.
+ bool should_snap_back_;
+
DISALLOW_COPY_AND_ASSIGN(AppListController);
};
diff --git a/ui/app_list/apps_grid_view.cc b/ui/app_list/apps_grid_view.cc
index e578303..380ca00 100644
--- a/ui/app_list/apps_grid_view.cc
+++ b/ui/app_list/apps_grid_view.cc
@@ -25,13 +25,6 @@ const int kPagePadding = 40;
const int kPreferredTileWidth = 88;
const int kPreferredTileHeight = 98;
-// Max extra column padding space in pixels for invalid page transition.
-const int kMaxExtraColPaddingForInvalidTransition = 15;
-
-// Extra column padding space in pixels of first column for invalid page
-// transition.
-const int kBaseExtraColPaddingForInvalidTransition = 50;
-
} // namespace
namespace app_list {
@@ -132,10 +125,7 @@ void AppsGridView::Layout() {
// Transition to right means negative offset.
const int dir = transition.target_page > current_page ? -1 : 1;
const int transition_offset = is_valid ?
- transition.progress * page_width * dir :
- transition.progress * kMaxExtraColPaddingForInvalidTransition * dir;
- const int base_transition_offset = is_valid ? 0 :
- transition.progress * kBaseExtraColPaddingForInvalidTransition * dir;
+ transition.progress * page_width * dir : 0;
const int first_visible_index = current_page * tiles_per_page();
const int last_visible_index = (current_page + 1) * tiles_per_page() - 1;
@@ -156,7 +146,6 @@ void AppsGridView::Layout() {
x_offset += transition_offset;
} else {
const int col = i % cols_;
- x_offset += base_transition_offset;
if (transition_offset > 0)
x_offset += transition_offset * col;
else
@@ -342,7 +331,12 @@ void AppsGridView::SelectedPageChanged(int old_selected, int new_selected) {
}
void AppsGridView::TransitionChanged() {
- Layout();
+ // Update layout for valid page transition only since over-scroll no longer
+ // animates app icons.
+ const PaginationModel::Transition& transition =
+ pagination_model_->transition();
+ if (pagination_model_->is_valid_page(transition.target_page))
+ Layout();
}
} // namespace app_list
diff --git a/ui/app_list/pagination_model.cc b/ui/app_list/pagination_model.cc
index cadc1ea..e05896c 100644
--- a/ui/app_list/pagination_model.cc
+++ b/ui/app_list/pagination_model.cc
@@ -15,6 +15,7 @@ PaginationModel::PaginationModel()
: total_pages_(-1),
selected_page_(-1),
transition_(-1, 0),
+ scrolling_(false),
pending_selected_page_(-1),
transition_duration_ms_(0) {
}
@@ -100,6 +101,7 @@ void PaginationModel::SetTransitionDuration(int duration_ms) {
}
void PaginationModel::StartScroll() {
+ scrolling_ = true;
// Cancels current transition animation (if any).
transition_animation_.reset();
}
@@ -131,6 +133,8 @@ void PaginationModel::UpdateScroll(double delta) {
}
void PaginationModel::EndScroll(bool cancel) {
+ scrolling_ = false;
+
if (!has_transition())
return;
diff --git a/ui/app_list/pagination_model.h b/ui/app_list/pagination_model.h
index 89b057a..7026294 100644
--- a/ui/app_list/pagination_model.h
+++ b/ui/app_list/pagination_model.h
@@ -80,6 +80,7 @@ class APP_LIST_EXPORT PaginationModel : public ui::AnimationDelegate {
int total_pages() const { return total_pages_; }
int selected_page() const { return selected_page_; }
const Transition& transition() const { return transition_; }
+ bool scrolling() const { return scrolling_; }
bool is_valid_page(int page) const {
return page >= 0 && page < total_pages_;
@@ -118,6 +119,8 @@ class APP_LIST_EXPORT PaginationModel : public ui::AnimationDelegate {
Transition transition_;
+ bool scrolling_; // Whether a scroll is in progress.
+
// Pending selected page when SelectedPage is called during a transition. If
// multiple SelectPage is called while a transition is in progress, only the
// last target page is remembered here.