Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 const int kFolderDroppingDelay = 150; | 87 const int kFolderDroppingDelay = 150; |
| 88 | 88 |
| 89 // Delays in milliseconds to show re-order preview. | 89 // Delays in milliseconds to show re-order preview. |
| 90 const int kReorderDelay = 120; | 90 const int kReorderDelay = 120; |
| 91 | 91 |
| 92 // Delays in milliseconds to show folder item reparent UI. | 92 // Delays in milliseconds to show folder item reparent UI. |
| 93 const int kFolderItemReparentDelay = 50; | 93 const int kFolderItemReparentDelay = 50; |
| 94 | 94 |
| 95 // Radius of the circle, in which if entered, show folder dropping preview | 95 // Radius of the circle, in which if entered, show folder dropping preview |
| 96 // UI. | 96 // UI. |
| 97 const int kFolderDroppingCircleRadius = 15; | 97 const int kFolderDroppingCircleRadius = 39; |
| 98 | 98 |
| 99 // RowMoveAnimationDelegate is used when moving an item into a different row. | 99 // RowMoveAnimationDelegate is used when moving an item into a different row. |
| 100 // Before running the animation, the item's layer is re-created and kept in | 100 // Before running the animation, the item's layer is re-created and kept in |
| 101 // the original position, then the item is moved to just before its target | 101 // the original position, then the item is moved to just before its target |
| 102 // position and opacity set to 0. When the animation runs, this delegate moves | 102 // position and opacity set to 0. When the animation runs, this delegate moves |
| 103 // the layer and fades it out while fading in the item at the same time. | 103 // the layer and fades it out while fading in the item at the same time. |
| 104 class RowMoveAnimationDelegate : public gfx::AnimationDelegate { | 104 class RowMoveAnimationDelegate : public gfx::AnimationDelegate { |
| 105 public: | 105 public: |
| 106 RowMoveAnimationDelegate(views::View* view, | 106 RowMoveAnimationDelegate(views::View* view, |
| 107 ui::Layer* layer, | 107 ui::Layer* layer, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE { | 182 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE { |
| 183 view_->SchedulePaint(); | 183 view_->SchedulePaint(); |
| 184 } | 184 } |
| 185 | 185 |
| 186 private: | 186 private: |
| 187 views::View* view_; | 187 views::View* view_; |
| 188 | 188 |
| 189 DISALLOW_COPY_AND_ASSIGN(ItemMoveAnimationDelegate); | 189 DISALLOW_COPY_AND_ASSIGN(ItemMoveAnimationDelegate); |
| 190 }; | 190 }; |
| 191 | 191 |
| 192 // Gets the distance between the centers of the |rect_1| and |rect_2|. | |
| 193 int GetDistanceBetweenRects(gfx::Rect rect_1, | |
| 194 gfx::Rect rect_2) { | |
| 195 return (rect_1.CenterPoint() - rect_2.CenterPoint()).Length(); | |
| 196 } | |
| 197 | |
| 198 // Returns true if the |item| is an folder item. | 192 // Returns true if the |item| is an folder item. |
| 199 bool IsFolderItem(AppListItem* item) { | 193 bool IsFolderItem(AppListItem* item) { |
| 200 return (item->GetItemType() == AppListFolderItem::kItemType); | 194 return (item->GetItemType() == AppListFolderItem::kItemType); |
| 201 } | 195 } |
| 202 | 196 |
| 203 bool IsOEMFolderItem(AppListItem* item) { | 197 bool IsOEMFolderItem(AppListItem* item) { |
| 204 return IsFolderItem(item) && | 198 return IsFolderItem(item) && |
| 205 (static_cast<AppListFolderItem*>(item))->folder_type() == | 199 (static_cast<AppListFolderItem*>(item))->folder_type() == |
| 206 AppListFolderItem::FOLDER_TYPE_OEM; | 200 AppListFolderItem::FOLDER_TYPE_OEM; |
| 207 } | 201 } |
| 208 | 202 |
| 203 int ClampToRange(int value, int min, int max) { | |
| 204 return std::min(std::max(value, min), max); | |
| 205 } | |
| 206 | |
| 209 } // namespace | 207 } // namespace |
| 210 | 208 |
| 211 #if defined(OS_WIN) | 209 #if defined(OS_WIN) |
| 212 // Interprets drag events sent from Windows via the drag/drop API and forwards | 210 // Interprets drag events sent from Windows via the drag/drop API and forwards |
| 213 // them to AppsGridView. | 211 // them to AppsGridView. |
| 214 // On Windows, in order to have the OS perform the drag properly we need to | 212 // On Windows, in order to have the OS perform the drag properly we need to |
| 215 // provide it with a shortcut file which may or may not exist at the time the | 213 // provide it with a shortcut file which may or may not exist at the time the |
| 216 // drag is started. Therefore while waiting for that shortcut to be located we | 214 // drag is started. Therefore while waiting for that shortcut to be located we |
| 217 // just do a regular "internal" drag and transition into the synchronous drag | 215 // just do a regular "internal" drag and transition into the synchronous drag |
| 218 // when the shortcut is found/created. Hence a synchronous drag is an optional | 216 // when the shortcut is found/created. Hence a synchronous drag is an optional |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 481 Pointer pointer, | 479 Pointer pointer, |
| 482 const ui::LocatedEvent& event) { | 480 const ui::LocatedEvent& event) { |
| 483 DCHECK(view); | 481 DCHECK(view); |
| 484 if (drag_view_ || pulsing_blocks_model_.view_size()) | 482 if (drag_view_ || pulsing_blocks_model_.view_size()) |
| 485 return; | 483 return; |
| 486 | 484 |
| 487 drag_view_ = view; | 485 drag_view_ = view; |
| 488 drag_view_init_index_ = GetIndexOfView(drag_view_); | 486 drag_view_init_index_ = GetIndexOfView(drag_view_); |
| 489 drag_view_offset_ = event.location(); | 487 drag_view_offset_ = event.location(); |
| 490 drag_start_page_ = pagination_model_.selected_page(); | 488 drag_start_page_ = pagination_model_.selected_page(); |
| 489 reorder_placeholder_ = GetIndexOfView(drag_view_); | |
| 491 ExtractDragLocation(event, &drag_start_grid_view_); | 490 ExtractDragLocation(event, &drag_start_grid_view_); |
| 492 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y()); | 491 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y()); |
| 493 } | 492 } |
| 494 | 493 |
| 495 void AppsGridView::StartSettingUpSynchronousDrag() { | 494 void AppsGridView::StartSettingUpSynchronousDrag() { |
| 496 #if defined(OS_WIN) | 495 #if defined(OS_WIN) |
| 497 if (!delegate_ || !use_synchronous_drag_) | 496 if (!delegate_ || !use_synchronous_drag_) |
| 498 return; | 497 return; |
| 499 | 498 |
| 500 // Folders and downloading items can't be integrated with the OS. | 499 // Folders and downloading items can't be integrated with the OS. |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 608 return; | 607 return; |
| 609 | 608 |
| 610 StartSettingUpSynchronousDrag(); | 609 StartSettingUpSynchronousDrag(); |
| 611 if (!dragging_for_reparent_item_) | 610 if (!dragging_for_reparent_item_) |
| 612 StartDragAndDropHostDrag(point); | 611 StartDragAndDropHostDrag(point); |
| 613 } | 612 } |
| 614 | 613 |
| 615 if (drag_pointer_ != pointer) | 614 if (drag_pointer_ != pointer) |
| 616 return; | 615 return; |
| 617 | 616 |
| 617 drag_view_->SetPosition(drag_view_start_ + drag_vector); | |
| 618 | |
| 618 last_drag_point_ = point; | 619 last_drag_point_ = point; |
| 619 const Index last_reorder_drop_target = reorder_drop_target_; | 620 const Index last_reorder_drop_target = reorder_drop_target_; |
| 620 const Index last_folder_drop_target = folder_drop_target_; | 621 const Index last_folder_drop_target = folder_drop_target_; |
| 621 DropAttempt last_drop_attempt = drop_attempt_; | 622 DropAttempt last_drop_attempt = drop_attempt_; |
| 622 CalculateDropTarget(last_drag_point_, false); | 623 CalculateDropTarget(); |
| 623 | 624 |
| 624 if (IsPointWithinDragBuffer(last_drag_point_)) | 625 MaybeStartPageFlipTimer(last_drag_point_); |
| 625 MaybeStartPageFlipTimer(last_drag_point_); | |
| 626 else | |
| 627 StopPageFlipTimer(); | |
| 628 | 626 |
| 629 if (page_switcher_view_) { | 627 if (page_switcher_view_) { |
| 630 gfx::Point page_switcher_point(last_drag_point_); | 628 gfx::Point page_switcher_point(last_drag_point_); |
| 631 views::View::ConvertPointToTarget( | 629 views::View::ConvertPointToTarget( |
| 632 this, page_switcher_view_, &page_switcher_point); | 630 this, page_switcher_view_, &page_switcher_point); |
| 633 page_switcher_view_->UpdateUIForDragPoint(page_switcher_point); | 631 page_switcher_view_->UpdateUIForDragPoint(page_switcher_point); |
| 634 } | 632 } |
| 635 | 633 |
| 636 if (!EnableFolderDragDropUI()) { | |
| 637 if (last_reorder_drop_target != reorder_drop_target_) | |
| 638 AnimateToIdealBounds(); | |
| 639 drag_view_->SetPosition(drag_view_start_ + drag_vector); | |
| 640 return; | |
| 641 } | |
| 642 | |
| 643 // Update drag with folder UI enabled. | |
| 644 if (last_folder_drop_target != folder_drop_target_ || | 634 if (last_folder_drop_target != folder_drop_target_ || |
| 645 last_reorder_drop_target != reorder_drop_target_ || | 635 last_reorder_drop_target != reorder_drop_target_ || |
| 646 last_drop_attempt != drop_attempt_) { | 636 last_drop_attempt != drop_attempt_) { |
| 647 if (drop_attempt_ == DROP_FOR_REORDER) { | 637 if (drop_attempt_ == DROP_FOR_REORDER) { |
| 648 folder_dropping_timer_.Stop(); | 638 folder_dropping_timer_.Stop(); |
| 649 reorder_timer_.Start(FROM_HERE, | 639 reorder_timer_.Start(FROM_HERE, |
| 650 base::TimeDelta::FromMilliseconds(kReorderDelay), | 640 base::TimeDelta::FromMilliseconds(kReorderDelay), |
| 651 this, &AppsGridView::OnReorderTimer); | 641 this, &AppsGridView::OnReorderTimer); |
| 652 } else if (drop_attempt_ == DROP_FOR_FOLDER) { | 642 } else if (drop_attempt_ == DROP_FOR_FOLDER) { |
| 653 reorder_timer_.Stop(); | 643 reorder_timer_.Stop(); |
| 654 folder_dropping_timer_.Start(FROM_HERE, | 644 folder_dropping_timer_.Start(FROM_HERE, |
| 655 base::TimeDelta::FromMilliseconds(kFolderDroppingDelay), | 645 base::TimeDelta::FromMilliseconds(kFolderDroppingDelay), |
| 656 this, &AppsGridView::OnFolderDroppingTimer); | 646 this, &AppsGridView::OnFolderDroppingTimer); |
| 657 } | 647 } |
| 658 | 648 |
| 659 // Reset the previous drop target. | 649 // Reset the previous drop target. |
| 660 SetAsFolderDroppingTarget(last_folder_drop_target, false); | 650 SetAsFolderDroppingTarget(last_folder_drop_target, false); |
| 661 } | 651 } |
| 662 | |
| 663 drag_view_->SetPosition(drag_view_start_ + drag_vector); | |
| 664 } | 652 } |
| 665 | 653 |
| 666 void AppsGridView::EndDrag(bool cancel) { | 654 void AppsGridView::EndDrag(bool cancel) { |
| 667 // EndDrag was called before if |drag_view_| is NULL. | 655 // EndDrag was called before if |drag_view_| is NULL. |
| 668 if (!drag_view_) | 656 if (!drag_view_) |
| 669 return; | 657 return; |
| 670 | 658 |
| 671 // Coming here a drag and drop was in progress. | 659 // Coming here a drag and drop was in progress. |
| 672 bool landed_in_drag_and_drop_host = forward_events_to_drag_and_drop_host_; | 660 bool landed_in_drag_and_drop_host = forward_events_to_drag_and_drop_host_; |
| 673 if (forward_events_to_drag_and_drop_host_) { | 661 if (forward_events_to_drag_and_drop_host_) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 692 if (IsDraggingForReparentInRootLevelGridView()) { | 680 if (IsDraggingForReparentInRootLevelGridView()) { |
| 693 // An EndDrag can be received during a reparent via a model change. This | 681 // An EndDrag can be received during a reparent via a model change. This |
| 694 // is always a cancel and needs to be forwarded to the folder. | 682 // is always a cancel and needs to be forwarded to the folder. |
| 695 DCHECK(cancel); | 683 DCHECK(cancel); |
| 696 delegate_->CancelDragInActiveFolder(); | 684 delegate_->CancelDragInActiveFolder(); |
| 697 return; | 685 return; |
| 698 } | 686 } |
| 699 | 687 |
| 700 if (!cancel && dragging()) { | 688 if (!cancel && dragging()) { |
| 701 // Regular drag ending path, ie, not for reparenting. | 689 // Regular drag ending path, ie, not for reparenting. |
| 702 CalculateDropTarget(last_drag_point_, true); | 690 CalculateDropTarget(); |
| 703 if (EnableFolderDragDropUI() && drop_attempt_ == DROP_FOR_FOLDER && | 691 if (EnableFolderDragDropUI() && drop_attempt_ == DROP_FOR_FOLDER && |
| 704 IsValidIndex(folder_drop_target_)) { | 692 IsValidIndex(folder_drop_target_)) { |
| 705 MoveItemToFolder(drag_view_, folder_drop_target_); | 693 MoveItemToFolder(drag_view_, folder_drop_target_); |
| 706 } else if (IsValidIndex(reorder_drop_target_)) { | 694 } else if (IsValidIndex(reorder_drop_target_)) { |
| 707 MoveItemInModel(drag_view_, reorder_drop_target_); | 695 MoveItemInModel(drag_view_, reorder_drop_target_); |
| 708 } | 696 } |
| 709 } | 697 } |
| 710 } | 698 } |
| 711 | 699 |
| 712 if (drag_and_drop_host_) { | 700 if (drag_and_drop_host_) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 777 layer()->SetOpacity(show ? 1.0f : 0.0f); | 765 layer()->SetOpacity(show ? 1.0f : 0.0f); |
| 778 } | 766 } |
| 779 | 767 |
| 780 void AppsGridView::InitiateDragFromReparentItemInRootLevelGridView( | 768 void AppsGridView::InitiateDragFromReparentItemInRootLevelGridView( |
| 781 AppListItemView* original_drag_view, | 769 AppListItemView* original_drag_view, |
| 782 const gfx::Rect& drag_view_rect, | 770 const gfx::Rect& drag_view_rect, |
| 783 const gfx::Point& drag_point) { | 771 const gfx::Point& drag_point) { |
| 784 DCHECK(original_drag_view && !drag_view_); | 772 DCHECK(original_drag_view && !drag_view_); |
| 785 DCHECK(!dragging_for_reparent_item_); | 773 DCHECK(!dragging_for_reparent_item_); |
| 786 | 774 |
| 775 // Since the item is new, its placeholder is conceptually at the back of the | |
| 776 // entire apps grid. | |
| 777 reorder_placeholder_ = GetLastViewIndex(); | |
| 778 | |
| 787 // Create a new AppListItemView to duplicate the original_drag_view in the | 779 // Create a new AppListItemView to duplicate the original_drag_view in the |
| 788 // folder's grid view. | 780 // folder's grid view. |
| 789 AppListItemView* view = new AppListItemView(this, original_drag_view->item()); | 781 AppListItemView* view = new AppListItemView(this, original_drag_view->item()); |
| 790 AddChildView(view); | 782 AddChildView(view); |
| 791 drag_view_ = view; | 783 drag_view_ = view; |
| 792 drag_view_->SetPaintToLayer(true); | 784 drag_view_->SetPaintToLayer(true); |
| 793 // Note: For testing purpose, SetFillsBoundsOpaquely can be set to true to | 785 // Note: For testing purpose, SetFillsBoundsOpaquely can be set to true to |
| 794 // show the gray background. | 786 // show the gray background. |
| 795 drag_view_->SetFillsBoundsOpaquely(false); | 787 drag_view_->SetFillsBoundsOpaquely(false); |
| 796 drag_view_->SetBoundsRect(drag_view_rect); | 788 drag_view_->SetBoundsRect(drag_view_rect); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 826 | 818 |
| 827 bool AppsGridView::IsDraggedView(const views::View* view) const { | 819 bool AppsGridView::IsDraggedView(const views::View* view) const { |
| 828 return drag_view_ == view; | 820 return drag_view_ == view; |
| 829 } | 821 } |
| 830 | 822 |
| 831 void AppsGridView::ClearDragState() { | 823 void AppsGridView::ClearDragState() { |
| 832 drop_attempt_ = DROP_FOR_NONE; | 824 drop_attempt_ = DROP_FOR_NONE; |
| 833 drag_pointer_ = NONE; | 825 drag_pointer_ = NONE; |
| 834 reorder_drop_target_ = Index(); | 826 reorder_drop_target_ = Index(); |
| 835 folder_drop_target_ = Index(); | 827 folder_drop_target_ = Index(); |
| 828 reorder_placeholder_ = Index(); | |
| 836 drag_start_grid_view_ = gfx::Point(); | 829 drag_start_grid_view_ = gfx::Point(); |
| 837 drag_start_page_ = -1; | 830 drag_start_page_ = -1; |
| 838 drag_view_offset_ = gfx::Point(); | 831 drag_view_offset_ = gfx::Point(); |
| 839 | 832 |
| 840 if (drag_view_) { | 833 if (drag_view_) { |
| 841 drag_view_->OnDragEnded(); | 834 drag_view_->OnDragEnded(); |
| 842 if (IsDraggingForReparentInRootLevelGridView()) { | 835 if (IsDraggingForReparentInRootLevelGridView()) { |
| 843 const int drag_view_index = view_model_.GetIndexOfView(drag_view_); | 836 const int drag_view_index = view_model_.GetIndexOfView(drag_view_); |
| 844 CHECK_EQ(view_model_.view_size() - 1, drag_view_index); | 837 CHECK_EQ(view_model_.view_size() - 1, drag_view_index); |
| 845 DeleteItemViewAtIndex(drag_view_index); | 838 DeleteItemViewAtIndex(drag_view_index); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1108 } | 1101 } |
| 1109 | 1102 |
| 1110 views::View* AppsGridView::GetViewAtIndex(const Index& index) const { | 1103 views::View* AppsGridView::GetViewAtIndex(const Index& index) const { |
| 1111 if (!IsValidIndex(index)) | 1104 if (!IsValidIndex(index)) |
| 1112 return NULL; | 1105 return NULL; |
| 1113 | 1106 |
| 1114 const int model_index = GetModelIndexFromIndex(index); | 1107 const int model_index = GetModelIndexFromIndex(index); |
| 1115 return view_model_.view_at(model_index); | 1108 return view_model_.view_at(model_index); |
| 1116 } | 1109 } |
| 1117 | 1110 |
| 1111 AppsGridView::Index AppsGridView::GetLastViewIndex() const { | |
| 1112 DCHECK_LT(0, view_model_.view_size()); | |
| 1113 int view_index = view_model_.view_size() - 1; | |
| 1114 return Index(view_index / tiles_per_page(), view_index % tiles_per_page()); | |
| 1115 } | |
| 1116 | |
| 1118 void AppsGridView::MoveSelected(int page_delta, | 1117 void AppsGridView::MoveSelected(int page_delta, |
| 1119 int slot_x_delta, | 1118 int slot_x_delta, |
| 1120 int slot_y_delta) { | 1119 int slot_y_delta) { |
| 1121 if (!selected_view_) | 1120 if (!selected_view_) |
| 1122 return SetSelectedItemByIndex(Index(pagination_model_.selected_page(), 0)); | 1121 return SetSelectedItemByIndex(Index(pagination_model_.selected_page(), 0)); |
| 1123 | 1122 |
| 1124 const Index& selected = GetIndexOfView(selected_view_); | 1123 const Index& selected = GetIndexOfView(selected_view_); |
| 1125 int target_slot = selected.slot + slot_x_delta + slot_y_delta * cols_; | 1124 int target_slot = selected.slot + slot_x_delta + slot_y_delta * cols_; |
| 1126 | 1125 |
| 1127 if (selected.slot % cols_ == 0 && slot_x_delta == -1) { | 1126 if (selected.slot % cols_ == 0 && slot_x_delta == -1) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1171 pagination_model_.transition(); | 1170 pagination_model_.transition(); |
| 1172 const bool is_valid = pagination_model_.is_valid_page(transition.target_page); | 1171 const bool is_valid = pagination_model_.is_valid_page(transition.target_page); |
| 1173 | 1172 |
| 1174 // Transition to previous page means negative offset. | 1173 // Transition to previous page means negative offset. |
| 1175 const int dir = transition.target_page > current_page ? -1 : 1; | 1174 const int dir = transition.target_page > current_page ? -1 : 1; |
| 1176 | 1175 |
| 1177 const int total_views = | 1176 const int total_views = |
| 1178 view_model_.view_size() + pulsing_blocks_model_.view_size(); | 1177 view_model_.view_size() + pulsing_blocks_model_.view_size(); |
| 1179 int slot_index = 0; | 1178 int slot_index = 0; |
| 1180 for (int i = 0; i < total_views; ++i) { | 1179 for (int i = 0; i < total_views; ++i) { |
| 1181 if (i < view_model_.view_size() && view_model_.view_at(i) == drag_view_) { | 1180 if (i < view_model_.view_size() && view_model_.view_at(i) == drag_view_) |
| 1182 if (EnableFolderDragDropUI() && drop_attempt_ == DROP_FOR_FOLDER) | |
| 1183 ++slot_index; | |
| 1184 continue; | 1181 continue; |
| 1185 } | |
| 1186 | 1182 |
| 1187 Index view_index = GetIndexFromModelIndex(slot_index); | 1183 Index view_index = GetIndexFromModelIndex(slot_index); |
| 1188 | 1184 |
| 1189 // Leaves a blank space in the grid for the current reorder drop target. | 1185 // Leaves a blank space in the grid for the current reorder placeholder. |
| 1190 if (reorder_drop_target_ == view_index && | 1186 if (reorder_placeholder_ == view_index) { |
| 1191 drop_attempt_ == DROP_FOR_REORDER) { | |
| 1192 ++slot_index; | 1187 ++slot_index; |
| 1193 view_index = GetIndexFromModelIndex(slot_index); | 1188 view_index = GetIndexFromModelIndex(slot_index); |
| 1194 } | 1189 } |
| 1195 | 1190 |
| 1196 // Decide the x or y offset for current item. | 1191 // Decide the x or y offset for current item. |
| 1197 int x_offset = 0; | 1192 int x_offset = 0; |
| 1198 int y_offset = 0; | 1193 int y_offset = 0; |
| 1199 | 1194 |
| 1200 if (pagination_controller_->scroll_axis() == | 1195 if (pagination_controller_->scroll_axis() == |
| 1201 PaginationController::SCROLL_AXIS_HORIZONTAL) { | 1196 PaginationController::SCROLL_AXIS_HORIZONTAL) { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1334 views::View::ConvertPointFromWidget(this, drag_point); | 1329 views::View::ConvertPointFromWidget(this, drag_point); |
| 1335 #else | 1330 #else |
| 1336 // For non-aura, root location is not clearly defined but |drag_view_| does | 1331 // For non-aura, root location is not clearly defined but |drag_view_| does |
| 1337 // not have the scale transform. So no round error would be introduced and | 1332 // not have the scale transform. So no round error would be introduced and |
| 1338 // it's okay to use View::ConvertPointToTarget. | 1333 // it's okay to use View::ConvertPointToTarget. |
| 1339 *drag_point = event.location(); | 1334 *drag_point = event.location(); |
| 1340 views::View::ConvertPointToTarget(drag_view_, this, drag_point); | 1335 views::View::ConvertPointToTarget(drag_view_, this, drag_point); |
| 1341 #endif | 1336 #endif |
| 1342 } | 1337 } |
| 1343 | 1338 |
| 1344 void AppsGridView::CalculateDropTarget(const gfx::Point& drag_point, | 1339 void AppsGridView::CalculateDropTarget() { |
| 1345 bool use_page_button_hovering) { | 1340 DCHECK(drag_view_); |
| 1346 if (EnableFolderDragDropUI()) { | 1341 |
| 1347 CalculateDropTargetWithFolderEnabled(drag_point, use_page_button_hovering); | 1342 gfx::Point point = drag_view_->icon()->bounds().CenterPoint(); |
| 1343 views::View::ConvertPointToTarget(drag_view_, this, &point); | |
| 1344 if (!IsPointWithinDragBuffer(point)) { | |
| 1345 // Reset the reorder target to the original position if the cursor is | |
| 1346 // outside the drag buffer. | |
| 1347 if (IsDraggingForReparentInRootLevelGridView()) { | |
| 1348 drop_attempt_ = DROP_FOR_NONE; | |
| 1349 return; | |
| 1350 } | |
| 1351 | |
| 1352 reorder_drop_target_ = drag_view_init_index_; | |
| 1353 drop_attempt_ = DROP_FOR_REORDER; | |
| 1354 return; | |
| 1355 } | |
| 1356 | |
| 1357 if (EnableFolderDragDropUI() && | |
| 1358 CalculateFolderDropTarget(point, &folder_drop_target_)) { | |
| 1359 drop_attempt_ = DROP_FOR_FOLDER; | |
| 1348 return; | 1360 return; |
| 1349 } | 1361 } |
| 1350 | 1362 |
| 1351 drop_attempt_ = DROP_FOR_REORDER; | 1363 drop_attempt_ = DROP_FOR_REORDER; |
| 1364 CalculateReorderDropTarget(point, &reorder_drop_target_); | |
| 1365 } | |
|
tapted
2014/09/15 06:12:53
neat!
calamity
2014/09/15 06:36:15
Acknowledged.
| |
| 1352 | 1366 |
| 1353 int current_page = pagination_model_.selected_page(); | 1367 bool AppsGridView::CalculateFolderDropTarget(const gfx::Point& point, |
| 1354 gfx::Point point(drag_point); | 1368 Index* drop_target) { |
|
tapted
2014/09/15 06:12:53
It would be nice if these functions were const. Bu
calamity
2014/09/15 06:36:15
Well. That was a lot easier than I thought it woul
| |
| 1355 if (!IsPointWithinDragBuffer(drag_point)) { | 1369 Index nearest_tile_index(GetNearestTileIndexForPoint(point)); |
| 1356 point = drag_start_grid_view_; | 1370 int distance_to_tile_center = |
| 1357 current_page = drag_start_page_; | 1371 (point - GetExpectedTileBounds(nearest_tile_index.slot).CenterPoint()) |
| 1372 .Length(); | |
| 1373 if (nearest_tile_index != reorder_placeholder_ && | |
| 1374 distance_to_tile_center < kFolderDroppingCircleRadius && | |
| 1375 !IsFolderItem(drag_view_->item()) && | |
| 1376 CanDropIntoTarget(nearest_tile_index)) { | |
| 1377 *drop_target = nearest_tile_index; | |
| 1378 return true; | |
| 1358 } | 1379 } |
| 1359 | 1380 |
| 1360 if (use_page_button_hovering && page_switcher_view_ && | 1381 return false; |
| 1361 page_switcher_view_->bounds().Contains(point)) { | 1382 } |
| 1362 gfx::Point page_switcher_point(point); | 1383 |
| 1363 views::View::ConvertPointToTarget(this, page_switcher_view_, | 1384 void AppsGridView::CalculateReorderDropTarget(const gfx::Point& point, |
| 1364 &page_switcher_point); | 1385 Index* drop_target) { |
| 1365 int page = page_switcher_view_->GetPageForPoint(page_switcher_point); | 1386 gfx::Rect bounds = GetContentsBounds(); |
| 1366 if (pagination_model_.is_valid_page(page)) { | 1387 Index grid_index = GetNearestTileIndexForPoint(point); |
| 1367 reorder_drop_target_.page = page; | 1388 gfx::Point reorder_placeholder_center = |
| 1368 reorder_drop_target_.slot = tiles_per_page() - 1; | 1389 GetExpectedTileBounds(reorder_placeholder_.slot).CenterPoint(); |
| 1369 } | 1390 |
| 1391 int column_offset_direction = 0; | |
| 1392 if (grid_index == reorder_placeholder_) { | |
| 1393 column_offset_direction = | |
| 1394 reorder_placeholder_center.x() < point.x() ? -1 : 1; | |
| 1370 } else { | 1395 } else { |
| 1371 gfx::Rect bounds(GetContentsBounds()); | 1396 column_offset_direction = reorder_placeholder_ < grid_index ? -1 : 1; |
| 1372 const int drop_row = (point.y() - bounds.y()) / kPreferredTileHeight; | |
| 1373 const int drop_col = std::min(cols_ - 1, | |
| 1374 (point.x() - bounds.x()) / kPreferredTileWidth); | |
| 1375 | |
| 1376 reorder_drop_target_.page = current_page; | |
| 1377 reorder_drop_target_.slot = std::max( | |
| 1378 0, std::min(tiles_per_page() - 1, drop_row * cols_ + drop_col)); | |
| 1379 } | 1397 } |
| 1380 | 1398 |
| 1381 // Limits to the last possible slot on last page. | 1399 int row = grid_index.slot / cols_; |
| 1382 if (reorder_drop_target_.page == pagination_model_.total_pages() - 1) { | 1400 |
| 1383 reorder_drop_target_.slot = | 1401 // Offset the target column based on the direction of the target. This will |
| 1384 std::min((view_model_.view_size() - 1) % tiles_per_page(), | 1402 // result in earlier targets getting their reorder zone shifted backwards |
| 1385 reorder_drop_target_.slot); | 1403 // and later targets getting their reorder zones shifted forwards. |
| 1404 // | |
| 1405 // This makes eordering feel like the user is slotting items into the spaces | |
| 1406 // between apps. | |
| 1407 int column_offset = column_offset_direction * | |
|
tapted
2014/09/15 06:12:53
nit: maybe a _px or _pixels suffix? Or even just `
calamity
2014/09/15 06:36:15
Done.
| |
| 1408 (kPreferredTileWidth - kFolderDroppingCircleRadius) / 2; | |
| 1409 int col = (point.x() - bounds.x() + column_offset) / kPreferredTileWidth; | |
| 1410 col = ClampToRange(col, 0, cols_ - 1); | |
| 1411 reorder_drop_target_ = | |
| 1412 std::min(Index(pagination_model_.selected_page(), row * cols_ + col), | |
| 1413 GetLastViewIndex()); | |
|
tapted
2014/09/15 06:12:53
nice
| |
| 1414 } | |
| 1415 | |
| 1416 void AppsGridView::OnReorderTimer() { | |
| 1417 if (drop_attempt_ == DROP_FOR_REORDER) { | |
| 1418 reorder_placeholder_ = reorder_drop_target_; | |
| 1419 AnimateToIdealBounds(); | |
| 1386 } | 1420 } |
| 1387 } | 1421 } |
| 1388 | 1422 |
| 1389 | |
| 1390 void AppsGridView::CalculateDropTargetWithFolderEnabled( | |
| 1391 const gfx::Point& drag_point, | |
| 1392 bool use_page_button_hovering) { | |
| 1393 gfx::Point point(drag_point); | |
| 1394 if (!IsPointWithinDragBuffer(drag_point)) { | |
| 1395 point = drag_start_grid_view_; | |
| 1396 } | |
| 1397 | |
| 1398 if (use_page_button_hovering && page_switcher_view_ && | |
| 1399 page_switcher_view_->bounds().Contains(point)) { | |
| 1400 gfx::Point page_switcher_point(point); | |
| 1401 views::View::ConvertPointToTarget(this, page_switcher_view_, | |
| 1402 &page_switcher_point); | |
| 1403 int page = page_switcher_view_->GetPageForPoint(page_switcher_point); | |
| 1404 if (pagination_model_.is_valid_page(page)) | |
| 1405 drop_attempt_ = DROP_FOR_NONE; | |
| 1406 } else { | |
| 1407 DCHECK(drag_view_); | |
| 1408 // Try to find the nearest target for folder dropping or re-ordering. | |
| 1409 CalculateNearestTileForDragView(); | |
| 1410 } | |
| 1411 } | |
| 1412 | |
| 1413 void AppsGridView::OnReorderTimer() { | |
| 1414 if (drop_attempt_ == DROP_FOR_REORDER) | |
| 1415 AnimateToIdealBounds(); | |
| 1416 } | |
| 1417 | |
| 1418 void AppsGridView::OnFolderItemReparentTimer() { | 1423 void AppsGridView::OnFolderItemReparentTimer() { |
| 1419 DCHECK(folder_delegate_); | 1424 DCHECK(folder_delegate_); |
| 1420 if (drag_out_of_folder_container_ && drag_view_) { | 1425 if (drag_out_of_folder_container_ && drag_view_) { |
| 1421 folder_delegate_->ReparentItem(drag_view_, last_drag_point_); | 1426 folder_delegate_->ReparentItem(drag_view_, last_drag_point_); |
| 1422 | 1427 |
| 1423 // Set the flag in the folder's grid view. | 1428 // Set the flag in the folder's grid view. |
| 1424 dragging_for_reparent_item_ = true; | 1429 dragging_for_reparent_item_ = true; |
| 1425 | 1430 |
| 1426 // Do not observe any data change since it is going to be hidden. | 1431 // Do not observe any data change since it is going to be hidden. |
| 1427 item_list_->RemoveObserver(this); | 1432 item_list_->RemoveObserver(this); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1506 void AppsGridView::EndDragFromReparentItemInRootLevel( | 1511 void AppsGridView::EndDragFromReparentItemInRootLevel( |
| 1507 bool events_forwarded_to_drag_drop_host, | 1512 bool events_forwarded_to_drag_drop_host, |
| 1508 bool cancel_drag) { | 1513 bool cancel_drag) { |
| 1509 // EndDrag was called before if |drag_view_| is NULL. | 1514 // EndDrag was called before if |drag_view_| is NULL. |
| 1510 if (!drag_view_) | 1515 if (!drag_view_) |
| 1511 return; | 1516 return; |
| 1512 | 1517 |
| 1513 DCHECK(IsDraggingForReparentInRootLevelGridView()); | 1518 DCHECK(IsDraggingForReparentInRootLevelGridView()); |
| 1514 bool cancel_reparent = cancel_drag || drop_attempt_ == DROP_FOR_NONE; | 1519 bool cancel_reparent = cancel_drag || drop_attempt_ == DROP_FOR_NONE; |
| 1515 if (!events_forwarded_to_drag_drop_host && !cancel_reparent) { | 1520 if (!events_forwarded_to_drag_drop_host && !cancel_reparent) { |
| 1516 CalculateDropTarget(last_drag_point_, true); | 1521 CalculateDropTarget(); |
| 1517 if (drop_attempt_ == DROP_FOR_REORDER && | 1522 if (drop_attempt_ == DROP_FOR_REORDER && |
| 1518 IsValidIndex(reorder_drop_target_)) { | 1523 IsValidIndex(reorder_drop_target_)) { |
| 1519 ReparentItemForReorder(drag_view_, reorder_drop_target_); | 1524 ReparentItemForReorder(drag_view_, reorder_drop_target_); |
| 1520 } else if (drop_attempt_ == DROP_FOR_FOLDER && | 1525 } else if (drop_attempt_ == DROP_FOR_FOLDER && |
| 1521 IsValidIndex(folder_drop_target_)) { | 1526 IsValidIndex(folder_drop_target_)) { |
| 1522 ReparentItemToAnotherFolder(drag_view_, folder_drop_target_); | 1527 ReparentItemToAnotherFolder(drag_view_, folder_drop_target_); |
| 1523 } | 1528 } |
| 1524 SetViewHidden(drag_view_, false /* show */, true /* no animate */); | 1529 SetViewHidden(drag_view_, false /* show */, true /* no animate */); |
| 1525 } | 1530 } |
| 1526 | 1531 |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1992 | 1997 |
| 1993 UpdatePaging(); | 1998 UpdatePaging(); |
| 1994 AnimateToIdealBounds(); | 1999 AnimateToIdealBounds(); |
| 1995 } | 2000 } |
| 1996 | 2001 |
| 1997 void AppsGridView::TotalPagesChanged() { | 2002 void AppsGridView::TotalPagesChanged() { |
| 1998 } | 2003 } |
| 1999 | 2004 |
| 2000 void AppsGridView::SelectedPageChanged(int old_selected, int new_selected) { | 2005 void AppsGridView::SelectedPageChanged(int old_selected, int new_selected) { |
| 2001 if (dragging()) { | 2006 if (dragging()) { |
| 2002 CalculateDropTarget(last_drag_point_, true); | 2007 CalculateDropTarget(); |
| 2003 Layout(); | 2008 Layout(); |
| 2004 MaybeStartPageFlipTimer(last_drag_point_); | 2009 MaybeStartPageFlipTimer(last_drag_point_); |
| 2005 } else { | 2010 } else { |
| 2006 ClearSelectedView(selected_view_); | 2011 ClearSelectedView(selected_view_); |
| 2007 Layout(); | 2012 Layout(); |
| 2008 } | 2013 } |
| 2009 } | 2014 } |
| 2010 | 2015 |
| 2011 void AppsGridView::TransitionStarted() { | 2016 void AppsGridView::TransitionStarted() { |
| 2012 CancelContextMenusOnCurrentPage(); | 2017 CancelContextMenusOnCurrentPage(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 2035 view->layer()->SetOpacity(hide ? 0 : 1); | 2040 view->layer()->SetOpacity(hide ? 0 : 1); |
| 2036 } | 2041 } |
| 2037 | 2042 |
| 2038 void AppsGridView::OnImplicitAnimationsCompleted() { | 2043 void AppsGridView::OnImplicitAnimationsCompleted() { |
| 2039 if (layer()->opacity() == 0.0f) | 2044 if (layer()->opacity() == 0.0f) |
| 2040 SetVisible(false); | 2045 SetVisible(false); |
| 2041 } | 2046 } |
| 2042 | 2047 |
| 2043 bool AppsGridView::EnableFolderDragDropUI() { | 2048 bool AppsGridView::EnableFolderDragDropUI() { |
| 2044 // Enable drag and drop folder UI only if it is at the app list root level | 2049 // Enable drag and drop folder UI only if it is at the app list root level |
| 2045 // and the switch is on and the target folder can still accept new items. | 2050 // and the switch is on. |
| 2046 return model_->folders_enabled() && !folder_delegate_ && | 2051 return model_->folders_enabled() && !folder_delegate_; |
| 2047 CanDropIntoTarget(folder_drop_target_); | |
| 2048 } | 2052 } |
| 2049 | 2053 |
| 2050 bool AppsGridView::CanDropIntoTarget(const Index& drop_target) { | 2054 bool AppsGridView::CanDropIntoTarget(const Index& drop_target) { |
| 2051 views::View* target_view = GetViewAtSlotOnCurrentPage(drop_target.slot); | 2055 views::View* target_view = GetViewAtIndex(drop_target); |
| 2052 if (!target_view) | 2056 if (!target_view) |
| 2053 return true; | 2057 return false; |
| 2054 | 2058 |
| 2055 AppListItem* target_item = | 2059 AppListItem* target_item = |
| 2056 static_cast<AppListItemView*>(target_view)->item(); | 2060 static_cast<AppListItemView*>(target_view)->item(); |
| 2057 // Items can be dropped into non-folders (which have no children) or folders | 2061 // Items can be dropped into non-folders (which have no children) or folders |
| 2058 // that have fewer than the max allowed items. | 2062 // that have fewer than the max allowed items. |
| 2059 // OEM folder does not allow to drag/drop other items in it. | 2063 // OEM folder does not allow to drag/drop other items in it. |
| 2060 return target_item->ChildItemCount() < kMaxFolderItems && | 2064 return target_item->ChildItemCount() < kMaxFolderItems && |
| 2061 !IsOEMFolderItem(target_item); | 2065 !IsOEMFolderItem(target_item); |
| 2062 } | 2066 } |
| 2063 | 2067 |
| 2064 // TODO(jennyz): Optimize the calculation for finding nearest tile. | 2068 AppsGridView::Index AppsGridView::GetNearestTileIndexForPoint( |
| 2065 void AppsGridView::CalculateNearestTileForDragView() { | 2069 const gfx::Point& point) const { |
| 2066 Index nearest_tile; | 2070 gfx::Rect bounds = GetContentsBounds(); |
| 2067 nearest_tile.page = -1; | 2071 int col = |
| 2068 nearest_tile.slot = -1; | 2072 ClampToRange((point.x() - bounds.x()) / kPreferredTileWidth, 0, cols_); |
| 2069 int d_min = -1; | 2073 int row = ClampToRange( |
| 2070 | 2074 (point.y() - bounds.y()) / kPreferredTileHeight, 0, rows_per_page_); |
| 2071 // Calculate the top left tile |drag_view| intersects. | 2075 return Index(pagination_model_.selected_page(), row * cols_ + col); |
| 2072 gfx::Point pt = drag_view_->bounds().origin(); | |
| 2073 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2074 | |
| 2075 // Calculate the top right tile |drag_view| intersects. | |
| 2076 pt = drag_view_->bounds().top_right(); | |
| 2077 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2078 | |
| 2079 // Calculate the bottom left tile |drag_view| intersects. | |
| 2080 pt = drag_view_->bounds().bottom_left(); | |
| 2081 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2082 | |
| 2083 // Calculate the bottom right tile |drag_view| intersects. | |
| 2084 pt = drag_view_->bounds().bottom_right(); | |
| 2085 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2086 | |
| 2087 const int d_folder_dropping = | |
| 2088 kFolderDroppingCircleRadius + kGridIconDimension / 2; | |
| 2089 const int d_reorder = kReorderDroppingCircleRadius + kGridIconDimension / 2; | |
| 2090 | |
| 2091 // If user drags an item across pages to the last page, and targets it | |
| 2092 // to the last empty slot on it, push the last item for re-ordering. | |
| 2093 if (IsLastPossibleDropTarget(nearest_tile) && d_min < d_reorder) { | |
| 2094 drop_attempt_ = DROP_FOR_REORDER; | |
| 2095 nearest_tile.slot = nearest_tile.slot - 1; | |
| 2096 reorder_drop_target_ = nearest_tile; | |
| 2097 return; | |
| 2098 } | |
| 2099 | |
| 2100 if (IsValidIndex(nearest_tile)) { | |
| 2101 if (d_min < d_folder_dropping) { | |
| 2102 views::View* target_view = GetViewAtSlotOnCurrentPage(nearest_tile.slot); | |
| 2103 if (target_view && | |
| 2104 !IsFolderItem(static_cast<AppListItemView*>(drag_view_)->item())) { | |
| 2105 // If a non-folder item is dragged to the target slot with an item | |
| 2106 // sitting on it, attempt to drop the dragged item into the folder | |
| 2107 // containing the item on nearest_tile. | |
| 2108 drop_attempt_ = DROP_FOR_FOLDER; | |
| 2109 folder_drop_target_ = nearest_tile; | |
| 2110 return; | |
| 2111 } else { | |
| 2112 // If the target slot is blank, or the dragged item is a folder, attempt | |
| 2113 // to re-order. | |
| 2114 drop_attempt_ = DROP_FOR_REORDER; | |
| 2115 reorder_drop_target_ = nearest_tile; | |
| 2116 return; | |
| 2117 } | |
| 2118 } else if (d_min < d_reorder) { | |
| 2119 // Entering the re-order circle of the slot. | |
| 2120 drop_attempt_ = DROP_FOR_REORDER; | |
| 2121 reorder_drop_target_ = nearest_tile; | |
| 2122 return; | |
| 2123 } | |
| 2124 } | |
| 2125 | |
| 2126 // If |drag_view| is not entering the re-order or folder dropping region of | |
| 2127 // any items, cancel any previous re-order or folder dropping timer. | |
| 2128 drop_attempt_ = DROP_FOR_NONE; | |
| 2129 reorder_timer_.Stop(); | |
| 2130 folder_dropping_timer_.Stop(); | |
| 2131 | |
| 2132 // When dragging for reparent a folder item, it should go back to its parent | |
| 2133 // folder item if there is no drop target. | |
| 2134 if (IsDraggingForReparentInRootLevelGridView()) { | |
| 2135 DCHECK(activated_folder_item_view_); | |
| 2136 folder_drop_target_ = GetIndexOfView(activated_folder_item_view_); | |
| 2137 } | |
| 2138 } | |
| 2139 | |
| 2140 void AppsGridView::CalculateNearestTileForVertex(const gfx::Point& vertex, | |
| 2141 Index* nearest_tile, | |
| 2142 int* d_min) { | |
| 2143 Index target_index; | |
| 2144 gfx::Rect target_bounds = GetTileBoundsForPoint(vertex, &target_index); | |
| 2145 | |
| 2146 if (target_bounds.IsEmpty() || target_index == *nearest_tile) | |
| 2147 return; | |
| 2148 | |
| 2149 // Do not count the tile, where drag_view_ used to sit on and is still moving | |
| 2150 // on top of it, in calculating nearest tile for drag_view_. | |
| 2151 views::View* target_view = GetViewAtSlotOnCurrentPage(target_index.slot); | |
| 2152 if (target_index == drag_view_init_index_ && !target_view && | |
| 2153 !IsDraggingForReparentInRootLevelGridView()) { | |
| 2154 return; | |
| 2155 } | |
| 2156 | |
| 2157 int d_center = GetDistanceBetweenRects(drag_view_->bounds(), target_bounds); | |
| 2158 if (*d_min < 0 || d_center < *d_min) { | |
| 2159 *d_min = d_center; | |
| 2160 *nearest_tile = target_index; | |
| 2161 } | |
| 2162 } | |
| 2163 | |
| 2164 gfx::Rect AppsGridView::GetTileBoundsForPoint(const gfx::Point& point, | |
| 2165 Index *tile_index) { | |
| 2166 // Check if |point| is outside of contents bounds. | |
| 2167 gfx::Rect bounds(GetContentsBounds()); | |
| 2168 if (!bounds.Contains(point)) | |
| 2169 return gfx::Rect(); | |
| 2170 | |
| 2171 // Calculate which tile |point| is enclosed in. | |
| 2172 int x = point.x(); | |
| 2173 int y = point.y(); | |
| 2174 int col = (x - bounds.x()) / kPreferredTileWidth; | |
| 2175 int row = (y - bounds.y()) / kPreferredTileHeight; | |
| 2176 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); | |
| 2177 | |
| 2178 // Check if |point| is outside a valid item's tile. | |
| 2179 Index index(pagination_model_.selected_page(), row * cols_ + col); | |
| 2180 *tile_index = index; | |
| 2181 return tile_rect; | |
| 2182 } | 2076 } |
| 2183 | 2077 |
| 2184 gfx::Size AppsGridView::GetTileGridSize() const { | 2078 gfx::Size AppsGridView::GetTileGridSize() const { |
| 2185 gfx::Rect bounds = GetExpectedTileBounds(0, 0); | 2079 gfx::Rect bounds = GetExpectedTileBounds(0, 0); |
| 2186 bounds.Union(GetExpectedTileBounds(rows_per_page_ - 1, cols_ - 1)); | 2080 bounds.Union(GetExpectedTileBounds(rows_per_page_ - 1, cols_ - 1)); |
| 2187 return bounds.size(); | 2081 return bounds.size(); |
| 2188 } | 2082 } |
| 2189 | 2083 |
| 2084 gfx::Rect AppsGridView::GetExpectedTileBounds(int slot) const { | |
| 2085 return GetExpectedTileBounds(slot / cols_, slot % cols_); | |
| 2086 } | |
| 2087 | |
| 2190 gfx::Rect AppsGridView::GetExpectedTileBounds(int row, int col) const { | 2088 gfx::Rect AppsGridView::GetExpectedTileBounds(int row, int col) const { |
| 2191 gfx::Rect bounds(GetContentsBounds()); | 2089 gfx::Rect bounds(GetContentsBounds()); |
| 2192 gfx::Size tile_size(kPreferredTileWidth, kPreferredTileHeight); | 2090 gfx::Size tile_size(kPreferredTileWidth, kPreferredTileHeight); |
| 2193 return gfx::Rect(gfx::Point(bounds.x() + col * tile_size.width(), | 2091 return gfx::Rect(gfx::Point(bounds.x() + col * tile_size.width(), |
| 2194 bounds.y() + row * tile_size.height()), | 2092 bounds.y() + row * tile_size.height()), |
| 2195 tile_size); | 2093 tile_size); |
| 2196 } | 2094 } |
| 2197 | 2095 |
| 2198 bool AppsGridView::IsLastPossibleDropTarget(const Index& index) const { | |
| 2199 int last_possible_slot = view_model_.view_size() % tiles_per_page(); | |
| 2200 return (index.page == pagination_model_.total_pages() - 1 && | |
| 2201 index.slot == last_possible_slot + 1); | |
| 2202 } | |
| 2203 | |
| 2204 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { | 2096 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { |
| 2205 if (slot < 0) | 2097 if (slot < 0) |
| 2206 return NULL; | 2098 return NULL; |
| 2207 | 2099 |
| 2208 // Calculate the original bound of the tile at |index|. | 2100 // Calculate the original bound of the tile at |index|. |
| 2209 int row = slot / cols_; | 2101 int row = slot / cols_; |
| 2210 int col = slot % cols_; | 2102 int col = slot % cols_; |
| 2211 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); | 2103 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); |
| 2212 | 2104 |
| 2213 for (int i = 0; i < view_model_.view_size(); ++i) { | 2105 for (int i = 0; i < view_model_.view_size(); ++i) { |
| 2214 views::View* view = view_model_.view_at(i); | 2106 views::View* view = view_model_.view_at(i); |
| 2215 if (view->bounds() == tile_rect && view != drag_view_) | 2107 if (view->bounds() == tile_rect && view != drag_view_) |
| 2216 return view; | 2108 return view; |
| 2217 } | 2109 } |
| 2218 return NULL; | 2110 return NULL; |
| 2219 } | 2111 } |
| 2220 | 2112 |
| 2221 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, | 2113 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, |
| 2222 bool is_target_folder) { | 2114 bool is_target_folder) { |
| 2223 AppListItemView* target_view = | 2115 AppListItemView* target_view = |
| 2224 static_cast<AppListItemView*>( | 2116 static_cast<AppListItemView*>( |
| 2225 GetViewAtSlotOnCurrentPage(target_index.slot)); | 2117 GetViewAtSlotOnCurrentPage(target_index.slot)); |
| 2226 if (target_view) | 2118 if (target_view) |
| 2227 target_view->SetAsAttemptedFolderTarget(is_target_folder); | 2119 target_view->SetAsAttemptedFolderTarget(is_target_folder); |
| 2228 } | 2120 } |
| 2229 | 2121 |
| 2230 } // namespace app_list | 2122 } // namespace app_list |
| OLD | NEW |