| Index: ui/app_list/cocoa/apps_grid_controller.mm
|
| diff --git a/ui/app_list/cocoa/apps_grid_controller.mm b/ui/app_list/cocoa/apps_grid_controller.mm
|
| deleted file mode 100644
|
| index d9f5e7b37c6a991137f7e0c47665fc0860a2389b..0000000000000000000000000000000000000000
|
| --- a/ui/app_list/cocoa/apps_grid_controller.mm
|
| +++ /dev/null
|
| @@ -1,684 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#import "ui/app_list/cocoa/apps_grid_controller.h"
|
| -
|
| -#include "base/mac/foundation_util.h"
|
| -#include "ui/app_list/app_list_item.h"
|
| -#include "ui/app_list/app_list_model.h"
|
| -#include "ui/app_list/app_list_model_observer.h"
|
| -#include "ui/app_list/app_list_view_delegate.h"
|
| -#import "ui/app_list/cocoa/apps_collection_view_drag_manager.h"
|
| -#import "ui/app_list/cocoa/apps_grid_view_item.h"
|
| -#import "ui/app_list/cocoa/apps_pagination_model_observer.h"
|
| -#include "ui/base/models/list_model_observer.h"
|
| -
|
| -namespace {
|
| -
|
| -// OSX app list has hardcoded rows and columns for now.
|
| -const int kFixedRows = 4;
|
| -const int kFixedColumns = 4;
|
| -const int kItemsPerPage = kFixedRows * kFixedColumns;
|
| -
|
| -// Padding space in pixels for fixed layout.
|
| -const CGFloat kGridTopPadding = 1;
|
| -const CGFloat kLeftRightPadding = 21;
|
| -const CGFloat kScrollerPadding = 16;
|
| -
|
| -// Preferred tile size when showing in fixed layout. These should be even
|
| -// numbers to ensure that if they are grown 50% they remain integers.
|
| -const CGFloat kPreferredTileWidth = 88;
|
| -const CGFloat kPreferredTileHeight = 98;
|
| -
|
| -const CGFloat kViewWidth =
|
| - kFixedColumns * kPreferredTileWidth + 2 * kLeftRightPadding;
|
| -const CGFloat kViewHeight = kFixedRows * kPreferredTileHeight;
|
| -
|
| -const NSTimeInterval kScrollWhileDraggingDelay = 1.0;
|
| -NSTimeInterval g_scroll_duration = 0.18;
|
| -
|
| -} // namespace
|
| -
|
| -@interface AppsGridController ()
|
| -
|
| -- (void)scrollToPageWithTimer:(size_t)targetPage;
|
| -- (void)onTimer:(NSTimer*)theTimer;
|
| -
|
| -// Cancel a currently running scroll animation.
|
| -- (void)cancelScrollAnimation;
|
| -
|
| -// Index of the page with the most content currently visible.
|
| -- (size_t)nearestPageIndex;
|
| -
|
| -// Bootstrap the views this class controls.
|
| -- (void)loadAndSetView;
|
| -
|
| -- (void)boundsDidChange:(NSNotification*)notification;
|
| -
|
| -// Action for buttons in the grid.
|
| -- (void)onItemClicked:(id)sender;
|
| -
|
| -- (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex
|
| - indexInPage:(size_t)indexInPage;
|
| -
|
| -// Return the button of the selected item.
|
| -- (NSButton*)selectedButton;
|
| -
|
| -// The scroll view holding the grid pages.
|
| -- (NSScrollView*)gridScrollView;
|
| -
|
| -- (NSView*)pagesContainerView;
|
| -
|
| -// Create any new pages after updating |items_|.
|
| -- (void)updatePages:(size_t)startItemIndex;
|
| -
|
| -- (void)updatePageContent:(size_t)pageIndex
|
| - resetModel:(BOOL)resetModel;
|
| -
|
| -// Bridged methods for AppListItemListObserver.
|
| -- (void)listItemAdded:(size_t)index
|
| - item:(app_list::AppListItem*)item;
|
| -
|
| -- (void)listItemRemoved:(size_t)index;
|
| -
|
| -- (void)listItemMovedFromIndex:(size_t)fromIndex
|
| - toModelIndex:(size_t)toIndex;
|
| -
|
| -// Moves the selection by |indexDelta| items.
|
| -- (BOOL)moveSelectionByDelta:(int)indexDelta;
|
| -
|
| -@end
|
| -
|
| -namespace app_list {
|
| -
|
| -class AppsGridDelegateBridge : public AppListItemListObserver {
|
| - public:
|
| - AppsGridDelegateBridge(AppsGridController* parent) : parent_(parent) {}
|
| -
|
| - private:
|
| - // Overridden from AppListItemListObserver:
|
| - void OnListItemAdded(size_t index, AppListItem* item) override {
|
| - [parent_ listItemAdded:index
|
| - item:item];
|
| - }
|
| - void OnListItemRemoved(size_t index, AppListItem* item) override {
|
| - [parent_ listItemRemoved:index];
|
| - }
|
| - void OnListItemMoved(size_t from_index,
|
| - size_t to_index,
|
| - AppListItem* item) override {
|
| - [parent_ listItemMovedFromIndex:from_index
|
| - toModelIndex:to_index];
|
| - }
|
| - void OnAppListItemHighlight(size_t index, bool highlight) override {
|
| - // NSCollectionView (or -[AppsGridController scrollToPage]) ensures only one
|
| - // item is highlighted, so clearing a highlight isn't necessary.
|
| - if (!highlight)
|
| - return;
|
| -
|
| - [parent_ selectItemAtIndex:index];
|
| - [parent_ scrollToPage:index / kItemsPerPage];
|
| - }
|
| -
|
| - AppsGridController* parent_; // Weak, owns us.
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(AppsGridDelegateBridge);
|
| -};
|
| -
|
| -} // namespace app_list
|
| -
|
| -@interface PageContainerView : NSView;
|
| -@end
|
| -
|
| -// The container view needs to flip coordinates so that it is laid out
|
| -// correctly whether or not there is a horizontal scrollbar.
|
| -@implementation PageContainerView
|
| -
|
| -- (BOOL)isFlipped {
|
| - return YES;
|
| -}
|
| -
|
| -@end
|
| -
|
| -@implementation AppsGridController
|
| -
|
| -+ (void)setScrollAnimationDuration:(NSTimeInterval)duration {
|
| - g_scroll_duration = duration;
|
| -}
|
| -
|
| -+ (CGFloat)scrollerPadding {
|
| - return kScrollerPadding;
|
| -}
|
| -
|
| -@synthesize paginationObserver = paginationObserver_;
|
| -
|
| -- (id)init {
|
| - if ((self = [super init])) {
|
| - bridge_.reset(new app_list::AppsGridDelegateBridge(self));
|
| - NSSize cellSize = NSMakeSize(kPreferredTileWidth, kPreferredTileHeight);
|
| - dragManager_.reset(
|
| - [[AppsCollectionViewDragManager alloc] initWithCellSize:cellSize
|
| - rows:kFixedRows
|
| - columns:kFixedColumns
|
| - gridController:self]);
|
| - pages_.reset([[NSMutableArray alloc] init]);
|
| - items_.reset([[NSMutableArray alloc] init]);
|
| - [self loadAndSetView];
|
| - [self updatePages:0];
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -- (void)dealloc {
|
| - [[NSNotificationCenter defaultCenter] removeObserver:self];
|
| - [super dealloc];
|
| -}
|
| -
|
| -- (NSCollectionView*)collectionViewAtPageIndex:(size_t)pageIndex {
|
| - return [pages_ objectAtIndex:pageIndex];
|
| -}
|
| -
|
| -- (size_t)pageIndexForCollectionView:(NSCollectionView*)page {
|
| - for (size_t pageIndex = 0; pageIndex < [pages_ count]; ++pageIndex) {
|
| - if (page == [self collectionViewAtPageIndex:pageIndex])
|
| - return pageIndex;
|
| - }
|
| - return NSNotFound;
|
| -}
|
| -
|
| -- (app_list::AppListModel*)model {
|
| - return delegate_ ? delegate_->GetModel() : NULL;
|
| -}
|
| -
|
| -- (void)setDelegate:(app_list::AppListViewDelegate*)newDelegate {
|
| - if (delegate_) {
|
| - app_list::AppListModel* oldModel = delegate_->GetModel();
|
| - if (oldModel)
|
| - oldModel->top_level_item_list()->RemoveObserver(bridge_.get());
|
| - }
|
| -
|
| - // Since the old model may be getting deleted, and the AppKit objects might
|
| - // be sitting in an NSAutoreleasePool, ensure there are no references to
|
| - // the model.
|
| - for (size_t i = 0; i < [items_ count]; ++i)
|
| - [[self itemAtIndex:i] setModel:NULL];
|
| -
|
| - [items_ removeAllObjects];
|
| - [self updatePages:0];
|
| - [self scrollToPage:0];
|
| -
|
| - delegate_ = newDelegate;
|
| - if (!delegate_)
|
| - return;
|
| -
|
| - app_list::AppListModel* newModel = delegate_->GetModel();
|
| - if (!newModel)
|
| - return;
|
| -
|
| - newModel->top_level_item_list()->AddObserver(bridge_.get());
|
| - for (size_t i = 0; i < newModel->top_level_item_list()->item_count(); ++i) {
|
| - app_list::AppListItem* itemModel =
|
| - newModel->top_level_item_list()->item_at(i);
|
| - [items_ insertObject:[NSValue valueWithPointer:itemModel]
|
| - atIndex:i];
|
| - }
|
| - [self updatePages:0];
|
| -}
|
| -
|
| -- (size_t)visiblePage {
|
| - return visiblePage_;
|
| -}
|
| -
|
| -- (void)activateSelection {
|
| - [[self selectedButton] performClick:self];
|
| -}
|
| -
|
| -- (size_t)pageCount {
|
| - return [pages_ count];
|
| -}
|
| -
|
| -- (size_t)itemCount {
|
| - return [items_ count];
|
| -}
|
| -
|
| -- (void)scrollToPage:(size_t)pageIndex {
|
| - NSClipView* clipView = [[self gridScrollView] contentView];
|
| - NSPoint newOrigin = [clipView bounds].origin;
|
| -
|
| - // Scrolling outside of this range is edge elasticity, which animates
|
| - // automatically.
|
| - if ((pageIndex == 0 && (newOrigin.x <= 0)) ||
|
| - (pageIndex + 1 == [self pageCount] &&
|
| - newOrigin.x >= pageIndex * kViewWidth)) {
|
| - return;
|
| - }
|
| -
|
| - // Clear any selection on the current page (unless it has been removed).
|
| - if (visiblePage_ < [pages_ count]) {
|
| - [[self collectionViewAtPageIndex:visiblePage_]
|
| - setSelectionIndexes:[NSIndexSet indexSet]];
|
| - }
|
| -
|
| - newOrigin.x = pageIndex * kViewWidth;
|
| - [NSAnimationContext beginGrouping];
|
| - [[NSAnimationContext currentContext] setDuration:g_scroll_duration];
|
| - [[clipView animator] setBoundsOrigin:newOrigin];
|
| - [NSAnimationContext endGrouping];
|
| - animatingScroll_ = YES;
|
| - targetScrollPage_ = pageIndex;
|
| - [self cancelScrollTimer];
|
| -}
|
| -
|
| -- (void)maybeChangePageForPoint:(NSPoint)locationInWindow {
|
| - NSPoint pointInView = [[self view] convertPoint:locationInWindow
|
| - fromView:nil];
|
| - // Check if the point is outside the view on the left or right.
|
| - if (pointInView.x <= 0 || pointInView.x >= NSWidth([[self view] bounds])) {
|
| - size_t targetPage = visiblePage_;
|
| - if (pointInView.x <= 0)
|
| - targetPage -= targetPage != 0 ? 1 : 0;
|
| - else
|
| - targetPage += targetPage < [pages_ count] - 1 ? 1 : 0;
|
| - [self scrollToPageWithTimer:targetPage];
|
| - return;
|
| - }
|
| -
|
| - if (paginationObserver_) {
|
| - NSInteger segment =
|
| - [paginationObserver_ pagerSegmentAtLocation:locationInWindow];
|
| - if (segment >= 0 && static_cast<size_t>(segment) != targetScrollPage_) {
|
| - [self scrollToPageWithTimer:segment];
|
| - return;
|
| - }
|
| - }
|
| -
|
| - // Otherwise the point may have moved back into the view.
|
| - [self cancelScrollTimer];
|
| -}
|
| -
|
| -- (void)cancelScrollTimer {
|
| - scheduledScrollPage_ = targetScrollPage_;
|
| - [scrollWhileDraggingTimer_ invalidate];
|
| -}
|
| -
|
| -- (void)scrollToPageWithTimer:(size_t)targetPage {
|
| - if (targetPage == targetScrollPage_) {
|
| - [self cancelScrollTimer];
|
| - return;
|
| - }
|
| -
|
| - if (targetPage == scheduledScrollPage_)
|
| - return;
|
| -
|
| - scheduledScrollPage_ = targetPage;
|
| - [scrollWhileDraggingTimer_ invalidate];
|
| - scrollWhileDraggingTimer_.reset(
|
| - [[NSTimer scheduledTimerWithTimeInterval:kScrollWhileDraggingDelay
|
| - target:self
|
| - selector:@selector(onTimer:)
|
| - userInfo:nil
|
| - repeats:NO] retain]);
|
| -}
|
| -
|
| -- (void)onTimer:(NSTimer*)theTimer {
|
| - if (scheduledScrollPage_ == targetScrollPage_)
|
| - return; // Already animating scroll.
|
| -
|
| - [self scrollToPage:scheduledScrollPage_];
|
| -}
|
| -
|
| -- (void)cancelScrollAnimation {
|
| - NSClipView* clipView = [[self gridScrollView] contentView];
|
| - [NSAnimationContext beginGrouping];
|
| - [[NSAnimationContext currentContext] setDuration:0];
|
| - [[clipView animator] setBoundsOrigin:[clipView bounds].origin];
|
| - [NSAnimationContext endGrouping];
|
| - animatingScroll_ = NO;
|
| -}
|
| -
|
| -- (size_t)nearestPageIndex {
|
| - return lround(
|
| - NSMinX([[[self gridScrollView] contentView] bounds]) / kViewWidth);
|
| -}
|
| -
|
| -- (void)userScrolling:(BOOL)isScrolling {
|
| - if (isScrolling) {
|
| - if (animatingScroll_)
|
| - [self cancelScrollAnimation];
|
| - } else {
|
| - [self scrollToPage:[self nearestPageIndex]];
|
| - }
|
| -}
|
| -
|
| -- (void)loadAndSetView {
|
| - base::scoped_nsobject<PageContainerView> pagesContainer(
|
| - [[PageContainerView alloc] initWithFrame:NSZeroRect]);
|
| -
|
| - NSRect scrollFrame = NSMakeRect(0, kGridTopPadding, kViewWidth,
|
| - kViewHeight + kScrollerPadding);
|
| - base::scoped_nsobject<ScrollViewWithNoScrollbars> scrollView(
|
| - [[ScrollViewWithNoScrollbars alloc] initWithFrame:scrollFrame]);
|
| - [scrollView setBorderType:NSNoBorder];
|
| - [scrollView setLineScroll:kViewWidth];
|
| - [scrollView setPageScroll:kViewWidth];
|
| - [scrollView setDelegate:self];
|
| - [scrollView setDocumentView:pagesContainer];
|
| - [scrollView setDrawsBackground:NO];
|
| -
|
| - [[NSNotificationCenter defaultCenter]
|
| - addObserver:self
|
| - selector:@selector(boundsDidChange:)
|
| - name:NSViewBoundsDidChangeNotification
|
| - object:[scrollView contentView]];
|
| -
|
| - [self setView:scrollView];
|
| -}
|
| -
|
| -- (void)boundsDidChange:(NSNotification*)notification {
|
| - size_t newPage = [self nearestPageIndex];
|
| - if (newPage == visiblePage_) {
|
| - [paginationObserver_ pageVisibilityChanged];
|
| - return;
|
| - }
|
| -
|
| - visiblePage_ = newPage;
|
| - [paginationObserver_ selectedPageChanged:newPage];
|
| - [paginationObserver_ pageVisibilityChanged];
|
| -}
|
| -
|
| -- (void)onItemClicked:(id)sender {
|
| - for (size_t i = 0; i < [items_ count]; ++i) {
|
| - AppsGridViewItem* gridItem = [self itemAtIndex:i];
|
| - if ([[gridItem button] isEqual:sender])
|
| - [gridItem model]->Activate(0);
|
| - }
|
| -}
|
| -
|
| -- (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex
|
| - indexInPage:(size_t)indexInPage {
|
| - return base::mac::ObjCCastStrict<AppsGridViewItem>(
|
| - [[self collectionViewAtPageIndex:pageIndex] itemAtIndex:indexInPage]);
|
| -}
|
| -
|
| -- (AppsGridViewItem*)itemAtIndex:(size_t)itemIndex {
|
| - const size_t pageIndex = itemIndex / kItemsPerPage;
|
| - return [self itemAtPageIndex:pageIndex
|
| - indexInPage:itemIndex - pageIndex * kItemsPerPage];
|
| -}
|
| -
|
| -- (NSUInteger)selectedItemIndex {
|
| - NSCollectionView* page = [self collectionViewAtPageIndex:visiblePage_];
|
| - NSUInteger indexOnPage = [[page selectionIndexes] firstIndex];
|
| - if (indexOnPage == NSNotFound)
|
| - return NSNotFound;
|
| -
|
| - return indexOnPage + visiblePage_ * kItemsPerPage;
|
| -}
|
| -
|
| -- (NSButton*)selectedButton {
|
| - NSUInteger index = [self selectedItemIndex];
|
| - if (index == NSNotFound)
|
| - return nil;
|
| -
|
| - return [[self itemAtIndex:index] button];
|
| -}
|
| -
|
| -- (NSScrollView*)gridScrollView {
|
| - return base::mac::ObjCCastStrict<NSScrollView>([self view]);
|
| -}
|
| -
|
| -- (NSView*)pagesContainerView {
|
| - return [[self gridScrollView] documentView];
|
| -}
|
| -
|
| -- (void)updatePages:(size_t)startItemIndex {
|
| - // Note there is always at least one page.
|
| - size_t targetPages = 1;
|
| - if ([items_ count] != 0)
|
| - targetPages = ([items_ count] - 1) / kItemsPerPage + 1;
|
| -
|
| - const size_t currentPages = [self pageCount];
|
| - // First see if the number of pages have changed.
|
| - if (targetPages != currentPages) {
|
| - if (targetPages < currentPages) {
|
| - // Pages need to be removed.
|
| - [pages_ removeObjectsInRange:NSMakeRange(targetPages,
|
| - currentPages - targetPages)];
|
| - } else {
|
| - // Pages need to be added.
|
| - for (size_t i = currentPages; i < targetPages; ++i) {
|
| - NSRect pageFrame = NSMakeRect(
|
| - kLeftRightPadding + kViewWidth * i, 0,
|
| - kViewWidth, kViewHeight);
|
| - [pages_ addObject:[dragManager_ makePageWithFrame:pageFrame]];
|
| - }
|
| - }
|
| -
|
| - [[self pagesContainerView] setSubviews:pages_];
|
| - NSSize pagesSize = NSMakeSize(kViewWidth * targetPages, kViewHeight);
|
| - [[self pagesContainerView] setFrameSize:pagesSize];
|
| - [paginationObserver_ totalPagesChanged];
|
| - }
|
| -
|
| - const size_t startPage = startItemIndex / kItemsPerPage;
|
| - // All pages on or after |startPage| may need items added or removed.
|
| - for (size_t pageIndex = startPage; pageIndex < targetPages; ++pageIndex) {
|
| - [self updatePageContent:pageIndex
|
| - resetModel:YES];
|
| - }
|
| -}
|
| -
|
| -- (void)updatePageContent:(size_t)pageIndex
|
| - resetModel:(BOOL)resetModel {
|
| - NSCollectionView* pageView = [self collectionViewAtPageIndex:pageIndex];
|
| - if (resetModel) {
|
| - // Clear the models first, otherwise removed items could be autoreleased at
|
| - // an unknown point in the future, when the model owner may have gone away.
|
| - for (size_t i = 0; i < [[pageView content] count]; ++i) {
|
| - AppsGridViewItem* gridItem = base::mac::ObjCCastStrict<AppsGridViewItem>(
|
| - [pageView itemAtIndex:i]);
|
| - [gridItem setModel:NULL];
|
| - }
|
| - }
|
| -
|
| - NSRange inPageRange = NSIntersectionRange(
|
| - NSMakeRange(pageIndex * kItemsPerPage, kItemsPerPage),
|
| - NSMakeRange(0, [items_ count]));
|
| - NSArray* pageContent = [items_ subarrayWithRange:inPageRange];
|
| - [pageView setContent:pageContent];
|
| - if (!resetModel)
|
| - return;
|
| -
|
| - for (size_t i = 0; i < [pageContent count]; ++i) {
|
| - AppsGridViewItem* gridItem = base::mac::ObjCCastStrict<AppsGridViewItem>(
|
| - [pageView itemAtIndex:i]);
|
| - [gridItem setModel:static_cast<app_list::AppListItem*>(
|
| - [[pageContent objectAtIndex:i] pointerValue])];
|
| - }
|
| -}
|
| -
|
| -- (void)moveItemInView:(size_t)fromIndex
|
| - toItemIndex:(size_t)toIndex {
|
| - base::scoped_nsobject<NSValue> item(
|
| - [[items_ objectAtIndex:fromIndex] retain]);
|
| - [items_ removeObjectAtIndex:fromIndex];
|
| - [items_ insertObject:item
|
| - atIndex:toIndex];
|
| -
|
| - size_t fromPageIndex = fromIndex / kItemsPerPage;
|
| - size_t toPageIndex = toIndex / kItemsPerPage;
|
| - if (fromPageIndex == toPageIndex) {
|
| - [self updatePageContent:fromPageIndex
|
| - resetModel:NO]; // Just reorder items.
|
| - return;
|
| - }
|
| -
|
| - if (fromPageIndex > toPageIndex)
|
| - std::swap(fromPageIndex, toPageIndex);
|
| -
|
| - for (size_t i = fromPageIndex; i <= toPageIndex; ++i) {
|
| - [self updatePageContent:i
|
| - resetModel:YES];
|
| - }
|
| -}
|
| -
|
| -// Compare with views implementation in AppsGridView::MoveItemInModel().
|
| -- (void)moveItemWithIndex:(size_t)itemIndex
|
| - toModelIndex:(size_t)modelIndex {
|
| - // Ingore no-op moves. Note that this is always the case when canceled.
|
| - if (itemIndex == modelIndex)
|
| - return;
|
| -
|
| - app_list::AppListItemList* itemList = [self model]->top_level_item_list();
|
| - itemList->RemoveObserver(bridge_.get());
|
| - itemList->MoveItem(itemIndex, modelIndex);
|
| - itemList->AddObserver(bridge_.get());
|
| -}
|
| -
|
| -- (AppsCollectionViewDragManager*)dragManager {
|
| - return dragManager_;
|
| -}
|
| -
|
| -- (size_t)scheduledScrollPage {
|
| - return scheduledScrollPage_;
|
| -}
|
| -
|
| -- (void)listItemAdded:(size_t)index
|
| - item:(app_list::AppListItem*)itemModel {
|
| - // Cancel any drag, to ensure the model stays consistent.
|
| - [dragManager_ cancelDrag];
|
| -
|
| - [items_ insertObject:[NSValue valueWithPointer:itemModel]
|
| - atIndex:index];
|
| -
|
| - [self updatePages:index];
|
| -}
|
| -
|
| -- (void)listItemRemoved:(size_t)index {
|
| - [dragManager_ cancelDrag];
|
| -
|
| - // Clear the models explicitly to avoid surprises from autorelease.
|
| - [[self itemAtIndex:index] setModel:NULL];
|
| -
|
| - [items_ removeObjectsInRange:NSMakeRange(index, 1)];
|
| - [self updatePages:index];
|
| -}
|
| -
|
| -- (void)listItemMovedFromIndex:(size_t)fromIndex
|
| - toModelIndex:(size_t)toIndex {
|
| - [dragManager_ cancelDrag];
|
| - [self moveItemInView:fromIndex
|
| - toItemIndex:toIndex];
|
| -}
|
| -
|
| -- (CGFloat)visiblePortionOfPage:(int)page {
|
| - CGFloat scrollOffsetOfPage =
|
| - NSMinX([[[self gridScrollView] contentView] bounds]) / kViewWidth - page;
|
| - if (scrollOffsetOfPage <= -1.0 || scrollOffsetOfPage >= 1.0)
|
| - return 0.0;
|
| -
|
| - if (scrollOffsetOfPage <= 0.0)
|
| - return scrollOffsetOfPage + 1.0;
|
| -
|
| - return -1.0 + scrollOffsetOfPage;
|
| -}
|
| -
|
| -- (void)onPagerClicked:(AppListPagerView*)sender {
|
| - int selectedSegment = [sender selectedSegment];
|
| - if (selectedSegment < 0)
|
| - return; // No selection.
|
| -
|
| - int pageIndex = [[sender cell] tagForSegment:selectedSegment];
|
| - if (pageIndex >= 0)
|
| - [self scrollToPage:pageIndex];
|
| -}
|
| -
|
| -- (BOOL)moveSelectionByDelta:(int)indexDelta {
|
| - if (indexDelta == 0)
|
| - return NO;
|
| -
|
| - NSUInteger oldIndex = [self selectedItemIndex];
|
| -
|
| - // If nothing is currently selected, select the first item on the page.
|
| - if (oldIndex == NSNotFound) {
|
| - [self selectItemAtIndex:visiblePage_ * kItemsPerPage];
|
| - return YES;
|
| - }
|
| -
|
| - // Can't select a negative index.
|
| - if (indexDelta < 0 && static_cast<NSUInteger>(-indexDelta) > oldIndex)
|
| - return NO;
|
| -
|
| - // Can't select an index greater or equal to the number of items.
|
| - if (oldIndex + indexDelta >= [items_ count]) {
|
| - if (visiblePage_ == [pages_ count] - 1)
|
| - return NO;
|
| -
|
| - // If we're not on the last page, then select the last item.
|
| - [self selectItemAtIndex:[items_ count] - 1];
|
| - return YES;
|
| - }
|
| -
|
| - [self selectItemAtIndex:oldIndex + indexDelta];
|
| - return YES;
|
| -}
|
| -
|
| -- (void)selectItemAtIndex:(NSUInteger)index {
|
| - if (index >= [items_ count])
|
| - return;
|
| -
|
| - if (index / kItemsPerPage != visiblePage_)
|
| - [self scrollToPage:index / kItemsPerPage];
|
| -
|
| - [[self itemAtIndex:index] setSelected:YES];
|
| -}
|
| -
|
| -- (BOOL)handleCommandBySelector:(SEL)command {
|
| - if (command == @selector(insertNewline:) ||
|
| - command == @selector(insertLineBreak:)) {
|
| - [self activateSelection];
|
| - return YES;
|
| - }
|
| -
|
| - NSUInteger oldIndex = [self selectedItemIndex];
|
| - // If nothing is currently selected, select the first item on the page.
|
| - if (oldIndex == NSNotFound) {
|
| - [self selectItemAtIndex:visiblePage_ * kItemsPerPage];
|
| - return YES;
|
| - }
|
| -
|
| - if (command == @selector(moveLeft:)) {
|
| - return oldIndex % kFixedColumns == 0 ?
|
| - [self moveSelectionByDelta:-kItemsPerPage + kFixedColumns - 1] :
|
| - [self moveSelectionByDelta:-1];
|
| - }
|
| -
|
| - if (command == @selector(moveRight:)) {
|
| - return oldIndex % kFixedColumns == kFixedColumns - 1 ?
|
| - [self moveSelectionByDelta:+kItemsPerPage - kFixedColumns + 1] :
|
| - [self moveSelectionByDelta:1];
|
| - }
|
| -
|
| - if (command == @selector(moveUp:)) {
|
| - return oldIndex / kFixedColumns % kFixedRows == 0 ?
|
| - NO : [self moveSelectionByDelta:-kFixedColumns];
|
| - }
|
| -
|
| - if (command == @selector(moveDown:)) {
|
| - return oldIndex / kFixedColumns % kFixedRows == kFixedRows - 1 ?
|
| - NO : [self moveSelectionByDelta:kFixedColumns];
|
| - }
|
| -
|
| - if (command == @selector(pageUp:) ||
|
| - command == @selector(scrollPageUp:))
|
| - return [self moveSelectionByDelta:-kItemsPerPage];
|
| -
|
| - if (command == @selector(pageDown:) ||
|
| - command == @selector(scrollPageDown:))
|
| - return [self moveSelectionByDelta:kItemsPerPage];
|
| -
|
| - return NO;
|
| -}
|
| -
|
| -@end
|
|
|