apps_grid_view.h 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef ASH_APP_LIST_VIEWS_APPS_GRID_VIEW_H_
  5. #define ASH_APP_LIST_VIEWS_APPS_GRID_VIEW_H_
  6. #include <stddef.h>
  7. #include <memory>
  8. #include <queue>
  9. #include <set>
  10. #include <sstream>
  11. #include <string>
  12. #include <tuple>
  13. #include <vector>
  14. #include "ash/app_list/app_list_metrics.h"
  15. #include "ash/app_list/grid_index.h"
  16. #include "ash/app_list/model/app_list_item_list_observer.h"
  17. #include "ash/app_list/model/app_list_model_observer.h"
  18. #include "ash/app_list/paged_view_structure.h"
  19. #include "ash/app_list/views/app_list_item_view.h"
  20. #include "ash/ash_export.h"
  21. #include "base/time/time.h"
  22. #include "base/timer/timer.h"
  23. #include "ui/base/metadata/metadata_header_macros.h"
  24. #include "ui/compositor/throughput_tracker.h"
  25. #include "ui/events/keycodes/keyboard_codes_posix.h"
  26. #include "ui/views/animation/animation_abort_handle.h"
  27. #include "ui/views/animation/bounds_animator_observer.h"
  28. #include "ui/views/view.h"
  29. #include "ui/views/view_model.h"
  30. namespace views {
  31. class BoundsAnimator;
  32. } // namespace views
  33. namespace ash {
  34. namespace test {
  35. class AppsGridViewTest;
  36. class AppsGridViewTestApi;
  37. } // namespace test
  38. class AppDragIconProxy;
  39. class AppListA11yAnnouncer;
  40. class ApplicationDragAndDropHost;
  41. class AppListConfig;
  42. class AppListFolderController;
  43. class AppListItem;
  44. class AppListItemList;
  45. class AppListItemView;
  46. class AppListKeyboardController;
  47. class AppListModel;
  48. class AppListViewDelegate;
  49. class AppsGridContextMenu;
  50. class AppsGridViewFolderDelegate;
  51. class PulsingBlockView;
  52. class AppsGridRowChangeAnimator;
  53. class GhostImageView;
  54. class AppsGridViewTest;
  55. class ScrollableAppsGridViewTest;
  56. class PagedAppsGridViewTestBase;
  57. // AppsGridView displays a grid of app icons. It is used for:
  58. // - The main grid of apps in the launcher
  59. // - The grid of apps in a folder
  60. class ASH_EXPORT AppsGridView : public views::View,
  61. public AppListItemView::GridDelegate,
  62. public AppListItemListObserver,
  63. public AppListModelObserver,
  64. public views::BoundsAnimatorObserver {
  65. public:
  66. METADATA_HEADER(AppsGridView);
  67. enum Pointer {
  68. NONE,
  69. MOUSE,
  70. TOUCH,
  71. };
  72. AppsGridView(AppListA11yAnnouncer* a11y_announcer,
  73. AppListViewDelegate* app_list_view_delegate,
  74. AppsGridViewFolderDelegate* folder_delegate,
  75. AppListFolderController* folder_controller,
  76. AppListKeyboardController* keyboard_controller);
  77. AppsGridView(const AppsGridView&) = delete;
  78. AppsGridView& operator=(const AppsGridView&) = delete;
  79. ~AppsGridView() override;
  80. // Initializes the class. Calls virtual methods, so its code cannot be in the
  81. // constructor.
  82. void Init();
  83. // Sets the `AppListConfig` that should be used to configure app list item
  84. // size within the grid. This will cause all items views to be updated to
  85. // adhere to new tile and icon dimensions, so it should be used sparingly.
  86. void UpdateAppListConfig(const AppListConfig* app_list_config);
  87. int cols() const { return cols_; }
  88. // Sets padding for apps grid items to use during layout if fixed padding
  89. // should be used. Otherwise, for paged apps grid, the padding will be
  90. // calculated to evenly space the items within the current apps grid view
  91. // bounds.
  92. void SetFixedTilePadding(int horizontal_tile_padding,
  93. int vertical_tile_padding);
  94. // Returns the size of a tile view including its padding. For paged apps grid,
  95. // padding can be different between tiles on the first page and tiles on other
  96. // pages.
  97. gfx::Size GetTotalTileSize(int page) const;
  98. // Returns the minimum size of the entire tile grid.
  99. gfx::Size GetMinimumTileGridSize(int cols, int rows_per_page) const;
  100. // Returns the maximum size of the entire tile grid.
  101. gfx::Size GetMaximumTileGridSize(int cols, int rows_per_page) const;
  102. // Cancels any in progress drag without running icon drop animation. If an
  103. // icon drop animation is in progress, it will be canceled, too.
  104. void CancelDragWithNoDropAnimation();
  105. // This resets the grid view to a fresh state for showing the app list.
  106. void ResetForShowApps();
  107. // All items in this view become unfocusable if |disabled| is true. This is
  108. // used to trap focus within the folder when it is opened.
  109. void DisableFocusForShowingActiveFolder(bool disabled);
  110. // Sets |model| to use. Note this does not take ownership of |model|.
  111. void SetModel(AppListModel* model);
  112. // Sets the |item_list| to render. Note this does not take ownership of
  113. // |item_list|.
  114. void SetItemList(AppListItemList* item_list);
  115. // AppListItemView::GridDelegate:
  116. bool IsInFolder() const override;
  117. void SetSelectedView(AppListItemView* view) override;
  118. void ClearSelectedView() override;
  119. bool IsSelectedView(const AppListItemView* view) const override;
  120. bool InitiateDrag(AppListItemView* view,
  121. const gfx::Point& location,
  122. const gfx::Point& root_location,
  123. base::OnceClosure drag_start_callback,
  124. base::OnceClosure drag_end_callback) override;
  125. void StartDragAndDropHostDragAfterLongPress() override;
  126. bool UpdateDragFromItem(bool is_touch,
  127. const ui::LocatedEvent& event) override;
  128. void EndDrag(bool cancel) override;
  129. void OnAppListItemViewActivated(AppListItemView* pressed_item_view,
  130. const ui::Event& event) override;
  131. bool IsDragging() const;
  132. bool IsDraggedView(const AppListItemView* view) const;
  133. void ClearDragState();
  134. // Set the drag and drop host for application links.
  135. void SetDragAndDropHostOfCurrentAppList(
  136. ApplicationDragAndDropHost* drag_and_drop_host);
  137. // Return true if the |bounds_animator_| is animating |view|.
  138. bool IsAnimatingView(AppListItemView* view);
  139. const AppListConfig* app_list_config() const { return app_list_config_; }
  140. bool has_selected_view() const { return selected_view_ != nullptr; }
  141. AppListItemView* selected_view() const { return selected_view_; }
  142. const AppListItemView* drag_view() const { return drag_view_; }
  143. bool has_dragged_item() const { return drag_item_ != nullptr; }
  144. const AppListItem* drag_item() const { return drag_item_; }
  145. // Overridden from views::View:
  146. gfx::Size CalculatePreferredSize() const override;
  147. bool OnKeyPressed(const ui::KeyEvent& event) override;
  148. bool OnKeyReleased(const ui::KeyEvent& event) override;
  149. void ViewHierarchyChanged(
  150. const views::ViewHierarchyChangedDetails& details) override;
  151. bool GetDropFormats(int* formats,
  152. std::set<ui::ClipboardFormatType>* format_types) override;
  153. bool CanDrop(const OSExchangeData& data) override;
  154. int OnDragUpdated(const ui::DropTargetEvent& event) override;
  155. // Updates the visibility of app list items according to |app_list_state| and
  156. // |is_in_drag|.
  157. void UpdateControlVisibility(AppListViewState app_list_state,
  158. bool is_in_drag);
  159. // Returns true if a touch or click lies between two occupied tiles.
  160. bool EventIsBetweenOccupiedTiles(const ui::LocatedEvent* event);
  161. // Returns the item view of the item with the provided item ID.
  162. // Returns nullptr if there is no such item.
  163. AppListItemView* GetItemViewForItem(const std::string& item_id);
  164. // Returns the item view of the item at |index|, or nullptr if there is no
  165. // view at |index|.
  166. AppListItemView* GetItemViewAt(size_t index) const;
  167. // Called to initiate drag for reparenting a folder item in root level grid
  168. // view.
  169. // `pointer` - The pointer that's used for dragging (mouse or touch).
  170. // `drag_point` is in the coordinates of root level grid view.
  171. // `cancellation_callback` - the callback that can be invoked from the root
  172. // level grid to cancel drag operation in the originating folder grid.
  173. void InitiateDragFromReparentItemInRootLevelGridView(
  174. Pointer pointer,
  175. AppListItemView* original_drag_view,
  176. const gfx::Point& drag_point,
  177. base::OnceClosure cancellation_callback);
  178. // Updates drag in the root level grid view when receiving the drag event
  179. // dispatched from the hidden grid view for reparenting a folder item.
  180. // `pointer` - The pointer that's used for dragging (mouse or touch).
  181. void UpdateDragFromReparentItem(Pointer pointer,
  182. const gfx::Point& drag_point);
  183. // Dispatches the drag event from hidden grid view to the top level grid view.
  184. // `pointer` - The pointer that's used for dragging (mouse or touch).
  185. void DispatchDragEventForReparent(Pointer pointer,
  186. const gfx::Point& drag_point);
  187. // Handles EndDrag event dispatched from the hidden folder grid view in the
  188. // root level grid view to end reparenting a folder item.
  189. // |original_parent_item_view|: The folder AppListView for the folder from
  190. // which drag item is being dragged.
  191. // |events_forwarded_to_drag_drop_host|: True if the dragged item is dropped
  192. // to the drag_drop_host, eg. dropped on shelf.
  193. // |cancel_drag|: True if the drag is ending because it has been canceled.
  194. // |drag_icon_proxy|: The app item drag icon proxy that was created by the
  195. // folder grid view for the drag. It's passed on the the root apps grid so the
  196. // root apps grid can set up the icon drop animation.
  197. void EndDragFromReparentItemInRootLevel(
  198. AppListItemView* original_parent_item_view,
  199. bool events_forwarded_to_drag_drop_host,
  200. bool cancel_drag,
  201. std::unique_ptr<AppDragIconProxy> drag_icon_proxy);
  202. // Handles EndDrag event in the hidden folder grid view to end reparenting
  203. // a folder item.
  204. void EndDragForReparentInHiddenFolderGridView();
  205. // Moves |reparented_view| from its folder to the root AppsGridView in the
  206. // direction of |key_code|.
  207. // |original_parent_item_view|: The folder AppListView for the folder from
  208. // which drag item is being dragged.
  209. void HandleKeyboardReparent(AppListItemView* reparented_view,
  210. AppListItemView* original_parent_item_view,
  211. ui::KeyboardCode key_code);
  212. // Updates paged view structure and save it to meta data.
  213. void UpdatePagedViewStructure();
  214. // Returns true if tablet mode is active. This class does not use
  215. // Shell::IsInTabletMode() because it has tests that are not derived from
  216. // AshTestBase.
  217. bool IsTabletMode() const;
  218. // Fades out visible items when reordering happens. Runs `done_callback` when
  219. // the fade out animation ends. The callback carries a boolean value that
  220. // is true if the animation is aborted. Returns an animation builder and it
  221. // can be used to tie other layer animations with scheduled item animaions.
  222. using ReorderAnimationCallback = base::RepeatingCallback<void(bool)>;
  223. views::AnimationBuilder FadeOutVisibleItemsForReorder(
  224. ReorderAnimationCallback done_callback);
  225. // Fades in items for reordering. Returns an animation builder and it can be
  226. // used to tie other layer animations with scheduled item animaions.
  227. views::AnimationBuilder FadeInVisibleItemsForReorder(
  228. ReorderAnimationCallback done_callback);
  229. // Slides visible items up when the continue section is hidden in tablet mode.
  230. // Each row of items has a different vertical offset, creating a "cascade"
  231. // effect. `base_offset` is the offset for the first row. Subsequent rows have
  232. // a smaller offset.
  233. void SlideVisibleItemsForHideContinueSection(int base_offset);
  234. // Whether the provided view is hidden to facilitate drag operation (for
  235. // example, the drag view for which a drag icon proxy has been created).
  236. bool IsViewHiddenForDrag(const views::View* view) const;
  237. // Whether `view` is the folder view that is animating out and in as part of
  238. // folder reorder animation that runs after folder is closed if the folder
  239. // position within the grid changed.
  240. bool IsViewHiddenForFolderReorder(const views::View* view) const;
  241. // Returns true if the whole apps grid is animating (for reordering, or hide
  242. // continue section). This function is public for testing.
  243. bool IsUnderWholeGridAnimation() const;
  244. // Returns whether `view` is hidden due to drag or folder reorder.
  245. bool IsViewExplicitlyHidden(const views::View* view) const;
  246. // Aborts the active whole-grid animation (for reordering, or hide continue
  247. // section), if any.
  248. void MaybeAbortWholeGridAnimation();
  249. // Passes scroll information from a parent view, so that subclasses may scroll
  250. // or switch pages.
  251. virtual void HandleScrollFromParentView(const gfx::Vector2d& offset,
  252. ui::EventType type) = 0;
  253. // Return the view model.
  254. views::ViewModelT<AppListItemView>* view_model() { return &view_model_; }
  255. const views::ViewModelT<AppListItemView>* view_model() const {
  256. return &view_model_;
  257. }
  258. // Returns true if any animation is running within the view.
  259. bool IsAnimationRunningForTest();
  260. AppsGridViewFolderDelegate* folder_delegate() const {
  261. return folder_delegate_;
  262. }
  263. void set_folder_delegate(AppsGridViewFolderDelegate* folder_delegate) {
  264. folder_delegate_ = folder_delegate;
  265. }
  266. const AppListModel* model() const { return model_; }
  267. GridIndex reorder_placeholder() const { return reorder_placeholder_; }
  268. bool FireFolderItemReparentTimerForTest();
  269. bool FireDragToShelfTimerForTest();
  270. // Carries two parameters:
  271. // (1) A boolean value that is true if the reorder is aborted.
  272. // (2) An enum that specifies the animation stage when the done callback runs.
  273. using TestReorderDoneCallbackType =
  274. base::RepeatingCallback<void(bool aborted,
  275. AppListGridAnimationStatus status)>;
  276. // Adds a callback that runs at the end of the app list reorder.
  277. void AddReorderCallbackForTest(TestReorderDoneCallbackType done_callback);
  278. // Adds a closure that runs at the start of the fade out animation triggered
  279. // by reorder.
  280. void AddFadeOutAnimationStartClosureForTest(base::OnceClosure start_closure);
  281. // Adds a closure that runs at the end of the fade out animation triggered
  282. // by reorder.
  283. void AddFadeOutAnimationDoneClosureForTest(base::OnceClosure done_closure);
  284. // Returns true if there is any waiting reorder animation test callback.
  285. bool HasAnyWaitingReorderDoneCallbackForTest() const;
  286. // For test: Return if the drag and drop handler was set.
  287. bool has_drag_and_drop_host_for_test() {
  288. return nullptr != drag_and_drop_host_;
  289. }
  290. // For test: Return if the drag and drop operation gets dispatched.
  291. bool forward_events_to_drag_and_drop_host_for_test() {
  292. return forward_events_to_drag_and_drop_host_;
  293. }
  294. views::BoundsAnimator* bounds_animator_for_testing() {
  295. return bounds_animator_.get();
  296. }
  297. base::OneShotTimer* reorder_timer_for_test() { return &reorder_timer_; }
  298. AppsGridContextMenu* context_menu_for_test() { return context_menu_.get(); }
  299. void set_enable_item_move_animation_for_test(bool enable) {
  300. enable_item_move_animation_ = enable;
  301. }
  302. AppListGridAnimationStatus grid_animation_status_for_test() const {
  303. return grid_animation_status_;
  304. }
  305. protected:
  306. friend AppsGridViewTest;
  307. friend ScrollableAppsGridViewTest;
  308. struct VisibleItemIndexRange {
  309. VisibleItemIndexRange();
  310. VisibleItemIndexRange(size_t first_index, size_t last_index);
  311. ~VisibleItemIndexRange();
  312. // The view index of the first visible item on the apps grid.
  313. size_t first_index = 0;
  314. // The view index of the last visible item on the apps grid.
  315. size_t last_index = 0;
  316. };
  317. // The duration in ms for most of the apps grid view animations.
  318. static constexpr int kDefaultAnimationDuration = 200;
  319. // Returns the size of a tile view excluding its padding.
  320. virtual gfx::Size GetTileViewSize() const = 0;
  321. // Returns the padding around a tile view.
  322. virtual gfx::Insets GetTilePadding(int page) const = 0;
  323. // Returns the size of the entire tile grid.
  324. virtual gfx::Size GetTileGridSize() const = 0;
  325. // Returns the max number of rows the grid can have on a page.
  326. virtual int GetMaxRowsInPage(int page) const = 0;
  327. // Calculates the offset distance to center the grid in the container.
  328. virtual gfx::Vector2d GetGridCenteringOffset(int page) const = 0;
  329. // Returns number of total pages, or one if the grid does not use pages.
  330. virtual int GetTotalPages() const = 0;
  331. // Returns the current selected page, or zero if the grid does not use pages.
  332. virtual int GetSelectedPage() const = 0;
  333. // Returns true if scrolling is vertical (the common case). Folders may scroll
  334. // horizontally.
  335. virtual bool IsScrollAxisVertical() const = 0;
  336. // Records the different ways to move an app in app list's apps grid for UMA
  337. // histograms.
  338. virtual void RecordAppMovingTypeMetrics(AppListAppMovingType type) = 0;
  339. // Updates or creates a border for this view.
  340. virtual void UpdateBorder() {}
  341. // Starts the "cardified" state if the subclass supports it.
  342. virtual void MaybeStartCardifiedView() {}
  343. // Ends the "cardified" state if the subclass supports it.
  344. virtual void MaybeEndCardifiedView() {}
  345. // Starts a page flip if the subclass supports it.
  346. virtual void MaybeStartPageFlip() {}
  347. // Stops a page flip (by ending its timer) if the subclass supports it.
  348. virtual void MaybeStopPageFlip() {}
  349. // Scrolls the container view up or down if the drag point is in the correct
  350. // location. Returns true if auto-scroll was started or an existing
  351. // auto-scroll is in-progress. Auto-scroll and page-flip are mutually
  352. // exclusive. TODO(tbarzic): Unify the two APIs.
  353. virtual bool MaybeAutoScroll() = 0;
  354. // Stops auto-scroll (by stopping its timer) if the subclass supports it.
  355. virtual void StopAutoScroll() = 0;
  356. // Sets the focus to the correct view when a drag ends. Focus is on the app
  357. // list item view during the drag.
  358. virtual void SetFocusAfterEndDrag(AppListItem* drag_item) = 0;
  359. // Calculates the index range of the visible item views.
  360. virtual absl::optional<VisibleItemIndexRange> GetVisibleItemIndexRange()
  361. const = 0;
  362. // Disables any change on the apps grid's opacity. Returns an scoped runner
  363. // that carries a closure to re-enable opacity updates.
  364. [[nodiscard]] virtual base::ScopedClosureRunner LockAppsGridOpacity() = 0;
  365. // Makes sure that the background cards render behind everything
  366. // else in the items container.
  367. virtual void StackCardsAtBottom() {}
  368. // Sets the max number of columns that the grid can have.
  369. // For root apps grid view, the grid size depends on the space available to
  370. // apps grid view only, and `cols()` will match `max_columns`. I.e. if the
  371. // grid doesn't have enough items to fill out all columns, it will leave empty
  372. // spaces in the UI.
  373. // For folder item grid, the grid size also depends on the number of items in
  374. // the grid, so number of actual columns may be smaller than `max_columns`.
  375. void SetMaxColumnsInternal(int max_columns);
  376. // Sets the ideal bounds for view at index `view_inde_in_model` in
  377. // `view_model_`. The bounds are set to match the expected tile bounds at
  378. // `view_grid_index` in the apps grid.
  379. void SetIdealBoundsForViewToGridIndex(size_t view_index_in_model,
  380. const GridIndex& view_grid_index);
  381. // Calculates the item views' bounds for both folder and non-folder.
  382. void CalculateIdealBounds();
  383. void CalculateIdealBoundsForPageStructureWithPartialPages();
  384. // Gets the bounds of the tile located at |index|, where |index| contains the
  385. // page/slot info.
  386. gfx::Rect GetExpectedTileBounds(const GridIndex& index) const;
  387. // Returns the number of app tiles per page. Takes a page number as an
  388. // argument as the first page might have less apps shown. Folder grids may
  389. // have different numbers of tiles from the main grid.
  390. int TilesPerPage(int page) const;
  391. GridIndex GetIndexOfView(const AppListItemView* view) const;
  392. AppListItemView* GetViewAtIndex(const GridIndex& index) const;
  393. // Returns true if an item view exists in the visual index.
  394. bool IsValidIndex(const GridIndex& index) const;
  395. // Returns the number of existing items in specified page. Returns 0 if |page|
  396. // is out of range.
  397. int GetNumberOfItemsOnPage(int page) const;
  398. // Updates |drop_target_| and |drop_target_region_| based on |drag_view_|'s
  399. // position.
  400. void UpdateDropTargetRegion();
  401. // Cancels any context menus showing for app items on the current page.
  402. void CancelContextMenusOnCurrentPage();
  403. // views::BoundsAnimatorObserver:
  404. void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override;
  405. void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override;
  406. // Destroys all item view layers if they are not required.
  407. void DestroyLayerItemsIfNotNeeded();
  408. // Whether app list item views require layers - for example during drag, or
  409. // folder repositioning animation.
  410. bool ItemViewsRequireLayers() const;
  411. void BeginHideCurrentGhostImageView();
  412. // Ensures layer for all app items before animations are started.
  413. void PrepareItemsForBoundsAnimation();
  414. bool ignore_layout() const { return ignore_layout_; }
  415. views::BoundsAnimator* bounds_animator() { return bounds_animator_.get(); }
  416. views::View* items_container() { return items_container_; }
  417. views::ViewModelT<PulsingBlockView>& pulsing_blocks_model() {
  418. return pulsing_blocks_model_;
  419. }
  420. const gfx::Point& last_drag_point() const { return last_drag_point_; }
  421. void set_last_drag_point(const gfx::Point& p) { last_drag_point_ = p; }
  422. bool handling_keyboard_move() const { return handling_keyboard_move_; }
  423. AppListViewDelegate* app_list_view_delegate() const {
  424. return app_list_view_delegate_;
  425. }
  426. const AppListItemList* item_list() const { return item_list_; }
  427. // View structure used only for non-folder.
  428. PagedViewStructure view_structure_{this};
  429. // The `AppListItemView` that is being dragged within the apps grid (i.e. the
  430. // AppListItemView for `drag_item_`) if the drag item is currently part of the
  431. // item list shown in the apps grid. `drag_view_` may be nullptr during item
  432. // reparent drag while being handled in the root app list grid (the drag item
  433. // will be added to target item list only when the drag ends).
  434. // Subclasses need non-const access.
  435. AppListItemView* drag_view_ = nullptr;
  436. // If set, a callback called when the dragged item starts moving during a drag
  437. // (i.e. when the drag icon proxy gets created).
  438. // Registered in `InitiateDrag()`
  439. base::OnceClosure drag_start_callback_;
  440. // If set, a callback called when an item drag ends, and drag state is
  441. // cleared. It may get called before the drag icon proxy drop animation
  442. // finishes.
  443. // Registered in `InitiateDrag()`.
  444. base::OnceClosure drag_end_callback_;
  445. // If app item drag is in progress, the icon proxy created for the app list
  446. // item.
  447. std::unique_ptr<AppDragIconProxy> drag_icon_proxy_;
  448. // If true, Layout() does nothing. See where set for details.
  449. bool ignore_layout_ = false;
  450. // True if the AppList is in cardified state. "Cardified" means showing a
  451. // rounded rectangle background "card" behind each page during a drag. The
  452. // grid icons are reduced in size in this state.
  453. // TODO(crbug.com/1211608): Move cardified state members to PagedAppsGridView.
  454. bool cardified_state_ = false;
  455. bool bounds_animation_for_cardified_state_in_progress_ = false;
  456. // Tile spacing between the tile views.
  457. int horizontal_tile_padding_ = 0;
  458. int vertical_tile_padding_ = 0;
  459. // Whether tile padding within the apps grid is fixed.
  460. bool has_fixed_tile_padding_ = false;
  461. // True if an extra page is opened after the user drags an app to the bottom
  462. // of last page with intention to put it in a new page. This is only used for
  463. // non-folder.
  464. bool extra_page_opened_ = false;
  465. GhostImageView* current_ghost_view_ = nullptr;
  466. GhostImageView* last_ghost_view_ = nullptr;
  467. private:
  468. friend class test::AppsGridViewTestApi;
  469. friend class test::AppsGridViewTest;
  470. friend class PagedAppsGridView;
  471. friend class PagedViewStructure;
  472. friend class AppsGridRowChangeAnimator;
  473. friend class PagedAppsGridViewTestBase;
  474. enum DropTargetRegion {
  475. NO_TARGET,
  476. ON_ITEM,
  477. NEAR_ITEM,
  478. BETWEEN_ITEMS,
  479. };
  480. class DragViewHider;
  481. class FolderIconItemHider;
  482. // Updates from model.
  483. void Update();
  484. // Updates page splits for item views.
  485. virtual void UpdatePaging() {}
  486. // On a grid with pages, records the total number of pages, and the number of
  487. // pages with empty slots for UMA histograms.
  488. virtual void RecordPageMetrics() {}
  489. // Calculates the offset for |page_of_view| based on current page and
  490. // transition target page. Returns an empty vector if the grid does not use
  491. // pages.
  492. virtual const gfx::Vector2d CalculateTransitionOffset(
  493. int page_of_view) const = 0;
  494. // Calculates the animation delay for the pulsing block animation based on the
  495. // position of the block.
  496. base::TimeDelta GetPulsingBlockAnimationDelayForIndex(int block_index);
  497. // Invoked when the animation for swapping a |placeholder| with an |app_view|
  498. // is done.
  499. void OnSwapAnimationDone(views::View* placeholder, AppListItemView* app_view);
  500. // Triggers the animation for swapping a pulsing block view with a
  501. // corresponding new asset at index on item list. (We use the item_list index
  502. // because the view is not added to the `view_model_` yet.)
  503. // Only triggers when there are pulsing blocks and the app list model is
  504. // syncing.
  505. AppListItemView* MaybeSwapPlaceholderAsset(size_t index);
  506. // Updates the number of pulsing block views based on AppListModel status and
  507. // number of apps.
  508. void UpdatePulsingBlockViews();
  509. std::unique_ptr<AppListItemView> CreateViewForItemAtIndex(size_t index);
  510. // Ensures the view is visible. Note that if there is a running page
  511. // transition, this does nothing.
  512. virtual void EnsureViewVisible(const GridIndex& index) = 0;
  513. void SetSelectedItemByIndex(const GridIndex& index);
  514. // Calculates ideal bounds for app list item views within the apps grid, and
  515. // animates their bounds (using `bounds_animator_`) to their ideal position.
  516. void AnimateToIdealBounds();
  517. // Extracts drag location info from |root_location| into |drag_point|.
  518. void ExtractDragLocation(const gfx::Point& root_location,
  519. gfx::Point* drag_point);
  520. bool DropTargetIsValidFolder();
  521. // Updates |drop_target_| as a location for potential reordering after the
  522. // currently dragged item is released.
  523. void UpdateDropTargetForReorder(const gfx::Point& point);
  524. // Called when the user is dragging an app. |point| is in grid view
  525. // coordinates.
  526. // `pointer` - The pointer that's used for dragging (mouse or touch).
  527. void UpdateDrag(Pointer pointer, const gfx::Point& point);
  528. // Returns true if the current drag is occurring within a certain range of the
  529. // nearest item.
  530. // `point` is the drag location in the apps grid's coordinates.
  531. bool DragIsCloseToItem(const gfx::Point& point);
  532. // Whether the current drag position is over an item.
  533. // `point` is the drag location in the apps grid's coordinates.
  534. bool DragPointIsOverItem(const gfx::Point& point);
  535. // Initiates drag and drop host drag as needed.
  536. // `pointer` - The pointer that's used for dragging.
  537. void TryStartDragAndDropHostDrag(Pointer pointer);
  538. // Prepares |drag_and_drop_host_| for dragging. |grid_location| contains
  539. // the drag point in this grid view's coordinates.
  540. void StartDragAndDropHostDrag();
  541. // Dispatch the drag and drop update event to the dnd host (if needed).
  542. void DispatchDragEventToDragAndDropHost(
  543. const gfx::Point& location_in_screen_coordinates);
  544. // Returns whether the target grid index for item move operation is on a new
  545. // apps grid page - i.e. if the move operation will create a new apps grid
  546. // page. Used to determine whether a new page break should be created after
  547. // app list item move.
  548. bool IsMoveTargetOnNewPage(const GridIndex& target) const;
  549. // Creates a page break just before the item in top level item list if the
  550. // item is not already preceded by a page break.
  551. void EnsurePageBreakBeforeItem(const std::string& item_id);
  552. // Updates `model_` to move `item` to `target` slot.
  553. void MoveItemInModel(AppListItem* item, const GridIndex& target);
  554. // Updates `model_` to move `item` into a folder containing item located at
  555. // `target` slot. Returns whether the move operation succeeded.
  556. // On success, `folder_id` will be set to the ID of the folder to which the
  557. // item was moved. This may be a folder that was created by the move, or a
  558. // preexisting folder.
  559. // `is_new_folder` indicates whether the move created a new folder.
  560. bool MoveItemToFolder(AppListItem* item,
  561. const GridIndex& target,
  562. AppListAppMovingType move_type,
  563. std::string* folder_id,
  564. bool* is_new_folder);
  565. // Updates data model for re-parenting a folder item to a new position in top
  566. // level item list. The view model is will get updated in response to the data
  567. // model changes.
  568. void ReparentItemForReorder(AppListItem* item, const GridIndex& target);
  569. // Records the user metrics action for deleting a folder if `folder_id` has
  570. // been removed from the data model. Called after an app item move which might
  571. // or might not cause a folder to be deleted.
  572. void MaybeRecordFolderDeleteUserAction(const std::string& folder_id);
  573. // Removes the AppListItemView at |index| in |view_model_|, removes it from
  574. // view structure as well and deletes it.
  575. void DeleteItemViewAtIndex(size_t index);
  576. // Returns true if |point| lies within the bounds of this grid view plus a
  577. // buffer area surrounding it that can trigger drop target change.
  578. bool IsPointWithinDragBuffer(const gfx::Point& point) const;
  579. // Schedules a Layout() call. If `previous_grid_size` is different from the
  580. // current grid size, calls PreferredSizeChanged().
  581. void ScheduleLayout(const gfx::Size& previous_grid_size);
  582. // Overridden from AppListItemListObserver:
  583. void OnListItemAdded(size_t index, AppListItem* item) override;
  584. void OnListItemRemoved(size_t index, AppListItem* item) override;
  585. void OnListItemMoved(size_t from_index,
  586. size_t to_index,
  587. AppListItem* item) override;
  588. // Overridden from AppListModelObserver:
  589. void OnAppListModelStatusChanged() override;
  590. // Animates `drag_icon_proxy_` to drop it into appropriate target bounds in
  591. // the apps grid when the item drag ends. Expects `drag_icon_proxy_` to be
  592. // set.
  593. // `drag_item` - The dragged item.
  594. // `target_folder_id` - If the item needs to be dropped into a folder, the
  595. // target folder ID.
  596. void AnimateDragIconToTargetPosition(AppListItem* drag_item,
  597. const std::string& target_folder_id);
  598. // Called when the `drag_icon_proxy_` animation started by
  599. // `AnimateDragIconToTargetPosition()` finishes. It resets `drag_icon_proxy_`
  600. // and shows the view that was hidden for drag.
  601. void OnDragIconDropDone();
  602. // Returns true if the dragged item isn't a folder, the drag is not
  603. // occurring inside a folder, and |drop_target_| is a valid index.
  604. bool DraggedItemCanEnterFolder();
  605. // Returns the slot number which the given |point| falls into or the closest
  606. // slot if |point| is outside the page's bounds.
  607. GridIndex GetNearestTileIndexForPoint(const gfx::Point& point) const;
  608. // Gets the item view currently displayed at |slot| on the current page. If
  609. // there is no item displayed at |slot|, returns nullptr. Note that this finds
  610. // an item *displayed* at a slot, which may differ from the item's location in
  611. // the model (as it may have been temporarily moved during a drag operation).
  612. AppListItemView* GetViewDisplayedAtSlotOnCurrentPage(int slot) const;
  613. // Sets state of the view with |target_index| to |is_target_folder| for
  614. // dropping |drag_view_|.
  615. void SetAsFolderDroppingTarget(const GridIndex& target_index,
  616. bool is_target_folder);
  617. // Invoked when |reorder_timer_| fires to show re-order preview UI.
  618. void OnReorderTimer();
  619. // Invoked when |folder_item_reparent_timer_| fires.
  620. void OnFolderItemReparentTimer(Pointer pointer);
  621. // Updates drag state for dragging inside a folder's grid view.
  622. // `pointer` - The pointer that's used for dragging (mouse or touch).
  623. void UpdateDragStateInsideFolder(Pointer pointer,
  624. const gfx::Point& drag_point);
  625. // Returns true if drag event is happening in the root level AppsGridView
  626. // for reparenting a folder item.
  627. bool IsDraggingForReparentInRootLevelGridView() const;
  628. // Returns true if drag event is happening in the hidden AppsGridView of the
  629. // folder during reparenting a folder item.
  630. bool IsDraggingForReparentInHiddenGridView() const;
  631. // Returns the target icon bounds for |drag_item| to fly back to its parent
  632. // |folder_item_view| in animation.
  633. gfx::Rect GetTargetIconRectInFolder(AppListItem* drag_item,
  634. AppListItemView* folder_item_view);
  635. // Returns true if the grid view is under an OEM folder.
  636. bool IsUnderOEMFolder();
  637. // Handles keyboard app reordering, foldering, and reparenting. Operations
  638. // effect |selected_view_|. |folder| is whether to move the app into or out of
  639. // a folder.
  640. void HandleKeyboardAppOperations(ui::KeyboardCode key_code, bool folder);
  641. // Handles either creating a folder with |selected_view_| or moving
  642. // |selected_view_| into an existing folder.
  643. void HandleKeyboardFoldering(ui::KeyboardCode key_code);
  644. // Returns whether |selected_view_| can be foldered to the item at
  645. // |target_index| in the root AppsGridView.
  646. bool CanMoveSelectedToTargetForKeyboardFoldering(
  647. const GridIndex& target_index) const;
  648. // Handle vertical focus movement triggered by arrow up and down.
  649. bool HandleVerticalFocusMovement(bool arrow_up);
  650. // Update number of columns and rows for apps within a folder.
  651. void UpdateColsAndRowsForFolder();
  652. // Returns true if the visual index is valid position to which an item view
  653. // can be moved.
  654. bool IsValidReorderTargetIndex(const GridIndex& index) const;
  655. // Returns model index of the item view of the specified item.
  656. size_t GetModelIndexOfItem(const AppListItem* item) const;
  657. // Returns the target model index based on item index. (Item index is the
  658. // index of an item in item list.) This should be used when the item is
  659. // updated in item list but its item view has not been updated in view model.
  660. size_t GetTargetModelIndexFromItemIndex(size_t item_index);
  661. // Returns the target GridIndex for a keyboard move.
  662. GridIndex GetTargetGridIndexForKeyboardMove(ui::KeyboardCode key_code) const;
  663. // Returns the target GridIndex to move an item from a folder to the root
  664. // AppsGridView.
  665. // `folder_index` - the grid index of the folder from which an item is
  666. // reparented.
  667. GridIndex GetTargetGridIndexForKeyboardReparent(
  668. const GridIndex& folder_index,
  669. ui::KeyboardCode key_code) const;
  670. // Swaps |selected_view_| with the item in relative position specified by
  671. // |key_code|.
  672. void HandleKeyboardMove(ui::KeyboardCode key_code);
  673. // During an app drag, creates an a11y event to verbalize dropping onto a
  674. // folder or creating a folder with two apps.
  675. void MaybeCreateFolderDroppingAccessibilityEvent();
  676. // During an app drag, creates an a11y event to verbalize drop target
  677. // location.
  678. void MaybeCreateDragReorderAccessibilityEvent();
  679. // Modifies the announcement view to verbalize |target_index|.
  680. void AnnounceReorder(const GridIndex& target_index);
  681. // Creates a new GhostImageView at |reorder_placeholder_| and initializes
  682. // |current_ghost_view_| and |last_ghost_view_|.
  683. void CreateGhostImageView();
  684. // Invoked when |host_drag_start_timer_| fires.
  685. void OnHostDragStartTimerFired();
  686. // Called at the end of the fade out animation. `callback` comes from the
  687. // caller that starts the fade out animation. `aborted` is true when the fade
  688. // out animation gets aborted.
  689. void OnFadeOutAnimationEnded(ReorderAnimationCallback callback, bool aborted);
  690. // Called at the end of the fade out animation. `callback` comes from the
  691. // caller that starts the fade in animation. `aborted` is true when the fade
  692. // in animation gets aborted.
  693. void OnFadeInAnimationEnded(ReorderAnimationCallback callback, bool aborted);
  694. // Called at the end of the hide continue section animation.
  695. void OnHideContinueSectionAnimationEnded();
  696. // Runs the animation callback popped from the test callback queue if the
  697. // queue is not empty. The parameters indicate the animation running result
  698. // and should be passed to the callback.
  699. void MaybeRunNextReorderAnimationCallbackForTest(
  700. bool aborted,
  701. AppListGridAnimationStatus animation_source);
  702. // Sets `open_folder_info_` for a folder that is about to be shown.
  703. // `folder_id` is the folder's item ID, `target_folder_position` is the grid
  704. // index at which the folder is located (or being created).
  705. // `position_to_skip`, if valid, is the grid index of an app list item that is
  706. // expected to be removed (for example, the reorder placeholder gets removed
  707. // after an app list item drag ends, and should thus be ignored when
  708. // calculating the final folder position during drag end). The target folder
  709. // position should be adjusted as if the item at this position is gone.
  710. void SetOpenFolderInfo(const std::string& folder_id,
  711. const GridIndex& target_folder_position,
  712. const GridIndex& position_to_skip);
  713. // Requsets a folder view for the provided app list folder item to be shown.
  714. // `new_folder` indicates whether the folder is a newly created folder.
  715. void ShowFolderForView(AppListItemView* folder_view, bool new_folder);
  716. // Called when a folder view that was opened from this apps grid hides (and
  717. // completes hide animation), either when user closes the folder, or when the
  718. // folder gets hidden during reparent drag.
  719. // `item_id` is the folder items app list model ID.
  720. void FolderHidden(const std::string& item_id);
  721. // When folder item view position in the grid changes while the folder view
  722. // was shown for the item, the folder item view animates out in old location,
  723. // and animate in in the new location upon folder view closure. This methods
  724. // schedules folder item fade-in animation, and schedule bounds animations for
  725. // other item views in the grid.
  726. void AnimateFolderItemViewIn();
  727. // Called when the folder view closes, and optional folder item view "position
  728. // change" animation completes.
  729. void OnFolderHideAnimationDone();
  730. class ScopedModelUpdate;
  731. AppListModel* model_ = nullptr; // Owned by AppListView.
  732. AppListItemList* item_list_ = nullptr; // Not owned.
  733. // This can be nullptr. Only grid views inside folders have a folder delegate.
  734. AppsGridViewFolderDelegate* folder_delegate_ = nullptr;
  735. // Used to request showing a folder UI for a folder item view.
  736. // May be nullptr if the AppsGridView is never expected to request a folder to
  737. // be shown. For example, it will be nullptr for folder items grids (which do
  738. // not support nested folder items).
  739. AppListFolderController* const folder_controller_;
  740. AppListA11yAnnouncer* const a11y_announcer_;
  741. AppListViewDelegate* const app_list_view_delegate_;
  742. // May be nullptr if this apps grid doesn't have custom focus handling, for
  743. // example, a folder apps grid.
  744. AppListKeyboardController* const keyboard_controller_;
  745. // Keeps the individual AppListItemView. Owned by views hierarchy.
  746. views::View* items_container_ = nullptr;
  747. // The `AppListConfig` currently used for sizing app list item views within
  748. // the grid.
  749. const AppListConfig* app_list_config_ = nullptr;
  750. // The max number of columns the grid can have.
  751. int max_cols_ = 0;
  752. int cols_ = 0;
  753. // List of app item views. There is a view per item in |model_|.
  754. views::ViewModelT<AppListItemView> view_model_;
  755. // List of pulsing block views.
  756. views::ViewModelT<PulsingBlockView> pulsing_blocks_model_;
  757. AppListItemView* selected_view_ = nullptr;
  758. // Set while the AppsGridView is handling drag operation for an app list item.
  759. // It's set to the drag item that is being dragged in the UI. If `drag_view_`
  760. // is set, it should have the same value as `drag_view_->item()`.
  761. AppListItem* drag_item_ = nullptr;
  762. // The index of the drag_view_ when the drag starts.
  763. GridIndex drag_view_init_index_;
  764. // The point where the drag started in GridView coordinates.
  765. gfx::Point drag_start_grid_view_;
  766. Pointer drag_pointer_ = NONE;
  767. // Whether the apps grid is currently updating the app list model.
  768. bool updating_model_ = false;
  769. // Object that while in scope hides the drag view from the UI during the drag
  770. // operation. Note that this may remain set even after ClearDragState(), while
  771. // the drag icon proxy animation is in progress.
  772. std::unique_ptr<DragViewHider> drag_view_hider_;
  773. // Object that while scope keeps an app list item icon hidden from a folder
  774. // view icon. Used to hide a drag item icon from a folder icon while the item
  775. // is being dropped into the folder.
  776. std::unique_ptr<FolderIconItemHider> folder_icon_item_hider_;
  777. // The most recent reorder drop target.
  778. GridIndex drop_target_;
  779. // The most recent folder drop target.
  780. GridIndex folder_drop_target_;
  781. // The index where an empty slot has been left as a placeholder for the
  782. // reorder drop target. This updates when the reorder animation triggers.
  783. GridIndex reorder_placeholder_;
  784. // The current action that ending a drag will perform.
  785. DropTargetRegion drop_target_region_ = NO_TARGET;
  786. // Timer for re-ordering the |drop_target_region_| and |drag_view_|.
  787. base::OneShotTimer reorder_timer_;
  788. // Timer for dragging a folder item out of folder container ink bubble.
  789. base::OneShotTimer folder_item_reparent_timer_;
  790. // Timer for |drag_and_drop_host_| to start handling drag operations.
  791. base::OneShotTimer host_drag_start_timer_;
  792. // An application target drag and drop host which accepts dnd operations.
  793. // Usually the shelf (e.g. ShelfView or ScrollableShelfView).
  794. ApplicationDragAndDropHost* drag_and_drop_host_ = nullptr;
  795. // The drag operation is currently inside the dnd host and events get
  796. // forwarded.
  797. bool forward_events_to_drag_and_drop_host_ = false;
  798. // Last mouse drag location in this view's coordinates.
  799. gfx::Point last_drag_point_;
  800. // Used to animate individual icon positions.
  801. std::unique_ptr<views::BoundsAnimator> bounds_animator_;
  802. // Tracks if drag_view_ is dragged out of the folder container bubble
  803. // when dragging a item inside a folder.
  804. bool drag_out_of_folder_container_ = false;
  805. // Whether a sequence of keyboard moves are happening.
  806. bool handling_keyboard_move_ = false;
  807. // True if the drag_view_ item is a folder item being dragged for reparenting.
  808. bool dragging_for_reparent_item_ = false;
  809. // The folder that should be opened after drag icon drop animation finishes.
  810. // This is set when an item drag ends in a folder creation, in which case the
  811. // created folder is expected to open after drag (assuming productivity
  812. // launcher feature is enabled).
  813. std::string folder_to_open_after_drag_icon_animation_;
  814. // When dragging for reparent in the root view, a callback registered by the
  815. // originating, hidden grid that when called will cancel drag operation in the
  816. // hidden view. Used in cases the root grid detects that the drag should end,
  817. // for example due to app list model changes.
  818. base::OnceClosure reparent_drag_cancellation_;
  819. // The drop location of the most recent reorder related accessibility event.
  820. GridIndex last_reorder_a11y_event_location_;
  821. // The location of the most recent foldering drag related accessibility event.
  822. GridIndex last_folder_dropping_a11y_event_location_;
  823. // The location when |current_ghost_view_| was shown.
  824. GridIndex current_ghost_location_;
  825. struct OpenFolderInfo {
  826. std::string item_id;
  827. GridIndex grid_index;
  828. };
  829. // Set when a folder view was opened from the apps grid - it contains the
  830. // opened folder ID and original location in the grid. While the folder
  831. // remains open, the folder item view position will be forced to the original
  832. // grid slot, to prevent folder UI from jumping, or empty slots from appearing
  833. // behind a folder when the gird item list changes (e.g. if another item gets
  834. // added by sync, or the folder item moves as a result of folder rename).
  835. absl::optional<OpenFolderInfo> open_folder_info_;
  836. // Folder item view that is being animated into it's target position. The
  837. // animation runs after a folder gets closed if the folder intended position
  838. // in the grid changed while the folder was open.
  839. absl::optional<views::View*> reordering_folder_view_;
  840. std::unique_ptr<AppsGridContextMenu> context_menu_;
  841. // The status of any whole-grid animation (reorder, hide continue section).
  842. AppListGridAnimationStatus grid_animation_status_ =
  843. AppListGridAnimationStatus::kEmpty;
  844. // A handle that aborts the active whole-grid animation.
  845. std::unique_ptr<views::AnimationAbortHandle> grid_animation_abort_handle_;
  846. // If false, the animation to move an app list item when the item's target
  847. // position changes is disabled. It is set to be false when we only care about
  848. // app list items' final positions instead of animation process.
  849. bool enable_item_move_animation_ = true;
  850. // Tracks the reorder animation triggered by the sort order change.
  851. absl::optional<ui::ThroughputTracker> reorder_animation_tracker_;
  852. // A queue of callbacks that run at the end of app list reorder. A reorder
  853. // ends if:
  854. // (1) Fade out animation is aborted, or
  855. // (2) Fade in animation is aborted or ends normally.
  856. std::queue<TestReorderDoneCallbackType>
  857. reorder_animation_callback_queue_for_test_;
  858. // A closure that runs at the start of the fade out animation.
  859. base::OnceClosure fade_out_start_closure_for_test_;
  860. // A closure that runs at the end of the fade out animation.
  861. base::OnceClosure fade_out_done_closure_for_test_;
  862. // Used to trigger and manage row change animations.
  863. std::unique_ptr<AppsGridRowChangeAnimator> row_change_animator_;
  864. base::WeakPtrFactory<AppsGridView> weak_factory_{this};
  865. };
  866. } // namespace ash
  867. #endif // ASH_APP_LIST_VIEWS_APPS_GRID_VIEW_H_