Permalink
Browse files

CollectionView now supports internal dragging; dragging items from th…

…e collectionview onto other items in the view
  • Loading branch information...
1 parent 7ec72e6 commit 6b427fcf3accddf8e4147c24f1cfd4678212d1ca @pieteromvlee pieteromvlee committed Jan 3, 2011
Showing with 291 additions and 57 deletions.
  1. +19 −0 BCCollectionView+Dragging.h
  2. +126 −0 BCCollectionView+Dragging.m
  3. +20 −10 BCCollectionView+Mouse.m
  4. +17 −9 BCCollectionView.h
  5. +95 −38 BCCollectionView.m
  6. +14 −0 BCCollectionViewDelegate.h
@@ -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
View
@@ -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
View
@@ -8,6 +8,7 @@
#import "BCCollectionView+Mouse.h"
#import "BCGeometryExtensions.h"
+#import "BCCollectionView+Dragging.h"
@implementation BCCollectionView (BCCollectionView_Mouse)
@@ -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]) {
@@ -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)];
View
@@ -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;
@@ -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
@@ -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
Oops, something went wrong.

0 comments on commit 6b427fc

Please sign in to comment.