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

Side by Side 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: 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/app_list/views/apps_container_view.h" 5 #include "ui/app_list/views/apps_container_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "ui/app_list/app_list_constants.h" 9 #include "ui/app_list/app_list_constants.h"
10 #include "ui/app_list/app_list_folder_item.h" 10 #include "ui/app_list/app_list_folder_item.h"
11 #include "ui/app_list/pagination_model.h" 11 #include "ui/app_list/pagination_model.h"
12 #include "ui/app_list/views/app_list_folder_view.h" 12 #include "ui/app_list/views/app_list_folder_view.h"
13 #include "ui/app_list/views/app_list_item_view.h"
13 #include "ui/app_list/views/app_list_main_view.h" 14 #include "ui/app_list/views/app_list_main_view.h"
14 #include "ui/app_list/views/apps_grid_view.h" 15 #include "ui/app_list/views/apps_grid_view.h"
16 #include "ui/compositor/scoped_layer_animation_settings.h"
15 #include "ui/events/event.h" 17 #include "ui/events/event.h"
18 #include "ui/gfx/image/image_skia_operations.h"
19 #include "ui/views/controls/image_view.h"
16 20
17 namespace app_list { 21 namespace app_list {
18 22
23 namespace {
24
25 // Transitional view used for top item icons animation when opening or closing
26 // a folder.
27 class TopIconAnimationView : public views::View,
28 public ui::ImplicitAnimationObserver {
29 public:
30
xiyuan 2014/01/16 01:46:48 nit: nuke empty line.
jennyz 2014/01/16 17:49:52 Done.
31 explicit TopIconAnimationView(const gfx::ImageSkia& icon,
xiyuan 2014/01/16 01:46:48 nit: "explicit" is not needed when ctor takes more
jennyz 2014/01/16 17:49:52 Done.
32 const gfx::Rect& scaled_rect,
33 bool open_folder)
34 : icon_size_(kPreferredIconDimension, kPreferredIconDimension),
35 icon_(new views::ImageView),
36 scaled_rect_(scaled_rect),
37 open_folder_(open_folder) {
38 DCHECK(!icon.isNull());
39 gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(
40 icon,
41 skia::ImageOperations::RESIZE_BEST, icon_size_));
42 icon_->SetImage(resized);
43 AddChildView(icon_);
44
45 #if defined(USE_AURA)
46 SetPaintToLayer(true);
47 SetFillsBoundsOpaquely(false);
xiyuan 2014/01/16 01:46:48 nit: 2 more space indent
jennyz 2014/01/16 17:49:52 Done.
48 #endif
49 }
50 virtual ~TopIconAnimationView() {}
51
52 void AddObserver(TopIconAnimationObserver* observer) {
53 observers_.AddObserver(observer);
54 }
55
56 void RemoveObserver(TopIconAnimationObserver* observer) {
57 observers_.RemoveObserver(observer);
58 }
59
60 private:
61 // views::View overrides:
62 virtual gfx::Size GetPreferredSize() OVERRIDE {
63 return icon_size_;
64 }
65
66 virtual void Layout() OVERRIDE {
67 icon_->SetBoundsRect(GetContentsBounds());
68 TransformView();
xiyuan 2014/01/16 01:46:48 TransforView() should not be called from Layout().
jennyz 2014/01/16 17:49:52 Done.
69 }
70
71 // ui::ImplicitAnimationObserver overrides:
72 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
73 SetVisible(false);
74 FOR_EACH_OBSERVER(TopIconAnimationObserver,
75 observers_,
76 OnTopIconAnimationsComplete(this));
77 }
78
79 void TransformView() {
80 // Transform used for scaling down the icon and move it back inside to the
81 // original folder icon.
82 const float kIconTransformScale = 0.33333f;
83 gfx::Transform transform;
84 transform.Translate(scaled_rect_.x() - layer()->bounds().x(),
85 scaled_rect_.y() - layer()->bounds().y());
86 transform.Scale(kIconTransformScale, kIconTransformScale);
87
88 if (open_folder_) {
89 // Transform to a scaled down icon inside the original folder icon.
90 layer()->SetTransform(transform);
91 }
92
93 // Animate the icon to its target location and scale when opening or
94 // closing a folder.
95 ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
96 settings.AddObserver(this);
97 settings.SetTransitionDuration(
98 base::TimeDelta::FromMilliseconds(kFolderTransitionInDurationMs));
99 layer()->SetTransform(open_folder_ ? gfx::Transform() : transform);
100 }
101
102 gfx::Size icon_size_;
103 views::ImageView* icon_; // Owned by views hierarchy.
104 // Rect of the scaled down top item icon inside folder icon's ink bubble.
105 gfx::Rect scaled_rect_;
106 // True: opening folder; False: closing folder.
107 bool open_folder_;
108
109 ObserverList<TopIconAnimationObserver> observers_;
110
111 DISALLOW_COPY_AND_ASSIGN(TopIconAnimationView);
112 };
113
114 } // namespace
115
19 AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view, 116 AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view,
20 PaginationModel* pagination_model, 117 PaginationModel* pagination_model,
21 AppListModel* model, 118 AppListModel* model,
22 content::WebContents* start_page_contents) 119 content::WebContents* start_page_contents)
23 : model_(model), 120 : model_(model),
24 show_state_(SHOW_APPS) { 121 show_state_(SHOW_APPS) {
25 apps_grid_view_ = new AppsGridView( 122 apps_grid_view_ = new AppsGridView(
26 app_list_main_view, pagination_model, start_page_contents); 123 app_list_main_view, pagination_model, start_page_contents);
27 apps_grid_view_->SetLayout(kPreferredIconDimension, 124 apps_grid_view_->SetLayout(kPreferredIconDimension,
28 kPreferredCols, 125 kPreferredCols,
(...skipping 10 matching lines...) Expand all
39 apps_grid_view_->SetModel(model_); 136 apps_grid_view_->SetModel(model_);
40 apps_grid_view_->SetItemList(model_->item_list()); 137 apps_grid_view_->SetItemList(model_->item_list());
41 } 138 }
42 139
43 AppsContainerView::~AppsContainerView() { 140 AppsContainerView::~AppsContainerView() {
44 } 141 }
45 142
46 void AppsContainerView::ShowActiveFolder(AppListFolderItem* folder_item) { 143 void AppsContainerView::ShowActiveFolder(AppListFolderItem* folder_item) {
47 app_list_folder_view_->SetAppListFolderItem(folder_item); 144 app_list_folder_view_->SetAppListFolderItem(folder_item);
48 SetShowState(SHOW_ACTIVE_FOLDER); 145 SetShowState(SHOW_ACTIVE_FOLDER);
146
147 CreateViewsForFolderTopItemsAnimation(folder_item, true);
49 } 148 }
50 149
51 void AppsContainerView::ShowApps() { 150 void AppsContainerView::ShowApps(AppListFolderItem* folder_item) {
151 CreateViewsForFolderTopItemsAnimation(folder_item, false);
152 // Hide the active folder view until the animation completes.
153 apps_grid_view_->activated_item_view()->SetVisible(false);
52 SetShowState(SHOW_APPS); 154 SetShowState(SHOW_APPS);
53 } 155 }
54 156
55 gfx::Size AppsContainerView::GetPreferredSize() { 157 gfx::Size AppsContainerView::GetPreferredSize() {
56 const gfx::Size grid_size = apps_grid_view_->GetPreferredSize(); 158 const gfx::Size grid_size = apps_grid_view_->GetPreferredSize();
57 const gfx::Size folder_view_size = app_list_folder_view_->GetPreferredSize(); 159 const gfx::Size folder_view_size = app_list_folder_view_->GetPreferredSize();
58 160
59 int width = std::max(grid_size.width(), folder_view_size.width()); 161 int width = std::max(grid_size.width(), folder_view_size.width());
60 int height = std::max(grid_size.height(), folder_view_size.height()); 162 int height = std::max(grid_size.height(), folder_view_size.height());
61 return gfx::Size(width, height); 163 return gfx::Size(width, height);
62 } 164 }
63 165
64 void AppsContainerView::Layout() { 166 void AppsContainerView::Layout() {
65 gfx::Rect rect(GetContentsBounds()); 167 gfx::Rect rect(GetContentsBounds());
66 if (rect.IsEmpty()) 168 if (rect.IsEmpty())
67 return; 169 return;
68 170
69 switch (show_state_) { 171 switch (show_state_) {
70 case SHOW_APPS: 172 case SHOW_APPS:
71 app_list_folder_view_->SetVisible(false); 173 app_list_folder_view_->ScheduleAnimationToShow(false);
72 apps_grid_view_->SetBoundsRect(rect); 174 apps_grid_view_->SetBoundsRect(rect);
73 apps_grid_view_->SetVisible(true); 175 apps_grid_view_->ScheduleAnimationToShow(true);
74 break; 176 break;
75 case SHOW_ACTIVE_FOLDER: 177 case SHOW_ACTIVE_FOLDER:
76 apps_grid_view_->SetVisible(false); 178 apps_grid_view_->ScheduleAnimationToShow(false);
77 app_list_folder_view_->SetBoundsRect(rect); 179 app_list_folder_view_->SetBoundsRect(rect);
78 app_list_folder_view_->SetVisible(true); 180 app_list_folder_view_->ScheduleAnimationToShow(true);
79 break; 181 break;
80 default: 182 default:
81 NOTREACHED(); 183 NOTREACHED();
82 } 184 }
83 } 185 }
84 186
85 bool AppsContainerView::OnKeyPressed(const ui::KeyEvent& event) { 187 bool AppsContainerView::OnKeyPressed(const ui::KeyEvent& event) {
86 if (show_state_ == SHOW_APPS) 188 if (show_state_ == SHOW_APPS)
87 return apps_grid_view_->OnKeyPressed(event); 189 return apps_grid_view_->OnKeyPressed(event);
88 else 190 else
89 return app_list_folder_view_->OnKeyPressed(event); 191 return app_list_folder_view_->OnKeyPressed(event);
90 } 192 }
91 193
194 void AppsContainerView::OnTopIconAnimationsComplete(views::View* icon_view) {
195 bool animations_done = true;
196 for (size_t i = 0; i < top_icon_views_.size(); ++i) {
197 if (top_icon_views_[i]->visible()) {
198 animations_done = false;
199 break;
200 }
201 }
202
203 if (animations_done) {
204 // Clean up the transitional views using for top item icon animation.
205 for (size_t i = 0; i < top_icon_views_.size(); ++i) {
206 TopIconAnimationView* icon_view =
207 static_cast<TopIconAnimationView*>(top_icon_views_[i]);
208 icon_view->RemoveObserver(this);
209 delete icon_view;
210 }
211 top_icon_views_.clear();
212
213 // Show the folder icon when closing the folder.
214 if (show_state_ == SHOW_APPS && apps_grid_view_->activated_item_view())
215 apps_grid_view_->activated_item_view()->SetVisible(true);
216 }
217 }
218
92 void AppsContainerView::SetShowState(ShowState show_state) { 219 void AppsContainerView::SetShowState(ShowState show_state) {
93 if (show_state_ == show_state) 220 if (show_state_ == show_state)
94 return; 221 return;
95 222
96 show_state_ = show_state; 223 show_state_ = show_state;
97 Layout(); 224 Layout();
98 } 225 }
99 226
227 TopIconsBounds AppsContainerView::GetTopItemIconBoundsInActiveFolder() {
228 // Get the active folder's icon bounds relative to AppsContainerView.
229 AppListItemView* folder_view = apps_grid_view_->activated_item_view();
230 gfx::Rect to_grid_view = folder_view->ConvertRectToParent(
231 folder_view->GetIconBounds());
232 gfx::Rect to_container = apps_grid_view_->ConvertRectToParent(to_grid_view);
233
234 return AppListFolderItem::GetTopIconsBounds(to_container);
235 }
236
237 void AppsContainerView::CreateViewsForFolderTopItemsAnimation(
238 AppListFolderItem* active_folder,
239 bool open_folder) {
240 top_icon_views_.clear();
241 std::vector<gfx::Rect> top_items_bounds =
242 GetTopItemIconBoundsInActiveFolder();
243 size_t top_items_count =
244 std::min(kNumFolderTopItems, active_folder->item_list()->item_count());
245 for (size_t i = 0; i < top_items_count; ++i) {
246 TopIconAnimationView* icon_view = new TopIconAnimationView(
247 active_folder->GetTopIcon(i), top_items_bounds[i], open_folder);
248 icon_view->AddObserver(this);
249 top_icon_views_.push_back(icon_view);
250
251 // Add the transitional views into child views, and set its bounds to the
252 // same location of the item in the folder list view.
253 AddChildView(top_icon_views_[i]);
254 top_icon_views_[i]->SetBoundsRect(
255 app_list_folder_view_->ConvertRectToParent(
256 app_list_folder_view_->GetItemIconBoundsAt(i)));
257 }
258 }
259
100 } // namespace app_list 260 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698