Skip to content
This repository has been archived by the owner on Aug 18, 2019. It is now read-only.

Commit

Permalink
CollectionView now supports internal dragging; dragging items from th…
Browse files Browse the repository at this point in the history
…e collectionview onto other items in the view
  • Loading branch information
pieteromvlee committed Jan 3, 2011
1 parent 7ec72e6 commit 6b427fc
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 57 deletions.
19 changes: 19 additions & 0 deletions BCCollectionView+Dragging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// BCCollectionView+Dragging.h
// Fontcase
//
// Created by Pieter Omvlee on 13/12/2010.
// Copyright 2010 Bohemian Coding. All rights reserved.
//

#import "BCCollectionView.h"

@interface BCCollectionView (BCCollectionView_Dragging)
- (void)initiateDraggingSessionWithEvent:(NSEvent *)anEvent;

//delegate shortcuts
- (BOOL)delegateSupportsDragForItemsAtIndexes:(NSIndexSet *)indexSet;
- (void)delegateWriteIndexes:(NSIndexSet *)indexSet toPasteboard:(NSPasteboard *)pasteboard;
- (BOOL)delegateCanDrop:(id)draggingInfo onIndex:(NSUInteger)index;
- (void)setDragHoverIndex:(NSInteger)hoverIndex;
@end
126 changes: 126 additions & 0 deletions BCCollectionView+Dragging.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//
// BCCollectionView+Dragging.m
// Fontcase
//
// Created by Pieter Omvlee on 13/12/2010.
// Copyright 2010 Bohemian Coding. All rights reserved.
//

#import "BCCollectionView+Dragging.h"

@implementation BCCollectionView (BCCollectionView_Dragging)

- (void)initiateDraggingSessionWithEvent:(NSEvent *)anEvent
{
NSUInteger index = [self indexOfItemAtPoint:mouseDownLocation];
NSRect itemRect = [self rectOfItemAtIndex:index];
NSView *currentView = [[self viewControllerForItemAtIndex:index] view];
NSData *imageData = [currentView dataWithPDFInsideRect:NSMakeRect(0,0,NSWidth(itemRect),NSHeight(itemRect))];
NSImage *pdfImage = [[[NSImage alloc] initWithData:imageData] autorelease];
NSImage *dragImage = [[NSImage alloc] initWithSize:[pdfImage size]];

[dragImage lockFocus];
[pdfImage drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:0.5];
[dragImage unlockFocus];

NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
[self delegateWriteIndexes:selectionIndexes toPasteboard:pasteboard];

[self dragImage:[dragImage autorelease]
at:NSMakePoint(NSMinX(itemRect), NSMaxY(itemRect))
offset:NSMakeSize(0, 0)
event:anEvent
pasteboard:pasteboard
source:self
slideBack:YES];
}

- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
if (dragHoverIndex != NSNotFound)
[self setNeedsDisplayInRect:[self rectOfItemAtIndex:dragHoverIndex]];

NSPoint mouse = [self convertPoint:[sender draggingLocation] fromView:nil];
NSUInteger index = [self indexOfItemAtPoint:mouse];

NSDragOperation operation = NSDragOperationNone;
if ([selectionIndexes containsIndex:index])
[self setDragHoverIndex:NSNotFound];
else if ([self delegateCanDrop:sender onIndex:index]) {
[self setDragHoverIndex:index];
operation = NSDragOperationMove;
} else
[self setDragHoverIndex:NSNotFound];

if (dragHoverIndex != NSNotFound)
[self setNeedsDisplayInRect:[self rectOfItemAtIndex:dragHoverIndex]];

return operation;
}

- (void)draggingEnded:(id <NSDraggingInfo>)sender
{
if (dragHoverIndex != NSNotFound)
[self setNeedsDisplayInRect:[self rectOfItemAtIndex:dragHoverIndex]];

[self setDragHoverIndex:NSNotFound];

if ([delegate respondsToSelector:@selector(collectionView:draggingEnded:)])
[delegate collectionView:self draggingEnded:sender];
}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
if ([delegate respondsToSelector:@selector(collectionView:performDragOperation:onViewController:forItem:)])
return [delegate collectionView:self
performDragOperation:sender
onViewController:[self viewControllerForItemAtIndex:dragHoverIndex]
forItem:[contentArray objectAtIndex:dragHoverIndex]];
else
return NO;
}

