Prevent Nscollectionview 'Lifting' an Item During Drag

NSCollectionView - dragging shows a hole - want it to look lke the Finder

This appears to be essentially the same question as Prevent NSCollectionView 'lifting' an item during drag

My initial solution was to use a custom view for the collection view item. In my subclass I override setHidden: to prevent the collection view from hiding my item view while the item is being dragged. This had some undesirable side-effects. It appears that NSCollectionView also hides item views when changing the layout.

The next idea (so far) works fine in my application. I un-hide the item views when dragging starts.

@interface HGImagesCollectionViewDelegate : NSObject <NSCollectionViewDelegate>

@end

@implementation HGImagesCollectionViewDelegate

- (void)collectionView:(NSCollectionView *)collectionView
draggingSession:(NSDraggingSession *)session
willBeginAtPoint:(NSPoint)screenPoint
forItemsAtIndexPaths:(NSSet<NSIndexPath *> *)indexPaths
{
// Prevent item from being hidden (creating a hole in the grid) while being dragged
for (NSIndexPath *indexPath in indexPaths) {
[[[collectionView itemAtIndexPath:indexPath] view] setHidden:NO];
}

// …

}

@end

NSCollectionView: Accept Drag Only Between Items, not Over

So, after some more research, I found that the validadeDrop method has
a parameter that describes exactly that, if the operation is over or in
between. And since it is given as a reference, one can change the
parameter to overwrite a certain behaviour. So, the solution is to add
this check to the method:

- (NSDragOperation)
collectionView:(NSCollectionView *)collectionView
validateDrop:(id<NSDraggingInfo>)draggingInfo
proposedIndex:(NSInteger *)proposedDropIndex
dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation
{
/* ... */

if (*proposedDropOperation == NSCollectionViewDropOn)
*proposedDropOperation = NSCollectionViewDropBefore;

/* ... */
}

Drag selecting in NSCollectionView from inside of items

Implement hitTest(_:) in the class of the item view to make the items "see through" for clicks. Return the collection view instead of the item view when the user clicks in the item view.

override func hitTest(_ point: NSPoint) -> NSView? {
var view = super.hitTest(point)
if view == self {
repeat {
view = view!.superview
} while view != nil && !(view is NSCollectionView)
}
return view;
}

OS X: How to pass mouse drag events through a view to superview

You can use the function on NSView

func unregisterDraggedTypes()

on the NSImageView that you create to stop them from eating up the images on the pasteboard.

That should allow the underlying NSTabView subclass to receive the drag events.

Alternatively if thats not working, place a NSView subclass which will receive the drag events over the top of the NSTabview and override the hitTest so clicks get through to the views underneath.

override func hitTest(aPoint: NSPoint) -> NSView? {
return nil
}

Alternative to NSCollectionView in pre-OSX10.5, Cocotron?

To work with NSCollectionView, you need to not only understand KVC and KVO, but also Bindings.

There's code for an NSCollectionView clone that works on Tiger here.



Related Topics



Leave a reply



Submit