Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / app_list / views / app_list_folder_view.cc
index 69fa761..435ef54 100644 (file)
 #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,
@@ -38,17 +45,20 @@ AppListFolderView::AppListFolderView(AppsContainerView* container_view,
     : container_view_(container_view),
       folder_header_view_(new FolderHeaderView(this)),
       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);
 
   items_grid_view_ = new AppsGridView(
       app_list_main_view, pagination_model_.get(), NULL);
   items_grid_view_->set_is_root_level(false);
-  items_grid_view_->SetLayout(kPreferredIconDimension,
-                              kPreferredCols,
-                              kPreferredRows);
+  items_grid_view_->SetLayout(
+      kPreferredIconDimension,
+      container_view->apps_grid_view()->cols(),
+      container_view->apps_grid_view()->rows_per_page());
   items_grid_view_->SetModel(model);
   AddChildView(items_grid_view_);
   view_model_->Add(items_grid_view_, kIndexChildItems);
@@ -57,9 +67,12 @@ AppListFolderView::AppListFolderView(AppsContainerView* container_view,
   SetPaintToLayer(true);
   SetFillsBoundsOpaquely(false);
 #endif
+
+  model_->item_list()->AddObserver(this);
 }
 
 AppListFolderView::~AppListFolderView() {
+  model_->item_list()->RemoveObserver(this);
   // Make sure |items_grid_view_| is deleted before |pagination_model_|.
   RemoveAllChildViews(true);
 }
@@ -70,7 +83,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();
 
@@ -79,11 +95,13 @@ 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);
+  animation.SetTweenType(
+      show ? kFolderFadeInTweenType : kFolderFadeOutTweenType);
   animation.AddObserver(this);
   animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
       show ? kFolderTransitionInDurationMs : kFolderTransitionOutDurationMs));
@@ -108,13 +126,39 @@ bool AppListFolderView::OnKeyPressed(const ui::KeyEvent& event) {
   return items_grid_view_->OnKeyPressed(event);
 }
 
+void AppListFolderView::OnListItemRemoved(size_t index, AppListItem* item) {
+  if (item == folder_item_) {
+    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);
+  }
+}
+
 void AppListFolderView::OnImplicitAnimationsCompleted() {
   // Show the top items when the opening folder animation is done.
   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() {
@@ -128,10 +172,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.
@@ -147,6 +207,75 @@ 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::HideViewImmediately() {
+  SetVisible(false);
+  hide_for_reparent_ = false;
+}
+
 void AppListFolderView::NavigateBack(AppListFolderItem* item,
                                      const ui::Event& event_flags) {
   container_view_->ShowApps(item);