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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 item_list_(NULL), | 341 item_list_(NULL), |
342 delegate_(delegate), | 342 delegate_(delegate), |
343 folder_delegate_(NULL), | 343 folder_delegate_(NULL), |
344 pagination_model_(pagination_model), | 344 pagination_model_(pagination_model), |
345 page_switcher_view_(new PageSwitcher(pagination_model)), | 345 page_switcher_view_(new PageSwitcher(pagination_model)), |
346 cols_(0), | 346 cols_(0), |
347 rows_per_page_(0), | 347 rows_per_page_(0), |
348 selected_view_(NULL), | 348 selected_view_(NULL), |
349 drag_view_(NULL), | 349 drag_view_(NULL), |
350 drag_start_page_(-1), | 350 drag_start_page_(-1), |
351 #if defined(OS_WIN) | |
352 use_synchronous_drag_(true), | |
353 #endif | |
351 drag_pointer_(NONE), | 354 drag_pointer_(NONE), |
352 drop_attempt_(DROP_FOR_NONE), | 355 drop_attempt_(DROP_FOR_NONE), |
353 drag_and_drop_host_(NULL), | 356 drag_and_drop_host_(NULL), |
354 forward_events_to_drag_and_drop_host_(false), | 357 forward_events_to_drag_and_drop_host_(false), |
355 page_flip_target_(-1), | 358 page_flip_target_(-1), |
356 page_flip_delay_in_ms_(kPageFlipDelayInMs), | 359 page_flip_delay_in_ms_(kPageFlipDelayInMs), |
357 bounds_animator_(this), | 360 bounds_animator_(this), |
358 activated_folder_item_view_(NULL), | 361 activated_folder_item_view_(NULL), |
359 dragging_for_reparent_item_(false) { | 362 dragging_for_reparent_item_(false) { |
360 SetPaintToLayer(true); | 363 SetPaintToLayer(true); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 void AppsGridView::ResetForShowApps() { | 398 void AppsGridView::ResetForShowApps() { |
396 activated_folder_item_view_ = NULL; | 399 activated_folder_item_view_ = NULL; |
397 ClearDragState(); | 400 ClearDragState(); |
398 layer()->SetOpacity(1.0f); | 401 layer()->SetOpacity(1.0f); |
399 SetVisible(true); | 402 SetVisible(true); |
400 // Set all views to visible in case they weren't made visible again by an | 403 // Set all views to visible in case they weren't made visible again by an |
401 // incomplete animation. | 404 // incomplete animation. |
402 for (int i = 0; i < view_model_.view_size(); ++i) { | 405 for (int i = 0; i < view_model_.view_size(); ++i) { |
403 view_model_.view_at(i)->SetVisible(true); | 406 view_model_.view_at(i)->SetVisible(true); |
404 } | 407 } |
408 DCHECK_EQ(item_list_->item_count(), | |
409 static_cast<size_t>(view_model_.view_size())); | |
405 } | 410 } |
406 | 411 |
407 void AppsGridView::SetModel(AppListModel* model) { | 412 void AppsGridView::SetModel(AppListModel* model) { |
408 if (model_) | 413 if (model_) |
409 model_->RemoveObserver(this); | 414 model_->RemoveObserver(this); |
410 | 415 |
411 model_ = model; | 416 model_ = model; |
412 if (model_) | 417 if (model_) |
413 model_->AddObserver(this); | 418 model_->AddObserver(this); |
414 | 419 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 drag_view_ = view; | 475 drag_view_ = view; |
471 drag_view_init_index_ = GetIndexOfView(drag_view_); | 476 drag_view_init_index_ = GetIndexOfView(drag_view_); |
472 drag_view_offset_ = event.location(); | 477 drag_view_offset_ = event.location(); |
473 drag_start_page_ = pagination_model_->selected_page(); | 478 drag_start_page_ = pagination_model_->selected_page(); |
474 ExtractDragLocation(event, &drag_start_grid_view_); | 479 ExtractDragLocation(event, &drag_start_grid_view_); |
475 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y()); | 480 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y()); |
476 } | 481 } |
477 | 482 |
478 void AppsGridView::StartSettingUpSynchronousDrag() { | 483 void AppsGridView::StartSettingUpSynchronousDrag() { |
479 #if defined(OS_WIN) | 484 #if defined(OS_WIN) |
480 if (!delegate_) | 485 if (!delegate_ || !use_synchronous_drag_) |
481 return; | 486 return; |
482 | 487 |
483 // Folders can't be integrated with the OS. | 488 // Folders can't be integrated with the OS. |
484 if (IsFolderItem(drag_view_->item())) | 489 if (IsFolderItem(drag_view_->item())) |
485 return; | 490 return; |
486 | 491 |
487 // Favor the drag and drop host over native win32 drag. For the Win8/ash | 492 // Favor the drag and drop host over native win32 drag. For the Win8/ash |
488 // launcher we want to have ashes drag and drop over win32's. | 493 // launcher we want to have ashes drag and drop over win32's. |
489 if (drag_and_drop_host_) | 494 if (drag_and_drop_host_) |
490 return; | 495 return; |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
805 drop_attempt_ = DROP_FOR_NONE; | 810 drop_attempt_ = DROP_FOR_NONE; |
806 drag_pointer_ = NONE; | 811 drag_pointer_ = NONE; |
807 drop_target_ = Index(); | 812 drop_target_ = Index(); |
808 drag_start_grid_view_ = gfx::Point(); | 813 drag_start_grid_view_ = gfx::Point(); |
809 drag_start_page_ = -1; | 814 drag_start_page_ = -1; |
810 drag_view_offset_ = gfx::Point(); | 815 drag_view_offset_ = gfx::Point(); |
811 | 816 |
812 if (drag_view_) { | 817 if (drag_view_) { |
813 drag_view_->OnDragEnded(); | 818 drag_view_->OnDragEnded(); |
814 if (IsDraggingForReparentInRootLevelGridView()) { | 819 if (IsDraggingForReparentInRootLevelGridView()) { |
815 DeleteItemViewAtIndex(view_model_.GetIndexOfView(drag_view_)); | 820 const int drag_view_index = view_model_.GetIndexOfView(drag_view_); |
821 DCHECK_EQ(view_model_.view_size() - 1, drag_view_index); | |
822 DeleteItemViewAtIndex(drag_view_index); | |
816 } | 823 } |
817 } | 824 } |
818 drag_view_ = NULL; | 825 drag_view_ = NULL; |
819 dragging_for_reparent_item_ = false; | 826 dragging_for_reparent_item_ = false; |
820 } | 827 } |
821 | 828 |
822 void AppsGridView::SetDragViewVisible(bool visible) { | 829 void AppsGridView::SetDragViewVisible(bool visible) { |
823 DCHECK(drag_view_); | 830 DCHECK(drag_view_); |
824 SetViewHidden(drag_view_, !visible, true); | 831 SetViewHidden(drag_view_, !visible, true); |
825 } | 832 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
932 bool handled = false; | 939 bool handled = false; |
933 if (selected_view_) | 940 if (selected_view_) |
934 handled = selected_view_->OnKeyReleased(event); | 941 handled = selected_view_->OnKeyReleased(event); |
935 | 942 |
936 return handled; | 943 return handled; |
937 } | 944 } |
938 | 945 |
939 void AppsGridView::ViewHierarchyChanged( | 946 void AppsGridView::ViewHierarchyChanged( |
940 const ViewHierarchyChangedDetails& details) { | 947 const ViewHierarchyChangedDetails& details) { |
941 if (!details.is_add && details.parent == this) { | 948 if (!details.is_add && details.parent == this) { |
949 // The view being delete should not have reference in |view_model_|. | |
950 DCHECK_EQ(-1, view_model_.GetIndexOfView(details.child)); | |
951 | |
942 if (selected_view_ == details.child) | 952 if (selected_view_ == details.child) |
943 selected_view_ = NULL; | 953 selected_view_ = NULL; |
944 if (activated_folder_item_view_ == details.child) | 954 if (activated_folder_item_view_ == details.child) |
945 activated_folder_item_view_ = NULL; | 955 activated_folder_item_view_ = NULL; |
946 | 956 |
947 if (drag_view_ == details.child) | 957 if (drag_view_ == details.child) |
948 EndDrag(true); | 958 EndDrag(true); |
949 | 959 |
950 bounds_animator_.StopAnimatingView(details.child); | 960 bounds_animator_.StopAnimatingView(details.child); |
951 } | 961 } |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1686 const Index& target) { | 1696 const Index& target) { |
1687 item_list_->RemoveObserver(this); | 1697 item_list_->RemoveObserver(this); |
1688 model_->RemoveObserver(this); | 1698 model_->RemoveObserver(this); |
1689 | 1699 |
1690 AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item(); | 1700 AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item(); |
1691 DCHECK(reparent_item->IsInFolder()); | 1701 DCHECK(reparent_item->IsInFolder()); |
1692 const std::string source_folder_id = reparent_item->folder_id(); | 1702 const std::string source_folder_id = reparent_item->folder_id(); |
1693 AppListFolderItem* source_folder = | 1703 AppListFolderItem* source_folder = |
1694 static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id)); | 1704 static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id)); |
1695 | 1705 |
1706 int target_model_index = GetModelIndexFromIndex(target); | |
1707 | |
1696 // Remove the source folder view if there is only 1 item in it, since the | 1708 // Remove the source folder view if there is only 1 item in it, since the |
1697 // source folder will be deleted after its only child item removed from it. | 1709 // source folder will be deleted after its only child item removed from it. |
1698 if (source_folder->ChildItemCount() == 1u) | 1710 if (source_folder->ChildItemCount() == 1u) { |
1699 DeleteItemViewAtIndex( | 1711 const int deleted_folder_index = |
1700 view_model_.GetIndexOfView(activated_folder_item_view())); | 1712 view_model_.GetIndexOfView(activated_folder_item_view()); |
1713 DeleteItemViewAtIndex(deleted_folder_index); | |
1714 | |
1715 // Adjust |target_model_index| if it is beyond the deleted folder index. | |
1716 if (target_model_index >= deleted_folder_index) | |
xiyuan
2014/05/27 19:57:26
This fixes the bad index for view_model_.Move belo
| |
1717 --target_model_index; | |
1718 } | |
1701 | 1719 |
1702 // Move the item from its parent folder to top level item list. | 1720 // Move the item from its parent folder to top level item list. |
1703 // Must move to target_model_index, the location we expect the target item | 1721 // Must move to target_model_index, the location we expect the target item |
1704 // to be, not the item location we want to insert before. | 1722 // to be, not the item location we want to insert before. |
1705 int target_model_index = GetModelIndexFromIndex(target); | |
1706 int current_model_index = view_model_.GetIndexOfView(item_view); | 1723 int current_model_index = view_model_.GetIndexOfView(item_view); |
1707 syncer::StringOrdinal target_position; | 1724 syncer::StringOrdinal target_position; |
1708 if (target_model_index < static_cast<int>(item_list_->item_count())) | 1725 if (target_model_index < static_cast<int>(item_list_->item_count())) |
1709 target_position = item_list_->item_at(target_model_index)->position(); | 1726 target_position = item_list_->item_at(target_model_index)->position(); |
1710 model_->MoveItemToFolderAt(reparent_item, "", target_position); | 1727 model_->MoveItemToFolderAt(reparent_item, "", target_position); |
1711 view_model_.Move(current_model_index, target_model_index); | 1728 view_model_.Move(current_model_index, target_model_index); |
1712 | 1729 |
1713 RemoveLastItemFromReparentItemFolderIfNecessary(source_folder_id); | 1730 RemoveLastItemFromReparentItemFolderIfNecessary(source_folder_id); |
1714 | 1731 |
1715 item_list_->AddObserver(this); | 1732 item_list_->AddObserver(this); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1797 // Delete view associated with the folder item to be removed. | 1814 // Delete view associated with the folder item to be removed. |
1798 DeleteItemViewAtIndex( | 1815 DeleteItemViewAtIndex( |
1799 view_model_.GetIndexOfView(activated_folder_item_view())); | 1816 view_model_.GetIndexOfView(activated_folder_item_view())); |
1800 | 1817 |
1801 // Now make the data change to remove the folder item in model. | 1818 // Now make the data change to remove the folder item in model. |
1802 AppListItem* last_item = source_folder->item_list()->item_at(0); | 1819 AppListItem* last_item = source_folder->item_list()->item_at(0); |
1803 model_->MoveItemToFolderAt(last_item, "", source_folder->position()); | 1820 model_->MoveItemToFolderAt(last_item, "", source_folder->position()); |
1804 | 1821 |
1805 // Create a new item view for the last item in folder. | 1822 // Create a new item view for the last item in folder. |
1806 size_t last_item_index; | 1823 size_t last_item_index; |
1807 item_list_->FindItemIndex(last_item->id(), &last_item_index); | 1824 if (!item_list_->FindItemIndex(last_item->id(), &last_item_index) || |
xiyuan
2014/05/27 19:57:26
Speculative fix for calling view_model_.Add with a
| |
1825 last_item_index > static_cast<size_t>(view_model_.view_size())) { | |
1826 NOTREACHED(); | |
1827 return; | |
1828 } | |
1808 views::View* last_item_view = CreateViewForItemAtIndex(last_item_index); | 1829 views::View* last_item_view = CreateViewForItemAtIndex(last_item_index); |
1809 view_model_.Add(last_item_view, last_item_index); | 1830 view_model_.Add(last_item_view, last_item_index); |
1810 AddChildView(last_item_view); | 1831 AddChildView(last_item_view); |
1811 } | 1832 } |
1812 | 1833 |
1813 void AppsGridView::CancelFolderItemReparent(AppListItemView* drag_item_view) { | 1834 void AppsGridView::CancelFolderItemReparent(AppListItemView* drag_item_view) { |
1814 // The icon of the dragged item must target to its final ideal bounds after | 1835 // The icon of the dragged item must target to its final ideal bounds after |
1815 // the animation completes. | 1836 // the animation completes. |
1816 CalculateIdealBounds(); | 1837 CalculateIdealBounds(); |
1817 | 1838 |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2009 pt = drag_view_->bounds().bottom_right(); | 2030 pt = drag_view_->bounds().bottom_right(); |
2010 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); | 2031 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); |
2011 | 2032 |
2012 const int d_folder_dropping = | 2033 const int d_folder_dropping = |
2013 kFolderDroppingCircleRadius + kPreferredIconDimension / 2; | 2034 kFolderDroppingCircleRadius + kPreferredIconDimension / 2; |
2014 const int d_reorder = | 2035 const int d_reorder = |
2015 kReorderDroppingCircleRadius + kPreferredIconDimension / 2; | 2036 kReorderDroppingCircleRadius + kPreferredIconDimension / 2; |
2016 | 2037 |
2017 // If user drags an item across pages to the last page, and targets it | 2038 // If user drags an item across pages to the last page, and targets it |
2018 // to the last empty slot on it, push the last item for re-ordering. | 2039 // to the last empty slot on it, push the last item for re-ordering. |
2019 if (IsFirstEmptySlot(nearest_tile) && d_min < d_reorder) { | 2040 if (IsLastPossibleDropTarget(nearest_tile) && d_min < d_reorder) { |
2020 drop_attempt_ = DROP_FOR_REORDER; | 2041 drop_attempt_ = DROP_FOR_REORDER; |
2021 nearest_tile.slot = nearest_tile.slot - 1; | 2042 nearest_tile.slot = nearest_tile.slot - 1; |
2022 return nearest_tile; | 2043 return nearest_tile; |
2023 } | 2044 } |
2024 | 2045 |
2025 if (IsValidIndex(nearest_tile)) { | 2046 if (IsValidIndex(nearest_tile)) { |
2026 if (d_min < d_folder_dropping) { | 2047 if (d_min < d_folder_dropping) { |
2027 views::View* target_view = GetViewAtSlotOnCurrentPage(nearest_tile.slot); | 2048 views::View* target_view = GetViewAtSlotOnCurrentPage(nearest_tile.slot); |
2028 if (target_view && | 2049 if (target_view && |
2029 !IsFolderItem(static_cast<AppListItemView*>(drag_view_)->item())) { | 2050 !IsFolderItem(static_cast<AppListItemView*>(drag_view_)->item())) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2112 gfx::Rect grid_rect(gfx::Size(tile_size.width() * cols_, | 2133 gfx::Rect grid_rect(gfx::Size(tile_size.width() * cols_, |
2113 tile_size.height() * rows_per_page_)); | 2134 tile_size.height() * rows_per_page_)); |
2114 grid_rect.Intersect(bounds); | 2135 grid_rect.Intersect(bounds); |
2115 gfx::Rect tile_rect( | 2136 gfx::Rect tile_rect( |
2116 gfx::Point(grid_rect.x() + col * tile_size.width(), | 2137 gfx::Point(grid_rect.x() + col * tile_size.width(), |
2117 grid_rect.y() + row * tile_size.height()), | 2138 grid_rect.y() + row * tile_size.height()), |
2118 tile_size); | 2139 tile_size); |
2119 return tile_rect; | 2140 return tile_rect; |
2120 } | 2141 } |
2121 | 2142 |
2122 bool AppsGridView::IsFirstEmptySlot(const Index& index) const { | 2143 bool AppsGridView::IsLastPossibleDropTarget(const Index& index) const { |
2123 // Don't count the hidden drag_view_ created from the item_dragged out of a | 2144 int last_possible_slot = view_model_.view_size() % tiles_per_page(); |
xiyuan
2014/05/27 19:57:26
No need to special case for dragging out of a fold
| |
2124 // folder during re-parenting into the total number of views that are visible | |
2125 // on all grid view pages. | |
2126 int total_views = IsDraggingForReparentInRootLevelGridView() | |
2127 ? view_model_.view_size() - 1 | |
2128 : view_model_.view_size(); | |
2129 int last_possible_slot = (total_views - 1) % tiles_per_page(); | |
2130 return (index.page == pagination_model_->total_pages() - 1 && | 2145 return (index.page == pagination_model_->total_pages() - 1 && |
2131 index.slot == last_possible_slot + 1); | 2146 index.slot == last_possible_slot + 1); |
2132 } | 2147 } |
2133 | 2148 |
2134 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { | 2149 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { |
2135 if (slot < 0) | 2150 if (slot < 0) |
2136 return NULL; | 2151 return NULL; |
2137 | 2152 |
2138 // Calculate the original bound of the tile at |index|. | 2153 // Calculate the original bound of the tile at |index|. |
2139 int row = slot / cols_; | 2154 int row = slot / cols_; |
(...skipping 11 matching lines...) Expand all Loading... | |
2151 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, | 2166 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, |
2152 bool is_target_folder) { | 2167 bool is_target_folder) { |
2153 AppListItemView* target_view = | 2168 AppListItemView* target_view = |
2154 static_cast<AppListItemView*>( | 2169 static_cast<AppListItemView*>( |
2155 GetViewAtSlotOnCurrentPage(target_index.slot)); | 2170 GetViewAtSlotOnCurrentPage(target_index.slot)); |
2156 if (target_view) | 2171 if (target_view) |
2157 target_view->SetAsAttemptedFolderTarget(is_target_folder); | 2172 target_view->SetAsAttemptedFolderTarget(is_target_folder); |
2158 } | 2173 } |
2159 | 2174 |
2160 } // namespace app_list | 2175 } // namespace app_list |
OLD | NEW |