I recently reviewed one of my Applications that I released a year ago.
And I see that nowadays the NSCollectionView
inside it has lost the selection functioning such as SHIFT + Select now it behaving as CMD + Select.
(Secondary issue: I am also not getting a selection rectangle when dragging with the mouse.)
Obviously I want this feature back, where using shift would expand the selection from the previously clicked cell to the shift-clicked cell.
What have I done:
//NSCollectionView * _picturesGridView; //is my iVar
//In initialization I have set my _picturesGridView as follows
//Initializations etc are omitted -- (only the selection related code is here)
[_picturesGridView setSelectable:YES];
[_picturesGridView setAllowsMultipleSelection:YES];
Question: Is there an easy way to get back this functionality? I don't see anything related in documentation and I couldn't find any solution on the internet.
Sub Question: If there is no easy way to achieve that -> Should I go ahead and create my own FancyPrefix##CollectionViewClass
and to reimplement this feature as I wish -- Or is it better to go over the existing NSCollectionView
and force it to behave as I wish?
Sub Note: Well if I will find myself reimplementing it it will be light weight class that will just comply to my own needs -- I mean I will not mimic the entire NSCollectionView
class.
P.S. I am able to select an item by clicking on it I am able to select multiple items only with CMD+Click or SHIFT+Click but the latter behaves exactly as CMD+Click which I don't want as well.
As for the mouse Selection Rectangle - I didn't override any Mouse events. It is not clear why I don't have this functionality.
Per Apple's documentation, shouldSelectItemsAtIndexPaths:
is the event that only gets invoked when the user interacts with the view, but not when the selection is modified by one's own code. Therefore, this approach avoids side effects that may occur when using didSelectItemsAt:
.
It works as follows:
NSCollectionView
is actually a subclass called CustomCollectionView
that has a property @property (strong) NSIndexPath * _Nullable lastClickedIndexPath;
- (NSSet<NSIndexPath *> *)collectionView:(CustomCollectionView *)collectionView shouldDeselectItemsAtIndexPaths:(NSSet<NSIndexPath*> *)indexPaths
{
collectionView.lastClickedIndexPath = nil;
return indexPaths;
}
- (NSSet<NSIndexPath *> *)collectionView:(CustomCollectionView *)collectionView shouldSelectItemsAtIndexPaths:(NSSet<NSIndexPath*> *)indexPaths
{
if (indexPaths.count != 1) {
// If it's not a single cell selection, then we also don't want to remember the last click position
collectionView.lastClickedIndexPath = nil;
return indexPaths;
}
NSIndexPath *clickedIndexPath = indexPaths.anyObject; // now there is only one selected item
NSIndexPath *prevIndexPath = collectionView.lastClickedIndexPath;
collectionView.lastClickedIndexPath = clickedIndexPath; // remember last click
BOOL shiftKeyDown = (NSEvent.modifierFlags & NSEventModifierFlagShift) != 0;
if (NOT shiftKeyDown || prevIndexPath == nil) {
// not an extension click
return indexPaths;
}
NSMutableSet<NSIndexPath*> *newIndexPaths = [NSMutableSet set];
NSInteger startIndex = [prevIndexPath indexAtPosition:1];
NSInteger endIndex = [clickedIndexPath indexAtPosition:1];
if (startIndex > endIndex) {
// swap start and end position so that we can always count upwards
NSInteger tmp = endIndex;
endIndex = startIndex;
startIndex = tmp;
}
for (NSInteger index = startIndex; index <= endIndex; ++index) {
NSUInteger path[2] = {0, index};
[newIndexPaths addObject:[NSIndexPath indexPathWithIndexes:path length:2]];
}
return newIndexPaths;
}
This answer has been made "Community wiki" so that anyone may improve this code. Please do so if you find a bug or can make it behave better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With