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

Side by Side Diff: ui/app_list/views/apps_grid_view.cc

Issue 136303008: Implement ui for re-parenting an item from an app list folder to another position or folder in the … (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review comments. Created 6 years, 10 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
« no previous file with comments | « ui/app_list/views/apps_grid_view.h ('k') | ui/app_list/views/contents_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_grid_view.h" 5 #include "ui/app_list/views/apps_grid_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 10
11 #include "base/guid.h" 11 #include "base/guid.h"
12 #include "content/public/browser/web_contents.h" 12 #include "content/public/browser/web_contents.h"
13 #include "ui/app_list/app_list_constants.h" 13 #include "ui/app_list/app_list_constants.h"
14 #include "ui/app_list/app_list_folder_item.h" 14 #include "ui/app_list/app_list_folder_item.h"
15 #include "ui/app_list/app_list_item.h" 15 #include "ui/app_list/app_list_item.h"
16 #include "ui/app_list/app_list_switches.h" 16 #include "ui/app_list/app_list_switches.h"
17 #include "ui/app_list/pagination_model.h" 17 #include "ui/app_list/pagination_model.h"
18 #include "ui/app_list/views/app_list_drag_and_drop_host.h" 18 #include "ui/app_list/views/app_list_drag_and_drop_host.h"
19 #include "ui/app_list/views/app_list_folder_view.h" 19 #include "ui/app_list/views/app_list_folder_view.h"
20 #include "ui/app_list/views/app_list_item_view.h" 20 #include "ui/app_list/views/app_list_item_view.h"
21 #include "ui/app_list/views/apps_grid_view_delegate.h" 21 #include "ui/app_list/views/apps_grid_view_delegate.h"
22 #include "ui/app_list/views/page_switcher.h" 22 #include "ui/app_list/views/page_switcher.h"
23 #include "ui/app_list/views/pulsing_block_view.h" 23 #include "ui/app_list/views/pulsing_block_view.h"
24 #include "ui/app_list/views/top_icon_animation_view.h"
24 #include "ui/compositor/scoped_layer_animation_settings.h" 25 #include "ui/compositor/scoped_layer_animation_settings.h"
25 #include "ui/events/event.h" 26 #include "ui/events/event.h"
26 #include "ui/gfx/animation/animation.h" 27 #include "ui/gfx/animation/animation.h"
27 #include "ui/views/border.h" 28 #include "ui/views/border.h"
28 #include "ui/views/controls/webview/webview.h" 29 #include "ui/views/controls/webview/webview.h"
29 #include "ui/views/view_model_utils.h" 30 #include "ui/views/view_model_utils.h"
30 #include "ui/views/widget/widget.h" 31 #include "ui/views/widget/widget.h"
31 32
32 #if defined(USE_AURA) 33 #if defined(USE_AURA)
33 #include "ui/aura/root_window.h" 34 #include "ui/aura/root_window.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 80
80 // The drag and drop proxy should get scaled by this factor. 81 // The drag and drop proxy should get scaled by this factor.
81 const float kDragAndDropProxyScale = 1.5f; 82 const float kDragAndDropProxyScale = 1.5f;
82 83
83 // Delays in milliseconds to show folder dropping preview circle. 84 // Delays in milliseconds to show folder dropping preview circle.
84 const int kFolderDroppingDelay = 250; 85 const int kFolderDroppingDelay = 250;
85 86
86 // Delays in milliseconds to show re-order preview. 87 // Delays in milliseconds to show re-order preview.
87 const int kReorderDelay = 50; 88 const int kReorderDelay = 50;
88 89
90 // Delays in milliseconds to show folder item reparent UI.
91 const int kFolderItemReparentDealy = 50;
92
89 // Radius of the circle, in which if entered, show folder dropping preview 93 // Radius of the circle, in which if entered, show folder dropping preview
90 // UI. 94 // UI.
91 const int kFolderDroppingCircleRadius = 15; 95 const int kFolderDroppingCircleRadius = 15;
92 96
93 // Radius of the circle, in which if entered, show re-order preview. 97 // Radius of the circle, in which if entered, show re-order preview.
94 const int kReorderDroppingCircleRadius = 30; 98 const int kReorderDroppingCircleRadius = 30;
95 99
96 // Max items allowed in a folder. 100 // Max items allowed in a folder.
97 size_t kMaxFolderItems = 16; 101 size_t kMaxFolderItems = 16;
98 102
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 drag_view_(NULL), 313 drag_view_(NULL),
310 drag_start_page_(-1), 314 drag_start_page_(-1),
311 drag_pointer_(NONE), 315 drag_pointer_(NONE),
312 drop_attempt_(DROP_FOR_NONE), 316 drop_attempt_(DROP_FOR_NONE),
313 drag_and_drop_host_(NULL), 317 drag_and_drop_host_(NULL),
314 forward_events_to_drag_and_drop_host_(false), 318 forward_events_to_drag_and_drop_host_(false),
315 page_flip_target_(-1), 319 page_flip_target_(-1),
316 page_flip_delay_in_ms_(kPageFlipDelayInMs), 320 page_flip_delay_in_ms_(kPageFlipDelayInMs),
317 bounds_animator_(this), 321 bounds_animator_(this),
318 is_root_level_(true), 322 is_root_level_(true),
319 activated_item_view_(NULL) { 323 activated_item_view_(NULL),
324 dragging_for_reparent_item_(false) {
320 SetPaintToLayer(true); 325 SetPaintToLayer(true);
321 SetFillsBoundsOpaquely(false); 326 SetFillsBoundsOpaquely(false);
322 327
323 pagination_model_->AddObserver(this); 328 pagination_model_->AddObserver(this);
324 AddChildView(page_switcher_view_); 329 AddChildView(page_switcher_view_);
325 330
326 if (start_page_contents) { 331 if (start_page_contents) {
327 start_page_view_ = 332 start_page_view_ =
328 new views::WebView(start_page_contents->GetBrowserContext()); 333 new views::WebView(start_page_contents->GetBrowserContext());
329 start_page_view_->SetWebContents(start_page_contents); 334 start_page_view_->SetWebContents(start_page_contents);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 void AppsGridView::CleanUpSynchronousDrag() { 476 void AppsGridView::CleanUpSynchronousDrag() {
472 #if defined(OS_WIN) 477 #if defined(OS_WIN)
473 synchronous_drag_ = NULL; 478 synchronous_drag_ = NULL;
474 #endif 479 #endif
475 } 480 }
476 481
477 void AppsGridView::UpdateDragFromItem(Pointer pointer, 482 void AppsGridView::UpdateDragFromItem(Pointer pointer,
478 const ui::LocatedEvent& event) { 483 const ui::LocatedEvent& event) {
479 DCHECK(drag_view_); 484 DCHECK(drag_view_);
480 485
486 if (!is_root_level_)
487 UpdateDragStateInsideFolder(pointer, event);
488
481 gfx::Point drag_point_in_grid_view; 489 gfx::Point drag_point_in_grid_view;
482 ExtractDragLocation(event, &drag_point_in_grid_view); 490 ExtractDragLocation(event, &drag_point_in_grid_view);
483 UpdateDrag(pointer, drag_point_in_grid_view); 491 UpdateDrag(pointer, drag_point_in_grid_view);
484 if (!dragging()) 492 if (!dragging())
485 return; 493 return;
486 494
487 // If a drag and drop host is provided, see if the drag operation needs to be 495 // If a drag and drop host is provided, see if the drag operation needs to be
488 // forwarded. 496 // forwarded.
489 gfx::Point location_in_screen = drag_point_in_grid_view; 497 gfx::Point location_in_screen = drag_point_in_grid_view;
490 views::View::ConvertPointToScreen(this, &location_in_screen); 498 views::View::ConvertPointToScreen(this, &location_in_screen);
(...skipping 10 matching lines...) Expand all
501 if (RunSynchronousDrag()) 509 if (RunSynchronousDrag())
502 return; 510 return;
503 511
504 gfx::Vector2d drag_vector(point - drag_start_grid_view_); 512 gfx::Vector2d drag_vector(point - drag_start_grid_view_);
505 if (!dragging() && ExceededDragThreshold(drag_vector)) { 513 if (!dragging() && ExceededDragThreshold(drag_vector)) {
506 drag_pointer_ = pointer; 514 drag_pointer_ = pointer;
507 // Move the view to the front so that it appears on top of other views. 515 // Move the view to the front so that it appears on top of other views.
508 ReorderChildView(drag_view_, -1); 516 ReorderChildView(drag_view_, -1);
509 bounds_animator_.StopAnimatingView(drag_view_); 517 bounds_animator_.StopAnimatingView(drag_view_);
510 StartSettingUpSynchronousDrag(); 518 StartSettingUpSynchronousDrag();
511 StartDragAndDropHostDrag(point); 519 if (!dragging_for_reparent_item_)
520 StartDragAndDropHostDrag(point);
512 } 521 }
513 522
514 if (drag_pointer_ != pointer) 523 if (drag_pointer_ != pointer)
515 return; 524 return;
516 525
517 last_drag_point_ = point; 526 last_drag_point_ = point;
518 const Index last_drop_target = drop_target_; 527 const Index last_drop_target = drop_target_;
519 DropAttempt last_drop_attempt = drop_attempt_; 528 DropAttempt last_drop_attempt = drop_attempt_;
520 CalculateDropTarget(last_drag_point_, false); 529 CalculateDropTarget(last_drag_point_, false);
521 530
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 SetAsFolderDroppingTarget(last_drop_target, false); 564 SetAsFolderDroppingTarget(last_drop_target, false);
556 } 565 }
557 566
558 drag_view_->SetPosition(drag_view_start_ + drag_vector); 567 drag_view_->SetPosition(drag_view_start_ + drag_vector);
559 } 568 }
560 569
561 void AppsGridView::EndDrag(bool cancel) { 570 void AppsGridView::EndDrag(bool cancel) {
562 // EndDrag was called before if |drag_view_| is NULL. 571 // EndDrag was called before if |drag_view_| is NULL.
563 if (!drag_view_) 572 if (!drag_view_)
564 return; 573 return;
574
565 // Coming here a drag and drop was in progress. 575 // Coming here a drag and drop was in progress.
566 bool landed_in_drag_and_drop_host = forward_events_to_drag_and_drop_host_; 576 bool landed_in_drag_and_drop_host = forward_events_to_drag_and_drop_host_;
567 if (forward_events_to_drag_and_drop_host_) { 577 if (forward_events_to_drag_and_drop_host_) {
578 DCHECK(!IsDraggingForReparentInRootLevelGridView());
568 forward_events_to_drag_and_drop_host_ = false; 579 forward_events_to_drag_and_drop_host_ = false;
569 drag_and_drop_host_->EndDrag(cancel); 580 drag_and_drop_host_->EndDrag(cancel);
581 if (IsDraggingForReprentInHiddenGridView()) {
582 static_cast<AppListFolderView*>(parent())->
583 DispatchEndDragEventForReparent(true);
584 }
570 } else if (!cancel && dragging()) { 585 } else if (!cancel && dragging()) {
571 CalculateDropTarget(last_drag_point_, true); 586 if (IsDraggingForReprentInHiddenGridView()) {
572 if (IsValidIndex(drop_target_)) { 587 // Forward the EndDrag event to the root level grid view.
573 if (!EnableFolderDragDropUI()) { 588 static_cast<AppListFolderView*>(parent())->
574 MoveItemInModel(drag_view_, drop_target_); 589 DispatchEndDragEventForReparent(false);
575 } else { 590 EndDragForReparentInHiddenFolderGridView();
576 if (drop_attempt_ == DROP_FOR_REORDER) 591 return;
577 MoveItemInModel(drag_view_, drop_target_); 592 } else {
578 else if (drop_attempt_ == DROP_FOR_FOLDER) 593 // Regular drag ending path, ie, not for reparenting.
579 MoveItemToFolder(drag_view_, drop_target_); 594 CalculateDropTarget(last_drag_point_, true);
595 if (IsValidIndex(drop_target_)) {
596 if (!EnableFolderDragDropUI()) {
597 MoveItemInModel(drag_view_, drop_target_);
598 } else {
599 if (drop_attempt_ == DROP_FOR_REORDER)
600 MoveItemInModel(drag_view_, drop_target_);
601 else if (drop_attempt_ == DROP_FOR_FOLDER)
602 MoveItemToFolder(drag_view_, drop_target_);
603 }
580 } 604 }
581 } 605 }
582 } 606 }
583 607
584 if (drag_and_drop_host_) { 608 if (drag_and_drop_host_) {
585 // If we had a drag and drop proxy icon, we delete it and make the real 609 // If we had a drag and drop proxy icon, we delete it and make the real
586 // item visible again. 610 // item visible again.
587 drag_and_drop_host_->DestroyDragIconProxy(); 611 drag_and_drop_host_->DestroyDragIconProxy();
588 if (landed_in_drag_and_drop_host) { 612 if (landed_in_drag_and_drop_host) {
589 // Move the item directly to the target location, avoiding the "zip back" 613 // Move the item directly to the target location, avoiding the "zip back"
590 // animation if the user was pinning it to the shelf. 614 // animation if the user was pinning it to the shelf.
591 int i = drop_target_.slot; 615 int i = drop_target_.slot;
592 gfx::Rect bounds = view_model_.ideal_bounds(i); 616 gfx::Rect bounds = view_model_.ideal_bounds(i);
593 drag_view_->SetBoundsRect(bounds); 617 drag_view_->SetBoundsRect(bounds);
594 } 618 }
595 // Fade in slowly if it landed in the shelf. 619 // Fade in slowly if it landed in the shelf.
596 SetViewHidden(drag_view_, 620 SetViewHidden(drag_view_,
597 false /* hide */, 621 false /* show */,
598 !landed_in_drag_and_drop_host /* animate */); 622 !landed_in_drag_and_drop_host /* animate */);
599 } 623 }
600 624
601 // The drag can be ended after the synchronous drag is created but before it 625 // The drag can be ended after the synchronous drag is created but before it
602 // is Run(). 626 // is Run().
603 CleanUpSynchronousDrag(); 627 CleanUpSynchronousDrag();
604 628
605 SetAsFolderDroppingTarget(drop_target_, false); 629 SetAsFolderDroppingTarget(drop_target_, false);
606 drop_attempt_ = DROP_FOR_NONE; 630 drop_attempt_ = DROP_FOR_NONE;
607 drag_pointer_ = NONE; 631 drag_pointer_ = NONE;
608 drop_target_ = Index(); 632 drop_target_ = Index();
609 drag_view_->OnDragEnded(); 633 drag_view_->OnDragEnded();
610 drag_view_ = NULL; 634 drag_view_ = NULL;
611 drag_start_grid_view_ = gfx::Point(); 635 drag_start_grid_view_ = gfx::Point();
612 drag_start_page_ = -1; 636 drag_start_page_ = -1;
613 drag_view_offset_ = gfx::Point(); 637 drag_view_offset_ = gfx::Point();
638 if (IsDraggingForReprentInHiddenGridView())
639 dragging_for_reparent_item_ = false;
614 AnimateToIdealBounds(); 640 AnimateToIdealBounds();
615 641
616 StopPageFlipTimer(); 642 StopPageFlipTimer();
643
644 // If user releases mouse inside a folder's grid view, burst the folder
645 // container ink bubble.
646 if (!is_root_level_ && !IsDraggingForReprentInHiddenGridView()) {
647 static_cast<AppListFolderView*>(parent())->
648 UpdateFolderViewBackground(false);
649 }
617 } 650 }
618 651
619 void AppsGridView::StopPageFlipTimer() { 652 void AppsGridView::StopPageFlipTimer() {
620 page_flip_timer_.Stop(); 653 page_flip_timer_.Stop();
621 page_flip_target_ = -1; 654 page_flip_target_ = -1;
622 } 655 }
623 656
624 AppListItemView* AppsGridView::GetItemViewAt(int index) const { 657 AppListItemView* AppsGridView::GetItemViewAt(int index) const {
625 DCHECK(index >= 0 && index < view_model_.view_size()); 658 DCHECK(index >= 0 && index < view_model_.view_size());
626 return static_cast<AppListItemView*>(view_model_.view_at(index)); 659 return static_cast<AppListItemView*>(view_model_.view_at(index));
(...skipping 16 matching lines...) Expand all
643 676
644 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); 677 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
645 animation.AddObserver(this); 678 animation.AddObserver(this);
646 animation.SetTweenType(gfx::Tween::EASE_IN_2); 679 animation.SetTweenType(gfx::Tween::EASE_IN_2);
647 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( 680 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
648 show ? kFolderTransitionInDurationMs : kFolderTransitionOutDurationMs)); 681 show ? kFolderTransitionInDurationMs : kFolderTransitionOutDurationMs));
649 682
650 layer()->SetOpacity(show ? 1.0f : 0.0f); 683 layer()->SetOpacity(show ? 1.0f : 0.0f);
651 } 684 }
652 685
686 void AppsGridView::InitiateDragFromReparentItemInRootLevelGridView(
687 AppListItemView* original_drag_view,
688 const gfx::Rect& drag_view_rect,
689 const gfx::Point& drag_point) {
690 DCHECK(original_drag_view && !drag_view_);
691 DCHECK(!dragging_for_reparent_item_);
692
693 // Create a new AppListItemView to duplicate the original_drag_view in the
694 // folder's grid view.
695 AppListItemView* view = new AppListItemView(this, original_drag_view->item());
696 AddChildView(view);
697 drag_view_ = view;
698 drag_view_->SetPaintToLayer(true);
699 // Note: For testing purpose, SetFillsBoundsOpaquely can be set to true to
700 // show the gray background.
701 drag_view_->SetFillsBoundsOpaquely(false);
702 drag_view_->SetIconSize(icon_size_);
703 drag_view_->SetBoundsRect(drag_view_rect);
704 drag_view_->SetDragUIState(); // Hide the title of the drag_view_.
705
706 // Hide the drag_view_ for drag icon proxy.
707 SetViewHidden(drag_view_,
708 true /* hide */,
709 true /* no animate */);
710
711 // Add drag_view_ to the end of the view_model_.
712 view_model_.Add(drag_view_, view_model_.view_size());
713
714 drag_start_page_ = pagination_model_->selected_page();
715 drag_start_grid_view_ = drag_point;
716
717 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y());
718
719 // Set the flag in root level grid view.
720 dragging_for_reparent_item_ = true;
721 }
722
723 void AppsGridView::UpdateDragFromReparentItem(
724 Pointer pointer,
725 const ui::LocatedEvent& event) {
726 DCHECK(drag_view_);
727 DCHECK(IsDraggingForReparentInRootLevelGridView());
728
729 gfx::Point drag_point_in_grid_view;
730 ExtractDragLocation(event, &drag_point_in_grid_view);
731 UpdateDrag(pointer, drag_point_in_grid_view);
732 }
733
653 bool AppsGridView::IsDraggedView(const views::View* view) const { 734 bool AppsGridView::IsDraggedView(const views::View* view) const {
654 return drag_view_ == view; 735 return drag_view_ == view;
655 } 736 }
656 737
657 void AppsGridView::SetDragAndDropHostOfCurrentAppList( 738 void AppsGridView::SetDragAndDropHostOfCurrentAppList(
658 ApplicationDragAndDropHost* drag_and_drop_host) { 739 ApplicationDragAndDropHost* drag_and_drop_host) {
659 drag_and_drop_host_ = drag_and_drop_host; 740 drag_and_drop_host_ = drag_and_drop_host;
660 } 741 }
661 742
662 void AppsGridView::Prerender(int page_index) { 743 void AppsGridView::Prerender(int page_index) {
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 // Try to find the nearest target for folder dropping or re-ordering. 1276 // Try to find the nearest target for folder dropping or re-ordering.
1196 drop_target_ = GetNearestTileForDragView(); 1277 drop_target_ = GetNearestTileForDragView();
1197 } 1278 }
1198 } 1279 }
1199 1280
1200 void AppsGridView::OnReorderTimer() { 1281 void AppsGridView::OnReorderTimer() {
1201 if (drop_attempt_ == DROP_FOR_REORDER) 1282 if (drop_attempt_ == DROP_FOR_REORDER)
1202 AnimateToIdealBounds(); 1283 AnimateToIdealBounds();
1203 } 1284 }
1204 1285
1286 void AppsGridView::OnFolderItemReparentTimer() {
1287 DCHECK(!is_root_level_);
1288 if (drag_out_of_folder_container_) {
1289 static_cast<AppListFolderView*>(parent())->ReparentItem(
1290 drag_view_, last_drag_point_);
1291
1292 // Set the flag in the folder's grid view.
1293 dragging_for_reparent_item_ = true;
1294
1295 // Do not observe any data change since it is going to be hidden.
1296 item_list_->RemoveObserver(this);
1297 item_list_ = NULL;
1298 }
1299 }
1300
1205 void AppsGridView::OnFolderDroppingTimer() { 1301 void AppsGridView::OnFolderDroppingTimer() {
1206 if (drop_attempt_ == DROP_FOR_FOLDER) 1302 if (drop_attempt_ == DROP_FOR_FOLDER)
1207 SetAsFolderDroppingTarget(drop_target_, true); 1303 SetAsFolderDroppingTarget(drop_target_, true);
1208 } 1304 }
1209 1305
1306 void AppsGridView::UpdateDragStateInsideFolder(
1307 Pointer pointer,
1308 const ui::LocatedEvent& event) {
1309 if (IsDraggingForReprentInHiddenGridView()) {
1310 // Dispatch drag event to root level grid view for re-parenting folder
1311 // folder item purpose.
1312 DispatchDragEventForReparent(pointer, event);
1313 return;
1314 }
1315
1316 // Regular drag and drop in a folder's grid view.
1317 AppListFolderView* folder_view = static_cast<AppListFolderView*>(parent());
1318 folder_view->UpdateFolderViewBackground(true);
1319
1320 // Calculate if the drag_view_ is dragged out of the folder's container
1321 // ink bubble.
1322 gfx::Rect bounds_to_folder_view = ConvertRectToParent(drag_view_->bounds());
1323 gfx::Point pt = bounds_to_folder_view.CenterPoint();
1324 bool is_item_dragged_out_of_folder =
1325 folder_view->IsPointOutsideOfFolderBoundray(pt);
1326 if (is_item_dragged_out_of_folder) {
1327 if (!drag_out_of_folder_container_) {
1328 folder_item_reparent_timer_.Start(FROM_HERE,
1329 base::TimeDelta::FromMilliseconds(kFolderItemReparentDealy),
1330 this, &AppsGridView::OnFolderItemReparentTimer);
1331 drag_out_of_folder_container_ = true;
1332 }
1333 } else {
1334 folder_item_reparent_timer_.Stop();
1335 drag_out_of_folder_container_ = false;
1336 }
1337 }
1338
1339 bool AppsGridView::IsDraggingForReparentInRootLevelGridView() const {
1340 return (is_root_level_ && dragging_for_reparent_item_);
1341 }
1342
1343 bool AppsGridView::IsDraggingForReprentInHiddenGridView() const {
1344 return (!is_root_level_ && dragging_for_reparent_item_);
1345 }
1346
1347 gfx::Rect AppsGridView::GetTargetIconRectInFolder(
1348 AppListItemView* drag_item_view,
1349 AppListItemView* folder_item_view) {
1350 gfx::Rect view_ideal_bounds = view_model_.ideal_bounds(
1351 view_model_.GetIndexOfView(folder_item_view));
1352 gfx::Rect icon_ideal_bounds =
1353 folder_item_view->GetIconBoundsForTargetViewBounds(view_ideal_bounds);
1354 AppListFolderItem* folder_item =
1355 static_cast<AppListFolderItem*>(folder_item_view->item());
1356 return folder_item->GetTargetIconRectInFolderForItem(
1357 drag_item_view->item(), icon_ideal_bounds);
1358 }
1359
1360 void AppsGridView::DispatchDragEventForReparent(
1361 Pointer pointer,
1362 const ui::LocatedEvent& event) {
1363 static_cast<AppListFolderView*>(parent())->
1364 DispatchDragEventForReparent(pointer, event);
1365 }
1366
1367 void AppsGridView::EndDragFromReparentItemInRootLevel(
1368 bool events_forwarded_to_drag_drop_host) {
1369 // EndDrag was called before if |drag_view_| is NULL.
1370 if (!drag_view_)
1371 return;
1372
1373 DCHECK(IsDraggingForReparentInRootLevelGridView());
1374 bool cancel_reparent = false;
1375 scoped_ptr<AppListItemView> cached_drag_view;
1376 if (!events_forwarded_to_drag_drop_host) {
1377 CalculateDropTarget(last_drag_point_, true);
1378 if (IsValidIndex(drop_target_)) {
1379 if (drop_attempt_ == DROP_FOR_REORDER)
1380 ReparentItemForReorder(drag_view_, drop_target_);
1381 else if (drop_attempt_ == DROP_FOR_FOLDER)
1382 ReparentItemToAnotherFolder(drag_view_, drop_target_);
1383 else { // DROP_FOR_NONE_
1384 cancel_reparent = true;
1385 // Note(jennyz): cached_drag_view makes sure drag_view_ will be deleted
1386 // after AnimateToIdealBounds() is called.
1387 // There is a problem in layer() animation which cause DCHECK failure
1388 // if a child view is deleted immediately before re-creating layer in
1389 // layer animation. The layer tree seems marked dirty, and complaining
1390 // when we try to re-create layer in AnimationBetweenRows when calling
1391 // AnimateToIdealBounds.
1392 cached_drag_view.reset(drag_view_);
1393 }
1394 }
1395
1396 if (!cancel_reparent) {
1397 SetViewHidden(drag_view_,
1398 false /* show */,
1399 true /* no animate */);
1400 }
1401 }
1402
1403 // The drag can be ended after the synchronous drag is created but before it
1404 // is Run().
1405 CleanUpSynchronousDrag();
1406
1407 SetAsFolderDroppingTarget(drop_target_, false);
1408 drop_attempt_ = DROP_FOR_NONE;
1409 drag_pointer_ = NONE;
1410 drop_target_ = Index();
1411 if (!cancel_reparent)
1412 drag_view_->OnDragEnded();
1413 drag_view_ = NULL;
1414 drag_start_grid_view_ = gfx::Point();
1415 drag_start_page_ = -1;
1416 drag_view_offset_ = gfx::Point();
1417 dragging_for_reparent_item_ = false;
1418 if (cancel_reparent)
1419 CancelFolderItemReparent(cached_drag_view.get());
1420 AnimateToIdealBounds();
1421
1422 StopPageFlipTimer();
1423 }
1424
1425 void AppsGridView::EndDragForReparentInHiddenFolderGridView() {
1426 if (drag_and_drop_host_) {
1427 // If we had a drag and drop proxy icon, we delete it and make the real
1428 // item visible again.
1429 drag_and_drop_host_->DestroyDragIconProxy();
1430 }
1431
1432 // The drag can be ended after the synchronous drag is created but before it
1433 // is Run().
1434 CleanUpSynchronousDrag();
1435
1436 SetAsFolderDroppingTarget(drop_target_, false);
1437 drop_attempt_ = DROP_FOR_NONE;
1438 drag_pointer_ = NONE;
1439 drop_target_ = Index();
1440 drag_view_->OnDragEnded();
1441 drag_view_ = NULL;
1442 drag_start_grid_view_ = gfx::Point();
1443 drag_start_page_ = -1;
1444 drag_view_offset_ = gfx::Point();
1445 dragging_for_reparent_item_ = false;
1446 }
1447
1448 void AppsGridView::OnFolderItemRemoved() {
1449 DCHECK(!is_root_level_);
1450 item_list_ = NULL;
1451 }
1452
1210 void AppsGridView::StartDragAndDropHostDrag(const gfx::Point& grid_location) { 1453 void AppsGridView::StartDragAndDropHostDrag(const gfx::Point& grid_location) {
1211 // When a drag and drop host is given, the item can be dragged out of the app 1454 // When a drag and drop host is given, the item can be dragged out of the app
1212 // list window. In that case a proxy widget needs to be used. 1455 // list window. In that case a proxy widget needs to be used.
1213 // Note: This code has very likely to be changed for Windows (non metro mode) 1456 // Note: This code has very likely to be changed for Windows (non metro mode)
1214 // when a |drag_and_drop_host_| gets implemented. 1457 // when a |drag_and_drop_host_| gets implemented.
1215 if (!drag_view_ || !drag_and_drop_host_) 1458 if (!drag_view_ || !drag_and_drop_host_)
1216 return; 1459 return;
1217 1460
1218 gfx::Point screen_location = grid_location; 1461 gfx::Point screen_location = grid_location;
1219 views::View::ConvertPointToScreen(this, &screen_location); 1462 views::View::ConvertPointToScreen(this, &screen_location);
1220 1463
1221 // Determine the mouse offset to the center of the icon so that the drag and 1464 // Determine the mouse offset to the center of the icon so that the drag and
1222 // drop host follows this layer. 1465 // drop host follows this layer.
1223 gfx::Vector2d delta = drag_view_offset_ - 1466 gfx::Vector2d delta = drag_view_offset_ -
1224 drag_view_->GetLocalBounds().CenterPoint(); 1467 drag_view_->GetLocalBounds().CenterPoint();
1225 delta.set_y(delta.y() + drag_view_->title()->size().height() / 2); 1468 delta.set_y(delta.y() + drag_view_->title()->size().height() / 2);
1226 1469
1227 // We have to hide the original item since the drag and drop host will do 1470 // We have to hide the original item since the drag and drop host will do
1228 // the OS dependent code to "lift off the dragged item". 1471 // the OS dependent code to "lift off the dragged item".
1472 DCHECK(!IsDraggingForReparentInRootLevelGridView());
1229 drag_and_drop_host_->CreateDragIconProxy(screen_location, 1473 drag_and_drop_host_->CreateDragIconProxy(screen_location,
1230 drag_view_->item()->icon(), 1474 drag_view_->item()->icon(),
1231 drag_view_, 1475 drag_view_,
1232 delta, 1476 delta,
1233 kDragAndDropProxyScale); 1477 kDragAndDropProxyScale);
1234 SetViewHidden(drag_view_, 1478 SetViewHidden(drag_view_,
1235 true /* hide */, 1479 true /* hide */,
1236 true /* no animation */); 1480 true /* no animation */);
1237 } 1481 }
1238 1482
1239 void AppsGridView::DispatchDragEventToDragAndDropHost( 1483 void AppsGridView::DispatchDragEventToDragAndDropHost(
1240 const gfx::Point& location_in_screen_coordinates) { 1484 const gfx::Point& location_in_screen_coordinates) {
1241 if (!drag_view_ || !drag_and_drop_host_) 1485 if (!drag_view_ || !drag_and_drop_host_)
1242 return; 1486 return;
1243 if (bounds().Contains(last_drag_point_)) { 1487
1488 if (GetLocalBounds().Contains(last_drag_point_)) {
1244 // The event was issued inside the app menu and we should get all events. 1489 // The event was issued inside the app menu and we should get all events.
1245 if (forward_events_to_drag_and_drop_host_) { 1490 if (forward_events_to_drag_and_drop_host_) {
1246 // The DnD host was previously called and needs to be informed that the 1491 // The DnD host was previously called and needs to be informed that the
1247 // session returns to the owner. 1492 // session returns to the owner.
1248 forward_events_to_drag_and_drop_host_ = false; 1493 forward_events_to_drag_and_drop_host_ = false;
1249 drag_and_drop_host_->EndDrag(true); 1494 drag_and_drop_host_->EndDrag(true);
1250 } 1495 }
1251 } else { 1496 } else {
1252 // The event happened outside our app menu and we might need to dispatch. 1497 // The event happened outside our app menu and we might need to dispatch.
1253 if (forward_events_to_drag_and_drop_host_) { 1498 if (forward_events_to_drag_and_drop_host_) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 item_list_->MoveItem(current_model_index, target_model_index); 1569 item_list_->MoveItem(current_model_index, target_model_index);
1325 view_model_.Move(current_model_index, target_model_index); 1570 view_model_.Move(current_model_index, target_model_index);
1326 item_list_->AddObserver(this); 1571 item_list_->AddObserver(this);
1327 1572
1328 if (pagination_model_->selected_page() != target.page) 1573 if (pagination_model_->selected_page() != target.page)
1329 pagination_model_->SelectPage(target.page, false); 1574 pagination_model_->SelectPage(target.page, false);
1330 } 1575 }
1331 1576
1332 void AppsGridView::MoveItemToFolder(views::View* item_view, 1577 void AppsGridView::MoveItemToFolder(views::View* item_view,
1333 const Index& target) { 1578 const Index& target) {
1334 const std::string& source_id = 1579 const std::string& source_item_id =
1335 static_cast<AppListItemView*>(item_view)->item()->id(); 1580 static_cast<AppListItemView*>(item_view)->item()->id();
1336 AppListItemView* target_view = 1581 AppListItemView* target_view =
1337 static_cast<AppListItemView*>(GetViewAtSlotOnCurrentPage(target.slot)); 1582 static_cast<AppListItemView*>(GetViewAtSlotOnCurrentPage(target.slot));
1338 const std::string& target_id = target_view->item()->id(); 1583 const std::string& target_view_item_id = target_view->item()->id();
1339 1584
1340 // Make change to data model. 1585 // Make change to data model.
1341 item_list_->RemoveObserver(this); 1586 item_list_->RemoveObserver(this);
1342 std::string folder_id = model_->MergeItems(target_id, source_id); 1587
1588 std::string folder_item_id =
1589 model_->MergeItems(target_view_item_id, source_item_id);
1343 item_list_->AddObserver(this); 1590 item_list_->AddObserver(this);
1344 1591
1345 if (folder_id != target_id) { 1592 if (folder_item_id != target_view_item_id) {
1346 // New folder was created, change the view model to replace the old target 1593 // New folder was created, change the view model to replace the old target
1347 // view with the new folder item view. 1594 // view with the new folder item view.
1348 size_t folder_index; 1595 size_t folder_item_index;
1349 if (item_list_->FindItemIndex(folder_id, &folder_index)) { 1596 if (item_list_->FindItemIndex(folder_item_id, &folder_item_index)) {
1350 int target_index = view_model_.GetIndexOfView(target_view); 1597 int target_view_index = view_model_.GetIndexOfView(target_view);
1351 view_model_.Remove(target_index); 1598 view_model_.Remove(target_view_index);
1352 delete target_view; 1599 delete target_view;
1353 views::View* target_folder_view = CreateViewForItemAtIndex(folder_index); 1600 views::View* target_folder_view =
1354 view_model_.Add(target_folder_view, target_index); 1601 CreateViewForItemAtIndex(folder_item_index);
1602 view_model_.Add(target_folder_view, target_view_index);
1355 AddChildView(target_folder_view); 1603 AddChildView(target_folder_view);
1356 } else { 1604 } else {
1357 LOG(ERROR) << "Folder no longer in item_list: " << folder_id; 1605 LOG(ERROR) << "Folder no longer in item_list: " << folder_item_id;
1358 } 1606 }
1359 } 1607 }
1360 1608
1361 // Fade out the drag_view_ and delete it when animation ends. 1609 // Fade out the drag_view_ and delete it when animation ends.
1362 int drag_view_index = view_model_.GetIndexOfView(drag_view_); 1610 int drag_view_index = view_model_.GetIndexOfView(drag_view_);
1363 view_model_.Remove(drag_view_index); 1611 view_model_.Remove(drag_view_index);
1364 bounds_animator_.AnimateViewTo(drag_view_, drag_view_->bounds()); 1612 bounds_animator_.AnimateViewTo(drag_view_, drag_view_->bounds());
1365 bounds_animator_.SetAnimationDelegate( 1613 bounds_animator_.SetAnimationDelegate(
1366 drag_view_, new ItemRemoveAnimationDelegate(drag_view_), true); 1614 drag_view_, new ItemRemoveAnimationDelegate(drag_view_), true);
1615 UpdatePaging();
1616 }
1367 1617
1618 void AppsGridView::ReparentItemForReorder(views::View* item_view,
1619 const Index& target) {
1620 item_list_->RemoveObserver(this);
1621 model_->RemoveObserver(this);
1622
1623 AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item();
1624 DCHECK(reparent_item->IsInFolder());
1625 AppListFolderItem* source_folder = static_cast<AppListFolderItem*>(
1626 item_list_->FindItem(reparent_item->folder_id()));
1627
1628 // Move the item from its parent folder to top level item list.
1629 // Must move to target_model_index, the location we expect the target item
1630 // to be, not the item location we want to insert before.
1631 int target_model_index = GetModelIndexFromIndex(target);
1632 int current_model_index = view_model_.GetIndexOfView(item_view);
1633 syncer::StringOrdinal target_position;
1634 if (target_model_index < static_cast<int>(item_list_->item_count()))
1635 target_position = item_list_->item_at(target_model_index)->position();
1636 model_->MoveItemToFolderAt(reparent_item, "", target_position);
1637 view_model_.Move(current_model_index, target_model_index);
1638
1639 if (source_folder->ChildItemCount() == 1)
1640 RemoveLastItemFromReparentItemFolder(source_folder);
1641
1642 item_list_->AddObserver(this);
1643 model_->AddObserver(this);
1368 UpdatePaging(); 1644 UpdatePaging();
1369 } 1645 }
1370 1646
1647 void AppsGridView::ReparentItemToAnotherFolder(views::View* item_view,
1648 const Index& target) {
1649 DCHECK(IsDraggingForReparentInRootLevelGridView());
1650
1651 // Make change to data model.
1652 item_list_->RemoveObserver(this);
1653
1654 AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item();
1655 DCHECK(reparent_item->IsInFolder());
1656 AppListFolderItem* source_folder = static_cast<AppListFolderItem*>(
1657 item_list_->FindItem(reparent_item->folder_id()));
1658
1659 AppListItemView* target_view =
1660 static_cast<AppListItemView*>(GetViewAtSlotOnCurrentPage(target.slot));
1661 AppListItem* target_item = target_view->item();
1662
1663 // Move item to the target folder.
1664 const std::string& target_id_after_merge =
1665 model_->MergeItems(target_item->id(), reparent_item->id());
1666
1667 if (target_id_after_merge != target_item->id()) {
1668 // New folder was created, change the view model to replace the old target
1669 // view with the new folder item view.
1670 const std::string& new_folder_id = reparent_item->folder_id();
1671 size_t new_folder_index;
1672 if (item_list_->FindItemIndex(new_folder_id, &new_folder_index)) {
1673 int target_view_index = view_model_.GetIndexOfView(target_view);
1674 view_model_.Remove(target_view_index);
1675 delete target_view;
1676 views::View* new_folder_view =
1677 CreateViewForItemAtIndex(new_folder_index);
1678 view_model_.Add(new_folder_view, target_view_index);
1679 AddChildView(new_folder_view);
1680 } else {
1681 LOG(ERROR) << "Folder no longer in item_list: " << new_folder_id;
1682 }
1683 }
1684
1685 if (source_folder->ChildItemCount() == 1)
1686 RemoveLastItemFromReparentItemFolder(source_folder);
1687
1688 item_list_->AddObserver(this);
1689
1690 // Fade out the drag_view_ and delete it when animation ends.
1691 int drag_view_index = view_model_.GetIndexOfView(drag_view_);
1692 view_model_.Remove(drag_view_index);
1693 bounds_animator_.AnimateViewTo(drag_view_, drag_view_->bounds());
1694 bounds_animator_.SetAnimationDelegate(
1695 drag_view_, new ItemRemoveAnimationDelegate(drag_view_), true);
1696 UpdatePaging();
1697 }
1698
1699 // After moving the re-parenting item out of the folder, if there is only 1 item
1700 // left, remove the last item out of the folder, delete the folder and insert it
1701 // to the data model at the same position. Make the same change to view_model_
1702 // accordingly.
1703 void AppsGridView::RemoveLastItemFromReparentItemFolder(
1704 AppListFolderItem* source_folder) {
1705 DCHECK(source_folder->ChildItemCount() == 1);
1706
1707 // Delete view associated with the folder item to be removed.
1708 AppListItemView* folder_item_view = activated_item_view();
1709 int folder_model_index = view_model_.GetIndexOfView(folder_item_view);
1710 view_model_.Remove(folder_model_index);
1711 delete folder_item_view;
1712
1713 // Now make the data change to remove the folder item in model.
1714 AppListItem* last_item = source_folder->item_list()->item_at(0);
1715 model_->MoveItemToFolderAt(last_item, "", source_folder->position());
1716
1717 // Create a new item view for the last item in folder.
1718 size_t last_item_index;
1719 item_list_->FindItemIndex(last_item->id(), &last_item_index);
1720 views::View* last_item_view = CreateViewForItemAtIndex(last_item_index);
1721 view_model_.Add(last_item_view, last_item_index);
1722 AddChildView(last_item_view);
1723 }
1724
1725 void AppsGridView::CancelFolderItemReparent(AppListItemView* drag_item_view) {
1726 // The icon of the dragged item must target to its final ideal bounds after
1727 // the animation completes.
1728 CalculateIdealBounds();
1729
1730 // Remove drag_view_ from view_model_, it will be deleted after the animation.
1731 int drag_view_index = view_model_.GetIndexOfView(drag_item_view);
1732 view_model_.Remove(drag_view_index);
1733
1734 gfx::Rect target_icon_rect =
1735 GetTargetIconRectInFolder(drag_item_view, activated_item_view_);
1736
1737 gfx::Rect drag_view_icon_to_grid =
1738 drag_item_view->ConvertRectToParent(drag_item_view->GetIconBounds());
1739 drag_view_icon_to_grid.ClampToCenteredSize(
1740 gfx::Size(kPreferredIconDimension, kPreferredIconDimension));
1741 TopIconAnimationView* icon_view = new TopIconAnimationView(
1742 drag_item_view->item()->icon(),
1743 target_icon_rect,
1744 false); /* animate like closing folder */
1745 AddChildView(icon_view);
1746 icon_view->SetBoundsRect(drag_view_icon_to_grid);
1747 icon_view->TransformView();
1748 }
1749
1371 void AppsGridView::CancelContextMenusOnCurrentPage() { 1750 void AppsGridView::CancelContextMenusOnCurrentPage() {
1372 int start = pagination_model_->selected_page() * tiles_per_page(); 1751 int start = pagination_model_->selected_page() * tiles_per_page();
1373 int end = std::min(view_model_.view_size(), start + tiles_per_page()); 1752 int end = std::min(view_model_.view_size(), start + tiles_per_page());
1374 for (int i = start; i < end; ++i) { 1753 for (int i = start; i < end; ++i) {
1375 AppListItemView* view = 1754 AppListItemView* view =
1376 static_cast<AppListItemView*>(view_model_.view_at(i)); 1755 static_cast<AppListItemView*>(view_model_.view_at(i));
1377 view->CancelContextMenu(); 1756 view->CancelContextMenu();
1378 } 1757 }
1379 } 1758 }
1380 1759
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 return nearest_tile; 1954 return nearest_tile;
1576 } 1955 }
1577 } 1956 }
1578 1957
1579 // If |drag_view| is not entering the re-order or fold dropping region of 1958 // If |drag_view| is not entering the re-order or fold dropping region of
1580 // any items, cancel any previous re-order or folder dropping timer, and 1959 // any items, cancel any previous re-order or folder dropping timer, and
1581 // return itself. 1960 // return itself.
1582 drop_attempt_ = DROP_FOR_NONE; 1961 drop_attempt_ = DROP_FOR_NONE;
1583 reorder_timer_.Stop(); 1962 reorder_timer_.Stop();
1584 folder_dropping_timer_.Stop(); 1963 folder_dropping_timer_.Stop();
1964
1965 // When dragging for reparent a folder item, it should go back to its parent
1966 // folder item if there is no drop target.
1967 if (IsDraggingForReparentInRootLevelGridView()) {
1968 DCHECK(activated_item_view_);
1969 return GetIndexOfView(activated_item_view_);
1970 }
1971
1585 return GetIndexOfView(drag_view_); 1972 return GetIndexOfView(drag_view_);
1586 } 1973 }
1587 1974
1588 void AppsGridView::CalculateNearestTileForVertex(const gfx::Point& vertex, 1975 void AppsGridView::CalculateNearestTileForVertex(const gfx::Point& vertex,
1589 Index* nearest_tile, 1976 Index* nearest_tile,
1590 int* d_min) { 1977 int* d_min) {
1591 Index target_index; 1978 Index target_index;
1592 gfx::Rect target_bounds = GetTileBoundsForPoint(vertex, &target_index); 1979 gfx::Rect target_bounds = GetTileBoundsForPoint(vertex, &target_index);
1593 1980
1594 if (target_bounds.IsEmpty() || target_index == *nearest_tile) 1981 if (target_bounds.IsEmpty() || target_index == *nearest_tile)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, 2045 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index,
1659 bool is_target_folder) { 2046 bool is_target_folder) {
1660 AppListItemView* target_view = 2047 AppListItemView* target_view =
1661 static_cast<AppListItemView*>( 2048 static_cast<AppListItemView*>(
1662 GetViewAtSlotOnCurrentPage(target_index.slot)); 2049 GetViewAtSlotOnCurrentPage(target_index.slot));
1663 if (target_view) 2050 if (target_view)
1664 target_view->SetAsAttemptedFolderTarget(is_target_folder); 2051 target_view->SetAsAttemptedFolderTarget(is_target_folder);
1665 } 2052 }
1666 2053
1667 } // namespace app_list 2054 } // namespace app_list
OLDNEW
« no previous file with comments | « ui/app_list/views/apps_grid_view.h ('k') | ui/app_list/views/contents_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698