forked from sketch-hq/BCCollectionView
-
Notifications
You must be signed in to change notification settings - Fork 2
/
BCCollectionView+Keyboard.m
158 lines (128 loc) · 5.04 KB
/
BCCollectionView+Keyboard.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Created by Pieter Omvlee on 25/11/2010.
// Copyright 2010 Bohemian Coding. All rights reserved.
#import "BCCollectionView+Keyboard.h"
#import "BCCollectionViewLayoutManager.h"
#import "BCCollectionViewLayoutItem.h"
@implementation BCCollectionView (BCCollectionView_Keyboard)
- (void)keyDown:(NSEvent *)theEvent
{
[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
}
- (void)clearAccumulatedBuffer
{
self.accumulatedKeyStrokes = @"";
}
- (void)insertText:(id)aString
{
if ([delegate respondsToSelector:@selector(collectionView:nameOfItem:startsWith:)]) {
[[NSRunLoop currentRunLoop] cancelPerformSelector:@selector(clearAccumulatedBuffer) target:self argument:nil];
[self performSelector:@selector(clearAccumulatedBuffer) withObject:nil afterDelay:1.0];
self.accumulatedKeyStrokes = [[accumulatedKeyStrokes stringByAppendingString:aString] lowercaseString];
NSInteger firstIndex = [contentArray indexOfObjectWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [delegate collectionView:self nameOfItem:obj startsWith:accumulatedKeyStrokes];
}];
if (firstIndex != NSNotFound) {
[self deselectAllItems];
[self selectItemAtIndex:firstIndex];
if (NSHeight([self frame]) > NSHeight([self visibleRect])) {
NSScrollView *scrollView = [self enclosingScrollView];
NSClipView *clipView = [[self enclosingScrollView] contentView];
[clipView scrollToPoint:NSMakePoint(0, MIN(NSHeight([self frame])-NSHeight([self visibleRect]),[layoutManager rectOfItemAtIndex:firstIndex].origin.y))];
[scrollView reflectScrolledClipView:clipView];
}
}
}
}
#pragma mark Helper Methods
- (void)simpleSelectItemAtIndex:(NSUInteger)anIndex
{
if (anIndex != NSNotFound) {
[self deselectAllItems];
[self selectItemAtIndex:anIndex];
[self scrollRectToVisible:[layoutManager rectOfItemAtIndex:anIndex]];
}
}
- (void)simpleExtendSelectionRange:(NSRange)range newIndex:(NSUInteger)newIndex
{
if (newIndex != NSNotFound) {
if ([selectionIndexes containsIndex:newIndex])
[self deselectItemsAtIndexes:[[NSIndexSet indexSetWithIndexesInRange:range] indexSetByRemovingIndex:newIndex]];
else
[self selectItemsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:range]];
lastSelectionIndex = newIndex;
[self scrollRectToVisible:[layoutManager rectOfItemAtIndex:newIndex]];
}
}
#pragma mark Arrow Keys
- (void)moveLeft:(id)sender
{
if (lastSelectionIndex > 0)
[self simpleSelectItemAtIndex:lastSelectionIndex-1];
}
- (void)moveLeftAndModifySelection:(id)sender
{
if (lastSelectionIndex > 0) {
NSUInteger newIndex = MAX(0ul, lastSelectionIndex-1);
[self simpleExtendSelectionRange:NSMakeRange(newIndex, 2) newIndex:newIndex];
}
}
- (void)moveRight:(id)sender
{
[self simpleSelectItemAtIndex:MIN([[self contentArray] count]-1, lastSelectionIndex+1)];
}
- (void)moveRightAndModifySelection:(id)sender
{
NSUInteger newIndex = MIN([[self contentArray] count]-1, lastSelectionIndex+1);
[self simpleExtendSelectionRange:NSMakeRange(lastSelectionIndex, 2) newIndex:newIndex];
}
- (void)moveUp:(id)sender
{
NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
[self simpleSelectItemAtIndex:[layoutManager indexOfItemAtRow:position.y-1 column:position.x]];
}
- (void)moveUpAndModifySelection:(id)sender
{
NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
NSUInteger newIndex = [layoutManager indexOfItemAtRow:position.y-1 column:position.x];
if (newIndex == NSNotFound)
newIndex = 0;
NSRange range = NSMakeRange(newIndex, lastSelectionIndex-newIndex);
if ([selectionIndexes containsIndex:newIndex])
range.location++;
[self simpleExtendSelectionRange:range newIndex:newIndex];
}
- (void)moveDown:(id)sender
{
NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
[self simpleSelectItemAtIndex:[layoutManager indexOfItemAtRow:position.y+1 column:position.x]];
}
- (void)moveDownAndModifySelection:(id)sender
{
NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
NSUInteger newIndex = [layoutManager indexOfItemAtRow:position.y+1 column:position.x];
if (newIndex == NSNotFound)
newIndex = [contentArray count]-1;
NSRange range = NSMakeRange(lastSelectionIndex, newIndex-lastSelectionIndex);
if (![selectionIndexes containsIndex:newIndex])
range.length++;
[self simpleExtendSelectionRange:range newIndex:newIndex];
}
#pragma mark Deleting
- (void)deleteBackward:(id)sender
{
if ([delegate respondsToSelector:@selector(collectionView:deleteItemsAtIndexes:)])
[delegate collectionView:self deleteItemsAtIndexes:selectionIndexes];
}
- (void)deleteForward:(id)sender
{
[self deleteBackward:sender];
}
@end
@implementation NSIndexSet (BCCollectionView_IndexSet)
- (NSIndexSet *)indexSetByRemovingIndex:(NSUInteger)index
{
return [self indexesPassingTest:^BOOL(NSUInteger idx, BOOL *stop) {
return index != idx;
}];
}
@end