#pragma mark -
#pragma mark Delegate Shortcuts

- (void)setDragHoverIndex:(NSInteger)hoverIndex
{
if (hoverIndex != dragHoverIndex) {
if (dragHoverIndex != NSNotFound)
[self setNeedsDisplayInRect:[self rectOfItemAtIndex:dragHoverIndex]];

if ([delegate respondsToSelector:@selector(collectionView:dragExitedViewController:)])
[delegate collectionView:self dragExitedViewController:[self viewControllerForItemAtIndex:dragHoverIndex]];

dragHoverIndex = hoverIndex;

if ([delegate respondsToSelector:@selector(collectionView:dragEnteredViewController:)])
[delegate collectionView:self dragEnteredViewController:[self viewControllerForItemAtIndex:dragHoverIndex]];

if (dragHoverIndex != NSNotFound)
[self setNeedsDisplayInRect:[self rectOfItemAtIndex:dragHoverIndex]];
}
}

- (BOOL)delegateSupportsDragForItemsAtIndexes:(NSIndexSet *)indexSet
{
if ([delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:)])
return [delegate collectionView:self canDragItemsAtIndexes:indexSet];
return NO;
}

- (void)delegateWriteIndexes:(NSIndexSet *)indexSet toPasteboard:(NSPasteboard *)pasteboard
{
if ([delegate respondsToSelector:@selector(collectionView:writeItemsAtIndexes:toPasteboard:)])
[delegate collectionView:self writeItemsAtIndexes:indexSet toPasteboard:pasteboard];
}

- (BOOL)delegateCanDrop:(id)draggingInfo onIndex:(NSUInteger)index
{
if ([delegate respondsToSelector:@selector(collectionView:validateDrop:onItemAtIndex:)])
return [delegate collectionView:self validateDrop:draggingInfo onItemAtIndex:index];
else
return NO;
}

@end
30 changes: 20 additions & 10 deletions BCCollectionView+Mouse.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "BCCollectionView+Mouse.h"
#import "BCGeometryExtensions.h"
#import "BCCollectionView+Dragging.h"

@implementation BCCollectionView (BCCollectionView_Mouse)

Expand All @@ -20,26 +21,27 @@ - (void)mouseDown:(NSEvent *)theEvent
{
[[self window] makeFirstResponder:self];

if (![self shiftOrCommandKeyPressed])
mouseDownLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
mouseDraggedLocation = mouseDownLocation;
NSUInteger index = [self indexOfItemContentRectAtPoint:mouseDownLocation];

if (![self shiftOrCommandKeyPressed] && ![selectionIndexes containsIndex:index])
[self deselectAllItems];

self.originalSelectionIndexes = [[selectionIndexes copy] autorelease];

mouseDownLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
mouseDraggedLocation = mouseDownLocation;

if ([theEvent clickCount] == 2 && [delegate respondsToSelector:@selector(collectionView:didDoubleClickViewControllerAtIndex:)])
[delegate collectionView:self didDoubleClickViewControllerAtIndex:[visibleViewControllers objectForKey:[NSNumber numberWithInt:[self indexOfItemAtPoint:mouseDownLocation]]]];


NSUInteger index = [self indexOfItemAtPoint:mouseDownLocation];
if ([self shiftOrCommandKeyPressed] && [self.originalSelectionIndexes containsIndex:index])
[self deselectItemAtIndex:index];
else
[self selectItemAtIndex:index];

firstDrag = YES;
}

- (void)mouseDragged:(NSEvent *)theEvent
- (void)regularMouseDragged:(NSEvent *)anEvent
{
[self deselectAllItems];
if ([self shiftOrCommandKeyPressed]) {
Expand All @@ -49,19 +51,27 @@ - (void)mouseDragged:(NSEvent *)theEvent
}
[self setNeedsDisplayInRect:BCRectFromTwoPoints(mouseDownLocation, mouseDraggedLocation)];

mouseDraggedLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
mouseDraggedLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];

