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

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

Issue 12701022: wrongbaseurl OSX App List Pager and root view controller. (Closed) Base URL: http://git.chromium.org/chromium/src.git@20130304-crbug-138633-osx-app-list-demo-polish-macbook
Patch Set: delegate should be owned by viewcontroller, test coverage Created 7 years, 9 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ui/app_list/cocoa/apps_grid_controller.h" 5 #import "ui/app_list/cocoa/apps_grid_controller.h"
6 6
7 #include "base/mac/foundation_util.h" 7 #include "base/mac/foundation_util.h"
8 #include "ui/app_list/app_list_model.h" 8 #include "ui/app_list/app_list_model.h"
9 #include "ui/app_list/app_list_model_observer.h" 9 #include "ui/app_list/app_list_model_observer.h"
10 #include "ui/app_list/app_list_view_delegate.h" 10 #include "ui/app_list/app_list_view_delegate.h"
11 #include "ui/app_list/cocoa/apps_grid_view_item.h" 11 #include "ui/app_list/cocoa/apps_grid_view_item.h"
12 #import "ui/app_list/cocoa/apps_pagination_model_observer.h"
12 #include "ui/base/models/list_model_observer.h" 13 #include "ui/base/models/list_model_observer.h"
13 14
14 namespace { 15 namespace {
15 16
16 // OSX app list has hardcoded rows and columns for now. 17 // OSX app list has hardcoded rows and columns for now.
17 const int kFixedRows = 4; 18 const int kFixedRows = 4;
18 const int kFixedColumns = 4; 19 const int kFixedColumns = 4;
19 const int kItemsPerPage = kFixedRows * kFixedColumns; 20 const int kItemsPerPage = kFixedRows * kFixedColumns;
20 21
21 // Padding space in pixels for fixed layout. 22 // Padding space in pixels for fixed layout.
22 const CGFloat kLeftRightPadding = 20; 23 const CGFloat kLeftRightPadding = 16;
23 const CGFloat kTopPadding = 16; 24 const CGFloat kTopPadding = 30;
24 25
25 // Preferred tile size when showing in fixed layout. 26 // Preferred tile size when showing in fixed layout.
26 const CGFloat kPreferredTileWidth = 88; 27 const CGFloat kPreferredTileWidth = 88;
27 const CGFloat kPreferredTileHeight = 98; 28 const CGFloat kPreferredTileHeight = 98;
28 29
29 const CGFloat kViewWidth = 30 const CGFloat kViewWidth =
30 kFixedColumns * kPreferredTileWidth + 2 * kLeftRightPadding; 31 kFixedColumns * kPreferredTileWidth + 2 * kLeftRightPadding;
31 const CGFloat kViewHeight = kFixedRows * kPreferredTileHeight; 32 const CGFloat kViewHeight = kFixedRows * kPreferredTileHeight;
32 33
34 NSTimeInterval g_scroll_duration = 0.18;
35
33 } // namespace 36 } // namespace
34 37
35 @interface AppsGridController () 38 @interface AppsGridController ()
36 39
37 // Cancel a currently running scroll animation. 40 // Cancel a currently running scroll animation.
38 - (void)cancelScrollAnimation; 41 - (void)cancelScrollAnimation;
39 42
40 // Index of the page with the most content currently visible. 43 // Index of the page with the most content currently visible.
41 - (size_t)nearestPageIndex; 44 - (size_t)nearestPageIndex;
42 45
43 // Make an empty NSCollectionView positioned horizontally for |pageIndex|. 46 // Make an empty NSCollectionView positioned horizontally for |pageIndex|.
44 - (NSCollectionView*)makePageForIndex:(size_t)pageIndex; 47 - (NSCollectionView*)makePageForIndex:(size_t)pageIndex;
45 48
46 // Bootstrap the views this class controls. 49 // Bootstrap the views this class controls.
47 - (void)loadAndSetView; 50 - (void)loadAndSetView;
48 51
52 - (void)boundsDidChange:(NSNotification*)notification;
53
49 // Action for buttons in the grid. 54 // Action for buttons in the grid.
50 - (void)onItemClicked:(id)sender; 55 - (void)onItemClicked:(id)sender;
51 56
52 - (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex 57 - (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex
53 indexInPage:(size_t)indexInPage; 58 indexInPage:(size_t)indexInPage;
54 59
55 // Update the model in full, and rebuild subviews. 60 // Update the model in full, and rebuild subviews.
56 - (void)modelUpdated; 61 - (void)modelUpdated;
57 62
58 // Return the button selected in first page with a selection. 63 // Return the button selected in first page with a selection.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 96
92 AppsGridController* parent_; // Weak, owns us. 97 AppsGridController* parent_; // Weak, owns us.
93 98
94 DISALLOW_COPY_AND_ASSIGN(AppsGridDelegateBridge); 99 DISALLOW_COPY_AND_ASSIGN(AppsGridDelegateBridge);
95 }; 100 };
96 101
97 } // namespace app_list 102 } // namespace app_list
98 103
99 @implementation AppsGridController 104 @implementation AppsGridController
100 105
101 - (id)initWithViewDelegate: 106 + (void)setScrollAnimationDuration:(NSTimeInterval)duration {
102 (scoped_ptr<app_list::AppListViewDelegate>)appListViewDelegate { 107 g_scroll_duration = duration;
108 }
109
110 @synthesize paginationObserver = paginationObserver_;
111
112 - (id)init {
103 if ((self = [super init])) { 113 if ((self = [super init])) {
104 scoped_ptr<app_list::AppListModel> model(new app_list::AppListModel);
105 delegate_.reset(appListViewDelegate.release());
106 bridge_.reset(new app_list::AppsGridDelegateBridge(self)); 114 bridge_.reset(new app_list::AppsGridDelegateBridge(self));
107 pages_.reset([[NSMutableArray alloc] init]); 115 pages_.reset([[NSMutableArray alloc] init]);
108 items_.reset([[NSMutableArray alloc] init]); 116 items_.reset([[NSMutableArray alloc] init]);
109 if (delegate_)
110 delegate_->SetModel(model.get());
111 [self loadAndSetView]; 117 [self loadAndSetView];
112 [self setModel:model.Pass()]; 118 [self updatePages:0];
113 } 119 }
114 return self; 120 return self;
115 } 121 }
116 122
117 - (void)dealloc { 123 - (void)dealloc {
124 [[NSNotificationCenter defaultCenter] removeObserver:self];
118 [self setModel:scoped_ptr<app_list::AppListModel>()]; 125 [self setModel:scoped_ptr<app_list::AppListModel>()];
119 [super dealloc]; 126 [super dealloc];
120 } 127 }
121 128
122 - (NSCollectionView*)collectionViewAtPageIndex:(size_t)pageIndex { 129 - (NSCollectionView*)collectionViewAtPageIndex:(size_t)pageIndex {
123 return [pages_ objectAtIndex:pageIndex]; 130 return [pages_ objectAtIndex:pageIndex];
124 } 131 }
125 132
126 - (app_list::AppListModel*)model { 133 - (app_list::AppListModel*)model {
127 return model_.get(); 134 return model_.get();
128 } 135 }
129 136
130 - (app_list::AppListViewDelegate*)delegate { 137 - (void)setModel:(scoped_ptr<app_list::AppListModel>)newModel {
131 return delegate_.get();
132 }
133
134 - (void)setModel:(scoped_ptr<app_list::AppListModel>)model {
135 if (model_) { 138 if (model_) {
136 model_->apps()->RemoveObserver(bridge_.get()); 139 model_->apps()->RemoveObserver(bridge_.get());
137 140
138 // Since the model is about to be deleted, and the AppKit objects might be 141 // Since the model is about to be deleted, and the AppKit objects might be
139 // sitting in an NSAutoreleasePool, ensure there are no references to the 142 // sitting in an NSAutoreleasePool, ensure there are no references to the
140 // model. 143 // model.
141 for (size_t i = 0; i < [items_ count]; ++i) 144 for (size_t i = 0; i < [items_ count]; ++i)
142 [[self itemAtIndex:i] setModel:NULL]; 145 [[self itemAtIndex:i] setModel:NULL];
143 } 146 }
144 147
145 model_.reset(model.release()); 148 model_.reset(newModel.release());
146 if (model_) 149 if (model_)
147 model_->apps()->AddObserver(bridge_.get()); 150 model_->apps()->AddObserver(bridge_.get());
148 151
149 [self modelUpdated]; 152 [self modelUpdated];
150 } 153 }
151 154
155 - (void)setDelegate:(app_list::AppListViewDelegate*)newDelegate {
156 scoped_ptr<app_list::AppListModel> newModel(new app_list::AppListModel);
157 delegate_ = newDelegate;
158 if (delegate_)
159 delegate_->SetModel(newModel.get()); // Populates items.
160 [self setModel:newModel.Pass()];
161 }
162
163 - (size_t)visiblePage {
164 return visiblePage_;
165 }
166
152 - (void)activateSelection { 167 - (void)activateSelection {
153 [[self selectedButton] performClick:self]; 168 [[self selectedButton] performClick:self];
154 } 169 }
155 170
156 - (size_t)pageCount { 171 - (size_t)pageCount {
157 return [pages_ count]; 172 return [pages_ count];
158 } 173 }
159 174
160 - (void)scrollToPage:(size_t)pageIndex { 175 - (void)scrollToPage:(size_t)pageIndex {
161 NSClipView* clipView = [[self gridScrollView] contentView]; 176 NSClipView* clipView = [[self gridScrollView] contentView];
162 NSPoint newOrigin = [clipView bounds].origin; 177 NSPoint newOrigin = [clipView bounds].origin;
163 178
164 // Scrolling outside of this range is edge elasticity, which animates 179 // Scrolling outside of this range is edge elasticity, which animates
165 // automatically. 180 // automatically.
166 if ((pageIndex == 0 && (newOrigin.x <= 0)) || 181 if ((pageIndex == 0 && (newOrigin.x <= 0)) ||
167 (pageIndex + 1 == [self pageCount] && 182 (pageIndex + 1 == [self pageCount] &&
168 newOrigin.x >= pageIndex * kViewWidth)) { 183 newOrigin.x >= pageIndex * kViewWidth)) {
169 return; 184 return;
170 } 185 }
171 186
172 newOrigin.x = pageIndex * kViewWidth; 187 newOrigin.x = pageIndex * kViewWidth;
173 [NSAnimationContext beginGrouping]; 188 [NSAnimationContext beginGrouping];
189 [[NSAnimationContext currentContext] setDuration:g_scroll_duration];
174 [[clipView animator] setBoundsOrigin:newOrigin]; 190 [[clipView animator] setBoundsOrigin:newOrigin];
175 [NSAnimationContext endGrouping]; 191 [NSAnimationContext endGrouping];
176 animatingScroll_ = YES; 192 animatingScroll_ = YES;
177 } 193 }
178 194
179 - (void)cancelScrollAnimation { 195 - (void)cancelScrollAnimation {
180 NSClipView* clipView = [[self gridScrollView] contentView]; 196 NSClipView* clipView = [[self gridScrollView] contentView];
181 [NSAnimationContext beginGrouping]; 197 [NSAnimationContext beginGrouping];
182 [[NSAnimationContext currentContext] setDuration:0]; 198 [[NSAnimationContext currentContext] setDuration:0];
183 [[clipView animator] setBoundsOrigin:[clipView bounds].origin]; 199 [[clipView animator] setBoundsOrigin:[clipView bounds].origin];
(...skipping 20 matching lines...) Expand all
204 kLeftRightPadding + kViewWidth * pageIndex, 0, 220 kLeftRightPadding + kViewWidth * pageIndex, 0,
205 kViewWidth, kViewHeight); 221 kViewWidth, kViewHeight);
206 NSSize itemSize = NSMakeSize(kPreferredTileWidth, kPreferredTileHeight); 222 NSSize itemSize = NSMakeSize(kPreferredTileWidth, kPreferredTileHeight);
207 scoped_nsobject<NSCollectionView> itemCollectionView( 223 scoped_nsobject<NSCollectionView> itemCollectionView(
208 [[NSCollectionView alloc] initWithFrame:pageFrame]); 224 [[NSCollectionView alloc] initWithFrame:pageFrame]);
209 [itemCollectionView setMaxNumberOfRows:kFixedRows]; 225 [itemCollectionView setMaxNumberOfRows:kFixedRows];
210 [itemCollectionView setMinItemSize:itemSize]; 226 [itemCollectionView setMinItemSize:itemSize];
211 [itemCollectionView setMaxItemSize:itemSize]; 227 [itemCollectionView setMaxItemSize:itemSize];
212 [itemCollectionView setSelectable:YES]; 228 [itemCollectionView setSelectable:YES];
213 [itemCollectionView setFocusRingType:NSFocusRingTypeNone]; 229 [itemCollectionView setFocusRingType:NSFocusRingTypeNone];
230 [itemCollectionView setBackgroundColors:
231 [NSArray arrayWithObject:[NSColor clearColor]]];
214 232
215 scoped_nsobject<AppsGridViewItem> itemPrototype( 233 scoped_nsobject<AppsGridViewItem> itemPrototype(
216 [[AppsGridViewItem alloc] initWithSize:itemSize]); 234 [[AppsGridViewItem alloc] initWithSize:itemSize]);
217 [[itemPrototype button] setTarget:self]; 235 [[itemPrototype button] setTarget:self];
218 [[itemPrototype button] setAction:@selector(onItemClicked:)]; 236 [[itemPrototype button] setAction:@selector(onItemClicked:)];
219 237
220 [itemCollectionView setItemPrototype:itemPrototype]; 238 [itemCollectionView setItemPrototype:itemPrototype];
221 return itemCollectionView.autorelease(); 239 return itemCollectionView.autorelease();
222 } 240 }
223 241
224 - (void)loadAndSetView { 242 - (void)loadAndSetView {
225 scoped_nsobject<NSView> pagesContainer( 243 scoped_nsobject<NSView> pagesContainer(
226 [[NSView alloc] initWithFrame:NSZeroRect]); 244 [[NSView alloc] initWithFrame:NSZeroRect]);
227 245
228 NSRect scrollFrame = NSMakeRect(0, 0, kViewWidth, kViewHeight + kTopPadding); 246 NSRect scrollFrame = NSMakeRect(0, 0, kViewWidth, kViewHeight + kTopPadding);
229 scoped_nsobject<ScrollViewWithNoScrollbars> scrollView( 247 scoped_nsobject<ScrollViewWithNoScrollbars> scrollView(
230 [[ScrollViewWithNoScrollbars alloc] initWithFrame:scrollFrame]); 248 [[ScrollViewWithNoScrollbars alloc] initWithFrame:scrollFrame]);
231 [scrollView setBorderType:NSNoBorder]; 249 [scrollView setBorderType:NSNoBorder];
232 [scrollView setLineScroll:kViewWidth]; 250 [scrollView setLineScroll:kViewWidth];
233 [scrollView setPageScroll:kViewWidth]; 251 [scrollView setPageScroll:kViewWidth];
234 [scrollView setDelegate:self]; 252 [scrollView setDelegate:self];
235 [scrollView setDocumentView:pagesContainer]; 253 [scrollView setDocumentView:pagesContainer];
254 [scrollView setDrawsBackground:NO];
255
256 [[NSNotificationCenter defaultCenter]
257 addObserver:self
258 selector:@selector(boundsDidChange:)
259 name:NSViewBoundsDidChangeNotification
260 object:[scrollView contentView]];
236 261
237 [self setView:scrollView]; 262 [self setView:scrollView];
238 } 263 }
239 264
265 - (void)boundsDidChange:(NSNotification*)notification {
266 if ([self nearestPageIndex] == visiblePage_)
267 return;
268
269 size_t oldPage = visiblePage_;
270 visiblePage_ = [self nearestPageIndex];
271
272 // Clear any selection on the previous page (unless it has been removed).
273 if (oldPage < [pages_ count]) {
274 [[self collectionViewAtPageIndex:oldPage]
275 setSelectionIndexes:[NSIndexSet indexSet]];
276 }
277 [paginationObserver_ selectedPageChanged:oldPage
278 newSelected:visiblePage_];
279 }
280
240 - (void)onItemClicked:(id)sender { 281 - (void)onItemClicked:(id)sender {
241 for (size_t i = 0; i < [items_ count]; ++i) { 282 for (size_t i = 0; i < [items_ count]; ++i) {
242 AppsGridViewItem* item = [self itemAtIndex:i]; 283 AppsGridViewItem* item = [self itemAtIndex:i];
243 if ([[item button] isEqual:sender]) 284 if ([[item button] isEqual:sender])
244 delegate_->ActivateAppListItem([item model], 0); 285 delegate_->ActivateAppListItem([item model], 0);
245 } 286 }
246 } 287 }
247 288
248 - (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex 289 - (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex
249 indexInPage:(size_t)indexInPage { 290 indexInPage:(size_t)indexInPage {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 currentPages - targetPages)]; 347 currentPages - targetPages)];
307 } else { 348 } else {
308 // Pages need to be added. 349 // Pages need to be added.
309 for (size_t i = currentPages; i < targetPages; ++i) 350 for (size_t i = currentPages; i < targetPages; ++i)
310 [pages_ addObject:[self makePageForIndex:i]]; 351 [pages_ addObject:[self makePageForIndex:i]];
311 } 352 }
312 353
313 [[self pagesContainerView] setSubviews:pages_]; 354 [[self pagesContainerView] setSubviews:pages_];
314 NSSize pagesSize = NSMakeSize(kViewWidth * targetPages, kViewHeight); 355 NSSize pagesSize = NSMakeSize(kViewWidth * targetPages, kViewHeight);
315 [[self pagesContainerView] setFrameSize:pagesSize]; 356 [[self pagesContainerView] setFrameSize:pagesSize];
357 [paginationObserver_ totalPagesChanged];
316 } 358 }
317 359
318 const size_t startPage = startItemIndex / kItemsPerPage; 360 const size_t startPage = startItemIndex / kItemsPerPage;
319 // All pages on or after |startPage| may need items added or removed. 361 // All pages on or after |startPage| may need items added or removed.
320 for (size_t pageIndex = startPage; pageIndex < targetPages; ++pageIndex) { 362 for (size_t pageIndex = startPage; pageIndex < targetPages; ++pageIndex) {
321 size_t startIndex = pageIndex * kItemsPerPage; 363 size_t startIndex = pageIndex * kItemsPerPage;
322 size_t length = kItemsPerPage; 364 size_t length = kItemsPerPage;
323 // Check if it's the last page, and it's not full. 365 // Check if it's the last page, and it's not full.
324 if (startIndex + length > [items_ count]) 366 if (startIndex + length > [items_ count])
325 length = [items_ count] - startIndex; 367 length = [items_ count] - startIndex;
(...skipping 14 matching lines...) Expand all
340 [items_ insertObject:[NSValue valueWithPointer:itemModel] 382 [items_ insertObject:[NSValue valueWithPointer:itemModel]
341 atIndex:i]; 383 atIndex:i];
342 } 384 }
343 385
344 [self updatePages:start]; 386 [self updatePages:start];
345 for (size_t i = start; i < start + count; ++i) 387 for (size_t i = start; i < start + count; ++i)
346 [[self itemAtIndex:i] setModel:model_->apps()->GetItemAt(i)]; 388 [[self itemAtIndex:i] setModel:model_->apps()->GetItemAt(i)];
347 } 389 }
348 390
349 @end 391 @end
OLDNEW
« no previous file with comments | « ui/app_list/cocoa/apps_grid_controller.h ('k') | ui/app_list/cocoa/apps_grid_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698