Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(545)

Unified Diff: ui/app_list/views/apps_container_view.cc

Issue 140203003: Implement animation UI for opening/closing an app list folder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address code review comments. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/app_list/views/apps_container_view.h ('k') | ui/app_list/views/apps_grid_view.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/app_list/views/apps_container_view.cc
diff --git a/ui/app_list/views/apps_container_view.cc b/ui/app_list/views/apps_container_view.cc
index 6b3054d1a4781fa22a20e53bd63e32d7804098d6..6a275558c81dd245672b416051c3794c6671ed1a 100644
--- a/ui/app_list/views/apps_container_view.cc
+++ b/ui/app_list/views/apps_container_view.cc
@@ -10,12 +10,107 @@
#include "ui/app_list/app_list_folder_item.h"
#include "ui/app_list/pagination_model.h"
#include "ui/app_list/views/app_list_folder_view.h"
+#include "ui/app_list/views/app_list_item_view.h"
#include "ui/app_list/views/app_list_main_view.h"
#include "ui/app_list/views/apps_grid_view.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/events/event.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/views/controls/image_view.h"
namespace app_list {
+namespace {
+
+// Transitional view used for top item icons animation when opening or closing
+// a folder.
+class TopIconAnimationView : public views::View,
+ public ui::ImplicitAnimationObserver {
+ public:
+ TopIconAnimationView(const gfx::ImageSkia& icon,
+ const gfx::Rect& scaled_rect,
+ bool open_folder)
+ : icon_size_(kPreferredIconDimension, kPreferredIconDimension),
+ icon_(new views::ImageView),
+ scaled_rect_(scaled_rect),
+ open_folder_(open_folder) {
+ DCHECK(!icon.isNull());
+ gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(
+ icon,
+ skia::ImageOperations::RESIZE_BEST, icon_size_));
+ icon_->SetImage(resized);
+ AddChildView(icon_);
+
+#if defined(USE_AURA)
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
+#endif
+ }
+ virtual ~TopIconAnimationView() {}
+
+ void AddObserver(TopIconAnimationObserver* observer) {
+ observers_.AddObserver(observer);
+ }
+
+ void RemoveObserver(TopIconAnimationObserver* observer) {
+ observers_.RemoveObserver(observer);
+ }
+
+ void TransformView() {
+ // Transform used for scaling down the icon and move it back inside to the
+ // original folder icon.
+ const float kIconTransformScale = 0.33333f;
+ gfx::Transform transform;
+ transform.Translate(scaled_rect_.x() - layer()->bounds().x(),
+ scaled_rect_.y() - layer()->bounds().y());
+ transform.Scale(kIconTransformScale, kIconTransformScale);
+
+ if (open_folder_) {
+ // Transform to a scaled down icon inside the original folder icon.
+ layer()->SetTransform(transform);
+ }
+
+ // Animate the icon to its target location and scale when opening or
+ // closing a folder.
+ ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
+ settings.AddObserver(this);
+ settings.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kFolderTransitionInDurationMs));
+ layer()->SetTransform(open_folder_ ? gfx::Transform() : transform);
+ }
+
+ private:
+ // views::View overrides:
+ virtual gfx::Size GetPreferredSize() OVERRIDE {
+ return icon_size_;
+ }
+
+ virtual void Layout() OVERRIDE {
+ icon_->SetBoundsRect(GetContentsBounds());
+ }
+
+ // ui::ImplicitAnimationObserver overrides:
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE {
+ SetVisible(false);
+ FOR_EACH_OBSERVER(TopIconAnimationObserver,
+ observers_,
+ OnTopIconAnimationsComplete(this));
+ }
+
+ gfx::Size icon_size_;
+ views::ImageView* icon_; // Owned by views hierarchy.
+ // Rect of the scaled down top item icon inside folder icon's ink bubble.
+ gfx::Rect scaled_rect_;
+ // True: opening folder; False: closing folder.
+ bool open_folder_;
+
+ ObserverList<TopIconAnimationObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(TopIconAnimationView);
+};
+
+} // namespace
+
AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view,
PaginationModel* pagination_model,
AppListModel* model,
@@ -46,9 +141,14 @@ AppsContainerView::~AppsContainerView() {
void AppsContainerView::ShowActiveFolder(AppListFolderItem* folder_item) {
app_list_folder_view_->SetAppListFolderItem(folder_item);
SetShowState(SHOW_ACTIVE_FOLDER);
+
+ CreateViewsForFolderTopItemsAnimation(folder_item, true);
}
-void AppsContainerView::ShowApps() {
+void AppsContainerView::ShowApps(AppListFolderItem* folder_item) {
+ CreateViewsForFolderTopItemsAnimation(folder_item, false);
+ // Hide the active folder view until the animation completes.
+ apps_grid_view_->activated_item_view()->SetVisible(false);
SetShowState(SHOW_APPS);
}
@@ -68,14 +168,14 @@ void AppsContainerView::Layout() {
switch (show_state_) {
case SHOW_APPS:
- app_list_folder_view_->SetVisible(false);
+ app_list_folder_view_->ScheduleShowHideAnimation(false);
apps_grid_view_->SetBoundsRect(rect);
- apps_grid_view_->SetVisible(true);
+ apps_grid_view_->ScheduleShowHideAnimation(true);
break;
case SHOW_ACTIVE_FOLDER:
- apps_grid_view_->SetVisible(false);
+ apps_grid_view_->ScheduleShowHideAnimation(false);
app_list_folder_view_->SetBoundsRect(rect);
- app_list_folder_view_->SetVisible(true);
+ app_list_folder_view_->ScheduleShowHideAnimation(true);
break;
default:
NOTREACHED();
@@ -89,6 +189,31 @@ bool AppsContainerView::OnKeyPressed(const ui::KeyEvent& event) {
return app_list_folder_view_->OnKeyPressed(event);
}
+void AppsContainerView::OnTopIconAnimationsComplete(views::View* icon_view) {
+ bool animations_done = true;
+ for (size_t i = 0; i < top_icon_views_.size(); ++i) {
+ if (top_icon_views_[i]->visible()) {
+ animations_done = false;
+ break;
+ }
+ }
+
+ if (animations_done) {
+ // Clean up the transitional views using for top item icon animation.
+ for (size_t i = 0; i < top_icon_views_.size(); ++i) {
+ TopIconAnimationView* icon_view =
+ static_cast<TopIconAnimationView*>(top_icon_views_[i]);
+ icon_view->RemoveObserver(this);
+ delete icon_view;
+ }
+ top_icon_views_.clear();
+
+ // Show the folder icon when closing the folder.
+ if (show_state_ == SHOW_APPS && apps_grid_view_->activated_item_view())
+ apps_grid_view_->activated_item_view()->SetVisible(true);
+ }
+}
+
void AppsContainerView::SetShowState(ShowState show_state) {
if (show_state_ == show_state)
return;
@@ -97,4 +222,38 @@ void AppsContainerView::SetShowState(ShowState show_state) {
Layout();
}
+Rects AppsContainerView::GetTopItemIconBoundsInActiveFolder() {
+ // Get the active folder's icon bounds relative to AppsContainerView.
+ AppListItemView* folder_view = apps_grid_view_->activated_item_view();
+ gfx::Rect to_grid_view = folder_view->ConvertRectToParent(
+ folder_view->GetIconBounds());
+ gfx::Rect to_container = apps_grid_view_->ConvertRectToParent(to_grid_view);
+
+ return AppListFolderItem::GetTopIconsBounds(to_container);
+}
+
+void AppsContainerView::CreateViewsForFolderTopItemsAnimation(
+ AppListFolderItem* active_folder,
+ bool open_folder) {
+ top_icon_views_.clear();
+ std::vector<gfx::Rect> top_items_bounds =
+ GetTopItemIconBoundsInActiveFolder();
+ size_t top_items_count =
+ std::min(kNumFolderTopItems, active_folder->item_list()->item_count());
+ for (size_t i = 0; i < top_items_count; ++i) {
+ TopIconAnimationView* icon_view = new TopIconAnimationView(
+ active_folder->GetTopIcon(i), top_items_bounds[i], open_folder);
+ icon_view->AddObserver(this);
+ top_icon_views_.push_back(icon_view);
+
+ // Add the transitional views into child views, and set its bounds to the
+ // same location of the item in the folder list view.
+ AddChildView(top_icon_views_[i]);
+ top_icon_views_[i]->SetBoundsRect(
+ app_list_folder_view_->ConvertRectToParent(
+ app_list_folder_view_->GetItemIconBoundsAt(i)));
+ static_cast<TopIconAnimationView*>(top_icon_views_[i])->TransformView();
+ }
+}
+
} // namespace app_list
« no previous file with comments | « ui/app_list/views/apps_container_view.h ('k') | ui/app_list/views/apps_grid_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698