Permalink
Browse files

Zooming, bug fixes and I dunno what more

  • Loading branch information...
pieteromvlee committed Jul 13, 2011
1 parent 0c003d7 commit 826320362c208d8a0e05505be122b39e806a3146
@@ -107,7 +107,6 @@ - (void)draggingExited:(id<NSDraggingInfo>)sender
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
- NSLog(@"performDragOperation %i", (int)dragHoverIndex);
id item = nil;
if (dragHoverIndex >= 0 && dragHoverIndex <[contentArray count])
item = [contentArray objectAtIndex:dragHoverIndex];
@@ -70,27 +70,26 @@ - (void)simpleExtendSelectionRange:(NSRange)range newIndex:(NSUInteger)newIndex
- (void)moveLeft:(id)sender
{
- NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
- [self simpleSelectItemAtIndex:[layoutManager indexOfItemAtRow:position.y column:position.x-1]];
+ if (lastSelectionIndex > 0)
+ [self simpleSelectItemAtIndex:lastSelectionIndex-1];
}
- (void)moveLeftAndModifySelection:(id)sender
{
- NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
- NSUInteger newIndex = [layoutManager indexOfItemAtRow:position.y column:position.x-1];
- [self simpleExtendSelectionRange:NSMakeRange(newIndex, 2) newIndex:newIndex];
+ if (lastSelectionIndex > 0) {
+ NSUInteger newIndex = MAX(0, lastSelectionIndex-1);
+ [self simpleExtendSelectionRange:NSMakeRange(newIndex, 2) newIndex:newIndex];
+ }
}
- (void)moveRight:(id)sender
{
- NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
- [self simpleSelectItemAtIndex:[layoutManager indexOfItemAtRow:position.y column:position.x+1]];
+ [self simpleSelectItemAtIndex:MIN([[self contentArray] count]-1, lastSelectionIndex+1)];
}
- (void)moveRightAndModifySelection:(id)sender
{
- NSPoint position = [layoutManager rowAndColumnPositionOfItemAtIndex:lastSelectionIndex];
- NSUInteger newIndex = [layoutManager indexOfItemAtRow:position.y column:position.x+1];
+ NSUInteger newIndex = MIN([[self contentArray] count]-1, lastSelectionIndex+1);
[self simpleExtendSelectionRange:NSMakeRange(lastSelectionIndex, 2) newIndex:newIndex];
}
View
@@ -30,7 +30,7 @@ - (void)mouseDown:(NSEvent *)theEvent
self.originalSelectionIndexes = [[selectionIndexes copy] autorelease];
- if ([theEvent clickCount] == 2 && [delegate respondsToSelector:@selector(collectionView:didDoubleClickViewControllerAtIndex:)])
+ if ([theEvent type] == NSLeftMouseDown && [theEvent clickCount] == 2 && [delegate respondsToSelector:@selector(collectionView:didDoubleClickViewControllerAtIndex:)])
[delegate collectionView:self didDoubleClickViewControllerAtIndex:[visibleViewControllers objectForKey:[NSNumber numberWithInt:index]]];
if ([self shiftOrCommandKeyPressed] && [self.originalSelectionIndexes containsIndex:index])
@@ -41,6 +41,9 @@ - (void)mouseDown:(NSEvent *)theEvent
- (void)regularMouseDragged:(NSEvent *)anEvent
{
+ NSIndexSet *originalSet = [[self selectionIndexes] copy];
+ selectionChangedDisabled = YES;
+
[self deselectAllItems];
if ([self shiftOrCommandKeyPressed]) {
[self.originalSelectionIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
@@ -69,19 +72,25 @@ - (void)regularMouseDragged:(NSEvent *)anEvent
}];
[self setNeedsDisplayInRect:BCRectFromTwoPoints(mouseDownLocation, mouseDraggedLocation)];
+
+ selectionChangedDisabled = NO;
+ if (![selectionIndexes isEqual:originalSet])
+ [self performSelector:@selector(delegateCollectionViewSelectionDidChange)];
}
-- (void)mouseDragged:(NSEvent *)theEvent
+- (void)mouseDragged:(NSEvent *)anEvent
{
+ [self autoscroll:anEvent];
+
if (isDragging) {
NSUInteger index = [layoutManager indexOfItemContentRectAtPoint:mouseDownLocation];
if (index != NSNotFound && [selectionIndexes count] > 0 && [self delegateSupportsDragForItemsAtIndexes:selectionIndexes]) {
- NSPoint mouse = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+ NSPoint mouse = [self convertPoint:[anEvent locationInWindow] fromView:nil];
CGFloat distance = sqrt(pow(mouse.x-mouseDownLocation.x,2)+pow(mouse.y-mouseDownLocation.y,2));
if (distance > 3)
- [self initiateDraggingSessionWithEvent:theEvent];
+ [self initiateDraggingSessionWithEvent:anEvent];
} else
- [self regularMouseDragged:theEvent];
+ [self regularMouseDragged:anEvent];
}
}
View
@@ -0,0 +1,9 @@
+// Created by Pieter Omvlee on 02/02/2011.
+// Copyright 2011 Bohemian Coding. All rights reserved.
+
+#import <Foundation/Foundation.h>
+#import "BCCollectionView.h"
+
+@interface BCCollectionView (BCCollectionView_Zoom)
+- (void)registerForZoomValueChangesInDefaultsForKey:(NSString *)key;
+@end
View
@@ -0,0 +1,72 @@
+// Created by Pieter Omvlee on 02/02/2011.
+// Copyright 2011 Bohemian Coding. All rights reserved.
+
+#import "BCCollectionView+Zoom.h"
+#import "BCCollectionViewLayoutManager.h"
+
+@interface BCCollectionView ()
+- (void)removeInvisibleViewControllers;
+- (void)addMissingViewControllersToView;
+@end
+
+@implementation BCCollectionView (BCCollectionView_Zoom)
+
+- (void)registerForZoomValueChangesInDefaultsForKey:(NSString *)key
+{
+ self.zoomValueObserverKey = key;
+ [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:key options:0 context:NULL];
+}
+
+- (void)zoomValueDidChange
+{
+ [self softReloadDataWithCompletionBlock:^{
+ if ([delegate respondsToSelector:@selector(colectionViewDidZoom:)])
+ [delegate colectionViewDidZoom:self];
+ }];
+}
+
+- (void)beginGestureWithEvent:(NSEvent *)event
+{
+ [self setAcceptsTouchEvents:YES];
+}
+
+- (void)endGestureWithEvent:(NSEvent *)event
+{
+ [self setAcceptsTouchEvents:NO];
+}
+
+- (void)touchesMovedWithEvent:(NSEvent *)event
+{
+ if (!zoomValueObserverKey)
+ return;
+
+ if (lastPinchMagnification != 0.0)
+ [self magnifyWithEvent:event];
+}
+
+- (void)magnifyWithEvent:(NSEvent *)event
+{
+ if (!zoomValueObserverKey)
+ return;
+
+ CGFloat magnification = [event type] == NSEventTypeMagnify ? [event magnification] : lastPinchMagnification;
+
+ CGFloat zoomValue = [[NSUserDefaults standardUserDefaults] integerForKey:zoomValueObserverKey];
+ zoomValue = zoomValue * (magnification+1);
+
+ NSRange scalingRange = [delegate validScalingRangeForCollectionView:self];
+ zoomValue = MAX(MIN(zoomValue, scalingRange.location + scalingRange.length), scalingRange.location);
+ [[NSUserDefaults standardUserDefaults] setInteger:zoomValue forKey:zoomValueObserverKey];
+
+ [self zoomValueDidChange];
+ [[[self enclosingScrollView] contentView] autoscroll:event];
+
+ lastPinchMagnification = magnification;
+}
+
+- (void)touchesEndedWithEvent:(NSEvent *)event
+{
+ lastPinchMagnification = 0.0;
+}
+
+@end
View
8 BCCollectionView.h 100644 → 100755
@@ -4,6 +4,10 @@
#import <Cocoa/Cocoa.h>
#import "BCCollectionViewDelegate.h"
+#ifndef BCArray
+#define BCArray(args...) [NSArray arrayWithObjects:args, nil]
+#endif
+
@class BCCollectionViewLayoutManager;
@interface BCCollectionView : NSView
{
@@ -32,6 +36,7 @@
BOOL isDragging;
BOOL firstDrag;
+ BOOL selectionChangedDisabled;
NSString *zoomValueObserverKey;
CGFloat lastPinchMagnification;
@@ -53,6 +58,7 @@
//designated way to load BCCollectionView
- (void)reloadDataWithItems:(NSArray *)newContent emptyCaches:(BOOL)shouldEmptyCaches;
- (void)reloadDataWithItems:(NSArray *)newContent groups:(NSArray *)newGroups emptyCaches:(BOOL)shouldEmptyCaches;
+- (void)reloadDataWithItems:(NSArray *)newContent groups:(NSArray *)newGroups emptyCaches:(BOOL)shouldEmptyCaches completionBlock:(dispatch_block_t)completionBlock;
//Managing Selections
- (void)selectItemAtIndex:(NSUInteger)index;
@@ -78,5 +84,5 @@
- (NSIndexSet *)indexesOfInvisibleViewControllers;
- (NSViewController *)viewControllerForItemAtIndex:(NSUInteger)index;
-- (void)softReloadData;
+- (void)softReloadDataWithCompletionBlock:(dispatch_block_t)block;
@end
View
@@ -44,10 +44,9 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
if ([self respondsToSelector:@selector(zoomValueDidChange)])
[self performSelector:@selector(zoomValueDidChange)];
} else if ([keyPath isEqualToString:@"isCollapsed"]) {
- [self softReloadData];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){
+ [self softReloadDataWithCompletionBlock:^{
[self performSelector:@selector(scrollViewDidScroll:)];
- });
+ }];
} else
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
@@ -145,7 +144,7 @@ - (void)delegateUpdateDeselectionForItemAtIndex:(NSUInteger)index
- (void)delegateCollectionViewSelectionDidChange
{
- if ([delegate respondsToSelector:@selector(collectionViewSelectionDidChange:)]) {
+ if (!selectionChangedDisabled && [delegate respondsToSelector:@selector(collectionViewSelectionDidChange:)]) {
[[NSRunLoop currentRunLoop] cancelPerformSelector:@selector(collectionViewSelectionDidChange:) target:delegate argument:self];
[(id)delegate performSelector:@selector(collectionViewSelectionDidChange:) withObject:self afterDelay:0.0];
}
@@ -201,22 +200,6 @@ - (NSIndexSet *)indexesOfItemContentRectsInRect:(NSRect)aRect
return NSIntersectsRect([itemLayout itemRect], aRect);
}];
return visibleIndexes;
-
- NSUInteger firstIndex = [layoutManager indexOfItemContentRectAtPoint:NSMakePoint(NSMinX(aRect), NSMinY(aRect))];
- NSUInteger lastIndex = [layoutManager indexOfItemContentRectAtPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
-
- if (firstIndex == NSNotFound)
- firstIndex = 0;
-
- if (lastIndex == NSNotFound)
- lastIndex = [contentArray count]-1;
-
- NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
- for (NSUInteger i=firstIndex; i<lastIndex+1; i++) {
- if (NSIntersectsRect(aRect, [layoutManager contentRectOfItemAtIndex:i]))
- [indexes addIndex:i];
- }
- return indexes;
}
- (NSRange)rangeOfVisibleItems
@@ -318,15 +301,18 @@ - (void)addMissingGroupHeaders
{
if ([groups count] > 0) {
[groups enumerateObjectsUsingBlock:^(id group, NSUInteger idx, BOOL *stop) {
- NSRect groupRect = NSMakeRect(0, NSMinY([layoutManager rectOfItemAtIndex:[group itemRange].location])-[self groupHeaderHeight],
- NSWidth([self visibleRect]), [self groupHeaderHeight]);
+ NSRect groupRect = NSMakeRect(0, NSMinY([layoutManager rectOfItemAtIndex:[group itemRange].location])-[self groupHeaderHeight], NSWidth([self visibleRect]), [self groupHeaderHeight]);
+ if (idx == 0 && ![group isCollapsed] && [delegate respondsToSelector:@selector(topOffsetForItemsInCollectionView:)])
+ groupRect.origin.y -= [delegate topOffsetForItemsInCollectionView:self];
+
BOOL groupShouldBeVisible = NSIntersectsRect(groupRect, [self visibleRect]);
NSViewController *groupViewController = [visibleGroupViewControllers objectForKey:[NSNumber numberWithInteger:idx]];
[[groupViewController view] setFrame:groupRect];
if (groupShouldBeVisible && !groupViewController) {
- groupViewController = [delegate collectionView:self headerViewControllerForGroup:group];
+ groupViewController = [delegate collectionView:self headerForGroup:group];
[self addSubview:[groupViewController view]];
[visibleGroupViewControllers setObject:groupViewController forKey:[NSNumber numberWithInteger:idx]];
+ [[groupViewController view] setFrame:groupRect];
} else if (!groupShouldBeVisible && groupViewController) {
[[groupViewController view] removeFromSuperview];
[visibleGroupViewControllers removeObjectForKey:[NSNumber numberWithInteger:idx]];
@@ -343,7 +329,6 @@ - (void)addMissingViewControllersToView
[self addMissingViewControllerForItemAtIndex:idx withFrame:[layoutManager rectOfItemAtIndex:idx]];
}
}];
-
[self addMissingGroupHeaders];
});
}
@@ -491,6 +476,11 @@ - (void)reloadDataWithItems:(NSArray *)newContent emptyCaches:(BOOL)shouldEmptyC
}
- (void)reloadDataWithItems:(NSArray *)newContent groups:(NSArray *)newGroups emptyCaches:(BOOL)shouldEmptyCaches
+{
+ [self reloadDataWithItems:newContent groups:newGroups emptyCaches:shouldEmptyCaches completionBlock:^{}];
+}
+
+- (void)reloadDataWithItems:(NSArray *)newContent groups:(NSArray *)newGroups emptyCaches:(BOOL)shouldEmptyCaches completionBlock:(dispatch_block_t)completionBlock
{
[self deselectAllItems];
[layoutManager cancelItemEnumerator];
@@ -506,19 +496,19 @@ - (void)reloadDataWithItems:(NSArray *)newContent groups:(NSArray *)newGroups em
self.groups = newGroups;
self.contentArray = newContent;
+ for (NSViewController *viewController in [visibleGroupViewControllers allValues])
+ [[viewController view] removeFromSuperview];
+ [visibleGroupViewControllers removeAllObjects];
+
if (shouldEmptyCaches) {
for (NSViewController *viewController in [visibleViewControllers allValues]) {
[[viewController view] removeFromSuperview];
if ([delegate respondsToSelector:@selector(collectionView:viewControllerBecameInvisible:)])
[delegate collectionView:self viewControllerBecameInvisible:viewController];
}
- for (NSViewController *viewController in [visibleGroupViewControllers allValues])
- [[viewController view] removeFromSuperview];
-
[reusableViewControllers removeAllObjects];
[visibleViewControllers removeAllObjects];
- [visibleGroupViewControllers removeAllObjects];
} else
[self softReloadVisibleViewControllers];
@@ -527,12 +517,15 @@ - (void)reloadDataWithItems:(NSArray *)newContent groups:(NSArray *)newGroups em
NSRect visibleRect = [self visibleRect];
[layoutManager enumerateItems:^(BCCollectionViewLayoutItem *layoutItem) {
NSViewController *viewController = [self viewControllerForItemAtIndex:[layoutItem itemIndex]];
- if (viewController)
+ if (viewController) {
+ [[viewController view] setFrame:[layoutItem itemRect]];
[delegate collectionView:self willShowViewController:viewController forItem:[contentArray objectAtIndex:[layoutItem itemIndex]]];
- else if (NSIntersectsRect(visibleRect, [layoutItem itemRect]))
+ } else if (NSIntersectsRect(visibleRect, [layoutItem itemRect]))
[self addMissingViewControllerForItemAtIndex:[layoutItem itemIndex] withFrame:[layoutItem itemRect]];
} completionBlock:^{
[self resizeFrameToFitContents];
+ [self addMissingGroupHeaders];
+ dispatch_async(dispatch_get_main_queue(), completionBlock);
}];
}
@@ -554,16 +547,15 @@ - (void)scrollViewDidScroll:(NSNotification *)note
- (void)viewDidResize
{
- if ([contentArray count] > 0)
- [self softReloadData];
+ if ([contentArray count] > 0 && [visibleViewControllers count] > 0)
+ [self softReloadDataWithCompletionBlock:NULL];
}
-- (void)softReloadData
+- (void)softReloadDataWithCompletionBlock:(dispatch_block_t)block
{
- NSRect visibleRect = [self visibleRect];
+ NSRange range = [self rangeOfVisibleItemsWithOverflow];
[layoutManager enumerateItems:^(BCCollectionViewLayoutItem *layoutItem) {
- BOOL shouldBeVisible = NSIntersectsRect([layoutItem itemRect], visibleRect);
- if (shouldBeVisible) {
+ if (NSLocationInRange([layoutItem itemIndex], range)) {
NSViewController *controller = [self viewControllerForItemAtIndex:[layoutItem itemIndex]];
if (controller)
[[controller view] setFrame:[layoutItem itemRect]];
@@ -576,11 +568,16 @@ - (void)softReloadData
} completionBlock:^(void) {
[self resizeFrameToFitContents];
[self addMissingGroupHeaders];
+ [self setNeedsDisplay:YES];
+ if (block != NULL)
+ block();
}];
}
- (NSMenu *)menuForEvent:(NSEvent *)anEvent
{
+ [self mouseDown:anEvent];
+
if ([delegate respondsToSelector:@selector(collectionView:menuForItemsAtIndexes:)])
return [delegate collectionView:self menuForItemsAtIndexes:[self selectionIndexes]];
else
@@ -46,7 +46,8 @@ enum {
//working with groups
- (NSUInteger)groupHeaderHeightForCollectionView:(BCCollectionView *)collectionView;
-- (id)collectionView:(BCCollectionView *)collectionView headerViewControllerForGroup:(BCCollectionViewGroup *)group;
+- (NSViewController *)collectionView:(BCCollectionView *)collectionView headerForGroup:(BCCollectionViewGroup *)group;
+- (NSInteger)topOffsetForItemsInCollectionView:(BCCollectionView *)collectionView;
//managing Drag & Drop (in order of occurence)
- (BOOL)collectionView:(BCCollectionView *)collectionView canDragItemsAtIndexes:(NSIndexSet *)indexSet;
@@ -67,6 +68,7 @@ enum {
//magnifiy events. This method is required BCCollectionView+Zoom is included
- (NSRange)validScalingRangeForCollectionView:(BCCollectionView *)collectionView;
+- (void)colectionViewDidZoom:(BCCollectionView *)collectionView;
//contextual menu
- (NSMenu *)collectionView:(BCCollectionView *)collectionView menuForItemsAtIndexes:(NSIndexSet *)indexSet
Oops, something went wrong.

0 comments on commit 8263203

Please sign in to comment.