Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: ui/app_list/cocoa/apps_collection_view_drag_manager.mm

Issue 187483005: Extending the Views-on-Mac experiment: whole app list grid. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: still compiles r263560 + crrev/195793005 Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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
5 #import "ui/app_list/cocoa/apps_collection_view_drag_manager.h"
6
7 #include "base/logging.h"
8 #include "base/mac/foundation_util.h"
9 #import "ui/app_list/cocoa/apps_grid_controller.h"
10 #import "ui/app_list/cocoa/apps_grid_view_item.h"
11 #import "ui/app_list/cocoa/item_drag_controller.h"
12
13 namespace {
14
15 // Distance cursor must travel in either x or y direction to start a drag.
16 const CGFloat kDragThreshold = 5;
17
18 } // namespace
19
20 @interface AppsCollectionViewDragManager ()
21
22 // Returns the item index that |theEvent| would hit in the page at |pageIndex|
23 // or NSNotFound if no item is hit.
24 - (size_t)itemIndexForPage:(size_t)pageIndex
25 hitWithEvent:(NSEvent*)theEvent;
26
27 - (void)initiateDrag:(NSEvent*)theEvent;
28 - (void)updateDrag:(NSEvent*)theEvent;
29 - (void)completeDrag;
30
31 - (NSMenu*)menuForEvent:(NSEvent*)theEvent
32 inPage:(NSCollectionView*)page;
33
34 @end
35
36 // An NSCollectionView that forwards mouse events to the factory they share.
37 @interface GridCollectionView : NSCollectionView {
38 @private
39 AppsCollectionViewDragManager* factory_;
40 }
41
42 @property(assign, nonatomic) AppsCollectionViewDragManager* factory;
43
44 @end
45
46 @implementation AppsCollectionViewDragManager
47
48 - (id)initWithCellSize:(NSSize)cellSize
49 rows:(size_t)rows
50 columns:(size_t)columns
51 gridController:(AppsGridController*)gridController {
52 if ((self = [super init])) {
53 cellSize_ = cellSize;
54 rows_ = rows;
55 columns_ = columns;
56 gridController_ = gridController;
57 }
58 return self;
59 }
60
61 - (NSCollectionView*)makePageWithFrame:(NSRect)pageFrame {
62 base::scoped_nsobject<GridCollectionView> itemCollectionView(
63 [[GridCollectionView alloc] initWithFrame:pageFrame]);
64 [itemCollectionView setFactory:self];
65 [itemCollectionView setMaxNumberOfRows:rows_];
66 [itemCollectionView setMinItemSize:cellSize_];
67 [itemCollectionView setMaxItemSize:cellSize_];
68 [itemCollectionView setSelectable:YES];
69 [itemCollectionView setFocusRingType:NSFocusRingTypeNone];
70 [itemCollectionView setBackgroundColors:
71 [NSArray arrayWithObject:[NSColor clearColor]]];
72 [itemCollectionView setDelegate:gridController_];
73
74 base::scoped_nsobject<AppsGridViewItem> itemPrototype(
75 [[AppsGridViewItem alloc] initWithSize:cellSize_]);
76 [[itemPrototype button] setTarget:gridController_];
77 [[itemPrototype button] setAction:@selector(onItemClicked:)];
78
79 [itemCollectionView setItemPrototype:itemPrototype];
80 return itemCollectionView.autorelease();
81 }
82
83 - (void)onMouseDownInPage:(NSCollectionView*)page
84 withEvent:(NSEvent*)theEvent {
85 size_t pageIndex = [gridController_ pageIndexForCollectionView:page];
86 itemHitIndex_ = [self itemIndexForPage:pageIndex
87 hitWithEvent:theEvent];
88 if (itemHitIndex_ == NSNotFound)
89 return;
90
91 mouseDownLocation_ = [theEvent locationInWindow];
92 [[[gridController_ itemAtIndex:itemHitIndex_] view] mouseDown:theEvent];
93 }
94
95 - (void)onMouseDragged:(NSEvent*)theEvent {
96 if (itemHitIndex_ == NSNotFound)
97 return;
98
99 if (dragging_) {
100 [self updateDrag:theEvent];
101 return;
102 }
103
104 NSPoint mouseLocation = [theEvent locationInWindow];
105 CGFloat deltaX = mouseLocation.x - mouseDownLocation_.x;
106 CGFloat deltaY = mouseLocation.y - mouseDownLocation_.y;
107 if (deltaX * deltaX + deltaY * deltaY > kDragThreshold * kDragThreshold) {
108 [self initiateDrag:theEvent];
109 return;
110 }
111
112 [[[gridController_ itemAtIndex:itemHitIndex_] view] mouseDragged:theEvent];
113 }
114
115 - (void)onMouseUp:(NSEvent*)theEvent {
116 if (itemHitIndex_ == NSNotFound)
117 return;
118
119 if (dragging_) {
120 [self completeDrag];
121 return;
122 }
123
124 [[[gridController_ itemAtIndex:itemHitIndex_] view] mouseUp:theEvent];
125 }
126
127 - (size_t)itemIndexForPage:(size_t)pageIndex
128 hitWithEvent:(NSEvent*)theEvent {
129 NSCollectionView* page =
130 [gridController_ collectionViewAtPageIndex:pageIndex];
131 NSPoint pointInView = [page convertPoint:[theEvent locationInWindow]
132 fromView:nil];
133
134 const size_t itemsInPage = [[page content] count];
135 for (size_t indexInPage = 0; indexInPage < itemsInPage; ++indexInPage) {
136 if ([page mouse:pointInView
137 inRect:[page frameForItemAtIndex:indexInPage]]) {
138 return indexInPage + pageIndex * rows_ * columns_;
139 }
140 }
141
142 return NSNotFound;
143 }
144
145 - (void)initiateDrag:(NSEvent*)theEvent {
146 DCHECK_LT(itemHitIndex_, [gridController_ itemCount]);
147 dragging_ = YES;
148
149 if (!itemDragController_) {
150 itemDragController_.reset(
151 [[ItemDragController alloc] initWithGridCellSize:cellSize_]);
152 [[[gridController_ view] superview] addSubview:[itemDragController_ view]];
153 }
154
155 [itemDragController_ initiate:[gridController_ itemAtIndex:itemHitIndex_]
156 mouseDownLocation:mouseDownLocation_
157 currentLocation:[theEvent locationInWindow]
158 timestamp:[theEvent timestamp]];
159
160 itemDragIndex_ = itemHitIndex_;
161 [self updateDrag:theEvent];
162 }
163
164 - (void)updateDrag:(NSEvent*)theEvent {
165 [itemDragController_ update:[theEvent locationInWindow]
166 timestamp:[theEvent timestamp]];
167 [gridController_ maybeChangePageForPoint:[theEvent locationInWindow]];
168
169 size_t visiblePage = [gridController_ visiblePage];
170 size_t itemIndexOver = [self itemIndexForPage:visiblePage
171 hitWithEvent:theEvent];
172 DCHECK_NE(0u, [gridController_ itemCount]);
173 if (itemIndexOver == NSNotFound) {
174 if (visiblePage != [gridController_ pageCount] - 1)
175 return;
176
177 // If nothing was hit, but the last page is shown, move to the end.
178 itemIndexOver = [gridController_ itemCount] - 1;
179 }
180
181 if (itemDragIndex_ == itemIndexOver)
182 return;
183
184 [gridController_ moveItemInView:itemDragIndex_
185 toItemIndex:itemIndexOver];
186 // A new item may be created when moving between pages. Ensure it is hidden.
187 [[[gridController_ itemAtIndex:itemIndexOver] button] setHidden:YES];
188 itemDragIndex_ = itemIndexOver;
189 }
190
191 - (void)cancelDrag {
192 if (!dragging_)
193 return;
194
195 [gridController_ moveItemInView:itemDragIndex_
196 toItemIndex:itemHitIndex_];
197 itemDragIndex_ = itemHitIndex_;
198 [self completeDrag];
199 itemHitIndex_ = NSNotFound; // Ignore future mouse events for this drag.
200 }
201
202 - (void)completeDrag {
203 DCHECK_GE(itemDragIndex_, 0u);
204 [gridController_ cancelScrollTimer];
205 AppsGridViewItem* item = [gridController_ itemAtIndex:itemDragIndex_];
206
207 // The item could still be animating in the NSCollectionView, so ask it where
208 // it would place the item.
209 NSCollectionView* pageView = base::mac::ObjCCastStrict<NSCollectionView>(
210 [[item view] superview]);
211 size_t indexInPage = itemDragIndex_ % (rows_ * columns_);
212 NSPoint targetOrigin = [[[itemDragController_ view] superview]
213 convertPoint:[pageView frameForItemAtIndex:indexInPage].origin
214 fromView:pageView];
215
216 [itemDragController_ complete:item
217 targetOrigin:targetOrigin];
218 [gridController_ moveItemWithIndex:itemHitIndex_
219 toModelIndex:itemDragIndex_];
220
221 dragging_ = NO;
222 }
223
224 - (NSMenu*)menuForEvent:(NSEvent*)theEvent
225 inPage:(NSCollectionView*)page {
226 size_t pageIndex = [gridController_ pageIndexForCollectionView:page];
227 size_t itemIndex = [self itemIndexForPage:pageIndex
228 hitWithEvent:theEvent];
229 if (itemIndex == NSNotFound)
230 return nil;
231
232 return [[gridController_ itemAtIndex:itemIndex] contextMenu];
233 }
234
235 @end
236
237 @implementation GridCollectionView
238
239 @synthesize factory = factory_;
240
241 - (NSMenu*)menuForEvent:(NSEvent*)theEvent {
242 return [factory_ menuForEvent:theEvent
243 inPage:self];
244 }
245
246 - (void)mouseDown:(NSEvent*)theEvent {
247 [factory_ onMouseDownInPage:self
248 withEvent:theEvent];
249 }
250
251 - (void)mouseDragged:(NSEvent*)theEvent {
252 [factory_ onMouseDragged:theEvent];
253 }
254
255 - (void)mouseUp:(NSEvent*)theEvent {
256 [factory_ onMouseUp:theEvent];
257 }
258
259 - (BOOL)acceptsFirstResponder {
260 return NO;
261 }
262
263 @end
OLDNEW
« no previous file with comments | « ui/app_list/cocoa/apps_collection_view_drag_manager.h ('k') | ui/app_list/cocoa/apps_grid_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698