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 171 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 } |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 481 Pointer pointer, | 475 Pointer pointer, |
| 482 const ui::LocatedEvent& event) { | 476 const ui::LocatedEvent& event) { |
| 483 DCHECK(view); | 477 DCHECK(view); |
| 484 if (drag_view_ || pulsing_blocks_model_.view_size()) | 478 if (drag_view_ || pulsing_blocks_model_.view_size()) |
| 485 return; | 479 return; |
| 486 | 480 |
| 487 drag_view_ = view; | 481 drag_view_ = view; |
| 488 drag_view_init_index_ = GetIndexOfView(drag_view_); | 482 drag_view_init_index_ = GetIndexOfView(drag_view_); |
| 489 drag_view_offset_ = event.location(); | 483 drag_view_offset_ = event.location(); |
| 490 drag_start_page_ = pagination_model_.selected_page(); | 484 drag_start_page_ = pagination_model_.selected_page(); |
| 485 reorder_placeholder_ = GetIndexOfView(drag_view_); | |
|
tapted
2014/09/11 08:08:54
nit: GetIndexOfView(drag_view_); -> drag_view_init
calamity
2014/09/15 03:26:10
Done.
tapted
2014/09/15 06:12:53
missed?
calamity
2014/09/15 06:36:15
Done for real.
| |
| 491 ExtractDragLocation(event, &drag_start_grid_view_); | 486 ExtractDragLocation(event, &drag_start_grid_view_); |
| 492 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y()); | 487 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y()); |
| 493 } | 488 } |
| 494 | 489 |
| 495 void AppsGridView::StartSettingUpSynchronousDrag() { | 490 void AppsGridView::StartSettingUpSynchronousDrag() { |
| 496 #if defined(OS_WIN) | 491 #if defined(OS_WIN) |
| 497 if (!delegate_ || !use_synchronous_drag_) | 492 if (!delegate_ || !use_synchronous_drag_) |
| 498 return; | 493 return; |
| 499 | 494 |
| 500 // Folders and downloading items can't be integrated with the OS. | 495 // Folders and downloading items can't be integrated with the OS. |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 777 layer()->SetOpacity(show ? 1.0f : 0.0f); | 772 layer()->SetOpacity(show ? 1.0f : 0.0f); |
| 778 } | 773 } |
| 779 | 774 |
| 780 void AppsGridView::InitiateDragFromReparentItemInRootLevelGridView( | 775 void AppsGridView::InitiateDragFromReparentItemInRootLevelGridView( |
| 781 AppListItemView* original_drag_view, | 776 AppListItemView* original_drag_view, |
| 782 const gfx::Rect& drag_view_rect, | 777 const gfx::Rect& drag_view_rect, |
| 783 const gfx::Point& drag_point) { | 778 const gfx::Point& drag_point) { |
| 784 DCHECK(original_drag_view && !drag_view_); | 779 DCHECK(original_drag_view && !drag_view_); |
| 785 DCHECK(!dragging_for_reparent_item_); | 780 DCHECK(!dragging_for_reparent_item_); |
| 786 | 781 |
| 782 // Since the item is new, it's placeholder is conceptually at the back of the | |
|
tapted
2014/09/11 08:08:54
nit: `it's` -> `its`
calamity
2014/09/15 03:26:09
Done.
| |
| 783 // entire apps grid. | |
| 784 reorder_placeholder_ = GetLastViewIndex(); | |
| 785 | |
| 787 // Create a new AppListItemView to duplicate the original_drag_view in the | 786 // Create a new AppListItemView to duplicate the original_drag_view in the |
| 788 // folder's grid view. | 787 // folder's grid view. |
| 789 AppListItemView* view = new AppListItemView(this, original_drag_view->item()); | 788 AppListItemView* view = new AppListItemView(this, original_drag_view->item()); |
| 790 AddChildView(view); | 789 AddChildView(view); |
| 791 drag_view_ = view; | 790 drag_view_ = view; |
| 792 drag_view_->SetPaintToLayer(true); | 791 drag_view_->SetPaintToLayer(true); |
| 793 // Note: For testing purpose, SetFillsBoundsOpaquely can be set to true to | 792 // Note: For testing purpose, SetFillsBoundsOpaquely can be set to true to |
| 794 // show the gray background. | 793 // show the gray background. |
| 795 drag_view_->SetFillsBoundsOpaquely(false); | 794 drag_view_->SetFillsBoundsOpaquely(false); |
| 796 drag_view_->SetBoundsRect(drag_view_rect); | 795 drag_view_->SetBoundsRect(drag_view_rect); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 826 | 825 |
| 827 bool AppsGridView::IsDraggedView(const views::View* view) const { | 826 bool AppsGridView::IsDraggedView(const views::View* view) const { |
| 828 return drag_view_ == view; | 827 return drag_view_ == view; |
| 829 } | 828 } |
| 830 | 829 |
| 831 void AppsGridView::ClearDragState() { | 830 void AppsGridView::ClearDragState() { |
| 832 drop_attempt_ = DROP_FOR_NONE; | 831 drop_attempt_ = DROP_FOR_NONE; |
| 833 drag_pointer_ = NONE; | 832 drag_pointer_ = NONE; |
| 834 reorder_drop_target_ = Index(); | 833 reorder_drop_target_ = Index(); |
| 835 folder_drop_target_ = Index(); | 834 folder_drop_target_ = Index(); |
| 835 reorder_placeholder_ = Index(); | |
| 836 drag_start_grid_view_ = gfx::Point(); | 836 drag_start_grid_view_ = gfx::Point(); |
| 837 drag_start_page_ = -1; | 837 drag_start_page_ = -1; |
| 838 drag_view_offset_ = gfx::Point(); | 838 drag_view_offset_ = gfx::Point(); |
| 839 | 839 |
| 840 if (drag_view_) { | 840 if (drag_view_) { |
| 841 drag_view_->OnDragEnded(); | 841 drag_view_->OnDragEnded(); |
| 842 if (IsDraggingForReparentInRootLevelGridView()) { | 842 if (IsDraggingForReparentInRootLevelGridView()) { |
| 843 const int drag_view_index = view_model_.GetIndexOfView(drag_view_); | 843 const int drag_view_index = view_model_.GetIndexOfView(drag_view_); |
| 844 CHECK_EQ(view_model_.view_size() - 1, drag_view_index); | 844 CHECK_EQ(view_model_.view_size() - 1, drag_view_index); |
| 845 DeleteItemViewAtIndex(drag_view_index); | 845 DeleteItemViewAtIndex(drag_view_index); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1108 } | 1108 } |
| 1109 | 1109 |
| 1110 views::View* AppsGridView::GetViewAtIndex(const Index& index) const { | 1110 views::View* AppsGridView::GetViewAtIndex(const Index& index) const { |
| 1111 if (!IsValidIndex(index)) | 1111 if (!IsValidIndex(index)) |
| 1112 return NULL; | 1112 return NULL; |
| 1113 | 1113 |
| 1114 const int model_index = GetModelIndexFromIndex(index); | 1114 const int model_index = GetModelIndexFromIndex(index); |
| 1115 return view_model_.view_at(model_index); | 1115 return view_model_.view_at(model_index); |
| 1116 } | 1116 } |
| 1117 | 1117 |
| 1118 AppsGridView::Index AppsGridView::GetLastViewIndex() const { | |
| 1119 int view_index = view_model_.view_size() - 1; | |
|
tapted
2014/09/11 08:08:53
DCHECK(!view_model_.empty()); .. assuming we can
calamity
2014/09/15 03:26:10
It'll be a shoddy guarantee.. (A component app sho
tapted
2014/09/15 06:12:52
Yep - that's all i'm after really. Since if it is
| |
| 1120 return Index(view_index / tiles_per_page(), view_index % tiles_per_page()); | |
| 1121 } | |
| 1122 | |
| 1118 void AppsGridView::MoveSelected(int page_delta, | 1123 void AppsGridView::MoveSelected(int page_delta, |
| 1119 int slot_x_delta, | 1124 int slot_x_delta, |
| 1120 int slot_y_delta) { | 1125 int slot_y_delta) { |
| 1121 if (!selected_view_) | 1126 if (!selected_view_) |
| 1122 return SetSelectedItemByIndex(Index(pagination_model_.selected_page(), 0)); | 1127 return SetSelectedItemByIndex(Index(pagination_model_.selected_page(), 0)); |
| 1123 | 1128 |
| 1124 const Index& selected = GetIndexOfView(selected_view_); | 1129 const Index& selected = GetIndexOfView(selected_view_); |
| 1125 int target_slot = selected.slot + slot_x_delta + slot_y_delta * cols_; | 1130 int target_slot = selected.slot + slot_x_delta + slot_y_delta * cols_; |
| 1126 | 1131 |
| 1127 if (selected.slot % cols_ == 0 && slot_x_delta == -1) { | 1132 if (selected.slot % cols_ == 0 && slot_x_delta == -1) { |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1379 // Limits to the last possible slot on last page. | 1384 // Limits to the last possible slot on last page. |
| 1380 if (reorder_drop_target_.page == pagination_model_.total_pages() - 1) { | 1385 if (reorder_drop_target_.page == pagination_model_.total_pages() - 1) { |
| 1381 reorder_drop_target_.slot = | 1386 reorder_drop_target_.slot = |
| 1382 std::min((view_model_.view_size() - 1) % tiles_per_page(), | 1387 std::min((view_model_.view_size() - 1) % tiles_per_page(), |
| 1383 reorder_drop_target_.slot); | 1388 reorder_drop_target_.slot); |
| 1384 } | 1389 } |
| 1385 } | 1390 } |
| 1386 | 1391 |
| 1387 | 1392 |
| 1388 void AppsGridView::CalculateDropTargetWithFolderEnabled( | 1393 void AppsGridView::CalculateDropTargetWithFolderEnabled( |
| 1389 const gfx::Point& drag_point, | 1394 const gfx::Point& drag_point, |
|
tapted
2014/09/11 08:08:53
|drag_point| looks unused now -> remove?
calamity
2014/09/15 03:26:10
Done.
| |
| 1390 bool use_page_button_hovering) { | 1395 bool use_page_button_hovering) { |
| 1391 gfx::Point point(drag_point); | 1396 gfx::Point point = drag_view_->icon()->bounds().CenterPoint(); |
| 1392 if (!IsPointWithinDragBuffer(drag_point)) { | 1397 views::View::ConvertPointToTarget(drag_view_, this, &point); |
| 1393 point = drag_start_grid_view_; | 1398 if (!IsPointWithinDragBuffer(point)) { |
| 1399 // Reset the reorder target to the original position if the cursor is | |
| 1400 // outside the drag buffer. | |
| 1401 if (!IsDraggingForReparentInRootLevelGridView()) | |
| 1402 reorder_drop_target_ = GetIndexOfView(drag_view_); | |
|
tapted
2014/09/11 08:08:53
maybe.. drag_view_init_index_
calamity
2014/09/15 03:26:11
Done.
| |
| 1403 drop_attempt_ = DROP_FOR_NONE; | |
| 1404 return; | |
| 1394 } | 1405 } |
| 1395 | 1406 |
| 1396 if (use_page_button_hovering && page_switcher_view_ && | 1407 if (use_page_button_hovering && page_switcher_view_ && |
| 1397 page_switcher_view_->bounds().Contains(point)) { | 1408 page_switcher_view_->bounds().Contains(point)) { |
| 1398 gfx::Point page_switcher_point(point); | 1409 gfx::Point page_switcher_point(point); |
| 1399 views::View::ConvertPointToTarget(this, page_switcher_view_, | 1410 views::View::ConvertPointToTarget(this, page_switcher_view_, |
| 1400 &page_switcher_point); | 1411 &page_switcher_point); |
| 1401 int page = page_switcher_view_->GetPageForPoint(page_switcher_point); | 1412 int page = page_switcher_view_->GetPageForPoint(page_switcher_point); |
| 1402 if (pagination_model_.is_valid_page(page)) | 1413 if (pagination_model_.is_valid_page(page)) |
| 1403 drop_attempt_ = DROP_FOR_NONE; | 1414 drop_attempt_ = DROP_FOR_NONE; |
| 1404 } else { | 1415 } else { |
|
tapted
2014/09/11 08:08:54
early return before this. no else.
calamity
2014/09/15 03:26:10
Done.
| |
| 1405 DCHECK(drag_view_); | 1416 DCHECK(drag_view_); |
|
tapted
2014/09/11 08:08:54
move this to the start of the function
calamity
2014/09/15 03:26:09
Done.
| |
| 1406 // Try to find the nearest target for folder dropping or re-ordering. | 1417 const int d_folder_dropping = |
|
tapted
2014/09/11 08:08:55
d looks like an abbreviation - maybe `folder_thres
calamity
2014/09/15 03:26:09
I think this is saying the radius is the distance
tapted
2014/09/15 06:12:52
yep - much nicer
| |
| 1407 CalculateNearestTileForDragView(); | 1418 kFolderDroppingCircleRadius + kGridIconDimension / 2; |
| 1419 | |
| 1420 Index nearest_tile_index(pagination_model_.selected_page(), | |
| 1421 GetNearestTileSlotForPoint(point)); | |
| 1422 | |
| 1423 int distance_to_tile_center = | |
| 1424 (point - GetExpectedTileBounds(nearest_tile_index.slot).CenterPoint()) | |
| 1425 .Length(); | |
| 1426 if (nearest_tile_index != reorder_placeholder_ && | |
| 1427 distance_to_tile_center < d_folder_dropping && | |
| 1428 !IsFolderItem(drag_view_->item()) && | |
| 1429 CanDropIntoTarget(nearest_tile_index)) { | |
|
tapted
2014/09/11 08:08:54
CanDropIntoTarget returns true if the drop_target
calamity
2014/09/15 03:26:09
Nope. Fixed.
| |
| 1430 drop_attempt_ = DROP_FOR_FOLDER; | |
| 1431 folder_drop_target_ = nearest_tile_index; | |
| 1432 return; | |
|
tapted
2014/09/11 08:08:53
there's a lot of state above that isn't used for t
calamity
2014/09/15 03:26:11
Done.
| |
| 1433 } | |
| 1434 | |
| 1435 gfx::Rect bounds = GetContentsBounds(); | |
| 1436 // Get coordinates in tile grid space. | |
| 1437 int x = point.x() - bounds.x(); | |
| 1438 int y = point.y() - bounds.y(); | |
| 1439 int row = y / kPreferredTileHeight; | |
| 1440 int grid_col = x / kPreferredTileWidth; | |
| 1441 Index grid_index(pagination_model_.selected_page(), | |
| 1442 std::min(row * cols_ + grid_col, view_model_.view_size())); | |
|
tapted
2014/09/11 08:08:54
This is pretty fiddly... but I don't see an obviou
calamity
2014/09/15 03:26:11
Done.
| |
| 1443 gfx::Point reorder_placeholder_origin = | |
| 1444 GetExpectedTileBounds(reorder_placeholder_.slot).CenterPoint(); | |
| 1445 | |
| 1446 int dir = 0; | |
|
tapted
2014/09/11 08:08:54
dir isn't a good name - maybe column_offset?
calamity
2014/09/15 03:26:09
Done.
| |
| 1447 if (grid_index == reorder_placeholder_) { | |
| 1448 dir = reorder_placeholder_origin.x() < point.x() ? 1 : -1; | |
| 1449 } else { | |
| 1450 dir = reorder_placeholder_ < grid_index ? 1 : -1; | |
| 1451 } | |
| 1452 | |
| 1453 // Offset the target column base on the direction of the target. This will | |
|
tapted
2014/09/11 08:08:54
nit: base->based
calamity
2014/09/15 03:26:09
Done.
| |
| 1454 // result in earlier targets getting their reorder zone shifted backwards | |
| 1455 // and later targets getting their reorder zones shifted forwards. | |
| 1456 // | |
| 1457 // This causes the animation to trigger when slotting items into the spaces | |
| 1458 // between apps. | |
| 1459 int col = (x - dir * kPreferredTileWidth / 3) / kPreferredTileWidth; | |
| 1460 col = std::min(std::max(col, 0), cols_ - 1); | |
| 1461 drop_attempt_ = DROP_FOR_REORDER; | |
| 1462 reorder_drop_target_ = | |
| 1463 std::min(Index(pagination_model_.selected_page(), row * cols_ + col), | |
| 1464 GetLastViewIndex()); | |
| 1408 } | 1465 } |
| 1409 } | 1466 } |
| 1410 | 1467 |
| 1411 void AppsGridView::OnReorderTimer() { | 1468 void AppsGridView::OnReorderTimer() { |
| 1412 if (drop_attempt_ == DROP_FOR_REORDER) | 1469 if (drop_attempt_ == DROP_FOR_REORDER) { |
| 1470 reorder_placeholder_ = reorder_drop_target_; | |
| 1413 AnimateToIdealBounds(); | 1471 AnimateToIdealBounds(); |
| 1472 } | |
| 1414 } | 1473 } |
| 1415 | 1474 |
| 1416 void AppsGridView::OnFolderItemReparentTimer() { | 1475 void AppsGridView::OnFolderItemReparentTimer() { |
| 1417 DCHECK(folder_delegate_); | 1476 DCHECK(folder_delegate_); |
| 1418 if (drag_out_of_folder_container_ && drag_view_) { | 1477 if (drag_out_of_folder_container_ && drag_view_) { |
| 1419 folder_delegate_->ReparentItem(drag_view_, last_drag_point_); | 1478 folder_delegate_->ReparentItem(drag_view_, last_drag_point_); |
| 1420 | 1479 |
| 1421 // Set the flag in the folder's grid view. | 1480 // Set the flag in the folder's grid view. |
| 1422 dragging_for_reparent_item_ = true; | 1481 dragging_for_reparent_item_ = true; |
| 1423 | 1482 |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2033 view->layer()->SetOpacity(hide ? 0 : 1); | 2092 view->layer()->SetOpacity(hide ? 0 : 1); |
| 2034 } | 2093 } |
| 2035 | 2094 |
| 2036 void AppsGridView::OnImplicitAnimationsCompleted() { | 2095 void AppsGridView::OnImplicitAnimationsCompleted() { |
| 2037 if (layer()->opacity() == 0.0f) | 2096 if (layer()->opacity() == 0.0f) |
| 2038 SetVisible(false); | 2097 SetVisible(false); |
| 2039 } | 2098 } |
| 2040 | 2099 |
| 2041 bool AppsGridView::EnableFolderDragDropUI() { | 2100 bool AppsGridView::EnableFolderDragDropUI() { |
| 2042 // Enable drag and drop folder UI only if it is at the app list root level | 2101 // Enable drag and drop folder UI only if it is at the app list root level |
| 2043 // and the switch is on and the target folder can still accept new items. | 2102 // and the switch is on. |
| 2044 return model_->folders_enabled() && !folder_delegate_ && | 2103 return model_->folders_enabled() && !folder_delegate_; |
| 2045 CanDropIntoTarget(folder_drop_target_); | |
|
tapted
2014/09/11 08:08:54
I don't think this belongs here. I'd always assume
calamity
2014/09/15 03:26:09
Nothing afaict. It was obviously needed for the "c
| |
| 2046 } | 2104 } |
| 2047 | 2105 |
| 2048 bool AppsGridView::CanDropIntoTarget(const Index& drop_target) { | 2106 bool AppsGridView::CanDropIntoTarget(const Index& drop_target) { |
| 2049 views::View* target_view = GetViewAtSlotOnCurrentPage(drop_target.slot); | 2107 views::View* target_view = GetViewAtSlotOnCurrentPage(drop_target.slot); |
| 2050 if (!target_view) | 2108 if (!target_view) |
| 2051 return true; | 2109 return true; |
| 2052 | 2110 |
| 2053 AppListItem* target_item = | 2111 AppListItem* target_item = |
| 2054 static_cast<AppListItemView*>(target_view)->item(); | 2112 static_cast<AppListItemView*>(target_view)->item(); |
| 2055 // Items can be dropped into non-folders (which have no children) or folders | 2113 // Items can be dropped into non-folders (which have no children) or folders |
| 2056 // that have fewer than the max allowed items. | 2114 // that have fewer than the max allowed items. |
| 2057 // OEM folder does not allow to drag/drop other items in it. | 2115 // OEM folder does not allow to drag/drop other items in it. |
| 2058 return target_item->ChildItemCount() < kMaxFolderItems && | 2116 return target_item->ChildItemCount() < kMaxFolderItems && |
| 2059 !IsOEMFolderItem(target_item); | 2117 !IsOEMFolderItem(target_item); |
| 2060 } | 2118 } |
| 2061 | 2119 |
| 2062 // TODO(jennyz): Optimize the calculation for finding nearest tile. | 2120 int AppsGridView::GetNearestTileSlotForPoint(const gfx::Point& point) { |
| 2063 void AppsGridView::CalculateNearestTileForDragView() { | 2121 gfx::Rect bounds = GetContentsBounds(); |
|
tapted
2014/09/11 08:08:54
maybe DCHECK(IsPointWithinDragBuffer(point)); befo
calamity
2014/09/15 03:26:09
Hmm. Unfortunately IsPointWithinDragBuffer include
tapted
2014/09/15 06:12:52
sweet
| |
| 2064 Index nearest_tile; | 2122 int col = (point.x() - bounds.x()) / kPreferredTileWidth; |
| 2065 nearest_tile.page = -1; | 2123 int row = (point.y() - bounds.y()) / kPreferredTileHeight; |
| 2066 nearest_tile.slot = -1; | 2124 return row * cols_ + col; |
| 2067 int d_min = -1; | |
| 2068 | |
| 2069 // Calculate the top left tile |drag_view| intersects. | |
| 2070 gfx::Point pt = drag_view_->bounds().origin(); | |
| 2071 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2072 | |
| 2073 // Calculate the top right tile |drag_view| intersects. | |
| 2074 pt = drag_view_->bounds().top_right(); | |
| 2075 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2076 | |
| 2077 // Calculate the bottom left tile |drag_view| intersects. | |
| 2078 pt = drag_view_->bounds().bottom_left(); | |
| 2079 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2080 | |
| 2081 // Calculate the bottom right tile |drag_view| intersects. | |
| 2082 pt = drag_view_->bounds().bottom_right(); | |
| 2083 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | |
| 2084 | |
| 2085 const int d_folder_dropping = | |
| 2086 kFolderDroppingCircleRadius + kGridIconDimension / 2; | |
| 2087 const int d_reorder = kReorderDroppingCircleRadius + kGridIconDimension / 2; | |
| 2088 | |
| 2089 // If user drags an item across pages to the last page, and targets it | |
| 2090 // to the last empty slot on it, push the last item for re-ordering. | |
| 2091 if (IsLastPossibleDropTarget(nearest_tile) && d_min < d_reorder) { | |
| 2092 drop_attempt_ = DROP_FOR_REORDER; | |
| 2093 nearest_tile.slot = nearest_tile.slot - 1; | |
| 2094 reorder_drop_target_ = nearest_tile; | |
| 2095 return; | |
| 2096 } | |
| 2097 | |
| 2098 if (IsValidIndex(nearest_tile)) { | |
| 2099 if (d_min < d_folder_dropping) { | |
| 2100 views::View* target_view = GetViewAtSlotOnCurrentPage(nearest_tile.slot); | |
| 2101 if (target_view && | |
| 2102 !IsFolderItem(static_cast<AppListItemView*>(drag_view_)->item())) { | |
| 2103 // If a non-folder item is dragged to the target slot with an item | |
| 2104 // sitting on it, attempt to drop the dragged item into the folder | |
| 2105 // containing the item on nearest_tile. | |
| 2106 drop_attempt_ = DROP_FOR_FOLDER; | |
| 2107 folder_drop_target_ = nearest_tile; | |
| 2108 return; | |
| 2109 } else { | |
| 2110 // If the target slot is blank, or the dragged item is a folder, attempt | |
| 2111 // to re-order. | |
| 2112 drop_attempt_ = DROP_FOR_REORDER; | |
| 2113 reorder_drop_target_ = nearest_tile; | |
| 2114 return; | |
| 2115 } | |
| 2116 } else if (d_min < d_reorder) { | |
| 2117 // Entering the re-order circle of the slot. | |
| 2118 drop_attempt_ = DROP_FOR_REORDER; | |
| 2119 reorder_drop_target_ = nearest_tile; | |
| 2120 return; | |
| 2121 } | |
| 2122 } | |
| 2123 | |
| 2124 // If |drag_view| is not entering the re-order or fold dropping region of | |
| 2125 // any items, cancel any previous re-order or folder dropping timer. | |
| 2126 drop_attempt_ = DROP_FOR_NONE; | |
| 2127 reorder_timer_.Stop(); | |
| 2128 folder_dropping_timer_.Stop(); | |
| 2129 | |
| 2130 // When dragging for reparent a folder item, it should go back to its parent | |
| 2131 // folder item if there is no drop target. | |
| 2132 if (IsDraggingForReparentInRootLevelGridView()) { | |
| 2133 DCHECK(activated_folder_item_view_); | |
| 2134 folder_drop_target_ = GetIndexOfView(activated_folder_item_view_); | |
| 2135 } | |
| 2136 } | |
| 2137 | |
| 2138 void AppsGridView::CalculateNearestTileForVertex(const gfx::Point& vertex, | |
| 2139 Index* nearest_tile, | |
| 2140 int* d_min) { | |
| 2141 Index target_index; | |
| 2142 gfx::Rect target_bounds = GetTileBoundsForPoint(vertex, &target_index); | |
| 2143 | |
| 2144 if (target_bounds.IsEmpty() || target_index == *nearest_tile) | |
| 2145 return; | |
| 2146 | |
| 2147 // Do not count the tile, where drag_view_ used to sit on and is still moving | |
| 2148 // on top of it, in calculating nearest tile for drag_view_. | |
| 2149 views::View* target_view = GetViewAtSlotOnCurrentPage(target_index.slot); | |
| 2150 if (target_index == drag_view_init_index_ && !target_view && | |
| 2151 !IsDraggingForReparentInRootLevelGridView()) { | |
| 2152 return; | |
| 2153 } | |
| 2154 | |
| 2155 int d_center = GetDistanceBetweenRects(drag_view_->bounds(), target_bounds); | |
| 2156 if (*d_min < 0 || d_center < *d_min) { | |
| 2157 *d_min = d_center; | |
| 2158 *nearest_tile = target_index; | |
| 2159 } | |
| 2160 } | |
| 2161 | |
| 2162 gfx::Rect AppsGridView::GetTileBoundsForPoint(const gfx::Point& point, | |
| 2163 Index *tile_index) { | |
| 2164 // Check if |point| is outside of contents bounds. | |
| 2165 gfx::Rect bounds(GetContentsBounds()); | |
| 2166 if (!bounds.Contains(point)) | |
| 2167 return gfx::Rect(); | |
| 2168 | |
| 2169 // Calculate which tile |point| is enclosed in. | |
| 2170 int x = point.x(); | |
| 2171 int y = point.y(); | |
| 2172 int col = (x - bounds.x()) / kPreferredTileWidth; | |
| 2173 int row = (y - bounds.y()) / kPreferredTileHeight; | |
| 2174 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); | |
| 2175 | |
| 2176 // Check if |point| is outside a valid item's tile. | |
| 2177 Index index(pagination_model_.selected_page(), row * cols_ + col); | |
| 2178 *tile_index = index; | |
| 2179 return tile_rect; | |
| 2180 } | 2125 } |
| 2181 | 2126 |
| 2182 gfx::Size AppsGridView::GetTileGridSize() const { | 2127 gfx::Size AppsGridView::GetTileGridSize() const { |
| 2183 gfx::Rect bounds = GetExpectedTileBounds(0, 0); | 2128 gfx::Rect bounds = GetExpectedTileBounds(0, 0); |
| 2184 bounds.Union(GetExpectedTileBounds(rows_per_page_ - 1, cols_ - 1)); | 2129 bounds.Union(GetExpectedTileBounds(rows_per_page_ - 1, cols_ - 1)); |
| 2185 return bounds.size(); | 2130 return bounds.size(); |
| 2186 } | 2131 } |
| 2187 | 2132 |
| 2133 gfx::Rect AppsGridView::GetExpectedTileBounds(int slot) const { | |
| 2134 return GetExpectedTileBounds(slot / cols_, slot % cols_); | |
| 2135 } | |
| 2136 | |
| 2188 gfx::Rect AppsGridView::GetExpectedTileBounds(int row, int col) const { | 2137 gfx::Rect AppsGridView::GetExpectedTileBounds(int row, int col) const { |
| 2189 gfx::Rect bounds(GetContentsBounds()); | 2138 gfx::Rect bounds(GetContentsBounds()); |
| 2190 gfx::Size tile_size(kPreferredTileWidth, kPreferredTileHeight); | 2139 gfx::Size tile_size(kPreferredTileWidth, kPreferredTileHeight); |
| 2191 return gfx::Rect(gfx::Point(bounds.x() + col * tile_size.width(), | 2140 return gfx::Rect(gfx::Point(bounds.x() + col * tile_size.width(), |
| 2192 bounds.y() + row * tile_size.height()), | 2141 bounds.y() + row * tile_size.height()), |
| 2193 tile_size); | 2142 tile_size); |
| 2194 } | 2143 } |
| 2195 | 2144 |
| 2196 bool AppsGridView::IsLastPossibleDropTarget(const Index& index) const { | |
| 2197 int last_possible_slot = view_model_.view_size() % tiles_per_page(); | |
| 2198 return (index.page == pagination_model_.total_pages() - 1 && | |
| 2199 index.slot == last_possible_slot + 1); | |
| 2200 } | |
| 2201 | |
| 2202 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { | 2145 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { |
| 2203 if (slot < 0) | 2146 if (slot < 0) |
| 2204 return NULL; | 2147 return NULL; |
| 2205 | 2148 |
| 2206 // Calculate the original bound of the tile at |index|. | 2149 // Calculate the original bound of the tile at |index|. |
| 2207 int row = slot / cols_; | 2150 int row = slot / cols_; |
| 2208 int col = slot % cols_; | 2151 int col = slot % cols_; |
| 2209 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); | 2152 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); |
| 2210 | 2153 |
| 2211 for (int i = 0; i < view_model_.view_size(); ++i) { | 2154 for (int i = 0; i < view_model_.view_size(); ++i) { |
| 2212 views::View* view = view_model_.view_at(i); | 2155 views::View* view = view_model_.view_at(i); |
| 2213 if (view->bounds() == tile_rect && view != drag_view_) | 2156 if (view->bounds() == tile_rect && view != drag_view_) |
| 2214 return view; | 2157 return view; |
| 2215 } | 2158 } |
| 2216 return NULL; | 2159 return NULL; |
| 2217 } | 2160 } |
| 2218 | 2161 |
| 2219 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, | 2162 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, |
| 2220 bool is_target_folder) { | 2163 bool is_target_folder) { |
| 2221 AppListItemView* target_view = | 2164 AppListItemView* target_view = |
| 2222 static_cast<AppListItemView*>( | 2165 static_cast<AppListItemView*>( |
| 2223 GetViewAtSlotOnCurrentPage(target_index.slot)); | 2166 GetViewAtSlotOnCurrentPage(target_index.slot)); |
| 2224 if (target_view) | 2167 if (target_view) |
| 2225 target_view->SetAsAttemptedFolderTarget(is_target_folder); | 2168 target_view->SetAsAttemptedFolderTarget(is_target_folder); |
| 2226 } | 2169 } |
| 2227 | 2170 |
| 2228 } // namespace app_list | 2171 } // namespace app_list |
| OLD | NEW |