15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/views/apps_grid_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <set>
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/guid.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/app_list/app_list_constants.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/app_list/app_list_folder_item.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_item.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/app_list/app_list_switches.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/app_list/pagination_controller.h"
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "ui/app_list/views/app_list_drag_and_drop_host.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/views/app_list_folder_view.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/views/app_list_item_view.h"
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/app_list/views/apps_grid_view_delegate.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/views/page_switcher.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/views/pulsing_block_view.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/views/top_icon_animation_view.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/animation.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/gfx/geometry/vector2d.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/gfx/geometry/vector2d_conversions.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/border.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view_model_utils.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA)
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window.h"
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/win/hwnd_util.h"
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif  // defined(OS_WIN)
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif  // defined(USE_AURA)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/command_line.h"
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/files/file_path.h"
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/win/shortcut.h"
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/dragdrop/drag_utils.h"
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/dragdrop/drop_target_win.h"
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/dragdrop/os_exchange_data.h"
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/gfx/win/dpi.h"
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace app_list {
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// Distance a drag needs to be from the app grid to be considered 'outside', at
57a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// which point we rearrange the apps to their pre-drag configuration, as a drop
58a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// then would be canceled. We have a buffer to make it easier to drag apps to
59a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// other pages.
60a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst int kDragBufferPx = 20;
61a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Padding space in pixels for fixed layout.
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kLeftRightPadding = 23;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTopPadding = 1;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Padding space in pixels between pages.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPagePadding = 40;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Preferred tile size when showing in fixed layout.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPreferredTileWidth = 88;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPreferredTileHeight = 98;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kExperimentalPreferredTileWidth = 90;
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kExperimentalPrefferedTileHeight = 90;
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Padding on each side of a tile.
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kExperimentalTileLeftRightPadding = 15;
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kExperimentalTileTopBottomPadding = 11;
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Width in pixels of the area on the sides that triggers a page flip.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPageFlipZoneSize = 40;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay in milliseconds to do the page flip.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPageFlipDelayInMs = 1000;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// How many pages on either side of the selected one we prerender.
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kPrerenderPages = 1;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// The drag and drop proxy should get scaled by this factor.
90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const float kDragAndDropProxyScale = 1.5f;
91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Delays in milliseconds to show folder dropping preview circle.
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kFolderDroppingDelay = 150;
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Delays in milliseconds to show re-order preview.
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kReorderDelay = 120;
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Delays in milliseconds to show folder item reparent UI.
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int kFolderItemReparentDelay = 50;
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Radius of the circle, in which if entered, show folder dropping preview
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// UI.
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kFolderDroppingCircleRadius = 39;
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns the size of a tile view excluding its padding.
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Size GetTileViewSize() {
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return switches::IsExperimentalAppListEnabled()
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             ? gfx::Size(kExperimentalPreferredTileWidth,
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         kExperimentalPrefferedTileHeight)
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             : gfx::Size(kPreferredTileWidth, kPreferredTileHeight);
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns the size of a tile view inccluding its padding.
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Size GetTotalTileSize() {
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size size = GetTileViewSize();
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (switches::IsExperimentalAppListEnabled())
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    size.Enlarge(2 * kExperimentalTileLeftRightPadding,
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 2 * kExperimentalTileTopBottomPadding);
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return size;
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RowMoveAnimationDelegate is used when moving an item into a different row.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Before running the animation, the item's layer is re-created and kept in
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the original position, then the item is moved to just before its target
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// position and opacity set to 0. When the animation runs, this delegate moves
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the layer and fades it out while fading in the item at the same time.
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class RowMoveAnimationDelegate : public gfx::AnimationDelegate {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RowMoveAnimationDelegate(views::View* view,
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           ui::Layer* layer,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           const gfx::Rect& layer_target)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : view_(view),
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        layer_(layer),
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        layer_start_(layer ? layer->bounds() : gfx::Rect()),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        layer_target_(layer_target) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~RowMoveAnimationDelegate() {}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // gfx::AnimationDelegate overrides:
140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(animation->GetCurrentValue());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->ScheduleDraw();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (layer_) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      layer_->SetOpacity(1 - animation->GetCurrentValue());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      layer_->SetBounds(animation->CurrentValueBetween(layer_start_,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       layer_target_));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      layer_->ScheduleDraw();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(1.0f);
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    view_->SchedulePaint();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(1.0f);
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    view_->SchedulePaint();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The view that needs to be wrapped. Owned by views hierarchy.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* view_;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::Layer> layer_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect layer_start_;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect layer_target_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RowMoveAnimationDelegate);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ItemRemoveAnimationDelegate is used to show animation for removing an item.
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// This happens when user drags an item into a folder. The dragged item will
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// be removed from the original list after it is dropped into the folder.
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ItemRemoveAnimationDelegate : public gfx::AnimationDelegate {
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  explicit ItemRemoveAnimationDelegate(views::View* view)
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : view_(view) {
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~ItemRemoveAnimationDelegate() {
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // gfx::AnimationDelegate overrides:
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE {
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    view_->layer()->SetOpacity(1 - animation->GetCurrentValue());
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    view_->layer()->ScheduleDraw();
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<views::View> view_;
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ItemRemoveAnimationDelegate);
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// ItemMoveAnimationDelegate observes when an item finishes animating when it is
196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// not moving between rows. This is to ensure an item is repainted for the
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// "zoom out" case when releasing an item being dragged.
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ItemMoveAnimationDelegate : public gfx::AnimationDelegate {
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public:
200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ItemMoveAnimationDelegate(views::View* view) : view_(view) {}
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE {
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    view_->SchedulePaint();
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE {
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    view_->SchedulePaint();
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private:
210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  views::View* view_;
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ItemMoveAnimationDelegate);
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)};
214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Returns true if the |item| is an folder item.
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IsFolderItem(AppListItem* item) {
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (item->GetItemType() == AppListFolderItem::kItemType);
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool IsOEMFolderItem(AppListItem* item) {
22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return IsFolderItem(item) &&
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         (static_cast<AppListFolderItem*>(item))->folder_type() ==
22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)             AppListFolderItem::FOLDER_TYPE_OEM;
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint ClampToRange(int value, int min, int max) {
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return std::min(std::max(value, min), max);
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Interprets drag events sent from Windows via the drag/drop API and forwards
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// them to AppsGridView.
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// On Windows, in order to have the OS perform the drag properly we need to
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// provide it with a shortcut file which may or may not exist at the time the
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// drag is started. Therefore while waiting for that shortcut to be located we
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// just do a regular "internal" drag and transition into the synchronous drag
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// when the shortcut is found/created. Hence a synchronous drag is an optional
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// phase of a regular drag and non-Windows platforms drags are equivalent to a
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Windows drag that never enters the synchronous drag phase.
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass SynchronousDrag : public ui::DragSourceWin {
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SynchronousDrag(AppsGridView* grid_view,
2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  AppListItemView* drag_view,
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  const gfx::Point& drag_view_offset)
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : grid_view_(grid_view),
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        drag_view_(drag_view),
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        drag_view_offset_(drag_view_offset),
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        has_shortcut_path_(false),
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        running_(false),
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        canceled_(false) {}
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void set_shortcut_path(const base::FilePath& shortcut_path) {
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    has_shortcut_path_ = true;
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    shortcut_path_ = shortcut_path;
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool running() { return running_; }
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool CanRun() {
262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return has_shortcut_path_ && !running_;
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Run() {
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK(CanRun());
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Prevent the synchronous dragger being destroyed while the drag is
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // running.
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_refptr<SynchronousDrag> this_ref = this;
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    running_ = true;
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ui::OSExchangeData data;
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SetupExchangeData(&data);
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Hide the dragged view because the OS is going to create its own.
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    drag_view_->SetVisible(false);
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Blocks until the drag is finished. Calls into the ui::DragSourceWin
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // methods.
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DWORD effects;
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data),
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch               this, DROPEFFECT_MOVE | DROPEFFECT_LINK, &effects);
284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // If |drag_view_| is NULL the drag was ended by some reentrant code.
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (drag_view_) {
2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      // Make the drag view visible again.
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      drag_view_->SetVisible(true);
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      drag_view_->OnSyncDragEnd();
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      grid_view_->EndDrag(canceled_ || !IsCursorWithinGridView());
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void EndDragExternally() {
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CancelDrag();
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(drag_view_);
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    drag_view_->SetVisible(true);
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    drag_view_ = NULL;
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Overridden from ui::DragSourceWin.
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDragSourceCancel() OVERRIDE {
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    canceled_ = true;
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDragSourceDrop() OVERRIDE {
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnDragSourceMove() OVERRIDE {
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    grid_view_->UpdateDrag(AppsGridView::MOUSE, GetCursorInGridViewCoords());
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void SetupExchangeData(ui::OSExchangeData* data) {
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    data->SetFilename(shortcut_path_);
317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gfx::ImageSkia image(drag_view_->GetDragImage());
318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gfx::Size image_size(image.size());
319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    drag_utils::SetDragImageOnDataObject(
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        image,
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        drag_view_offset_ - drag_view_->GetDragImageOffset(),
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        data);
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HWND GetGridViewHWND() {
326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return views::HWNDForView(grid_view_);
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool IsCursorWithinGridView() {
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    POINT p;
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    GetCursorPos(&p);
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return GetGridViewHWND() == WindowFromPoint(p);
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Point GetCursorInGridViewCoords() {
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    POINT p;
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    GetCursorPos(&p);
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ScreenToClient(GetGridViewHWND(), &p);
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gfx::Point grid_view_pt(p.x, p.y);
3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    grid_view_pt = gfx::win::ScreenToDIPPoint(grid_view_pt);
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    views::View::ConvertPointFromWidget(grid_view_, &grid_view_pt);
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return grid_view_pt;
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AppsGridView* grid_view_;
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AppListItemView* drag_view_;
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Point drag_view_offset_;
348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool has_shortcut_path_;
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath shortcut_path_;
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool running_;
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool canceled_;
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(SynchronousDrag);
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif  // defined(OS_WIN)
356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AppsGridView::AppsGridView(AppsGridViewDelegate* delegate)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : model_(NULL),
3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      item_list_(NULL),
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_(delegate),
361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      folder_delegate_(NULL),
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      page_switcher_view_(NULL),
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cols_(0),
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rows_per_page_(0),
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_view_(NULL),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_view_(NULL),
367a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      drag_start_page_(-1),
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_WIN)
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      use_synchronous_drag_(true),
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_pointer_(NONE),
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      drop_attempt_(DROP_FOR_NONE),
373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      drag_and_drop_host_(NULL),
374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      forward_events_to_drag_and_drop_host_(false),
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      page_flip_target_(-1),
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      page_flip_delay_in_ms_(kPageFlipDelayInMs),
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bounds_animator_(this),
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      activated_folder_item_view_(NULL),
379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      dragging_for_reparent_item_(false) {
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetPaintToLayer(true);
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Clip any icons that are outside the grid view's bounds. These icons would
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // otherwise be visible to the user when the grid view is off screen.
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  layer()->SetMasksToBounds(true);
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetFillsBoundsOpaquely(false);
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pagination_model_.SetTransitionDurations(kPageTransitionDurationInMs,
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                           kOverscrollPageTransitionDurationMs);
38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pagination_model_.AddObserver(this);
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The experimental app list transitions vertically.
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PaginationController::ScrollAxis scroll_axis =
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      app_list::switches::IsExperimentalAppListEnabled()
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ? PaginationController::SCROLL_AXIS_VERTICAL
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          : PaginationController::SCROLL_AXIS_HORIZONTAL;
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  pagination_controller_.reset(
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new PaginationController(&pagination_model_, scroll_axis));
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!switches::IsExperimentalAppListEnabled()) {
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    page_switcher_view_ = new PageSwitcher(&pagination_model_);
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AddChildView(page_switcher_view_);
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppsGridView::~AppsGridView() {
40468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Coming here |drag_view_| should already be canceled since otherwise the
40568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // drag would disappear after the app list got animated away and closed,
40668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // which would look odd.
40768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(!drag_view_);
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (drag_view_)
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EndDrag(true);
41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (model_)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_->RemoveObserver(this);
41346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pagination_model_.RemoveObserver(this);
4141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (item_list_)
4161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    item_list_->RemoveObserver(this);
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Make sure |page_switcher_view_| is deleted before |pagination_model_|.
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  view_model_.Clear();
42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  RemoveAllChildViews(true);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void AppsGridView::SetLayout(int cols, int rows_per_page) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cols_ = cols;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rows_per_page_ = rows_per_page;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBorder(views::Border::CreateEmptyBorder(
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      switches::IsExperimentalAppListEnabled() ? 0 : kTopPadding,
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      kLeftRightPadding,
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      0,
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      kLeftRightPadding));
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4344ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid AppsGridView::ResetForShowApps() {
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  activated_folder_item_view_ = NULL;
436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ClearDragState();
4374ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  layer()->SetOpacity(1.0f);
4384ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  SetVisible(true);
4394ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Set all views to visible in case they weren't made visible again by an
4404ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // incomplete animation.
4414ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  for (int i = 0; i < view_model_.view_size(); ++i) {
4424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    view_model_.view_at(i)->SetVisible(true);
4434ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_EQ(item_list_->item_count(),
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           static_cast<size_t>(view_model_.view_size()));
4464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
4474ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::SetModel(AppListModel* model) {
4491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (model_)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_->RemoveObserver(this);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_ = model;
4531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (model_)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_->AddObserver(this);
4551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Update();
4571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AppsGridView::SetItemList(AppListItemList* item_list) {
4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (item_list_)
4611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    item_list_->RemoveObserver(this);
4621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  item_list_ = item_list;
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (item_list_)
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_list_->AddObserver(this);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Update();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::SetSelectedView(views::View* view) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsSelectedView(view) || IsDraggedView(view))
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Index index = GetIndexOfView(view);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsValidIndex(index))
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetSelectedItemByIndex(index);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::ClearSelectedView(views::View* view) {
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (view && IsSelectedView(view)) {
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    selected_view_->SchedulePaint();
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    selected_view_ = NULL;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AppsGridView::ClearAnySelectedView() {
485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (selected_view_) {
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    selected_view_->SchedulePaint();
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    selected_view_ = NULL;
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppsGridView::IsSelectedView(const views::View* view) const {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return selected_view_ == view;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::EnsureViewVisible(const views::View* view) {
49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (pagination_model_.has_transition())
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Index index = GetIndexOfView(view);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsValidIndex(index))
50146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    pagination_model_.SelectPage(index.page, false);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void AppsGridView::InitiateDrag(AppListItemView* view,
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                Pointer pointer,
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const ui::LocatedEvent& event) {
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(view);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drag_view_ || pulsing_blocks_model_.view_size())
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_view_ = view;
512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  drag_view_init_index_ = GetIndexOfView(drag_view_);
513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  drag_view_offset_ = event.location();
51446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  drag_start_page_ = pagination_model_.selected_page();
5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  reorder_placeholder_ = drag_view_init_index_;
516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ExtractDragLocation(event, &drag_start_grid_view_);
517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y());
518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid AppsGridView::StartSettingUpSynchronousDrag() {
521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!delegate_ || !use_synchronous_drag_)
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Folders and downloading items can't be integrated with the OS.
526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (IsFolderItem(drag_view_->item()) || drag_view_->item()->is_installing())
52758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
52858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Favor the drag and drop host over native win32 drag. For the Win8/ash
530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // launcher we want to have ashes drag and drop over win32's.
531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (drag_and_drop_host_)
532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5344ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Never create a second synchronous drag if the drag started in a folder.
5354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (IsDraggingForReparentInRootLevelGridView())
5364ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    return;
5374ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  synchronous_drag_ = new SynchronousDrag(this, drag_view_, drag_view_offset_);
5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  delegate_->GetShortcutPathForApp(drag_view_->item()->id(),
5405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                   base::Bind(&AppsGridView::OnGotShortcutPath,
5415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                              base::Unretained(this),
5425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                              synchronous_drag_));
543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool AppsGridView::RunSynchronousDrag() {
547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!synchronous_drag_)
549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
550010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
551010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (synchronous_drag_->CanRun()) {
552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (IsDraggingForReparentInHiddenGridView())
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      folder_delegate_->SetRootLevelDragViewVisible(false);
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    synchronous_drag_->Run();
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    synchronous_drag_ = NULL;
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return true;
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (!synchronous_drag_->running()) {
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // The OS drag is not ready yet. If the root grid has a drag view because
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // a reparent has started, ensure it is visible.
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (IsDraggingForReparentInHiddenGridView())
561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      folder_delegate_->SetRootLevelDragViewVisible(true);
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid AppsGridView::CleanUpSynchronousDrag() {
568a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (synchronous_drag_)
570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    synchronous_drag_->EndDragExternally();
571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  synchronous_drag_ = NULL;
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(OS_WIN)
5775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid AppsGridView::OnGotShortcutPath(
5785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_refptr<SynchronousDrag> synchronous_drag,
5795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const base::FilePath& path) {
5805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Drag may have ended before we get the shortcut path or a new drag may have
5815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // begun.
5825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (synchronous_drag_ != synchronous_drag)
5835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
5845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Setting the shortcut path here means the next time we hit UpdateDrag()
5855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // we'll enter the synchronous drag.
5865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // NOTE we don't Run() the drag here because that causes animations not to
5875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // update for some reason.
5885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  synchronous_drag_->set_shortcut_path(path);
5895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(synchronous_drag_->CanRun());
5905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
5925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AppsGridView::UpdateDragFromItem(Pointer pointer,
594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                      const ui::LocatedEvent& event) {
5956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!drag_view_)
5966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;  // Drag canceled.
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Point drag_point_in_grid_view;
599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ExtractDragLocation(event, &drag_point_in_grid_view);
600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UpdateDrag(pointer, drag_point_in_grid_view);
6017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!dragging())
602a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If a drag and drop host is provided, see if the drag operation needs to be
605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // forwarded.
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point location_in_screen = drag_point_in_grid_view;
607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  views::View::ConvertPointToScreen(this, &location_in_screen);
608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DispatchDragEventToDragAndDropHost(location_in_screen);
609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (drag_and_drop_host_)
610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    drag_and_drop_host_->UpdateDragIconProxy(location_in_screen);
611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid AppsGridView::UpdateDrag(Pointer pointer, const gfx::Point& point) {
6154ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (folder_delegate_)
6164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    UpdateDragStateInsideFolder(pointer, point);
6174ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!drag_view_)
6196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return;  // Drag canceled.
620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (RunSynchronousDrag())
622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Vector2d drag_vector(point - drag_start_grid_view_);
625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!dragging() && ExceededDragThreshold(drag_vector)) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_pointer_ = pointer;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Move the view to the front so that it appears on top of other views.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReorderChildView(drag_view_, -1);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds_animator_.StopAnimatingView(drag_view_);
630010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Stopping the animation may have invalidated our drag view due to the
631010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // view hierarchy changing.
632010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!drag_view_)
633010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
634010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    StartSettingUpSynchronousDrag();
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!dragging_for_reparent_item_)
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      StartDragAndDropHostDrag(point);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (drag_pointer_ != pointer)
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  drag_view_->SetPosition(drag_view_start_ + drag_vector);
6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  last_drag_point_ = point;
6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const Index last_reorder_drop_target = reorder_drop_target_;
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const Index last_folder_drop_target = folder_drop_target_;
648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DropAttempt last_drop_attempt = drop_attempt_;
6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CalculateDropTarget();
650a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MaybeStartPageFlipTimer(last_drag_point_);
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (page_switcher_view_) {
6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::Point page_switcher_point(last_drag_point_);
6551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    views::View::ConvertPointToTarget(
6561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this, page_switcher_view_, &page_switcher_point);
6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    page_switcher_view_->UpdateUIForDragPoint(page_switcher_point);
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (last_folder_drop_target != folder_drop_target_ ||
6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      last_reorder_drop_target != reorder_drop_target_ ||
662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      last_drop_attempt != drop_attempt_) {
663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (drop_attempt_ == DROP_FOR_REORDER) {
664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      folder_dropping_timer_.Stop();
665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      reorder_timer_.Start(FROM_HERE,
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          base::TimeDelta::FromMilliseconds(kReorderDelay),
667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          this, &AppsGridView::OnReorderTimer);
668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else if (drop_attempt_ == DROP_FOR_FOLDER) {
669f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      reorder_timer_.Stop();
670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      folder_dropping_timer_.Start(FROM_HERE,
671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          base::TimeDelta::FromMilliseconds(kFolderDroppingDelay),
672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          this, &AppsGridView::OnFolderDroppingTimer);
673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
675f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Reset the previous drop target.
6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SetAsFolderDroppingTarget(last_folder_drop_target, false);
677f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::EndDrag(bool cancel) {
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // EndDrag was called before if |drag_view_| is NULL.
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!drag_view_)
683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
68558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Coming here a drag and drop was in progress.
68658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool landed_in_drag_and_drop_host = forward_events_to_drag_and_drop_host_;
687b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (forward_events_to_drag_and_drop_host_) {
6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!IsDraggingForReparentInRootLevelGridView());
689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    forward_events_to_drag_and_drop_host_ = false;
690b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    drag_and_drop_host_->EndDrag(cancel);
691010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (IsDraggingForReparentInHiddenGridView()) {
692010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      folder_delegate_->DispatchEndDragEventForReparent(
693010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          true /* events_forwarded_to_drag_drop_host */,
694010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          cancel /* cancel_drag */);
695010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
6964ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  } else {
697effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (IsDraggingForReparentInHiddenGridView()) {
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Forward the EndDrag event to the root level grid view.
699010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      folder_delegate_->DispatchEndDragEventForReparent(
700010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          false /* events_forwarded_to_drag_drop_host */,
701010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          cancel /* cancel_drag */);
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EndDragForReparentInHiddenFolderGridView();
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
7044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
7054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
7066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (IsDraggingForReparentInRootLevelGridView()) {
7076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // An EndDrag can be received during a reparent via a model change. This
7086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // is always a cancel and needs to be forwarded to the folder.
7096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      DCHECK(cancel);
7106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      delegate_->CancelDragInActiveFolder();
7116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
7126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
7136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
7144ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (!cancel && dragging()) {
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Regular drag ending path, ie, not for reparenting.
7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CalculateDropTarget();
7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (EnableFolderDragDropUI() && drop_attempt_ == DROP_FOR_FOLDER &&
7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          IsValidIndex(folder_drop_target_)) {
7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        MoveItemToFolder(drag_view_, folder_drop_target_);
7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else if (IsValidIndex(reorder_drop_target_)) {
7211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        MoveItemInModel(drag_view_, reorder_drop_target_);
722f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
723f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
726a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (drag_and_drop_host_) {
727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If we had a drag and drop proxy icon, we delete it and make the real
728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // item visible again.
729a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    drag_and_drop_host_->DestroyDragIconProxy();
73058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (landed_in_drag_and_drop_host) {
73158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Move the item directly to the target location, avoiding the "zip back"
73258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // animation if the user was pinning it to the shelf.
7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int i = reorder_drop_target_.slot;
73458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      gfx::Rect bounds = view_model_.ideal_bounds(i);
73558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      drag_view_->SetBoundsRect(bounds);
73658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
73758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Fade in slowly if it landed in the shelf.
73858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    SetViewHidden(drag_view_,
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  false /* show */,
7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  !landed_in_drag_and_drop_host /* animate */);
741a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
742a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The drag can be ended after the synchronous drag is created but before it
744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // is Run().
745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CleanUpSynchronousDrag();
746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetAsFolderDroppingTarget(folder_drop_target_, false);
748010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ClearDragState();
749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AnimateToIdealBounds();
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StopPageFlipTimer();
7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If user releases mouse inside a folder's grid view, burst the folder
7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // container ink bubble.
755effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (folder_delegate_ && !IsDraggingForReparentInHiddenGridView())
756effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    folder_delegate_->UpdateFolderViewBackground(false);
757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid AppsGridView::StopPageFlipTimer() {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  page_flip_timer_.Stop();
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  page_flip_target_ = -1;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListItemView* AppsGridView::GetItemViewAt(int index) const {
7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(index >= 0 && index < view_model_.view_size());
7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return static_cast<AppListItemView*>(view_model_.view_at(index));
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::SetTopItemViewsVisible(bool visible) {
7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int top_item_count = std::min(static_cast<int>(kNumFolderTopItems),
7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                view_model_.view_size());
7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < top_item_count; ++i)
773116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetItemViewAt(i)->icon()->SetVisible(visible);
7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::ScheduleShowHideAnimation(bool show) {
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Stop any previous animation.
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  layer()->GetAnimator()->StopAnimating();
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set initial state.
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetVisible(true);
7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  layer()->SetOpacity(show ? 0.0f : 1.0f);
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  animation.AddObserver(this);
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  animation.SetTweenType(
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      show ? kFolderFadeInTweenType : kFolderFadeOutTweenType);
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      show ? kFolderTransitionInDurationMs : kFolderTransitionOutDurationMs));
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  layer()->SetOpacity(show ? 1.0f : 0.0f);
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::InitiateDragFromReparentItemInRootLevelGridView(
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListItemView* original_drag_view,
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::Rect& drag_view_rect,
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::Point& drag_point) {
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(original_drag_view && !drag_view_);
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!dragging_for_reparent_item_);
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Since the item is new, its placeholder is conceptually at the back of the
8021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // entire apps grid.
8031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  reorder_placeholder_ = GetLastViewIndex();
8041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a new AppListItemView to duplicate the original_drag_view in the
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // folder's grid view.
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItemView* view = new AppListItemView(this, original_drag_view->item());
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddChildView(view);
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_view_ = view;
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_view_->SetPaintToLayer(true);
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Note: For testing purpose, SetFillsBoundsOpaquely can be set to true to
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // show the gray background.
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_view_->SetFillsBoundsOpaquely(false);
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_view_->SetBoundsRect(drag_view_rect);
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_view_->SetDragUIState();  // Hide the title of the drag_view_.
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Hide the drag_view_ for drag icon proxy.
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetViewHidden(drag_view_,
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                true /* hide */,
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                true /* no animate */);
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Add drag_view_ to the end of the view_model_.
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view_model_.Add(drag_view_, view_model_.view_size());
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
82546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  drag_start_page_ = pagination_model_.selected_page();
8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_start_grid_view_ = drag_point;
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y());
8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set the flag in root level grid view.
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dragging_for_reparent_item_ = true;
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8344ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid AppsGridView::UpdateDragFromReparentItem(Pointer pointer,
8354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                              const gfx::Point& drag_point) {
8366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Note that if a cancel ocurrs while reparenting, the |drag_view_| in both
8376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // root and folder grid views is cleared, so the check in UpdateDragFromItem()
8386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // for |drag_view_| being NULL (in the folder grid) is sufficient.
8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(drag_view_);
8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsDraggingForReparentInRootLevelGridView());
8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  UpdateDrag(pointer, drag_point);
8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppsGridView::IsDraggedView(const views::View* view) const {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return drag_view_ == view;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
849010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AppsGridView::ClearDragState() {
850010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  drop_attempt_ = DROP_FOR_NONE;
851010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  drag_pointer_ = NONE;
8521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  reorder_drop_target_ = Index();
8531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  folder_drop_target_ = Index();
8541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  reorder_placeholder_ = Index();
855010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  drag_start_grid_view_ = gfx::Point();
856010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  drag_start_page_ = -1;
857010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  drag_view_offset_ = gfx::Point();
858010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
859010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (drag_view_) {
860010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    drag_view_->OnDragEnded();
861010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (IsDraggingForReparentInRootLevelGridView()) {
862cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const int drag_view_index = view_model_.GetIndexOfView(drag_view_);
863cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CHECK_EQ(view_model_.view_size() - 1, drag_view_index);
864cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DeleteItemViewAtIndex(drag_view_index);
865010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
866010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
867010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  drag_view_ = NULL;
868010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  dragging_for_reparent_item_ = false;
869010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
870010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
871010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AppsGridView::SetDragViewVisible(bool visible) {
872010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(drag_view_);
873010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SetViewHidden(drag_view_, !visible, true);
874010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
875010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
876b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void AppsGridView::SetDragAndDropHostOfCurrentAppList(
877b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ApplicationDragAndDropHost* drag_and_drop_host) {
878b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  drag_and_drop_host_ = drag_and_drop_host;
879b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
880b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
8811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppsGridView::Prerender() {
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Layout();
8831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int selected_page = std::max(0, pagination_model_.selected_page());
8841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int start = std::max(0, (selected_page - kPrerenderPages) * tiles_per_page());
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int end = std::min(view_model_.view_size(),
8861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     (selected_page + 1 + kPrerenderPages) * tiles_per_page());
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = start; i < end; i++) {
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AppListItemView* v = static_cast<AppListItemView*>(view_model_.view_at(i));
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v->Prerender();
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
893010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool AppsGridView::IsAnimatingView(views::View* view) {
894010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return bounds_animator_.IsAnimating(view);
895010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
896010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
897cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size AppsGridView::GetPreferredSize() const {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Insets insets(GetInsets());
8991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int page_switcher_height = 0;
9001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (page_switcher_view_)
9011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    page_switcher_height = page_switcher_view_->GetPreferredSize().height();
9021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size size = GetTileGridSize();
9031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size.Enlarge(insets.width(), insets.height() + page_switcher_height);
9041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return size;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool AppsGridView::GetDropFormats(
908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int* formats,
909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::set<OSExchangeData::CustomFormat>* custom_formats) {
910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(koz): Only accept a specific drag type for app shortcuts.
911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  *formats = OSExchangeData::FILE_NAME;
912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return true;
913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool AppsGridView::CanDrop(const OSExchangeData& data) {
916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return true;
917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint AppsGridView::OnDragUpdated(const ui::DropTargetEvent& event) {
920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return ui::DragDropTypes::DRAG_MOVE;
921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::Layout() {
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bounds_animator_.IsAnimating())
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds_animator_.Cancel();
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateIdealBounds();
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < view_model_.view_size(); ++i) {
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* view = view_model_.view_at(i);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (view != drag_view_)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view->SetBoundsRect(view_model_.ideal_bounds(i));
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::ViewModelUtils::SetViewBoundsToIdealBounds(pulsing_blocks_model_);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (page_switcher_view_) {
9361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const int page_switcher_height =
9371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        page_switcher_view_->GetPreferredSize().height();
9381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::Rect rect(GetContentsBounds());
9391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    rect.set_y(rect.bottom() - page_switcher_height);
9401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    rect.set_height(page_switcher_height);
9411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    page_switcher_view_->SetBoundsRect(rect);
9421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppsGridView::OnKeyPressed(const ui::KeyEvent& event) {
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = false;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (selected_view_)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handled = selected_view_->OnKeyPressed(event);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handled) {
951a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const int forward_dir = base::i18n::IsRTL() ? -1 : 1;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (event.key_code()) {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ui::VKEY_LEFT:
95490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MoveSelected(0, -forward_dir, 0);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ui::VKEY_RIGHT:
95790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MoveSelected(0, forward_dir, 0);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ui::VKEY_UP:
96090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MoveSelected(0, 0, -1);
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ui::VKEY_DOWN:
96390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MoveSelected(0, 0, 1);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ui::VKEY_PRIOR: {
96690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MoveSelected(-1, 0, 0);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ui::VKEY_NEXT: {
97090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MoveSelected(1, 0, 0);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppsGridView::OnKeyReleased(const ui::KeyEvent& event) {
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = false;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (selected_view_)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handled = selected_view_->OnKeyReleased(event);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AppsGridView::OnMouseWheel(const ui::MouseWheelEvent& event) {
9901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return pagination_controller_->OnScroll(
9911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Vector2d(event.x_offset(), event.y_offset()));
9921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
9931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
994a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void AppsGridView::ViewHierarchyChanged(
995a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const ViewHierarchyChangedDetails& details) {
996a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!details.is_add && details.parent == this) {
997cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // The view being delete should not have reference in |view_model_|.
998cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CHECK_EQ(-1, view_model_.GetIndexOfView(details.child));
999cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1000a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (selected_view_ == details.child)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_view_ = NULL;
1002cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (activated_folder_item_view_ == details.child)
1003cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      activated_folder_item_view_ = NULL;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (drag_view_ == details.child)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EndDrag(true);
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1008a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    bounds_animator_.StopAnimatingView(details.child);
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppsGridView::OnGestureEvent(ui::GestureEvent* event) {
10131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (pagination_controller_->OnGestureEvent(*event, GetContentsBounds()))
10141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    event->SetHandled();
10151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
10161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppsGridView::OnScrollEvent(ui::ScrollEvent* event) {
10181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (event->type() == ui::ET_SCROLL_FLING_CANCEL)
10191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
10201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Vector2dF offset(event->x_offset(), event->y_offset());
10221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (pagination_controller_->OnScroll(gfx::ToFlooredVector2d(offset))) {
10231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    event->SetHandled();
10241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    event->StopPropagation();
10251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
10261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
10271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::Update() {
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!selected_view_ && !drag_view_);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_model_.Clear();
10315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!item_list_ || !item_list_->item_count())
10321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
10331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (size_t i = 0; i < item_list_->item_count(); ++i) {
10341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    views::View* view = CreateViewForItemAtIndex(i);
10351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    view_model_.Add(view, i);
10361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    AddChildView(view);
10371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
10381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UpdatePaging();
10391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UpdatePulsingBlockViews();
10401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Layout();
10411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SchedulePaint();
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::UpdatePaging() {
1045effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  int total_page = view_model_.view_size() && tiles_per_page()
1046effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       ? (view_model_.view_size() - 1) / tiles_per_page() + 1
1047effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       : 0;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
104946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pagination_model_.SetTotalPages(total_page);
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::UpdatePulsingBlockViews() {
1053f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int existing_items = item_list_ ? item_list_->item_count() : 0;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int available_slots =
1055f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      tiles_per_page() - existing_items % tiles_per_page();
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int desired = model_->status() == AppListModel::STATUS_SYNCING ?
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      available_slots : 0;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pulsing_blocks_model_.view_size() == desired)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (pulsing_blocks_model_.view_size() > desired) {
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* view = pulsing_blocks_model_.view_at(0);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pulsing_blocks_model_.Remove(0);
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete view;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (pulsing_blocks_model_.view_size() < desired) {
10691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    views::View* view = new PulsingBlockView(GetTotalTileSize(), true);
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pulsing_blocks_model_.Add(view, 0);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildView(view);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* AppsGridView::CreateViewForItemAtIndex(size_t index) {
1076f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The drag_view_ might be pending for deletion, therefore view_model_
1077f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // may have one more item than item_list_.
1078f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_LE(index, item_list_->item_count());
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppListItemView* view = new AppListItemView(this,
10801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                              item_list_->item_at(index));
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->SetPaintToLayer(true);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->SetFillsBoundsOpaquely(false);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return view;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)AppsGridView::Index AppsGridView::GetIndexFromModelIndex(
10874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int model_index) const {
1088effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return Index(model_index / tiles_per_page(), model_index % tiles_per_page());
10894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
10904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int AppsGridView::GetModelIndexFromIndex(const Index& index) const {
1092effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return index.page * tiles_per_page() + index.slot;
10934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
10944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::SetSelectedItemByIndex(const Index& index) {
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetIndexOfView(selected_view_) == index)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::View* new_selection = GetViewAtIndex(index);
11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!new_selection)
11012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;  // Keep current selection.
11022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (selected_view_)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_view_->SchedulePaint();
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnsureViewVisible(new_selection);
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  selected_view_ = new_selection;
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  selected_view_->SchedulePaint();
1109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  selected_view_->NotifyAccessibilityEvent(
1110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ui::AX_EVENT_FOCUS, true);
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppsGridView::IsValidIndex(const Index& index) const {
111446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return index.page >= 0 && index.page < pagination_model_.total_pages() &&
1115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         index.slot >= 0 && index.slot < tiles_per_page() &&
11164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         GetModelIndexFromIndex(index) < view_model_.view_size();
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppsGridView::Index AppsGridView::GetIndexOfView(
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const views::View* view) const {
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int model_index = view_model_.GetIndexOfView(view);
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_index == -1)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Index();
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return GetIndexFromModelIndex(model_index);
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* AppsGridView::GetViewAtIndex(const Index& index) const {
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValidIndex(index))
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const int model_index = GetModelIndexFromIndex(index);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return view_model_.view_at(model_index);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAppsGridView::Index AppsGridView::GetLastViewIndex() const {
11371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_LT(0, view_model_.view_size());
11381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int view_index = view_model_.view_size() - 1;
11391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return Index(view_index / tiles_per_page(), view_index % tiles_per_page());
11401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
11411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
114290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void AppsGridView::MoveSelected(int page_delta,
114390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                int slot_x_delta,
114490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                int slot_y_delta) {
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!selected_view_)
114646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return SetSelectedItemByIndex(Index(pagination_model_.selected_page(), 0));
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Index& selected = GetIndexOfView(selected_view_);
114990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int target_slot = selected.slot + slot_x_delta + slot_y_delta * cols_;
115090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
115190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (selected.slot % cols_ == 0 && slot_x_delta == -1) {
115290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (selected.page > 0) {
115390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      page_delta = -1;
115490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      target_slot = selected.slot + cols_ - 1;
115590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
115690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      target_slot = selected.slot;
115790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
115890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
115990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
116090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (selected.slot % cols_ == cols_ - 1 && slot_x_delta == 1) {
116146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (selected.page < pagination_model_.total_pages() - 1) {
116290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      page_delta = 1;
116390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      target_slot = selected.slot - cols_ + 1;
116490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
116590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      target_slot = selected.slot;
116690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
116790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
116890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
116990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Clamp the target slot to the last item if we are moving to the last page
117090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // but our target slot is past the end of the item list.
117190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (page_delta &&
117246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      selected.page + page_delta == pagination_model_.total_pages() - 1) {
117390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int last_item_slot = (view_model_.view_size() - 1) % tiles_per_page();
117490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (last_item_slot < target_slot) {
117590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      target_slot = last_item_slot;
117690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int target_page = std::min(pagination_model_.total_pages() - 1,
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             std::max(selected.page + page_delta, 0));
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetSelectedItemByIndex(Index(target_page, target_slot));
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::CalculateIdealBounds() {
11855b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  // TODO(calamity): This fixes http://crbug.com/422604 on ChromeOS but it's
11865b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  // unclear why. This should be investigated to fix the issue on Linux Ash.
11875b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  if (GetContentsBounds().IsEmpty())
11885b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    return;
11895b892326406927b709cdaf6c384d4ababf456332Ben Murdoch
11901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size grid_size = GetTileGridSize();
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Page size including padding pixels. A tile.x + page_width means the same
11931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // tile slot in the next page; similarly for tile.y + page_height.
11941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const int page_width = grid_size.width() + kPagePadding;
11951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const int page_height = grid_size.height() + kPagePadding;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is a transition, calculates offset for current and target page.
119846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const int current_page = pagination_model_.selected_page();
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PaginationModel::Transition& transition =
120046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      pagination_model_.transition();
120146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const bool is_valid = pagination_model_.is_valid_page(transition.target_page);
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Transition to previous page means negative offset.
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int dir = transition.target_page > current_page ? -1 : 1;
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int total_views =
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view_model_.view_size() + pulsing_blocks_model_.view_size();
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int slot_index = 0;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < total_views; ++i) {
12101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (i < view_model_.view_size() && view_model_.view_at(i) == drag_view_)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Index view_index = GetIndexFromModelIndex(slot_index);
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Leaves a blank space in the grid for the current reorder placeholder.
12161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (reorder_placeholder_ == view_index) {
12171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ++slot_index;
12181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      view_index = GetIndexFromModelIndex(slot_index);
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Decide the x or y offset for current item.
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x_offset = 0;
12231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int y_offset = 0;
12241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (pagination_controller_->scroll_axis() ==
12261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        PaginationController::SCROLL_AXIS_HORIZONTAL) {
12271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (view_index.page < current_page)
12281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        x_offset = -page_width;
12291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      else if (view_index.page > current_page)
12301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        x_offset = page_width;
12311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (is_valid) {
12331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (view_index.page == current_page ||
12341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            view_index.page == transition.target_page) {
12351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          x_offset += transition.progress * page_width * dir;
12361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
12371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
12381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
12391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (view_index.page < current_page)
12401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        y_offset = -page_height;
12411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      else if (view_index.page > current_page)
12421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        y_offset = page_height;
12431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (is_valid) {
12451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (view_index.page == current_page ||
12461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            view_index.page == transition.target_page) {
12471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          y_offset += transition.progress * page_height * dir;
12481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
12494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int row = view_index.slot / cols_;
12534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int col = view_index.slot % cols_;
12541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::Rect tile_slot = GetExpectedTileBounds(row, col);
12551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    tile_slot.Offset(x_offset, y_offset);
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i < view_model_.view_size()) {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view_model_.set_ideal_bounds(i, tile_slot);
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pulsing_blocks_model_.set_ideal_bounds(i - view_model_.view_size(),
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             tile_slot);
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++slot_index;
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::AnimateToIdealBounds() {
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect visible_bounds(GetVisibleBounds());
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateIdealBounds();
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < view_model_.view_size(); ++i) {
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* view = view_model_.view_at(i);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (view == drag_view_)
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& target = view_model_.ideal_bounds(i);
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bounds_animator_.GetTargetBounds(view) == target)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& current = view->bounds();
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool current_visible = visible_bounds.Intersects(current);
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool target_visible = visible_bounds.Intersects(target);
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool visible = current_visible || target_visible;
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int y_diff = target.y() - current.y();
12861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (visible && y_diff && y_diff % GetTotalTileSize().height() == 0) {
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AnimationBetweenRows(view,
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           current_visible,
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           current,
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           target_visible,
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           target);
1292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (visible || bounds_animator_.IsAnimating(view)) {
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds_animator_.AnimateViewTo(view, target);
1294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      bounds_animator_.SetAnimationDelegate(
1295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          view,
1296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          scoped_ptr<gfx::AnimationDelegate>(
1297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              new ItemMoveAnimationDelegate(view)));
1298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
1299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      view->SetBoundsRect(target);
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::AnimationBetweenRows(views::View* view,
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool animate_current,
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const gfx::Rect& current,
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool animate_target,
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const gfx::Rect& target) {
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine page of |current| and |target|. -1 means in the left invisible
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // page, 0 is the center visible page and 1 means in the right invisible page.
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int current_page = current.x() < 0 ? -1 :
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current.x() >= width() ? 1 : 0;
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int target_page = target.x() < 0 ? -1 :
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target.x() >= width() ? 1 : 0;
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int dir = current_page < target_page ||
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (current_page == target_page && current.y() < target.y()) ? 1 : -1;
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::Layer> layer;
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (animate_current) {
1321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    layer = view->RecreateLayer();
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    layer->SuppressPaint();
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view->SetFillsBoundsOpaquely(false);
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view->layer()->SetOpacity(0.f);
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size total_tile_size = GetTotalTileSize();
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect current_out(current);
13301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  current_out.Offset(dir * total_tile_size.width(), 0);
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect target_in(target);
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (animate_target)
13341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    target_in.Offset(-dir * total_tile_size.width(), 0);
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->SetBoundsRect(target_in);
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_.AnimateViewTo(view, target);
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_.SetAnimationDelegate(
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view,
1340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_ptr<gfx::AnimationDelegate>(
1341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          new RowMoveAnimationDelegate(view, layer.release(), current_out)));
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppsGridView::ExtractDragLocation(const ui::LocatedEvent& event,
13452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       gfx::Point* drag_point) {
1346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_AURA) && !defined(OS_WIN)
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Use root location of |event| instead of location in |drag_view_|'s
13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // coordinates because |drag_view_| has a scale transform and location
13492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // could have integer round error and causes jitter.
13502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *drag_point = event.root_location();
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetWidget() could be NULL for tests.
13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetWidget()) {
13542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::Window::ConvertPointToTarget(
13552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetWidget()->GetNativeWindow()->GetRootWindow(),
13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetWidget()->GetNativeWindow(),
13572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        drag_point);
13582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::View::ConvertPointFromWidget(this, drag_point);
13612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
13622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For non-aura, root location is not clearly defined but |drag_view_| does
13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not have the scale transform. So no round error would be introduced and
13642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it's okay to use View::ConvertPointToTarget.
13652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *drag_point = event.location();
13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::View::ConvertPointToTarget(drag_view_, this, drag_point);
13672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
13682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppsGridView::CalculateDropTarget() {
13711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(drag_view_);
13721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
13731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Point point = drag_view_->icon()->bounds().CenterPoint();
13741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  views::View::ConvertPointToTarget(drag_view_, this, &point);
13751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!IsPointWithinDragBuffer(point)) {
13761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Reset the reorder target to the original position if the cursor is
13771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // outside the drag buffer.
13781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (IsDraggingForReparentInRootLevelGridView()) {
13791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      drop_attempt_ = DROP_FOR_NONE;
13801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
13811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
13821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
13831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    reorder_drop_target_ = drag_view_init_index_;
13841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    drop_attempt_ = DROP_FOR_REORDER;
1385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
1386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
13881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (EnableFolderDragDropUI() &&
13891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CalculateFolderDropTarget(point, &folder_drop_target_)) {
13901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    drop_attempt_ = DROP_FOR_FOLDER;
13911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1392a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  drop_attempt_ = DROP_FOR_REORDER;
13951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CalculateReorderDropTarget(point, &reorder_drop_target_);
13961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AppsGridView::CalculateFolderDropTarget(const gfx::Point& point,
13991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             Index* drop_target) const {
14001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Index nearest_tile_index(GetNearestTileIndexForPoint(point));
14011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int distance_to_tile_center =
14021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      (point - GetExpectedTileBounds(nearest_tile_index.slot).CenterPoint())
14031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          .Length();
14041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (nearest_tile_index != reorder_placeholder_ &&
14051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      distance_to_tile_center < kFolderDroppingCircleRadius &&
14061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !IsFolderItem(drag_view_->item()) &&
14071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CanDropIntoTarget(nearest_tile_index)) {
14081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    *drop_target = nearest_tile_index;
14091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(IsValidIndex(*drop_target));
14101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return false;
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppsGridView::CalculateReorderDropTarget(const gfx::Point& point,
14171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              Index* drop_target) const {
14181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect bounds = GetContentsBounds();
14191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Index grid_index = GetNearestTileIndexForPoint(point);
14201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Point reorder_placeholder_center =
14211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetExpectedTileBounds(reorder_placeholder_.slot).CenterPoint();
1422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int x_offset_direction = 0;
14241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (grid_index == reorder_placeholder_) {
14251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    x_offset_direction = reorder_placeholder_center.x() < point.x() ? -1 : 1;
1426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
14271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    x_offset_direction = reorder_placeholder_ < grid_index ? -1 : 1;
1428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
14291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
14301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size total_tile_size = GetTotalTileSize();
14311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int row = grid_index.slot / cols_;
14321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
14331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Offset the target column based on the direction of the target. This will
14341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // result in earlier targets getting their reorder zone shifted backwards
14351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // and later targets getting their reorder zones shifted forwards.
14361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //
14371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // This makes eordering feel like the user is slotting items into the spaces
14381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // between apps.
14391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int x_offset = x_offset_direction *
14401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 (total_tile_size.width() - kFolderDroppingCircleRadius) / 2;
14411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int col = (point.x() - bounds.x() + x_offset) / total_tile_size.width();
14421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  col = ClampToRange(col, 0, cols_ - 1);
14431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *drop_target =
14441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::min(Index(pagination_model_.selected_page(), row * cols_ + col),
14451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               GetLastViewIndex());
14461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(IsValidIndex(*drop_target));
1447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AppsGridView::OnReorderTimer() {
14501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (drop_attempt_ == DROP_FOR_REORDER) {
14511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    reorder_placeholder_ = reorder_drop_target_;
1452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AnimateToIdealBounds();
14531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::OnFolderItemReparentTimer() {
1457effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(folder_delegate_);
1458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (drag_out_of_folder_container_ && drag_view_) {
1459effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    folder_delegate_->ReparentItem(drag_view_, last_drag_point_);
14605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Set the flag in the folder's grid view.
14625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dragging_for_reparent_item_ = true;
14635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Do not observe any data change since it is going to be hidden.
14655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_list_->RemoveObserver(this);
14665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_list_ = NULL;
14675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
14685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
14695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AppsGridView::OnFolderDroppingTimer() {
1471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (drop_attempt_ == DROP_FOR_FOLDER)
14721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SetAsFolderDroppingTarget(folder_drop_target_, true);
1473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14754ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid AppsGridView::UpdateDragStateInsideFolder(Pointer pointer,
14764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                               const gfx::Point& drag_point) {
147723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (IsUnderOEMFolder())
147823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
147923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1480effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (IsDraggingForReparentInHiddenGridView()) {
14815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Dispatch drag event to root level grid view for re-parenting folder
14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // folder item purpose.
14834ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    DispatchDragEventForReparent(pointer, drag_point);
14845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
14865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Regular drag and drop in a folder's grid view.
1488effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  folder_delegate_->UpdateFolderViewBackground(true);
14895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Calculate if the drag_view_ is dragged out of the folder's container
14915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ink bubble.
14925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect bounds_to_folder_view = ConvertRectToParent(drag_view_->bounds());
14935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Point pt = bounds_to_folder_view.CenterPoint();
14945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool is_item_dragged_out_of_folder =
1495effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      folder_delegate_->IsPointOutsideOfFolderBoundary(pt);
14965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_item_dragged_out_of_folder) {
14975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!drag_out_of_folder_container_) {
1498c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      folder_item_reparent_timer_.Start(
1499c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          FROM_HERE,
1500c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          base::TimeDelta::FromMilliseconds(kFolderItemReparentDelay),
1501c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          this,
1502c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          &AppsGridView::OnFolderItemReparentTimer);
15035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      drag_out_of_folder_container_ = true;
15045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
15055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
15065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    folder_item_reparent_timer_.Stop();
15075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    drag_out_of_folder_container_ = false;
15085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
15095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppsGridView::IsDraggingForReparentInRootLevelGridView() const {
1512effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return (!folder_delegate_ && dragging_for_reparent_item_);
15135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool AppsGridView::IsDraggingForReparentInHiddenGridView() const {
1516effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return (folder_delegate_ && dragging_for_reparent_item_);
15175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gfx::Rect AppsGridView::GetTargetIconRectInFolder(
15205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListItemView* drag_item_view,
15215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppListItemView* folder_item_view) {
15225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect view_ideal_bounds = view_model_.ideal_bounds(
15235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      view_model_.GetIndexOfView(folder_item_view));
15245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect icon_ideal_bounds =
15255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      folder_item_view->GetIconBoundsForTargetViewBounds(view_ideal_bounds);
15265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListFolderItem* folder_item =
15275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      static_cast<AppListFolderItem*>(folder_item_view->item());
15285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return folder_item->GetTargetIconRectInFolderForItem(
15295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      drag_item_view->item(), icon_ideal_bounds);
15305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
153223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool AppsGridView::IsUnderOEMFolder() {
1533effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!folder_delegate_)
153423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
153523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1536effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return folder_delegate_->IsOEMFolder();
153723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
153823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
15394ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid AppsGridView::DispatchDragEventForReparent(Pointer pointer,
15404ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                                const gfx::Point& drag_point) {
15414ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  folder_delegate_->DispatchDragEventForReparent(pointer, drag_point);
15425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::EndDragFromReparentItemInRootLevel(
1545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool events_forwarded_to_drag_drop_host,
1546010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool cancel_drag) {
15475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // EndDrag was called before if |drag_view_| is NULL.
15485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!drag_view_)
15495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
15505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsDraggingForReparentInRootLevelGridView());
1552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool cancel_reparent = cancel_drag || drop_attempt_ == DROP_FOR_NONE;
1553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!events_forwarded_to_drag_drop_host && !cancel_reparent) {
15541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CalculateDropTarget();
15551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (drop_attempt_ == DROP_FOR_REORDER &&
15561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        IsValidIndex(reorder_drop_target_)) {
15571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ReparentItemForReorder(drag_view_, reorder_drop_target_);
15581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else if (drop_attempt_ == DROP_FOR_FOLDER &&
15591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               IsValidIndex(folder_drop_target_)) {
15601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ReparentItemToAnotherFolder(drag_view_, folder_drop_target_);
15611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
15621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NOTREACHED();
15635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1564010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SetViewHidden(drag_view_, false /* show */, true /* no animate */);
15655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
15665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The drag can be ended after the synchronous drag is created but before it
15685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is Run().
15695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CleanUpSynchronousDrag();
15705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetAsFolderDroppingTarget(folder_drop_target_, false);
1572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (cancel_reparent) {
1573010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    CancelFolderItemReparent(drag_view_);
1574010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
1575010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // By setting |drag_view_| to NULL here, we prevent ClearDragState() from
1576010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // cleaning up the newly created AppListItemView, effectively claiming
1577010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // ownership of the newly created drag view.
15785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    drag_view_->OnDragEnded();
1579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    drag_view_ = NULL;
1580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
1581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ClearDragState();
15825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AnimateToIdealBounds();
15835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StopPageFlipTimer();
15855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::EndDragForReparentInHiddenFolderGridView() {
15885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (drag_and_drop_host_) {
15895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If we had a drag and drop proxy icon, we delete it and make the real
15905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // item visible again.
15915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    drag_and_drop_host_->DestroyDragIconProxy();
15925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
15935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The drag can be ended after the synchronous drag is created but before it
15955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is Run().
15965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CleanUpSynchronousDrag();
15975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetAsFolderDroppingTarget(folder_drop_target_, false);
1599010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ClearDragState();
16005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::OnFolderItemRemoved() {
1603effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(folder_delegate_);
16045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_ = NULL;
16055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid AppsGridView::StartDragAndDropHostDrag(const gfx::Point& grid_location) {
16087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // When a drag and drop host is given, the item can be dragged out of the app
16097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // list window. In that case a proxy widget needs to be used.
16107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Note: This code has very likely to be changed for Windows (non metro mode)
16117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // when a |drag_and_drop_host_| gets implemented.
16127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!drag_view_ || !drag_and_drop_host_)
16137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
16147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
16157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Point screen_location = grid_location;
16167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  views::View::ConvertPointToScreen(this, &screen_location);
16177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
16187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Determine the mouse offset to the center of the icon so that the drag and
16197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // drop host follows this layer.
16207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Vector2d delta = drag_view_offset_ -
16217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                        drag_view_->GetLocalBounds().CenterPoint();
16227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  delta.set_y(delta.y() + drag_view_->title()->size().height() / 2);
16237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
16247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // We have to hide the original item since the drag and drop host will do
16257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // the OS dependent code to "lift off the dragged item".
16265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!IsDraggingForReparentInRootLevelGridView());
16277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  drag_and_drop_host_->CreateDragIconProxy(screen_location,
16285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           drag_view_->item()->icon(),
16297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                           drag_view_,
16307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                           delta,
16317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                           kDragAndDropProxyScale);
163258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SetViewHidden(drag_view_,
163358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)           true /* hide */,
163458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)           true /* no animation */);
16357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
16367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1637b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void AppsGridView::DispatchDragEventToDragAndDropHost(
1638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const gfx::Point& location_in_screen_coordinates) {
1639b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!drag_view_ || !drag_and_drop_host_)
1640b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
16415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (GetLocalBounds().Contains(last_drag_point_)) {
1643b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // The event was issued inside the app menu and we should get all events.
1644b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (forward_events_to_drag_and_drop_host_) {
1645b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // The DnD host was previously called and needs to be informed that the
1646b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // session returns to the owner.
1647b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      forward_events_to_drag_and_drop_host_ = false;
1648b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      drag_and_drop_host_->EndDrag(true);
1649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
1650b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else {
165123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (IsFolderItem(drag_view_->item()))
165223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return;
165323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1654b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // The event happened outside our app menu and we might need to dispatch.
1655b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (forward_events_to_drag_and_drop_host_) {
1656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // Dispatch since we have already started.
1657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!drag_and_drop_host_->Drag(location_in_screen_coordinates)) {
1658b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // The host is not active any longer and we cancel the operation.
1659b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        forward_events_to_drag_and_drop_host_ = false;
1660b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        drag_and_drop_host_->EndDrag(true);
1661b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      }
1662b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    } else {
16635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (drag_and_drop_host_->StartDrag(drag_view_->item()->id(),
1664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         location_in_screen_coordinates)) {
1665b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // From now on we forward the drag events.
1666b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        forward_events_to_drag_and_drop_host_ = true;
1667b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // Any flip operations are stopped.
1668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        StopPageFlipTimer();
1669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      }
1670b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
1671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
1672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
1673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::MaybeStartPageFlipTimer(const gfx::Point& drag_point) {
1675a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (!IsPointWithinDragBuffer(drag_point))
1676a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    StopPageFlipTimer();
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int new_page_flip_target = -1;
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Drag zones are at the edges of the scroll axis.
16801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (pagination_controller_->scroll_axis() ==
16811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PaginationController::SCROLL_AXIS_VERTICAL) {
16821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (drag_point.y() < kPageFlipZoneSize)
16831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new_page_flip_target = pagination_model_.selected_page() - 1;
16841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else if (drag_point.y() > height() - kPageFlipZoneSize)
16851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new_page_flip_target = pagination_model_.selected_page() + 1;
16861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
16871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (page_switcher_view_->bounds().Contains(drag_point)) {
16881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Point page_switcher_point(drag_point);
16891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      views::View::ConvertPointToTarget(
16901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this, page_switcher_view_, &page_switcher_point);
16911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new_page_flip_target =
16921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          page_switcher_view_->GetPageForPoint(page_switcher_point);
16931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(xiyuan): Fix this for RTL.
16961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (new_page_flip_target == -1 && drag_point.x() < kPageFlipZoneSize)
16971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new_page_flip_target = pagination_model_.selected_page() - 1;
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (new_page_flip_target == -1 &&
17001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        drag_point.x() > width() - kPageFlipZoneSize) {
17011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new_page_flip_target = pagination_model_.selected_page() + 1;
17021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_page_flip_target == page_flip_target_)
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1708a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  StopPageFlipTimer();
170946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (pagination_model_.is_valid_page(new_page_flip_target)) {
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    page_flip_target_ = new_page_flip_target;
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
171246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (page_flip_target_ != pagination_model_.selected_page()) {
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      page_flip_timer_.Start(FROM_HERE,
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::TimeDelta::FromMilliseconds(page_flip_delay_in_ms_),
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, &AppsGridView::OnPageFlipTimer);
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::OnPageFlipTimer() {
172146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(pagination_model_.is_valid_page(page_flip_target_));
172246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pagination_model_.SelectPage(page_flip_target_, true);
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::MoveItemInModel(views::View* item_view,
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const Index& target) {
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int current_model_index = view_model_.GetIndexOfView(item_view);
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(current_model_index, 0);
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int target_model_index = GetModelIndexFromIndex(target);
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target_model_index == current_model_index)
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  item_list_->RemoveObserver(this);
17351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  item_list_->MoveItem(current_model_index, target_model_index);
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_model_.Move(current_model_index, target_model_index);
17371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  item_list_->AddObserver(this);
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
173946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (pagination_model_.selected_page() != target.page)
174046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    pagination_model_.SelectPage(target.page, false);
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AppsGridView::MoveItemToFolder(views::View* item_view,
1744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    const Index& target) {
17455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string& source_item_id =
17465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      static_cast<AppListItemView*>(item_view)->item()->id();
1747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppListItemView* target_view =
1748f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      static_cast<AppListItemView*>(GetViewAtSlotOnCurrentPage(target.slot));
17495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string&  target_view_item_id = target_view->item()->id();
1750f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1751f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Make change to data model.
1752f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  item_list_->RemoveObserver(this);
17535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string folder_item_id =
17545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      model_->MergeItems(target_view_item_id, source_item_id);
17555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_->AddObserver(this);
175623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (folder_item_id.empty()) {
175723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    LOG(ERROR) << "Unable to merge into item id: " << target_view_item_id;
175823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
175923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
17605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (folder_item_id != target_view_item_id) {
17615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // New folder was created, change the view model to replace the old target
17625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // view with the new folder item view.
17635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_t folder_item_index;
17645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (item_list_->FindItemIndex(folder_item_id, &folder_item_index)) {
17655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int target_view_index = view_model_.GetIndexOfView(target_view);
1766a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      gfx::Rect target_view_bounds = target_view->bounds();
1767c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DeleteItemViewAtIndex(target_view_index);
17685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      views::View* target_folder_view =
17695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CreateViewForItemAtIndex(folder_item_index);
1770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      target_folder_view->SetBoundsRect(target_view_bounds);
17715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      view_model_.Add(target_folder_view, target_view_index);
17725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddChildView(target_folder_view);
17735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
17745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LOG(ERROR) << "Folder no longer in item_list: " << folder_item_id;
17755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1776f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1777f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1778f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Fade out the drag_view_ and delete it when animation ends.
1779f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int drag_view_index = view_model_.GetIndexOfView(drag_view_);
1780f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  view_model_.Remove(drag_view_index);
1781f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bounds_animator_.AnimateViewTo(drag_view_, drag_view_->bounds());
1782f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bounds_animator_.SetAnimationDelegate(
1783f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      drag_view_,
1784f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_ptr<gfx::AnimationDelegate>(
1785f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          new ItemRemoveAnimationDelegate(drag_view_)));
17865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdatePaging();
17875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
17885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::ReparentItemForReorder(views::View* item_view,
17905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          const Index& target) {
17915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_->RemoveObserver(this);
17925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  model_->RemoveObserver(this);
17935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item();
17955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(reparent_item->IsInFolder());
1796c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const std::string source_folder_id = reparent_item->folder_id();
1797c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  AppListFolderItem* source_folder =
1798c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id));
1799c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1800cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int target_model_index = GetModelIndexFromIndex(target);
1801cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1802c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Remove the source folder view if there is only 1 item in it, since the
1803c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // source folder will be deleted after its only child item removed from it.
1804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (source_folder->ChildItemCount() == 1u) {
1805cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const int deleted_folder_index =
1806cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        view_model_.GetIndexOfView(activated_folder_item_view());
1807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DeleteItemViewAtIndex(deleted_folder_index);
1808cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1809cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Adjust |target_model_index| if it is beyond the deleted folder index.
1810cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (target_model_index > deleted_folder_index)
1811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      --target_model_index;
1812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
18135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Move the item from its parent folder to top level item list.
18155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Must move to target_model_index, the location we expect the target item
18165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to be, not the item location we want to insert before.
18175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int current_model_index = view_model_.GetIndexOfView(item_view);
18185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  syncer::StringOrdinal target_position;
18195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (target_model_index < static_cast<int>(item_list_->item_count()))
18205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    target_position = item_list_->item_at(target_model_index)->position();
18215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  model_->MoveItemToFolderAt(reparent_item, "", target_position);
18225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view_model_.Move(current_model_index, target_model_index);
18235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1824c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RemoveLastItemFromReparentItemFolderIfNecessary(source_folder_id);
18255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_->AddObserver(this);
18275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  model_->AddObserver(this);
18285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdatePaging();
18295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
18305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::ReparentItemToAnotherFolder(views::View* item_view,
18325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               const Index& target) {
18335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsDraggingForReparentInRootLevelGridView());
18345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AppListItemView* target_view =
1836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<AppListItemView*>(GetViewAtSlotOnCurrentPage(target.slot));
1837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!target_view)
1838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
1839cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
18405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make change to data model.
18415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_->RemoveObserver(this);
18425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item();
18445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(reparent_item->IsInFolder());
1845c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const std::string source_folder_id = reparent_item->folder_id();
1846c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  AppListFolderItem* source_folder =
1847c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id));
1848c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1849c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Remove the source folder view if there is only 1 item in it, since the
1850c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // source folder will be deleted after its only child item merged into the
1851c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // target item.
1852c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (source_folder->ChildItemCount() == 1u)
1853cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DeleteItemViewAtIndex(
1854cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        view_model_.GetIndexOfView(activated_folder_item_view()));
1855f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* target_item = target_view->item();
18575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Move item to the target folder.
185923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string target_id_after_merge =
18605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      model_->MergeItems(target_item->id(), reparent_item->id());
186123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (target_id_after_merge.empty()) {
186223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    LOG(ERROR) << "Unable to reparent to item id: " << target_item->id();
186323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    item_list_->AddObserver(this);
186423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
186523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
18665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (target_id_after_merge != target_item->id()) {
18685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // New folder was created, change the view model to replace the old target
18695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // view with the new folder item view.
18705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& new_folder_id = reparent_item->folder_id();
18715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_t new_folder_index;
18725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (item_list_->FindItemIndex(new_folder_id, &new_folder_index)) {
18735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int target_view_index = view_model_.GetIndexOfView(target_view);
1874c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DeleteItemViewAtIndex(target_view_index);
18755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      views::View* new_folder_view =
18765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CreateViewForItemAtIndex(new_folder_index);
18775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      view_model_.Add(new_folder_view, target_view_index);
18785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddChildView(new_folder_view);
18795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
18805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LOG(ERROR) << "Folder no longer in item_list: " << new_folder_id;
18815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
18825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
18835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1884c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RemoveLastItemFromReparentItemFolderIfNecessary(source_folder_id);
18855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  item_list_->AddObserver(this);
18875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Fade out the drag_view_ and delete it when animation ends.
18895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int drag_view_index = view_model_.GetIndexOfView(drag_view_);
18905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view_model_.Remove(drag_view_index);
18915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bounds_animator_.AnimateViewTo(drag_view_, drag_view_->bounds());
18925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bounds_animator_.SetAnimationDelegate(
1893f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      drag_view_,
1894f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_ptr<gfx::AnimationDelegate>(
1895f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          new ItemRemoveAnimationDelegate(drag_view_)));
1896f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdatePaging();
1897f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1898f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// After moving the re-parenting item out of the folder, if there is only 1 item
19005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// left, remove the last item out of the folder, delete the folder and insert it
19015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// to the data model at the same position. Make the same change to view_model_
19025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// accordingly.
1903c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid AppsGridView::RemoveLastItemFromReparentItemFolderIfNecessary(
1904c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& source_folder_id) {
1905c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  AppListFolderItem* source_folder =
1906c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id));
1907c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!source_folder || source_folder->ChildItemCount() != 1u)
1908c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
19095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Delete view associated with the folder item to be removed.
1911cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DeleteItemViewAtIndex(
1912cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      view_model_.GetIndexOfView(activated_folder_item_view()));
19135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now make the data change to remove the folder item in model.
19155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* last_item = source_folder->item_list()->item_at(0);
19165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  model_->MoveItemToFolderAt(last_item, "", source_folder->position());
19175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a new item view for the last item in folder.
19195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t last_item_index;
1920cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!item_list_->FindItemIndex(last_item->id(), &last_item_index) ||
1921cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      last_item_index > static_cast<size_t>(view_model_.view_size())) {
1922cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NOTREACHED();
1923cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
1924cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
19255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::View* last_item_view = CreateViewForItemAtIndex(last_item_index);
19265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  view_model_.Add(last_item_view, last_item_index);
19275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddChildView(last_item_view);
19285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
19295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::CancelFolderItemReparent(AppListItemView* drag_item_view) {
19315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The icon of the dragged item must target to its final ideal bounds after
19325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the animation completes.
19335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CalculateIdealBounds();
19345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect target_icon_rect =
1936cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetTargetIconRectInFolder(drag_item_view, activated_folder_item_view_);
19375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect drag_view_icon_to_grid =
19395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      drag_item_view->ConvertRectToParent(drag_item_view->GetIconBounds());
19405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_view_icon_to_grid.ClampToCenteredSize(
19416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      gfx::Size(kGridIconDimension, kGridIconDimension));
19425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TopIconAnimationView* icon_view = new TopIconAnimationView(
19435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      drag_item_view->item()->icon(),
19445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      target_icon_rect,
19455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      false);    /* animate like closing folder */
19465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AddChildView(icon_view);
19475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  icon_view->SetBoundsRect(drag_view_icon_to_grid);
19485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  icon_view->TransformView();
19495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
19505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid AppsGridView::CancelContextMenusOnCurrentPage() {
195246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int start = pagination_model_.selected_page() * tiles_per_page();
19537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int end = std::min(view_model_.view_size(), start + tiles_per_page());
19547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (int i = start; i < end; ++i) {
19557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    AppListItemView* view =
19567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        static_cast<AppListItemView*>(view_model_.view_at(i));
19577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    view->CancelContextMenu();
19587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
19597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
19607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1961c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid AppsGridView::DeleteItemViewAtIndex(int index) {
1962c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  views::View* item_view = view_model_.view_at(index);
1963c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  view_model_.Remove(index);
1964010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (item_view == drag_view_)
1965010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    drag_view_ = NULL;
1966c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  delete item_view;
1967c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1968c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1969a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool AppsGridView::IsPointWithinDragBuffer(const gfx::Point& point) const {
1970a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  gfx::Rect rect(GetLocalBounds());
1971a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  rect.Inset(-kDragBufferPx, -kDragBufferPx, -kDragBufferPx, -kDragBufferPx);
1972a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return rect.Contains(point);
1973a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
1974a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::ButtonPressed(views::Button* sender,
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const ui::Event& event) {
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dragging())
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1980b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (strcmp(sender->GetClassName(), AppListItemView::kViewClassName))
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_) {
1984cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Always set the previous activated_folder_item_view_ to be visible. This
1985cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // prevents a case where the item would remain hidden due the
1986cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // |activated_folder_item_view_| changing during the animation. We only
1987cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // need to track |activated_folder_item_view_| in the root level grid view.
1988cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!folder_delegate_) {
1989cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (activated_folder_item_view_)
1990cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        activated_folder_item_view_->SetVisible(true);
1991cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      AppListItemView* pressed_item_view =
1992cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          static_cast<AppListItemView*>(sender);
1993cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (IsFolderItem(pressed_item_view->item()))
1994cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        activated_folder_item_view_ = pressed_item_view;
1995cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      else
1996cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        activated_folder_item_view_ = NULL;
1997cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
19985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    delegate_->ActivateApp(static_cast<AppListItemView*>(sender)->item(),
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           event.flags());
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::OnListItemAdded(size_t index, AppListItem* item) {
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EndDrag(true);
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  views::View* view = CreateViewForItemAtIndex(index);
20071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  view_model_.Add(view, index);
20081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AddChildView(view);
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePaging();
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePulsingBlockViews();
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::OnListItemRemoved(size_t index, AppListItem* item) {
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EndDrag(true);
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2019c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DeleteItemViewAtIndex(index);
2020a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePaging();
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePulsingBlockViews();
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AppsGridView::OnListItemMoved(size_t from_index,
20281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                   size_t to_index,
20295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   AppListItem* item) {
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EndDrag(true);
20311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  view_model_.Move(from_index, to_index);
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePaging();
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnimateToIdealBounds();
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::TotalPagesChanged() {
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::SelectedPageChanged(int old_selected, int new_selected) {
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dragging()) {
20421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CalculateDropTarget();
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Layout();
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MaybeStartPageFlipTimer(last_drag_point_);
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
20462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ClearSelectedView(selected_view_);
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Layout();
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid AppsGridView::TransitionStarted() {
20527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CancelContextMenusOnCurrentPage();
20537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
20547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::TransitionChanged() {
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update layout for valid page transition only since over-scroll no longer
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // animates app icons.
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PaginationModel::Transition& transition =
205946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      pagination_model_.transition();
206046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (pagination_model_.is_valid_page(transition.target_page))
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Layout();
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppsGridView::OnAppListModelStatusChanged() {
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePulsingBlockViews();
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
207058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void AppsGridView::SetViewHidden(views::View* view, bool hide, bool immediate) {
2071868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ui::ScopedLayerAnimationSettings animator(view->layer()->GetAnimator());
207258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  animator.SetPreemptionStrategy(
207358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      immediate ? ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET :
207458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  ui::LayerAnimator::BLEND_WITH_CURRENT_ANIMATION);
2075868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  view->layer()->SetOpacity(hide ? 0 : 1);
2076868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppsGridView::OnImplicitAnimationsCompleted() {
20795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (layer()->opacity() == 0.0f)
20805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetVisible(false);
20815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
20825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2083f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool AppsGridView::EnableFolderDragDropUI() {
2084f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Enable drag and drop folder UI only if it is at the app list root level
20851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // and the switch is on.
20861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return model_->folders_enabled() && !folder_delegate_;
2087f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2088f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AppsGridView::CanDropIntoTarget(const Index& drop_target) const {
209034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  views::View* target_view = GetViewAtSlotOnCurrentPage(drop_target.slot);
209134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)
2092f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!target_view)
20931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2094f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListItem* target_item =
20965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      static_cast<AppListItemView*>(target_view)->item();
20975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Items can be dropped into non-folders (which have no children) or folders
20985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // that have fewer than the max allowed items.
209923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // OEM folder does not allow to drag/drop other items in it.
210023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return target_item->ChildItemCount() < kMaxFolderItems &&
210123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         !IsOEMFolderItem(target_item);
2102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAppsGridView::Index AppsGridView::GetNearestTileIndexForPoint(
21051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const gfx::Point& point) const {
21061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect bounds = GetContentsBounds();
21071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size total_tile_size = GetTotalTileSize();
21081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int col = ClampToRange(
21091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      (point.x() - bounds.x()) / total_tile_size.width(), 0, cols_ - 1);
21101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int row = ClampToRange((point.y() - bounds.y()) / total_tile_size.height(),
21111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         0,
21121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         rows_per_page_ - 1);
21131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return Index(pagination_model_.selected_page(), row * cols_ + col);
2114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Size AppsGridView::GetTileGridSize() const {
21171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect bounds = GetExpectedTileBounds(0, 0);
21181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bounds.Union(GetExpectedTileBounds(rows_per_page_ - 1, cols_ - 1));
21191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (switches::IsExperimentalAppListEnabled())
21201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bounds.Inset(-kExperimentalTileLeftRightPadding,
21211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 -kExperimentalTileTopBottomPadding);
21221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return bounds.size();
2123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Rect AppsGridView::GetExpectedTileBounds(int slot) const {
21261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return GetExpectedTileBounds(slot / cols_, slot % cols_);
2127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Rect AppsGridView::GetExpectedTileBounds(int row, int col) const {
2130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds(GetContentsBounds());
21311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size total_tile_size = GetTotalTileSize();
21321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect tile_bounds(gfx::Point(bounds.x() + col * total_tile_size.width(),
21331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   bounds.y() + row * total_tile_size.height()),
21341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        total_tile_size);
21351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  tile_bounds.ClampToCenteredSize(GetTileViewSize());
21361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return tile_bounds;
2137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
2138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
213934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) const {
2140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (slot < 0)
2141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return NULL;
2142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Calculate the original bound of the tile at |index|.
2144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int row = slot / cols_;
2145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int col = slot % cols_;
21461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect tile_rect = GetExpectedTileBounds(row, col);
2147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (int i = 0; i < view_model_.view_size(); ++i) {
2149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    views::View* view = view_model_.view_at(i);
2150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (view->bounds() == tile_rect && view != drag_view_)
2151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return view;
2152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
2153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return NULL;
2154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index,
2157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                             bool is_target_folder) {
2158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppListItemView* target_view =
2159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      static_cast<AppListItemView*>(
2160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          GetViewAtSlotOnCurrentPage(target_index.slot));
2161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (target_view)
2162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    target_view->SetAsAttemptedFolderTarget(is_target_folder);
2163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace app_list
2166