Index: ui/app_list/views/apps_grid_view.cc |
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc |
index e8c60f58eda899c85948ea8536ee797800f21884..52034d8c024b4de49027bdab98b83935e43982c5 100644 |
--- a/ui/app_list/views/apps_grid_view.cc |
+++ b/ui/app_list/views/apps_grid_view.cc |
@@ -348,6 +348,9 @@ AppsGridView::AppsGridView(AppsGridViewDelegate* delegate, |
selected_view_(NULL), |
drag_view_(NULL), |
drag_start_page_(-1), |
+#if defined(OS_WIN) |
+ use_synchronous_drag_(true), |
+#endif |
drag_pointer_(NONE), |
drop_attempt_(DROP_FOR_NONE), |
drag_and_drop_host_(NULL), |
@@ -402,6 +405,8 @@ void AppsGridView::ResetForShowApps() { |
for (int i = 0; i < view_model_.view_size(); ++i) { |
view_model_.view_at(i)->SetVisible(true); |
} |
+ CHECK_EQ(item_list_->item_count(), |
+ static_cast<size_t>(view_model_.view_size())); |
} |
void AppsGridView::SetModel(AppListModel* model) { |
@@ -477,7 +482,7 @@ void AppsGridView::InitiateDrag(AppListItemView* view, |
void AppsGridView::StartSettingUpSynchronousDrag() { |
#if defined(OS_WIN) |
- if (!delegate_) |
+ if (!delegate_ || !use_synchronous_drag_) |
return; |
// Folders can't be integrated with the OS. |
@@ -812,7 +817,9 @@ void AppsGridView::ClearDragState() { |
if (drag_view_) { |
drag_view_->OnDragEnded(); |
if (IsDraggingForReparentInRootLevelGridView()) { |
- DeleteItemViewAtIndex(view_model_.GetIndexOfView(drag_view_)); |
+ const int drag_view_index = view_model_.GetIndexOfView(drag_view_); |
+ CHECK_EQ(view_model_.view_size() - 1, drag_view_index); |
+ DeleteItemViewAtIndex(drag_view_index); |
} |
} |
drag_view_ = NULL; |
@@ -939,6 +946,9 @@ bool AppsGridView::OnKeyReleased(const ui::KeyEvent& event) { |
void AppsGridView::ViewHierarchyChanged( |
const ViewHierarchyChangedDetails& details) { |
if (!details.is_add && details.parent == this) { |
+ // The view being delete should not have reference in |view_model_|. |
+ CHECK_EQ(-1, view_model_.GetIndexOfView(details.child)); |
+ |
if (selected_view_ == details.child) |
selected_view_ = NULL; |
if (activated_folder_item_view_ == details.child) |
@@ -1693,16 +1703,23 @@ void AppsGridView::ReparentItemForReorder(views::View* item_view, |
AppListFolderItem* source_folder = |
static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id)); |
+ int target_model_index = GetModelIndexFromIndex(target); |
+ |
// Remove the source folder view if there is only 1 item in it, since the |
// source folder will be deleted after its only child item removed from it. |
- if (source_folder->ChildItemCount() == 1u) |
- DeleteItemViewAtIndex( |
- view_model_.GetIndexOfView(activated_folder_item_view())); |
+ if (source_folder->ChildItemCount() == 1u) { |
+ const int deleted_folder_index = |
+ view_model_.GetIndexOfView(activated_folder_item_view()); |
+ DeleteItemViewAtIndex(deleted_folder_index); |
+ |
+ // Adjust |target_model_index| if it is beyond the deleted folder index. |
+ if (target_model_index > deleted_folder_index) |
+ --target_model_index; |
+ } |
// Move the item from its parent folder to top level item list. |
// Must move to target_model_index, the location we expect the target item |
// to be, not the item location we want to insert before. |
- int target_model_index = GetModelIndexFromIndex(target); |
int current_model_index = view_model_.GetIndexOfView(item_view); |
syncer::StringOrdinal target_position; |
if (target_model_index < static_cast<int>(item_list_->item_count())) |
@@ -1804,7 +1821,11 @@ void AppsGridView::RemoveLastItemFromReparentItemFolderIfNecessary( |
// Create a new item view for the last item in folder. |
size_t last_item_index; |
- item_list_->FindItemIndex(last_item->id(), &last_item_index); |
+ if (!item_list_->FindItemIndex(last_item->id(), &last_item_index) || |
+ last_item_index > static_cast<size_t>(view_model_.view_size())) { |
+ NOTREACHED(); |
+ return; |
+ } |
views::View* last_item_view = CreateViewForItemAtIndex(last_item_index); |
view_model_.Add(last_item_view, last_item_index); |
AddChildView(last_item_view); |
@@ -2016,7 +2037,7 @@ AppsGridView::Index AppsGridView::GetNearestTileForDragView() { |
// If user drags an item across pages to the last page, and targets it |
// to the last empty slot on it, push the last item for re-ordering. |
- if (IsFirstEmptySlot(nearest_tile) && d_min < d_reorder) { |
+ if (IsLastPossibleDropTarget(nearest_tile) && d_min < d_reorder) { |
drop_attempt_ = DROP_FOR_REORDER; |
nearest_tile.slot = nearest_tile.slot - 1; |
return nearest_tile; |
@@ -2119,14 +2140,8 @@ gfx::Rect AppsGridView::GetTileBounds(int row, int col) const { |
return tile_rect; |
} |
-bool AppsGridView::IsFirstEmptySlot(const Index& index) const { |
- // Don't count the hidden drag_view_ created from the item_dragged out of a |
- // folder during re-parenting into the total number of views that are visible |
- // on all grid view pages. |
- int total_views = IsDraggingForReparentInRootLevelGridView() |
- ? view_model_.view_size() - 1 |
- : view_model_.view_size(); |
- int last_possible_slot = (total_views - 1) % tiles_per_page(); |
+bool AppsGridView::IsLastPossibleDropTarget(const Index& index) const { |
+ int last_possible_slot = view_model_.view_size() % tiles_per_page(); |
return (index.page == pagination_model_->total_pages() - 1 && |
index.slot == last_possible_slot + 1); |
} |