NSIndexSet *newIndexes = [self indexesOfItemsInRect:BCRectFromTwoPoints(mouseDownLocation, mouseDraggedLocation)];
NSIndexSet *newIndexes = [self indexesOfItemContentRectsInRect:BCRectFromTwoPoints(mouseDownLocation, mouseDraggedLocation)];
[newIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
if ([self.originalSelectionIndexes containsIndex:idx])
[self deselectItemAtIndex:idx];
else
[self selectItemAtIndex:idx];
}];

[self setNeedsDisplayInRect:BCRectFromTwoPoints(mouseDownLocation, mouseDraggedLocation)];
}

- (void)mouseDragged:(NSEvent *)theEvent
{
if (firstDrag && [selectionIndexes count] > 0 && [self delegateSupportsDragForItemsAtIndexes:selectionIndexes])
[self initiateDraggingSessionWithEvent:theEvent];
else
[self regularMouseDragged:theEvent];
firstDrag = NO;
}

- (void)mouseUp:(NSEvent *)theEvent
{
[self setNeedsDisplayInRect:BCRectFromTwoPoints(mouseDownLocation, mouseDraggedLocation)];
Expand Down
26 changes: 17 additions & 9 deletions BCCollectionView.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@

NSMutableArray *reusableViewControllers;
NSMutableDictionary *visibleViewControllers;

NSMutableIndexSet *selectionIndexes;
NSIndexSet *originalSelectionIndexes;

NSColor *backgroundColor;

NSUInteger lastSelectionIndex;

@private
NSPoint mouseDownLocation;
NSPoint mouseDraggedLocation;
NSRect previousFrameBounds;

NSUInteger lastSelectionIndex;
NSIndexSet *originalSelectionIndexes;
NSInteger dragHoverIndex;

BOOL firstDrag;
}
@property (nonatomic, assign) id<BCCollectionViewDelegate> delegate;
@property (nonatomic, retain) NSColor *backgroundColor;
Expand All @@ -37,6 +39,7 @@
@property (nonatomic, copy) NSIndexSet *originalSelectionIndexes;
@property (nonatomic, copy) NSArray *contentArray;

//designated way to load BCCollectionView
- (void)reloadDataWithItems:(NSArray *)newContent emptyCaches:(BOOL)shouldEmptyCaches;

//Managing Selections
Expand All @@ -47,21 +50,26 @@
- (void)deselectItemAtIndex:(NSUInteger)index;
- (void)deselectItemsAtIndexes:(NSIndexSet *)indexes;
- (void)deselectAllItems;
- (NSIndexSet *)selectionIndexes;

//Basic Cell Information
- (NSUInteger)numberOfRows;
- (NSUInteger)numberOfItemsPerRow;
- (NSSize)cellSize;
- (NSUInteger)indexOfItemAtPointOrClosestGuess:(NSPoint)p;
- (NSRange)rangeOfVisibleItems;

- (NSRect)rectOfItemAtIndex:(NSUInteger)anIndex;
- (NSIndexSet *)indexesOfItemsInRect:(NSRect)aRect;
- (NSRect)contentRectOfItemAtIndex:(NSUInteger)anIndex;

- (NSUInteger)indexOfItemAtPoint:(NSPoint)p;
- (NSUInteger)indexOfItemAtPointOrClosestGuess:(NSPoint)p;
- (NSViewController *)viewControllerForItemAtIndex:(NSUInteger)index;
- (NSUInteger)indexOfItemContentRectAtPoint:(NSPoint)p;

- (NSIndexSet *)indexesOfInvisibleViewControllers;
- (NSRange)rangeOfVisibleItems;
- (NSIndexSet *)indexesOfItemsInRect:(NSRect)aRect;
- (NSIndexSet *)indexesOfItemContentRectsInRect:(NSRect)aRect;

//Querying ViewControllers
- (NSIndexSet *)indexesOfViewControllers;
- (NSIndexSet *)indexesOfInvisibleViewControllers;
- (NSViewController *)viewControllerForItemAtIndex:(NSUInteger)index;
@end
Loading

0 comments on commit 6b427fc

Please sign in to comment.