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 |