OLD | NEW |
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/app_list_folder_view.h" | 5 #include "ui/app_list/views/app_list_folder_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/app_list_model.h" | 11 #include "ui/app_list/app_list_model.h" |
12 #include "ui/app_list/pagination_model.h" | 12 #include "ui/app_list/pagination_model.h" |
13 #include "ui/app_list/views/app_list_item_view.h" | 13 #include "ui/app_list/views/app_list_item_view.h" |
14 #include "ui/app_list/views/app_list_main_view.h" | 14 #include "ui/app_list/views/app_list_main_view.h" |
15 #include "ui/app_list/views/apps_container_view.h" | 15 #include "ui/app_list/views/apps_container_view.h" |
16 #include "ui/app_list/views/apps_grid_view.h" | 16 #include "ui/app_list/views/apps_grid_view.h" |
17 #include "ui/app_list/views/contents_view.h" | 17 #include "ui/app_list/views/contents_view.h" |
| 18 #include "ui/app_list/views/folder_background_view.h" |
18 #include "ui/app_list/views/folder_header_view.h" | 19 #include "ui/app_list/views/folder_header_view.h" |
19 #include "ui/compositor/scoped_layer_animation_settings.h" | 20 #include "ui/compositor/scoped_layer_animation_settings.h" |
20 #include "ui/events/event.h" | 21 #include "ui/events/event.h" |
| 22 #include "ui/gfx/rect_conversions.h" |
21 #include "ui/views/view_model.h" | 23 #include "ui/views/view_model.h" |
22 #include "ui/views/view_model_utils.h" | 24 #include "ui/views/view_model_utils.h" |
23 | 25 |
24 namespace app_list { | 26 namespace app_list { |
25 | 27 |
26 namespace { | 28 namespace { |
27 | 29 |
28 // Indexes of interesting views in ViewModel of AppListFolderView. | 30 // Indexes of interesting views in ViewModel of AppListFolderView. |
29 const int kIndexFolderHeader = 0; | 31 const int kIndexFolderHeader = 0; |
30 const int kIndexChildItems = 1; | 32 const int kIndexChildItems = 1; |
31 | 33 |
| 34 // Threshold for the distance from the center of the item to the circle of the |
| 35 // folder container ink bubble, beyond which, the item is considered dragged |
| 36 // out of the folder boundary. |
| 37 const int kOutOfFolderContainerBubbleDelta = 30; |
| 38 |
32 } // namespace | 39 } // namespace |
33 | 40 |
34 AppListFolderView::AppListFolderView(AppsContainerView* container_view, | 41 AppListFolderView::AppListFolderView(AppsContainerView* container_view, |
35 AppListModel* model, | 42 AppListModel* model, |
36 AppListMainView* app_list_main_view, | 43 AppListMainView* app_list_main_view, |
37 content::WebContents* start_page_contents) | 44 content::WebContents* start_page_contents) |
38 : container_view_(container_view), | 45 : container_view_(container_view), |
39 folder_header_view_(new FolderHeaderView(this)), | 46 folder_header_view_(new FolderHeaderView(this)), |
40 view_model_(new views::ViewModel), | 47 view_model_(new views::ViewModel), |
41 model_(model), | 48 model_(model), |
42 folder_item_(NULL), | 49 folder_item_(NULL), |
43 pagination_model_(new PaginationModel) { | 50 pagination_model_(new PaginationModel), |
| 51 hide_for_reparent_(false) { |
44 AddChildView(folder_header_view_); | 52 AddChildView(folder_header_view_); |
45 view_model_->Add(folder_header_view_, kIndexFolderHeader); | 53 view_model_->Add(folder_header_view_, kIndexFolderHeader); |
46 | 54 |
47 items_grid_view_ = new AppsGridView( | 55 items_grid_view_ = new AppsGridView( |
48 app_list_main_view, pagination_model_.get(), NULL); | 56 app_list_main_view, pagination_model_.get(), NULL); |
49 items_grid_view_->set_is_root_level(false); | 57 items_grid_view_->set_is_root_level(false); |
50 items_grid_view_->SetLayout(kPreferredIconDimension, | 58 items_grid_view_->SetLayout(kPreferredIconDimension, |
51 kPreferredCols, | 59 kPreferredCols, |
52 kPreferredRows); | 60 kPreferredRows); |
53 items_grid_view_->SetModel(model); | 61 items_grid_view_->SetModel(model); |
(...skipping 13 matching lines...) Expand all Loading... |
67 // Make sure |items_grid_view_| is deleted before |pagination_model_|. | 75 // Make sure |items_grid_view_| is deleted before |pagination_model_|. |
68 RemoveAllChildViews(true); | 76 RemoveAllChildViews(true); |
69 } | 77 } |
70 | 78 |
71 void AppListFolderView::SetAppListFolderItem(AppListFolderItem* folder) { | 79 void AppListFolderView::SetAppListFolderItem(AppListFolderItem* folder) { |
72 folder_item_ = folder; | 80 folder_item_ = folder; |
73 items_grid_view_->SetItemList(folder_item_->item_list()); | 81 items_grid_view_->SetItemList(folder_item_->item_list()); |
74 folder_header_view_->SetFolderItem(folder_item_); | 82 folder_header_view_->SetFolderItem(folder_item_); |
75 } | 83 } |
76 | 84 |
77 void AppListFolderView::ScheduleShowHideAnimation(bool show) { | 85 void AppListFolderView::ScheduleShowHideAnimation(bool show, |
| 86 bool hide_for_reparent) { |
| 87 hide_for_reparent_ = hide_for_reparent; |
| 88 |
78 // Stop any previous animation. | 89 // Stop any previous animation. |
79 layer()->GetAnimator()->StopAnimating(); | 90 layer()->GetAnimator()->StopAnimating(); |
80 | 91 |
81 // Hide the top items temporarily if showing the view for opening the folder. | 92 // Hide the top items temporarily if showing the view for opening the folder. |
82 if (show) | 93 if (show) |
83 items_grid_view_->SetTopItemViewsVisible(false); | 94 items_grid_view_->SetTopItemViewsVisible(false); |
84 | 95 |
85 // Set initial state. | 96 // Set initial state. |
| 97 layer()->SetOpacity(show ? 0.0f : 1.0f); |
86 SetVisible(true); | 98 SetVisible(true); |
87 layer()->SetOpacity(show ? 0.0f : 1.0f); | 99 UpdateFolderNameVisibility(true); |
88 | 100 |
89 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); | 101 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); |
90 animation.SetTweenType(gfx::Tween::EASE_IN_2); | 102 animation.SetTweenType(gfx::Tween::EASE_IN_2); |
91 animation.AddObserver(this); | 103 animation.AddObserver(this); |
92 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( | 104 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |
93 show ? kFolderTransitionInDurationMs : kFolderTransitionOutDurationMs)); | 105 show ? kFolderTransitionInDurationMs : kFolderTransitionOutDurationMs)); |
94 | 106 |
95 layer()->SetOpacity(show ? 1.0f : 0.0f); | 107 layer()->SetOpacity(show ? 1.0f : 0.0f); |
96 } | 108 } |
97 | 109 |
98 gfx::Size AppListFolderView::GetPreferredSize() { | 110 gfx::Size AppListFolderView::GetPreferredSize() { |
99 const gfx::Size header_size = folder_header_view_->GetPreferredSize(); | 111 const gfx::Size header_size = folder_header_view_->GetPreferredSize(); |
100 const gfx::Size grid_size = items_grid_view_->GetPreferredSize(); | 112 const gfx::Size grid_size = items_grid_view_->GetPreferredSize(); |
101 int width = std::max(header_size.width(), grid_size.width()); | 113 int width = std::max(header_size.width(), grid_size.width()); |
102 int height = header_size.height() + grid_size.height(); | 114 int height = header_size.height() + grid_size.height(); |
103 return gfx::Size(width, height); | 115 return gfx::Size(width, height); |
104 } | 116 } |
105 | 117 |
106 void AppListFolderView::Layout() { | 118 void AppListFolderView::Layout() { |
107 CalculateIdealBounds(); | 119 CalculateIdealBounds(); |
108 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); | 120 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); |
109 } | 121 } |
110 | 122 |
111 bool AppListFolderView::OnKeyPressed(const ui::KeyEvent& event) { | 123 bool AppListFolderView::OnKeyPressed(const ui::KeyEvent& event) { |
112 return items_grid_view_->OnKeyPressed(event); | 124 return items_grid_view_->OnKeyPressed(event); |
113 } | 125 } |
114 | 126 |
115 void AppListFolderView::OnListItemRemoved(size_t index, AppListItem* item) { | 127 void AppListFolderView::OnListItemRemoved(size_t index, AppListItem* item) { |
116 // If the folder item associated with this view is removed from the model, | |
117 // (e.g. the last item in the folder was deleted), reset the view and signal | |
118 // the container view to show the app list instead. | |
119 if (item == folder_item_) { | 128 if (item == folder_item_) { |
120 items_grid_view_->SetItemList(NULL); | 129 items_grid_view_->OnFolderItemRemoved(); |
121 folder_header_view_->SetFolderItem(NULL); | 130 folder_header_view_->OnFolderItemRemoved(); |
122 folder_item_ = NULL; | 131 folder_item_ = NULL; |
| 132 |
| 133 // Do not change state if it is hidden. |
| 134 if (layer()->opacity() == 0.0f) |
| 135 return; |
| 136 |
| 137 // If the folder item associated with this view is removed from the model, |
| 138 // (e.g. the last item in the folder was deleted), reset the view and signal |
| 139 // the container view to show the app list instead. |
123 // Pass NULL to ShowApps() to avoid triggering animation from the deleted | 140 // Pass NULL to ShowApps() to avoid triggering animation from the deleted |
124 // folder. | 141 // folder. |
125 container_view_->ShowApps(NULL); | 142 container_view_->ShowApps(NULL); |
126 } | 143 } |
127 } | 144 } |
128 | 145 |
129 void AppListFolderView::OnImplicitAnimationsCompleted() { | 146 void AppListFolderView::OnImplicitAnimationsCompleted() { |
130 // Show the top items when the opening folder animation is done. | 147 // Show the top items when the opening folder animation is done. |
131 if (layer()->opacity() == 1.0f) | 148 if (layer()->opacity() == 1.0f) |
132 items_grid_view_->SetTopItemViewsVisible(true); | 149 items_grid_view_->SetTopItemViewsVisible(true); |
133 | 150 |
134 if (layer()->opacity() == 0.0f) | 151 // If the view is hidden for reparenting a folder item, it has to be visible, |
| 152 // so that drag_view_ can keep receiving mouse events. |
| 153 if (layer()->opacity() == 0.0f && !hide_for_reparent_) |
135 SetVisible(false); | 154 SetVisible(false); |
| 155 |
| 156 // Set the view bounds to a small rect, so that it won't overlap the root |
| 157 // level apps grid view during folder item reprenting transitional period. |
| 158 if (hide_for_reparent_) |
| 159 SetBoundsRect(gfx::Rect(bounds().x(), bounds().y(), 1, 1)); |
136 } | 160 } |
137 | 161 |
138 void AppListFolderView::CalculateIdealBounds() { | 162 void AppListFolderView::CalculateIdealBounds() { |
139 gfx::Rect rect(GetContentsBounds()); | 163 gfx::Rect rect(GetContentsBounds()); |
140 if (rect.IsEmpty()) | 164 if (rect.IsEmpty()) |
141 return; | 165 return; |
142 | 166 |
143 gfx::Rect header_frame(rect); | 167 gfx::Rect header_frame(rect); |
144 gfx::Size size = folder_header_view_->GetPreferredSize(); | 168 gfx::Size size = folder_header_view_->GetPreferredSize(); |
145 header_frame.set_height(size.height()); | 169 header_frame.set_height(size.height()); |
146 view_model_->set_ideal_bounds(kIndexFolderHeader, header_frame); | 170 view_model_->set_ideal_bounds(kIndexFolderHeader, header_frame); |
147 | 171 |
148 gfx::Rect grid_frame(rect); | 172 gfx::Rect grid_frame(rect); |
149 grid_frame.set_y(header_frame.height()); | 173 grid_frame.Subtract(header_frame); |
150 view_model_->set_ideal_bounds(kIndexChildItems, grid_frame); | 174 view_model_->set_ideal_bounds(kIndexChildItems, grid_frame); |
151 } | 175 } |
152 | 176 |
| 177 void AppListFolderView::StartSetupDragInRootLevelAppsGridView( |
| 178 AppListItemView* original_drag_view, |
| 179 const gfx::Point& drag_point_in_root_grid) { |
| 180 // Converts the original_drag_view's bounds to the coordinate system of |
| 181 // root level grid view. |
| 182 gfx::RectF rect_f(original_drag_view->bounds()); |
| 183 views::View::ConvertRectToTarget(items_grid_view_, |
| 184 container_view_->apps_grid_view(), |
| 185 &rect_f); |
| 186 gfx::Rect rect_in_root_grid_view = gfx::ToEnclosingRect(rect_f); |
| 187 |
| 188 container_view_->apps_grid_view()-> |
| 189 InitiateDragFromReparentItemInRootLevelGridView( |
| 190 original_drag_view, rect_in_root_grid_view, drag_point_in_root_grid); |
| 191 } |
| 192 |
153 gfx::Rect AppListFolderView::GetItemIconBoundsAt(int index) { | 193 gfx::Rect AppListFolderView::GetItemIconBoundsAt(int index) { |
154 AppListItemView* item_view = items_grid_view_->GetItemViewAt(index); | 194 AppListItemView* item_view = items_grid_view_->GetItemViewAt(index); |
155 // Icon bounds relative to AppListItemView. | 195 // Icon bounds relative to AppListItemView. |
156 const gfx::Rect icon_bounds = item_view->GetIconBounds(); | 196 const gfx::Rect icon_bounds = item_view->GetIconBounds(); |
157 gfx::Rect to_apps_grid_view = item_view->ConvertRectToParent(icon_bounds); | 197 gfx::Rect to_apps_grid_view = item_view->ConvertRectToParent(icon_bounds); |
158 gfx::Rect to_folder = | 198 gfx::Rect to_folder = |
159 items_grid_view_->ConvertRectToParent(to_apps_grid_view); | 199 items_grid_view_->ConvertRectToParent(to_apps_grid_view); |
160 | 200 |
161 // Get the icon image's bound. | 201 // Get the icon image's bound. |
162 to_folder.ClampToCenteredSize( | 202 to_folder.ClampToCenteredSize( |
163 gfx::Size(kPreferredIconDimension, kPreferredIconDimension)); | 203 gfx::Size(kPreferredIconDimension, kPreferredIconDimension)); |
164 | 204 |
165 return to_folder; | 205 return to_folder; |
166 } | 206 } |
167 | 207 |
| 208 void AppListFolderView::UpdateFolderViewBackground(bool show_bubble) { |
| 209 if (hide_for_reparent_) |
| 210 return; |
| 211 |
| 212 // Before showing the folder container inking bubble, hide the folder name. |
| 213 if (show_bubble) |
| 214 UpdateFolderNameVisibility(false); |
| 215 |
| 216 container_view_->folder_background_view()->UpdateFolderContainerBubble( |
| 217 show_bubble ? FolderBackgroundView::SHOW_BUBBLE : |
| 218 FolderBackgroundView::HIDE_BUBBLE); |
| 219 } |
| 220 |
| 221 void AppListFolderView::UpdateFolderNameVisibility(bool visible) { |
| 222 folder_header_view_->UpdateFolderNameVisibility(visible); |
| 223 } |
| 224 |
| 225 bool AppListFolderView::IsPointOutsideOfFolderBoundray( |
| 226 const gfx::Point& point) { |
| 227 if (!GetLocalBounds().Contains(point)) |
| 228 return true; |
| 229 |
| 230 gfx::Point center = GetLocalBounds().CenterPoint(); |
| 231 float delta = (point - center).Length(); |
| 232 return delta > container_view_->folder_background_view()-> |
| 233 GetFolderContainerBubbleRadius() + kOutOfFolderContainerBubbleDelta; |
| 234 } |
| 235 |
| 236 // When user drags a folder item out of the folder boundary ink bubble, the |
| 237 // folder view UI will be hidden, and switch back to top level AppsGridView. |
| 238 // The dragged item will seamlessly move on the top level AppsGridView. |
| 239 // In order to achieve the above, we keep the folder view and its child grid |
| 240 // view visible with opacity 0, so that the drag_view_ on the hidden grid view |
| 241 // will keep receiving mouse event. At the same time, we initiated a new |
| 242 // drag_view_ in the top level grid view, and keep it moving with the hidden |
| 243 // grid view's drag_view_, so that the dragged item can be engaged in drag and |
| 244 // drop flow in the top level grid view. During the reparenting process, the |
| 245 // drag_view_ in hidden grid view will dispatch the drag and drop event to |
| 246 // the top level grid view, until the drag ends. |
| 247 void AppListFolderView::ReparentItem( |
| 248 AppListItemView* original_drag_view, |
| 249 const gfx::Point& drag_point_in_folder_grid) { |
| 250 // Convert the drag point relative to the root level AppsGridView. |
| 251 gfx::Point to_root_level_grid = drag_point_in_folder_grid; |
| 252 ConvertPointToTarget(items_grid_view_, |
| 253 container_view_->apps_grid_view(), |
| 254 &to_root_level_grid); |
| 255 StartSetupDragInRootLevelAppsGridView(original_drag_view, to_root_level_grid); |
| 256 container_view_->ReparentFolderItemTransit(folder_item_); |
| 257 } |
| 258 |
| 259 void AppListFolderView::DispatchDragEventForReparent( |
| 260 AppsGridView::Pointer pointer, |
| 261 const ui::LocatedEvent& event) { |
| 262 container_view_->apps_grid_view()->UpdateDragFromReparentItem(pointer, event); |
| 263 } |
| 264 |
| 265 void AppListFolderView::DispatchEndDragEventForReparent( |
| 266 bool events_forwarded_to_drag_drop_host) { |
| 267 container_view_->apps_grid_view()-> |
| 268 EndDragFromReparentItemInRootLevel(events_forwarded_to_drag_drop_host); |
| 269 } |
| 270 |
168 void AppListFolderView::NavigateBack(AppListFolderItem* item, | 271 void AppListFolderView::NavigateBack(AppListFolderItem* item, |
169 const ui::Event& event_flags) { | 272 const ui::Event& event_flags) { |
170 container_view_->ShowApps(item); | 273 container_view_->ShowApps(item); |
171 } | 274 } |
172 | 275 |
173 } // namespace app_list | 276 } // namespace app_list |
OLD | NEW |