Update path of checkdeps to buildtools checkout
[chromium-blink-merge.git] / ui / app_list / views / apps_grid_view.h
blobc6c9efa6f800626ace779214e5aa5590cacb5a5d
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.
5 #ifndef UI_APP_LIST_VIEWS_APPS_GRID_VIEW_H_
6 #define UI_APP_LIST_VIEWS_APPS_GRID_VIEW_H_
8 #include <set>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/timer/timer.h"
14 #include "ui/app_list/app_list_export.h"
15 #include "ui/app_list/app_list_model.h"
16 #include "ui/app_list/app_list_model_observer.h"
17 #include "ui/app_list/pagination_model_observer.h"
18 #include "ui/base/models/list_model_observer.h"
19 #include "ui/compositor/layer_animation_observer.h"
20 #include "ui/gfx/image/image_skia_operations.h"
21 #include "ui/views/animation/bounds_animator.h"
22 #include "ui/views/controls/button/button.h"
23 #include "ui/views/controls/image_view.h"
24 #include "ui/views/view.h"
25 #include "ui/views/view_model.h"
27 #if defined(OS_WIN)
28 #include "ui/base/dragdrop/drag_source_win.h"
29 #endif
31 namespace content {
32 class WebContents;
35 namespace views {
36 class ButtonListener;
37 class DragImageView;
38 class WebView;
41 namespace app_list {
43 #if defined(OS_WIN)
44 class SynchronousDrag;
45 #endif
47 namespace test {
48 class AppsGridViewTestApi;
51 class ApplicationDragAndDropHost;
52 class AppListItemView;
53 class AppsGridViewDelegate;
54 class AppsGridViewFolderDelegate;
55 class PageSwitcher;
56 class PaginationModel;
58 // AppsGridView displays a grid for AppListItemList sub model.
59 class APP_LIST_EXPORT AppsGridView : public views::View,
60 public views::ButtonListener,
61 public AppListItemListObserver,
62 public PaginationModelObserver,
63 public AppListModelObserver,
64 public ui::ImplicitAnimationObserver {
65 public:
66 enum Pointer {
67 NONE,
68 MOUSE,
69 TOUCH,
72 // Constructs the app icon grid view. |delegate| is the delegate of this
73 // view, which usually is the hosting AppListView. |pagination_model| is
74 // the paging info shared within the launcher UI.
75 AppsGridView(AppsGridViewDelegate* delegate,
76 PaginationModel* pagination_model);
77 virtual ~AppsGridView();
79 // Sets fixed layout parameters. After setting this, CalculateLayout below
80 // is no longer called to dynamically choosing those layout params.
81 void SetLayout(int icon_size, int cols, int rows_per_page);
83 int cols() { return cols_; }
84 int rows_per_page() { return rows_per_page_; }
86 // This resets the grid view to a fresh state for showing the app list.
87 void ResetForShowApps();
89 // Sets |model| to use. Note this does not take ownership of |model|.
90 void SetModel(AppListModel* model);
92 // Sets the |item_list| to render. Note this does not take ownership of
93 // |item_list|.
94 void SetItemList(AppListItemList* item_list);
96 void SetSelectedView(views::View* view);
97 void ClearSelectedView(views::View* view);
98 void ClearAnySelectedView();
99 bool IsSelectedView(const views::View* view) const;
101 // Ensures the view is visible. Note that if there is a running page
102 // transition, this does nothing.
103 void EnsureViewVisible(const views::View* view);
105 void InitiateDrag(AppListItemView* view,
106 Pointer pointer,
107 const ui::LocatedEvent& event);
109 // Called from AppListItemView when it receives a drag event. Returns true
110 // if the drag is still happening.
111 bool UpdateDragFromItem(Pointer pointer, const ui::LocatedEvent& event);
113 // Called when the user is dragging an app. |point| is in grid view
114 // coordinates.
115 void UpdateDrag(Pointer pointer, const gfx::Point& point);
116 void EndDrag(bool cancel);
117 bool IsDraggedView(const views::View* view) const;
118 void ClearDragState();
119 void SetDragViewVisible(bool visible);
121 // Set the drag and drop host for application links.
122 void SetDragAndDropHostOfCurrentAppList(
123 ApplicationDragAndDropHost* drag_and_drop_host);
125 // Prerenders the icons on and around |page_index|.
126 void Prerender(int page_index);
128 // Return true if the |bounds_animator_| is animating |view|.
129 bool IsAnimatingView(views::View* view);
131 bool has_dragged_view() const { return drag_view_ != NULL; }
132 bool dragging() const { return drag_pointer_ != NONE; }
134 // Overridden from views::View:
135 virtual gfx::Size GetPreferredSize() const OVERRIDE;
136 virtual void Layout() OVERRIDE;
137 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
138 virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
139 virtual void ViewHierarchyChanged(
140 const ViewHierarchyChangedDetails& details) OVERRIDE;
141 virtual bool GetDropFormats(
142 int* formats,
143 std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
144 virtual bool CanDrop(const OSExchangeData& data) OVERRIDE;
145 virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE;
147 // Stops the timer that triggers a page flip during a drag.
148 void StopPageFlipTimer();
150 // Returns the item view of the item at |index|.
151 AppListItemView* GetItemViewAt(int index) const;
153 // Show or hide the top item views.
154 void SetTopItemViewsVisible(bool visible);
156 // Schedules an animation to show or hide the view.
157 void ScheduleShowHideAnimation(bool show);
159 // Called to initiate drag for reparenting a folder item in root level grid
160 // view.
161 // Both |drag_view_rect| and |drag_pint| is in the coordinates of root level
162 // grid view.
163 void InitiateDragFromReparentItemInRootLevelGridView(
164 AppListItemView* original_drag_view,
165 const gfx::Rect& drag_view_rect,
166 const gfx::Point& drag_point);
168 // Updates drag in the root level grid view when receiving the drag event
169 // dispatched from the hidden grid view for reparenting a folder item.
170 void UpdateDragFromReparentItem(Pointer pointer,
171 const gfx::Point& drag_point);
173 // Dispatches the drag event from hidden grid view to the top level grid view.
174 void DispatchDragEventForReparent(Pointer pointer,
175 const gfx::Point& drag_point);
177 // Handles EndDrag event dispatched from the hidden folder grid view in the
178 // root level grid view to end reparenting a folder item.
179 // |events_forwarded_to_drag_drop_host|: True if the dragged item is dropped
180 // to the drag_drop_host, eg. dropped on shelf.
181 // |cancel_drag|: True if the drag is ending because it has been canceled.
182 void EndDragFromReparentItemInRootLevel(
183 bool events_forwarded_to_drag_drop_host,
184 bool cancel_drag);
186 // Handles EndDrag event in the hidden folder grid view to end reparenting
187 // a folder item.
188 void EndDragForReparentInHiddenFolderGridView();
190 // Called when the folder item associated with the grid view is removed.
191 // The grid view must be inside a folder view.
192 void OnFolderItemRemoved();
194 // Return the view model for test purposes.
195 const views::ViewModel* view_model_for_test() const { return &view_model_; }
197 // For test: Return if the drag and drop handler was set.
198 bool has_drag_and_drop_host_for_test() { return NULL != drag_and_drop_host_; }
200 // For test: Return if the drag and drop operation gets dispatched.
201 bool forward_events_to_drag_and_drop_host_for_test() {
202 return forward_events_to_drag_and_drop_host_;
205 void set_folder_delegate(AppsGridViewFolderDelegate* folder_delegate) {
206 folder_delegate_ = folder_delegate;
209 AppListItemView* activated_folder_item_view() const {
210 return activated_folder_item_view_;
213 private:
214 friend class test::AppsGridViewTestApi;
216 enum DropAttempt {
217 DROP_FOR_NONE,
218 DROP_FOR_REORDER,
219 DROP_FOR_FOLDER,
222 // Represents the index to an item view in the grid.
223 struct Index {
224 Index() : page(-1), slot(-1) {}
225 Index(int page, int slot) : page(page), slot(slot) {}
227 bool operator==(const Index& other) const {
228 return page == other.page && slot == other.slot;
230 bool operator!=(const Index& other) const {
231 return page != other.page || slot != other.slot;
234 int page; // Which page an item view is on.
235 int slot; // Which slot in the page an item view is in.
238 int tiles_per_page() const { return cols_ * rows_per_page_; }
240 // Updates from model.
241 void Update();
243 // Updates page splits for item views.
244 void UpdatePaging();
246 // Updates the number of pulsing block views based on AppListModel status and
247 // number of apps.
248 void UpdatePulsingBlockViews();
250 views::View* CreateViewForItemAtIndex(size_t index);
252 // Convert between the model index and the visual index. The model index
253 // is the index of the item in AppListModel. The visual index is the Index
254 // struct above with page/slot info of where to display the item.
255 Index GetIndexFromModelIndex(int model_index) const;
256 int GetModelIndexFromIndex(const Index& index) const;
258 void SetSelectedItemByIndex(const Index& index);
259 bool IsValidIndex(const Index& index) const;
261 Index GetIndexOfView(const views::View* view) const;
262 views::View* GetViewAtIndex(const Index& index) const;
264 void MoveSelected(int page_delta, int slot_x_delta, int slot_y_delta);
266 void CalculateIdealBounds();
267 void AnimateToIdealBounds();
269 // Invoked when the given |view|'s current bounds and target bounds are on
270 // different rows. To avoid moving diagonally, |view| would be put into a
271 // slot prior |target| and fade in while moving to |target|. In the meanwhile,
272 // a layer copy of |view| would start at |current| and fade out while moving
273 // to succeeding slot of |current|. |animate_current| controls whether to run
274 // fading out animation from |current|. |animate_target| controls whether to
275 // run fading in animation to |target|.
276 void AnimationBetweenRows(views::View* view,
277 bool animate_current,
278 const gfx::Rect& current,
279 bool animate_target,
280 const gfx::Rect& target);
282 // Extracts drag location info from |event| into |drag_point|.
283 void ExtractDragLocation(const ui::LocatedEvent& event,
284 gfx::Point* drag_point);
286 // Calculates |drop_target_| based on |drag_point|. |drag_point| is in the
287 // grid view's coordinates. When |use_page_button_hovering| is true and
288 // |drag_point| is hovering on a page button, use the last slot on that page
289 // as drop target.
290 void CalculateDropTarget(const gfx::Point& drag_point,
291 bool use_page_button_hovering);
293 // Same as CalculateDropTarget, but with folder UI enabled. The |drop_target_|
294 // can be either a target for re-ordering, or a target folder to move the
295 // dragged item into if |drag_view_| enters its re-ordering or folder
296 // dropping circle.
297 void CalculateDropTargetWithFolderEnabled(const gfx::Point& drag_point,
298 bool use_page_button_hovering);
300 // Prepares |drag_and_drop_host_| for dragging. |grid_location| contains
301 // the drag point in this grid view's coordinates.
302 void StartDragAndDropHostDrag(const gfx::Point& grid_location);
304 // Dispatch the drag and drop update event to the dnd host (if needed).
305 void DispatchDragEventToDragAndDropHost(
306 const gfx::Point& location_in_screen_coordinates);
308 // Starts the page flip timer if |drag_point| is in left/right side page flip
309 // zone or is over page switcher.
310 void MaybeStartPageFlipTimer(const gfx::Point& drag_point);
312 // Invoked when |page_flip_timer_| fires.
313 void OnPageFlipTimer();
315 // Updates |model_| to move item represented by |item_view| to |target| slot.
316 void MoveItemInModel(views::View* item_view, const Index& target);
318 // Updates |model_| to move item represented by |item_view| into a folder
319 // containing item located at |target| slot, also update |view_model_| for
320 // the related view changes.
321 void MoveItemToFolder(views::View* item_view, const Index& target);
323 // Updates both data model and view_model_ for re-parenting a folder item to a
324 // new position in top level item list.
325 void ReparentItemForReorder(views::View* item_view, const Index& target);
327 // Updates both data model and view_model_ for re-parenting a folder item
328 // to anther folder target.
329 void ReparentItemToAnotherFolder(views::View* item_view, const Index& target);
331 // If there is only 1 item left in the source folder after reparenting an item
332 // from it, updates both data model and view_model_ for removing last item
333 // from the source folder and removes the source folder.
334 void RemoveLastItemFromReparentItemFolderIfNecessary(
335 const std::string& source_folder_id);
337 // If user does not drop the re-parenting folder item to any valid target,
338 // cancel the re-parenting action, let the item go back to its original
339 // parent folder with UI animation.
340 void CancelFolderItemReparent(AppListItemView* drag_item_view);
342 // Cancels any context menus showing for app items on the current page.
343 void CancelContextMenusOnCurrentPage();
345 // Removes the AppListItemView at |index| in |view_model_| and deletes it.
346 void DeleteItemViewAtIndex(int index);
348 // Returns true if |point| lies within the bounds of this grid view plus a
349 // buffer area surrounding it.
350 bool IsPointWithinDragBuffer(const gfx::Point& point) const;
352 // Overridden from views::ButtonListener:
353 virtual void ButtonPressed(views::Button* sender,
354 const ui::Event& event) OVERRIDE;
356 // Overridden from AppListItemListObserver:
357 virtual void OnListItemAdded(size_t index, AppListItem* item) OVERRIDE;
358 virtual void OnListItemRemoved(size_t index, AppListItem* item) OVERRIDE;
359 virtual void OnListItemMoved(size_t from_index,
360 size_t to_index,
361 AppListItem* item) OVERRIDE;
363 // Overridden from PaginationModelObserver:
364 virtual void TotalPagesChanged() OVERRIDE;
365 virtual void SelectedPageChanged(int old_selected, int new_selected) OVERRIDE;
366 virtual void TransitionStarted() OVERRIDE;
367 virtual void TransitionChanged() OVERRIDE;
369 // Overridden from AppListModelObserver:
370 virtual void OnAppListModelStatusChanged() OVERRIDE;
372 // ui::ImplicitAnimationObserver overrides:
373 virtual void OnImplicitAnimationsCompleted() OVERRIDE;
375 // Hide a given view temporarily without losing (mouse) events and / or
376 // changing the size of it. If |immediate| is set the change will be
377 // immediately applied - otherwise it will change gradually.
378 // If |hide| is set the view will get hidden, otherwise it gets shown.
379 void SetViewHidden(views::View* view, bool hide, bool immediate);
381 // Whether the folder drag-and-drop UI should be enabled.
382 bool EnableFolderDragDropUI();
384 // Whether target specified by |drap_target| can accept more items to be
385 // dropped into it.
386 bool CanDropIntoTarget(const Index& drop_target);
388 // Returns the visual index of the nearest tile in which |drag_view_| enters
389 // either its re-ordering or folder dropping circle.
390 Index GetNearestTileForDragView();
392 // Calculates |nearest_tile| in which |vertex| of the |drag_view| is
393 // enclosed.
394 // *|nearest_tile| and *|d_min| will be updated based on the calculation.
395 // *|d_min| is the distance between |nearest_tile| and |drag_view_|.
396 void CalculateNearestTileForVertex(
397 const gfx::Point& vertex, Index* nearest_tile, int* d_min);
399 // Returns the bounds of the tile in which |point| is enclosed if there
400 // is a valid item sits on the tile.
401 gfx::Rect GetTileBoundsForPoint(const gfx::Point& point, Index* tile_index);
403 // Gets the bounds of the tile located at |row| and |col| on current page.
404 gfx::Rect GetTileBounds(int row, int col) const;
406 // Returns true if the slot of |index| is the last possible slot to drop
407 // an item, i.e. first empty slot next to the last item on the last page.
408 bool IsLastPossibleDropTarget(const Index& index) const;
410 // Gets the item view located at |slot| on the current page. If there is
411 // no item located at |slot|, returns NULL.
412 views::View* GetViewAtSlotOnCurrentPage(int slot);
414 // Sets state of the view with |target_index| to |is_target_folder| for
415 // dropping |drag_view_|.
416 void SetAsFolderDroppingTarget(const Index& target_index,
417 bool is_target_folder);
419 // Invoked when |reorder_timer_| fires to show re-order preview UI.
420 void OnReorderTimer();
422 // Invoked when |folder_item_reparent_timer_| fires.
423 void OnFolderItemReparentTimer();
425 // Invoked when |folder_dropping_timer_| fires to show folder dropping
426 // preview UI.
427 void OnFolderDroppingTimer();
429 // Updates drag state for dragging inside a folder's grid view.
430 void UpdateDragStateInsideFolder(Pointer pointer,
431 const gfx::Point& drag_point);
433 // Returns true if drag event is happening in the root level AppsGridView
434 // for reparenting a folder item.
435 bool IsDraggingForReparentInRootLevelGridView() const;
437 // Returns true if drag event is happening in the hidden AppsGridView of the
438 // folder during reparenting a folder item.
439 bool IsDraggingForReparentInHiddenGridView() const;
441 // Returns the target icon bounds for |drag_item_view| to fly back
442 // to its parent |folder_item_view| in animation.
443 gfx::Rect GetTargetIconRectInFolder(AppListItemView* drag_item_view,
444 AppListItemView* folder_item_view);
446 // Returns true if the grid view is under an OEM folder.
447 bool IsUnderOEMFolder();
449 void StartSettingUpSynchronousDrag();
450 bool RunSynchronousDrag();
451 void CleanUpSynchronousDrag();
452 #if defined(OS_WIN)
453 void OnGotShortcutPath(scoped_refptr<SynchronousDrag> drag,
454 const base::FilePath& path);
455 #endif
457 AppListModel* model_; // Owned by AppListView.
458 AppListItemList* item_list_; // Not owned.
459 AppsGridViewDelegate* delegate_;
461 // This can be NULL. Only grid views inside folders have a folder delegate.
462 AppsGridViewFolderDelegate* folder_delegate_;
464 PaginationModel* pagination_model_; // Owned by AppListController.
465 PageSwitcher* page_switcher_view_; // Owned by views hierarchy.
467 gfx::Size icon_size_;
468 int cols_;
469 int rows_per_page_;
471 // Tracks app item views. There is a view per item in |model_|.
472 views::ViewModel view_model_;
474 // Tracks pulsing block views.
475 views::ViewModel pulsing_blocks_model_;
477 views::View* selected_view_;
479 AppListItemView* drag_view_;
481 // The index of the drag_view_ when the drag starts.
482 Index drag_view_init_index_;
484 // The point where the drag started in AppListItemView coordinates.
485 gfx::Point drag_view_offset_;
487 // The point where the drag started in GridView coordinates.
488 gfx::Point drag_start_grid_view_;
490 // The location of |drag_view_| when the drag started.
491 gfx::Point drag_view_start_;
493 // Page the drag started on.
494 int drag_start_page_;
496 #if defined(OS_WIN)
497 // Created when a drag is started (ie: drag exceeds the drag threshold), but
498 // not Run() until supplied with a shortcut path.
499 scoped_refptr<SynchronousDrag> synchronous_drag_;
501 // Whether to use SynchronousDrag to support dropping to task bar etc.
502 bool use_synchronous_drag_;
503 #endif
505 Pointer drag_pointer_;
506 Index drop_target_;
507 DropAttempt drop_attempt_;
509 // Timer for re-ordering the |drop_target_| and |drag_view_|.
510 base::OneShotTimer<AppsGridView> reorder_timer_;
512 // Timer for dropping |drag_view_| into the folder containing
513 // the |drop_target_|.
514 base::OneShotTimer<AppsGridView> folder_dropping_timer_;
516 // Timer for dragging a folder item out of folder container ink bubble.
517 base::OneShotTimer<AppsGridView> folder_item_reparent_timer_;
519 // An application target drag and drop host which accepts dnd operations.
520 ApplicationDragAndDropHost* drag_and_drop_host_;
522 // The drag operation is currently inside the dnd host and events get
523 // forwarded.
524 bool forward_events_to_drag_and_drop_host_;
526 // Last mouse drag location in this view's coordinates.
527 gfx::Point last_drag_point_;
529 // Timer to auto flip page when dragging an item near the left/right edges.
530 base::OneShotTimer<AppsGridView> page_flip_timer_;
532 // Target page to switch to when |page_flip_timer_| fires.
533 int page_flip_target_;
535 // Delay in milliseconds of when |page_flip_timer_| should fire after user
536 // drags an item near the edges.
537 int page_flip_delay_in_ms_;
539 views::BoundsAnimator bounds_animator_;
541 // The most recent activated folder item view.
542 AppListItemView* activated_folder_item_view_;
544 // Tracks if drag_view_ is dragged out of the folder container bubble
545 // when dragging a item inside a folder.
546 bool drag_out_of_folder_container_;
548 // True if the drag_view_ item is a folder item being dragged for reparenting.
549 bool dragging_for_reparent_item_;
551 DISALLOW_COPY_AND_ASSIGN(AppsGridView);
554 } // namespace app_list
556 #endif // UI_APP_LIST_VIEWS_APPS_GRID_VIEW_H_