Index: ui/app_list/views/app_list_folder_view.cc |
diff --git a/ui/app_list/views/app_list_folder_view.cc b/ui/app_list/views/app_list_folder_view.cc |
index 03c27a7f06c26542805a984c3a236d736ad49397..78273ef6aff416cdbec839e955e6f9703fe02611 100644 |
--- a/ui/app_list/views/app_list_folder_view.cc |
+++ b/ui/app_list/views/app_list_folder_view.cc |
@@ -15,9 +15,11 @@ |
#include "ui/app_list/views/apps_container_view.h" |
#include "ui/app_list/views/apps_grid_view.h" |
#include "ui/app_list/views/contents_view.h" |
+#include "ui/app_list/views/folder_background_view.h" |
#include "ui/app_list/views/folder_header_view.h" |
#include "ui/compositor/scoped_layer_animation_settings.h" |
#include "ui/events/event.h" |
+#include "ui/gfx/rect_conversions.h" |
#include "ui/views/view_model.h" |
#include "ui/views/view_model_utils.h" |
@@ -29,6 +31,11 @@ namespace { |
const int kIndexFolderHeader = 0; |
const int kIndexChildItems = 1; |
+// Threshold for the distance from the center of the item to the circle of the |
+// folder container ink bubble, beyond which, the item is considered dragged |
+// out of the folder boundary. |
+const int kOutOfFolderContainerBubbleDelta = 30; |
+ |
} // namespace |
AppListFolderView::AppListFolderView(AppsContainerView* container_view, |
@@ -40,7 +47,8 @@ AppListFolderView::AppListFolderView(AppsContainerView* container_view, |
view_model_(new views::ViewModel), |
model_(model), |
folder_item_(NULL), |
- pagination_model_(new PaginationModel) { |
+ pagination_model_(new PaginationModel), |
+ hide_for_reparent_(false) { |
AddChildView(folder_header_view_); |
view_model_->Add(folder_header_view_, kIndexFolderHeader); |
@@ -74,7 +82,10 @@ void AppListFolderView::SetAppListFolderItem(AppListFolderItem* folder) { |
folder_header_view_->SetFolderItem(folder_item_); |
} |
-void AppListFolderView::ScheduleShowHideAnimation(bool show) { |
+void AppListFolderView::ScheduleShowHideAnimation(bool show, |
+ bool hide_for_reparent) { |
+ hide_for_reparent_ = hide_for_reparent; |
+ |
// Stop any previous animation. |
layer()->GetAnimator()->StopAnimating(); |
@@ -83,8 +94,9 @@ void AppListFolderView::ScheduleShowHideAnimation(bool show) { |
items_grid_view_->SetTopItemViewsVisible(false); |
// Set initial state. |
- SetVisible(true); |
layer()->SetOpacity(show ? 0.0f : 1.0f); |
+ SetVisible(true); |
+ UpdateFolderNameVisibility(true); |
ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); |
animation.SetTweenType(gfx::Tween::EASE_IN_2); |
@@ -113,13 +125,18 @@ bool AppListFolderView::OnKeyPressed(const ui::KeyEvent& event) { |
} |
void AppListFolderView::OnListItemRemoved(size_t index, AppListItem* item) { |
- // If the folder item associated with this view is removed from the model, |
- // (e.g. the last item in the folder was deleted), reset the view and signal |
- // the container view to show the app list instead. |
if (item == folder_item_) { |
- items_grid_view_->SetItemList(NULL); |
- folder_header_view_->SetFolderItem(NULL); |
+ items_grid_view_->OnFolderItemRemoved(); |
+ folder_header_view_->OnFolderItemRemoved(); |
folder_item_ = NULL; |
+ |
+ // Do not change state if it is hidden. |
+ if (layer()->opacity() == 0.0f) |
+ return; |
+ |
+ // If the folder item associated with this view is removed from the model, |
+ // (e.g. the last item in the folder was deleted), reset the view and signal |
+ // the container view to show the app list instead. |
// Pass NULL to ShowApps() to avoid triggering animation from the deleted |
// folder. |
container_view_->ShowApps(NULL); |
@@ -131,8 +148,15 @@ void AppListFolderView::OnImplicitAnimationsCompleted() { |
if (layer()->opacity() == 1.0f) |
items_grid_view_->SetTopItemViewsVisible(true); |
- if (layer()->opacity() == 0.0f) |
+ // If the view is hidden for reparenting a folder item, it has to be visible, |
+ // so that drag_view_ can keep receiving mouse events. |
+ if (layer()->opacity() == 0.0f && !hide_for_reparent_) |
SetVisible(false); |
+ |
+ // Set the view bounds to a small rect, so that it won't overlap the root |
+ // level apps grid view during folder item reprenting transitional period. |
+ if (hide_for_reparent_) |
+ SetBoundsRect(gfx::Rect(bounds().x(), bounds().y(), 1, 1)); |
} |
void AppListFolderView::CalculateIdealBounds() { |
@@ -146,10 +170,26 @@ void AppListFolderView::CalculateIdealBounds() { |
view_model_->set_ideal_bounds(kIndexFolderHeader, header_frame); |
gfx::Rect grid_frame(rect); |
- grid_frame.set_y(header_frame.height()); |
+ grid_frame.Subtract(header_frame); |
view_model_->set_ideal_bounds(kIndexChildItems, grid_frame); |
} |
+void AppListFolderView::StartSetupDragInRootLevelAppsGridView( |
+ AppListItemView* original_drag_view, |
+ const gfx::Point& drag_point_in_root_grid) { |
+ // Converts the original_drag_view's bounds to the coordinate system of |
+ // root level grid view. |
+ gfx::RectF rect_f(original_drag_view->bounds()); |
+ views::View::ConvertRectToTarget(items_grid_view_, |
+ container_view_->apps_grid_view(), |
+ &rect_f); |
+ gfx::Rect rect_in_root_grid_view = gfx::ToEnclosingRect(rect_f); |
+ |
+ container_view_->apps_grid_view()-> |
+ InitiateDragFromReparentItemInRootLevelGridView( |
+ original_drag_view, rect_in_root_grid_view, drag_point_in_root_grid); |
+} |
+ |
gfx::Rect AppListFolderView::GetItemIconBoundsAt(int index) { |
AppListItemView* item_view = items_grid_view_->GetItemViewAt(index); |
// Icon bounds relative to AppListItemView. |
@@ -165,6 +205,69 @@ gfx::Rect AppListFolderView::GetItemIconBoundsAt(int index) { |
return to_folder; |
} |
+void AppListFolderView::UpdateFolderViewBackground(bool show_bubble) { |
+ if (hide_for_reparent_) |
+ return; |
+ |
+ // Before showing the folder container inking bubble, hide the folder name. |
+ if (show_bubble) |
+ UpdateFolderNameVisibility(false); |
+ |
+ container_view_->folder_background_view()->UpdateFolderContainerBubble( |
+ show_bubble ? FolderBackgroundView::SHOW_BUBBLE : |
+ FolderBackgroundView::HIDE_BUBBLE); |
+} |
+ |
+void AppListFolderView::UpdateFolderNameVisibility(bool visible) { |
+ folder_header_view_->UpdateFolderNameVisibility(visible); |
+} |
+ |
+bool AppListFolderView::IsPointOutsideOfFolderBoundray( |
+ const gfx::Point& point) { |
+ if (!GetLocalBounds().Contains(point)) |
+ return true; |
+ |
+ gfx::Point center = GetLocalBounds().CenterPoint(); |
+ float delta = (point - center).Length(); |
+ return delta > container_view_->folder_background_view()-> |
+ GetFolderContainerBubbleRadius() + kOutOfFolderContainerBubbleDelta; |
+} |
+ |
+// When user drags a folder item out of the folder boundary ink bubble, the |
+// folder view UI will be hidden, and switch back to top level AppsGridView. |
+// The dragged item will seamlessly move on the top level AppsGridView. |
+// In order to achieve the above, we keep the folder view and its child grid |
+// view visible with opacity 0, so that the drag_view_ on the hidden grid view |
+// will keep receiving mouse event. At the same time, we initiated a new |
+// drag_view_ in the top level grid view, and keep it moving with the hidden |
+// grid view's drag_view_, so that the dragged item can be engaged in drag and |
+// drop flow in the top level grid view. During the reparenting process, the |
+// drag_view_ in hidden grid view will dispatch the drag and drop event to |
+// the top level grid view, until the drag ends. |
+void AppListFolderView::ReparentItem( |
+ AppListItemView* original_drag_view, |
+ const gfx::Point& drag_point_in_folder_grid) { |
+ // Convert the drag point relative to the root level AppsGridView. |
+ gfx::Point to_root_level_grid = drag_point_in_folder_grid; |
+ ConvertPointToTarget(items_grid_view_, |
+ container_view_->apps_grid_view(), |
+ &to_root_level_grid); |
+ StartSetupDragInRootLevelAppsGridView(original_drag_view, to_root_level_grid); |
+ container_view_->ReparentFolderItemTransit(folder_item_); |
+} |
+ |
+void AppListFolderView::DispatchDragEventForReparent( |
+ AppsGridView::Pointer pointer, |
+ const ui::LocatedEvent& event) { |
+ container_view_->apps_grid_view()->UpdateDragFromReparentItem(pointer, event); |
+} |
+ |
+void AppListFolderView::DispatchEndDragEventForReparent( |
+ bool events_forwarded_to_drag_drop_host) { |
+ container_view_->apps_grid_view()-> |
+ EndDragFromReparentItemInRootLevel(events_forwarded_to_drag_drop_host); |
+} |
+ |
void AppListFolderView::NavigateBack(AppListFolderItem* item, |
const ui::Event& event_flags) { |
container_view_->ShowApps(item); |