Skip to content
Browse files

Moved user interaction methods into a new category

  • Loading branch information...
1 parent 35da629 commit f89a40f61805eccef368861c64cd0331e00e9945 Alex Rozanski committed Mar 27, 2011
View
1 Classes/PXListDocumentView.m
@@ -10,6 +10,7 @@
#import "PXListView.h"
#import "PXListView+Private.h"
+#import "PXListView+UserInteraction.h"
@implementation PXListDocumentView
View
3 Classes/PXListView+Private.h
@@ -37,9 +37,6 @@ typedef NSInteger PXIsDragStartResult;
- (void)updateCells;
- (void)enqueueCell:(PXListViewCell*)cell;
-- (void)handleMouseDown:(NSEvent*)theEvent inCell:(PXListViewCell*)theCell;
-- (void)handleMouseDownOutsideCells:(NSEvent*)theEvent;
-
- (void)contentViewBoundsDidChange:(NSNotification*)notification;
@end
View
13 Classes/PXListView+UserInteraction.h
@@ -8,7 +8,18 @@
#import <Foundation/Foundation.h>
+#import "PXListView.h"
-@interface PXListView (PXListView_UserInteraction)
+@interface PXListView (UserInteraction)
+
+- (void)handleMouseDown:(NSEvent*)theEvent inCell:(PXListViewCell*)theCell;
+- (void)handleMouseDownOutsideCells:(NSEvent*)theEvent;
+
+- (BOOL)attemptDragWithMouseDown:(NSEvent*)theEvent inCell:(PXListViewCell*)theCell;
+- (NSImage*)dragImageForRowsWithIndexes:(NSIndexSet *)dragRows
+ event:(NSEvent*)dragEvent clickedCell:(PXListViewCell*)clickedCell
+ offset:(NSPointPointer)dragImageOffset;
+- (void)setShowsDropHighlight:(BOOL)inState;
+- (void)setDropRow:(NSUInteger)row dropHighlight:(PXListViewDropHighlight)dropHighlight;
@end
View
564 Classes/PXListView+UserInteraction.m
@@ -6,9 +6,571 @@
// Copyright 2011 Alex Rozanski. All rights reserved.
//
+#import <iso646.h>
+
#import "PXListView+UserInteraction.h"
+#import "PXListView+Private.h"
+
+// Apple sadly doesn't provide CGFloat variants of these:
+#if CGFLOAT_IS_DOUBLE
+#define CGFLOATABS(n) fabs(n)
+#else
+#define CGFLOATABS(n) fabsf(n)
+#endif
+
+// This is a renamed copy of UKIsDragStart from <http://github.com/uliwitness/UliKit>:
+static PXIsDragStartResult PXIsDragStart( NSEvent *startEvent, NSTimeInterval theTimeout )
+{
+ if( theTimeout == 0.0 )
+ theTimeout = 1.5;
+
+ NSPoint startPos = [startEvent locationInWindow];
+ NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
+ NSDate* expireTime = [NSDate dateWithTimeIntervalSinceReferenceDate: startTime +theTimeout];
+
+ NSAutoreleasePool *pool = nil;
+ while( ([expireTime timeIntervalSinceReferenceDate] -[NSDate timeIntervalSinceReferenceDate]) > 0 )
+ {
+ [pool release];
+ pool = [[NSAutoreleasePool alloc] init];
+
+ NSEvent* currEvent = [NSApp nextEventMatchingMask: NSLeftMouseUpMask | NSRightMouseUpMask | NSOtherMouseUpMask
+ | NSLeftMouseDraggedMask | NSRightMouseDraggedMask | NSOtherMouseDraggedMask
+ untilDate: expireTime inMode: NSEventTrackingRunLoopMode dequeue: YES];
+ if( currEvent )
+ {
+ switch( [currEvent type] )
+ {
+ case NSLeftMouseUp:
+ case NSRightMouseUp:
+ case NSOtherMouseUp:
+ {
+ [pool release];
+ return PXIsDragStartMouseReleased; // Mouse released within the wait time.
+ break;
+ }
+
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ {
+ NSPoint newPos = [currEvent locationInWindow];
+ CGFloat xMouseMovement = CGFLOATABS(newPos.x -startPos.x);
+ CGFloat yMouseMovement = CGFLOATABS(newPos.y -startPos.y);
+ if( xMouseMovement > 2 or yMouseMovement > 2 )
+ {
+ [pool release];
+ return (xMouseMovement > yMouseMovement) ? PXIsDragStartMouseMovedHorizontally : PXIsDragStartMouseMovedVertically; // Mouse moved within the wait time, probably a drag!
+ }
+ break;
+ }
+ }
+ }
+
+ }
+
+ [pool release];
+ return PXIsDragStartTimedOut; // If they held the mouse that long, they probably wanna drag.
+}
+
+
+@implementation PXListView (UserInteraction)
+
+#pragma mark -
+#pragma mark NSResponder
+
+- (BOOL)canBecomeKeyView
+{
+ return YES;
+}
+
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL)becomeFirstResponder
+{
+ return YES;
+}
+
+
+- (BOOL)resignFirstResponder
+{
+ return YES;
+}
+
+#pragma mark -
+#pragma mark Keyboard Handling
+
+- (void)keyDown:(NSEvent *)theEvent
+{
+ [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+}
+
+
+- (void)moveUp:(id)sender
+{
+ if([_selectedRows count]>0) {
+ NSUInteger firstIndex = [_selectedRows firstIndex];
+
+ if(firstIndex>0) {
+ NSUInteger newRow = firstIndex-1;
+ [self setSelectedRow:newRow];
+ [self scrollRowToVisible:newRow];
+ }
+ }
+}
+
+
+- (void)moveDown:(id)sender
+{
+ if([_selectedRows count]>0) {
+ NSUInteger lastIndex = [_selectedRows lastIndex];
+
+ if(lastIndex<(_numberOfRows-1)) {
+ NSUInteger newRow = lastIndex+1;
+ [self setSelectedRow:newRow];
+ [self scrollRowToVisible:newRow];
+ }
+ }
+}
+
+
+- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
+{
+ if([menuItem action] == @selector(selectAll:))
+ {
+ return _allowsMultipleSelection && [_selectedRows count] != _numberOfRows; // No "select all" if everything's already selected or we can only select one row.
+ }
+
+ if([menuItem action] == @selector(deselectAll:))
+ {
+ return _allowsEmptySelection && [_selectedRows count] != 0; // No "deselect all" if nothing's selected or we must have at least one row selected.
+ }
+
+ return NO;
+}
+
+#pragma mark - Mouse Events
+
+- (void)handleMouseDown:(NSEvent*)theEvent inCell:(PXListViewCell*)theCell // Central funnel for cell clicks so cells don't have to know about multi-selection, modifiers etc.
+{
+ // theEvent is NIL if we get a "press" action from accessibility. In that case, try to toggle, so users can selectively turn on/off an item.
+ [[self window] makeFirstResponder:self];
+
+ BOOL tryDraggingAgain = YES;
+ BOOL shouldToggle = theEvent == nil || ([theEvent modifierFlags] & NSCommandKeyMask) || ([theEvent modifierFlags] & NSShiftKeyMask); // +++ Shift should really be a continuous selection.
+ BOOL isSelected = [_selectedRows containsIndex: [theCell row]];
+ NSIndexSet *clickedIndexSet = [NSIndexSet indexSetWithIndex: [theCell row]];
+
+ // If a cell is already selected, we can drag it out, in which case we shouldn't toggle it:
+ if( theEvent && isSelected && [self attemptDragWithMouseDown: theEvent inCell: theCell] )
+ return;
+
+ if( _allowsMultipleSelection )
+ {
+ if( isSelected && shouldToggle )
+ {
+ if( [_selectedRows count] == 1 && !_allowsEmptySelection )
+ return;
+ [self deselectRowIndexes: clickedIndexSet];
+ }
+ else if( !isSelected && shouldToggle )
+ [self selectRowIndexes: clickedIndexSet byExtendingSelection: YES];
+ else if( !isSelected && !shouldToggle )
+ [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
+ else if( isSelected && !shouldToggle && [_selectedRows count] != 1 )
+ {
+ [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
+ tryDraggingAgain = NO;
+ }
+ }
+ else if( shouldToggle && _allowsEmptySelection )
+ {
+ if( isSelected )
+ {
+ [self deselectRowIndexes: clickedIndexSet];
+ tryDraggingAgain = NO;
+ }
+ else
+ [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
+ }
+ else
+ {
+ [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
+ }
+
+ // If a user selects a cell, they need to be able to drag it off right away, so check for that case here:
+ if( tryDraggingAgain && theEvent && [_selectedRows containsIndex: [theCell row]] )
+ [self attemptDragWithMouseDown: theEvent inCell: theCell];
+}
+
+
+- (void)handleMouseDownOutsideCells: (NSEvent*)theEvent
+{
+#pragma unused(theEvent)
+ [[self window] makeFirstResponder: self];
+
+ if( _allowsEmptySelection )
+ [self deselectRows];
+ else if( _numberOfRows > 1 )
+ {
+ NSUInteger idx = 0;
+ NSPoint pos = [self convertPoint: [theEvent locationInWindow] fromView: nil];
+ for( NSUInteger x = 0; x < _numberOfRows; x++ )
+ {
+ if( _cellYOffsets[x] > pos.y )
+ break;
+
+ idx = x;
+ }
+
+ [self setSelectedRow: idx];
+ }
+}
+
+#pragma mark -
+#pragma mark Drag and Drop
+
+- (BOOL)attemptDragWithMouseDown:(NSEvent*)theEvent inCell:(PXListViewCell*)theCell
+{
+ PXIsDragStartResult dragResult = PXIsDragStart( theEvent, 0.0 );
+ if( dragResult != PXIsDragStartMouseReleased /*&& (_verticalMotionCanBeginDrag || dragResult != PXIsDragStartMouseMovedVertically)*/ ) // Was a drag, not a click? Cool!
+ {
+ NSPoint dragImageOffset = NSZeroPoint;
+ NSImage *dragImage = [self dragImageForRowsWithIndexes: _selectedRows event: theEvent clickedCell: theCell offset: &dragImageOffset];
+ NSPasteboard *dragPasteboard = [NSPasteboard pasteboardWithUniqueName];
+
+ if( [_delegate respondsToSelector: @selector(listView:writeRowsWithIndexes:toPasteboard:)]
+ and [_delegate listView: self writeRowsWithIndexes: _selectedRows toPasteboard: dragPasteboard] )
+ {
+ [theCell dragImage: dragImage at: dragImageOffset offset: NSZeroSize event: theEvent
+ pasteboard: dragPasteboard source: self slideBack: YES];
+
+ return YES;
+ }
+ }
+
+ return NO;
+}
+
+-(NSImage*) dragImageForRowsWithIndexes: (NSIndexSet *)dragRows event: (NSEvent*)dragEvent clickedCell: (PXListViewCell*)clickedCell offset: (NSPointPointer)dragImageOffset
+{
+#pragma unused(dragEvent)
+ CGFloat minX = CGFLOAT_MAX, maxX = CGFLOAT_MIN,
+ minY = CGFLOAT_MAX, maxY = CGFLOAT_MIN;
+ NSPoint localMouse = [self convertPoint: NSZeroPoint fromView: clickedCell];
+
+ if ([clickedCell isFlipped]) {
+ localMouse = [self convertPoint:CGPointMake(0, NSHeight(clickedCell.frame) * 2) fromView:clickedCell];
+ }
+
+ localMouse.y += [self documentVisibleRect].origin.y;
+
+ // Determine how large an image we'll need to hold all cells, with their
+ // *unclipped* rectangles:
+ for( PXListViewCell* currCell in _visibleCells )
+ {
+ NSUInteger currRow = [currCell row];
+ if( [dragRows containsIndex: currRow] )
+ {
+ NSRect rowRect = [self rectOfRow: currRow];
+ if( rowRect.origin.x < minX )
+ minX = rowRect.origin.x;
+ if( rowRect.origin.y < minY )
+ minY = rowRect.origin.y;
+ if( NSMaxX(rowRect) > maxX )
+ maxX = NSMaxX(rowRect);
+ if( NSMaxY(rowRect) > maxY )
+ maxY = NSMaxY(rowRect);
+ }
+ }
+
+ // Now draw all cells into the image at the proper relative position:
+ NSSize imageSize = NSMakeSize( maxX -minX, maxY -minY);
+ NSImage* dragImage = [[[NSImage alloc] initWithSize: imageSize] autorelease];
+
+ [dragImage lockFocus];
+
+ for( PXListViewCell* currCell in _visibleCells )
+ {
+ NSUInteger currRow = [currCell row];
+ if( [dragRows containsIndex: currRow] )
+ {
+ NSRect rowRect = [self rectOfRow: currRow];
+ NSBitmapImageRep* bir = [currCell bitmapImageRepForCachingDisplayInRect: [currCell bounds]];
+ [currCell cacheDisplayInRect: [currCell bounds] toBitmapImageRep: bir];
+ NSPoint thePos = NSMakePoint( rowRect.origin.x -minX, rowRect.origin.y -minY);
+ thePos.y = imageSize.height -(thePos.y +rowRect.size.height); // Document view is flipped, so flip the coordinates before drawing into image, or the list items will be reversed.
+ [bir drawAtPoint: thePos];
+ }
+ }
+
+ [dragImage unlockFocus];
+
+ // Give caller the right offset so the image ends up right atop the actual views:
+ if( dragImageOffset )
+ {
+ dragImageOffset->x = -(localMouse.x -minX);
+ dragImageOffset->y = (localMouse.y -minY) -imageSize.height;
+ }
+
+ return dragImage;
+}
+
+
+-(void) setShowsDropHighlight: (BOOL)inState
+{
+ [[self documentView] setDropHighlight: (inState ? PXListViewDropOn : PXListViewDropNowhere)];
+}
+
+
+-(NSUInteger) indexOfRowAtPoint: (NSPoint)pos returningProposedDropHighlight: (PXListViewDropHighlight*)outDropHighlight
+{
+ PXLog( @"====================" );
+ *outDropHighlight = PXListViewDropOn;
+
+ if( _numberOfRows > 0 )
+ {
+ NSUInteger idx = 0;
+ for( NSUInteger x = 0; x < _numberOfRows; x++ )
+ {
+ if( _cellYOffsets[x] > pos.y )
+ {
+ PXLog( @"cellYOffset[%ld] = %f > %f", x, _cellYOffsets[x], pos.y );
+ break;
+ }
+
+ idx = x;
+ }
+
+ PXLog( @"idx = %ld", idx );
+
+ CGFloat cellHeight = 0,
+ cellOffset = 0,
+ nextCellOffset = 0;
+ if( (idx +1) < _numberOfRows )
+ {
+ cellOffset = _cellYOffsets[idx];
+ nextCellOffset = _cellYOffsets[idx+1];
+ cellHeight = nextCellOffset -cellOffset;
+ if( cellHeight < 0 )
+ PXLog( @"Urk. (1)" );
+ }
+ else if( idx < _numberOfRows && _numberOfRows > 0 ) // drag is somewhere close to or beyond end of list.
+ {
+ PXListViewCell* theCell = [self visibleCellForRow: idx];
+ cellHeight = [theCell frame].size.height;
+ cellOffset = [theCell frame].origin.y;
+ nextCellOffset = cellOffset +cellHeight;
+ if( cellHeight < 0 )
+ PXLog( @"Urk. (2)" );
+ }
+ else if( idx >= _numberOfRows && _numberOfRows > 0 ) // drag is somewhere close to or beyond end of list.
+ {
+ cellHeight = 0;
+ cellOffset = [[self documentView] frame].size.height;
+ nextCellOffset = cellOffset;
+ idx = NSUIntegerMax;
+ if( cellHeight < 0 )
+ PXLog( @"Urk. (3)" );
+ }
+
+ PXLog( @"cellHeight = %f", cellHeight );
+ if( pos.y < (cellOffset +(cellHeight / 6.0)) )
+ {
+ *outDropHighlight = PXListViewDropAbove;
+ PXLog( @"*** ABOVE %ld", idx );
+ }
+ else if( pos.y > (nextCellOffset -(cellHeight / 6.0)) )
+ {
+ idx++;
+ *outDropHighlight = PXListViewDropAbove;
+ PXLog( @"*** ABOVE %ld (below %d)", idx, idx -1 );
+ }
+ else
+ PXLog( @"*** ON %ld", idx );
+
+ if( idx > _numberOfRows )
+ idx = NSUIntegerMax;
+
+ return idx;
+ }
+ else
+ {
+ PXLog( @"*** ON %d", NSUIntegerMax );
+ return NSUIntegerMax;
+ }
+}
+
+
+-(PXListViewCell*) cellForDropHighlight: (PXListViewDropHighlight*)dhl row: (NSUInteger*)idx
+{
+ PXListViewCell* newCell = nil;
+ if( (*idx) >= _numberOfRows && _numberOfRows > 0 )
+ {
+ *dhl = PXListViewDropBelow;
+ *idx = _numberOfRows -1;
+ newCell = [self visibleCellForRow: _numberOfRows -1];
+ }
+ else
+ {
+ newCell = ((*idx) >= _numberOfRows) ? nil : [self visibleCellForRow: *idx];
+ }
+
+ return newCell;
+}
+
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ PXLog( @"draggingEntered" );
+
+ NSDragOperation theOperation = NSDragOperationNone;
+
+ NSUInteger oldDropRow = _dropRow;
+ PXListViewDropHighlight oldDropHighlight = _dropHighlight;
+
+ if( [_delegate respondsToSelector: @selector(listView:validateDrop:proposedRow:proposedDropHighlight:)] )
+ {
+ NSPoint dragMouse = [[self documentView] convertPoint: [sender draggingLocation] fromView: nil];
+ PXLog( @"dragMouse = %@", NSStringFromPoint(dragMouse) );
+ _dropRow = [self indexOfRowAtPoint: dragMouse returningProposedDropHighlight: &_dropHighlight];
+
+ theOperation = [_delegate listView: self validateDrop: sender proposedRow: _dropRow
+ proposedDropHighlight: _dropHighlight];
+ }
+
+ PXLog( @"op = %lu, row = %ld, hl = %lu", theOperation, _dropRow, _dropHighlight );
+
+ if( theOperation != NSDragOperationNone )
+ {
+ if( oldDropRow != _dropRow
+ || oldDropHighlight != _dropHighlight )
+ {
+ PXListViewCell* newCell = [self cellForDropHighlight: &_dropHighlight row: &_dropRow];
+ PXListViewCell* oldCell = [self cellForDropHighlight: &oldDropHighlight row: &oldDropRow];
+
+ [oldCell setDropHighlight: PXListViewDropNowhere];
+ [newCell setDropHighlight: _dropHighlight];
+ PXListViewDropHighlight dropHL = ((_dropRow == _numberOfRows) ? PXListViewDropAbove : PXListViewDropOn);
+ PXLog( @"TOTAL DROP %s", dropHL == PXListViewDropOn ? "on" : "above" );
+ [[self documentView] setDropHighlight: dropHL];
+ }
+ else
+ PXLog(@"TOTAL DROP unchanged");
+ }
+ else
+ PXLog( @"TOTAL DROP NOWHERE" );
+
+ return theOperation;
+}
+
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender /* if the destination responded to draggingEntered: but not to draggingUpdated: the return value from draggingEntered: is used */
+{
+ PXLog( @"draggingUpdated" );
+
+ NSDragOperation theOperation = NSDragOperationNone;
+
+ NSUInteger oldDropRow = _dropRow;
+ PXListViewDropHighlight oldDropHighlight = _dropHighlight;
+
+ if( [_delegate respondsToSelector: @selector(listView:validateDrop:proposedRow:proposedDropHighlight:)] )
+ {
+ NSPoint dragMouse = [[self documentView] convertPoint: [sender draggingLocation] fromView: nil];
+ PXLog( @"dragMouse = %@", NSStringFromPoint(dragMouse) );
+ _dropRow = [self indexOfRowAtPoint: dragMouse returningProposedDropHighlight: &_dropHighlight];
+
+ theOperation = [_delegate listView: self validateDrop: sender proposedRow: _dropRow
+ proposedDropHighlight: _dropHighlight];
+ }
+
+ NSLog( @"op = %lu, row = %ld, hl = %lu", theOperation, _dropRow, _dropHighlight );
+
+ if( theOperation != NSDragOperationNone )
+ {
+ if( oldDropRow != _dropRow
+ || oldDropHighlight != _dropHighlight )
+ {
+ PXListViewCell* newCell = [self cellForDropHighlight: &_dropHighlight row: &_dropRow];
+ PXListViewCell* oldCell = [self cellForDropHighlight: &oldDropHighlight row: &oldDropRow];
+
+ [oldCell setDropHighlight: PXListViewDropNowhere];
+ [newCell setDropHighlight: _dropHighlight];
+ PXListViewDropHighlight dropHL = ((_dropRow == _numberOfRows) ? PXListViewDropAbove : PXListViewDropOn);
+ NSLog( @"TOTAL DROP %s", dropHL == PXListViewDropOn ? "on" : "above" );
+ [[self documentView] setDropHighlight: dropHL];
+ }
+ else
+ PXLog(@"TOTAL DROP unchanged");
+ }
+ else
+ {
+ PXLog( @"TOTAL DROP NOWHERE" );
+ [self setShowsDropHighlight: NO];
+ }
+
+ return theOperation;
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender
+{
+#pragma unused(sender)
+ PXListViewCell* oldCell = _dropRow == NSUIntegerMax ? nil : [self visibleCellForRow: _dropRow];
+ [oldCell setDropHighlight: PXListViewDropNowhere];
+
+ [self setShowsDropHighlight: NO];
+
+ _dropRow = 0;
+ _dropHighlight = PXListViewDropNowhere;
+}
+
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ if( ![[self delegate] respondsToSelector: @selector(listView:acceptDrop:row:dropHighlight:)] )
+ return NO;
+
+ BOOL accepted = [[self delegate] listView: self acceptDrop: sender row: _dropRow dropHighlight: _dropHighlight];
+
+ _dropRow = 0;
+ _dropHighlight = PXListViewDropNowhere;
+
+ return accepted;
+}
+
+
+- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
+{
+#pragma unused(sender)
+}
+
+
+- (void)draggingEnded:(id <NSDraggingInfo>)sender
+{
+#pragma unused(sender)
+ PXListViewCell* oldCell = _dropRow == NSUIntegerMax ? nil : [self visibleCellForRow: _dropRow];
+ [oldCell setDropHighlight: PXListViewDropNowhere];
+
+ [self setShowsDropHighlight: NO];
+}
+
+
+- (BOOL)wantsPeriodicDraggingUpdates
+{
+ return YES;
+}
-@implementation PXListView (PXListView_UserInteraction)
+-(void)setDropRow:(NSUInteger)row dropHighlight: (PXListViewDropHighlight)dropHighlight
+{
+ _dropRow = row;
+ _dropHighlight = dropHighlight;
+
+ [self setNeedsDisplay: YES];
+}
@end
View
6 Classes/PXListView.h
@@ -72,10 +72,4 @@
- (void)scrollToRow:(NSUInteger)row;
- (void)scrollRowToVisible:(NSUInteger)row;
-- (NSImage*)dragImageForRowsWithIndexes:(NSIndexSet *)dragRows
- event:(NSEvent*)dragEvent clickedCell:(PXListViewCell*)clickedCell
- offset:(NSPointPointer)dragImageOffset;
-- (void)setShowsDropHighlight:(BOOL)inState;
-- (void)setDropRow:(NSUInteger)row dropHighlight:(PXListViewDropHighlight)dropHighlight;
-
@end
View
574 Classes/PXListView.m
@@ -9,76 +9,13 @@
#import "PXListView.h"
#import "PXListView+Private.h"
-#import <iso646.h>
-
#import "PXListViewCell.h"
#import "PXListViewCell+Private.h"
+#import "PXListView+UserInteraction.h"
NSString * const PXListViewSelectionDidChange = @"PXListViewSelectionDidChange";
-// Apple sadly doesn't provide CGFloat variants of these:
-#if CGFLOAT_IS_DOUBLE
-#define CGFLOATABS(n) fabs(n)
-#else
-#define CGFLOATABS(n) fabsf(n)
-#endif
-
-// This is a renamed copy of UKIsDragStart from <http://github.com/uliwitness/UliKit>:
-static PXIsDragStartResult PXIsDragStart( NSEvent *startEvent, NSTimeInterval theTimeout )
-{
- if( theTimeout == 0.0 )
- theTimeout = 1.5;
-
- NSPoint startPos = [startEvent locationInWindow];
- NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
- NSDate* expireTime = [NSDate dateWithTimeIntervalSinceReferenceDate: startTime +theTimeout];
-
- NSAutoreleasePool *pool = nil;
- while( ([expireTime timeIntervalSinceReferenceDate] -[NSDate timeIntervalSinceReferenceDate]) > 0 )
- {
- [pool release];
- pool = [[NSAutoreleasePool alloc] init];
-
- NSEvent* currEvent = [NSApp nextEventMatchingMask: NSLeftMouseUpMask | NSRightMouseUpMask | NSOtherMouseUpMask
- | NSLeftMouseDraggedMask | NSRightMouseDraggedMask | NSOtherMouseDraggedMask
- untilDate: expireTime inMode: NSEventTrackingRunLoopMode dequeue: YES];
- if( currEvent )
- {
- switch( [currEvent type] )
- {
- case NSLeftMouseUp:
- case NSRightMouseUp:
- case NSOtherMouseUp:
- {
- [pool release];
- return PXIsDragStartMouseReleased; // Mouse released within the wait time.
- break;
- }
-
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
- {
- NSPoint newPos = [currEvent locationInWindow];
- CGFloat xMouseMovement = CGFLOATABS(newPos.x -startPos.x);
- CGFloat yMouseMovement = CGFLOATABS(newPos.y -startPos.y);
- if( xMouseMovement > 2 or yMouseMovement > 2 )
- {
- [pool release];
- return (xMouseMovement > yMouseMovement) ? PXIsDragStartMouseMovedHorizontally : PXIsDragStartMouseMovedVertically; // Mouse moved within the wait time, probably a drag!
- }
- break;
- }
- }
- }
-
- }
-
- [pool release];
- return PXIsDragStartTimedOut; // If they held the mouse that long, they probably wanna drag.
-}
-
@implementation PXListView
@synthesize cellSpacing = _cellSpacing;
@@ -473,182 +410,6 @@ - (void)updateCells
_currentRange = visibleRange;
}
-
-- (BOOL)attemptDragWithMouseDown:(NSEvent*)theEvent inCell:(PXListViewCell*)theCell
-{
- PXIsDragStartResult dragResult = PXIsDragStart( theEvent, 0.0 );
- if( dragResult != PXIsDragStartMouseReleased /*&& (_verticalMotionCanBeginDrag || dragResult != PXIsDragStartMouseMovedVertically)*/ ) // Was a drag, not a click? Cool!
- {
- NSPoint dragImageOffset = NSZeroPoint;
- NSImage *dragImage = [self dragImageForRowsWithIndexes: _selectedRows event: theEvent clickedCell: theCell offset: &dragImageOffset];
- NSPasteboard *dragPasteboard = [NSPasteboard pasteboardWithUniqueName];
-
- if( [_delegate respondsToSelector: @selector(listView:writeRowsWithIndexes:toPasteboard:)]
- and [_delegate listView: self writeRowsWithIndexes: _selectedRows toPasteboard: dragPasteboard] )
- {
- [theCell dragImage: dragImage at: dragImageOffset offset: NSZeroSize event: theEvent
- pasteboard: dragPasteboard source: self slideBack: YES];
-
- return YES;
- }
- }
-
- return NO;
-}
-
-- (void)handleMouseDown:(NSEvent*)theEvent inCell:(PXListViewCell*)theCell // Central funnel for cell clicks so cells don't have to know about multi-selection, modifiers etc.
-{
- // theEvent is NIL if we get a "press" action from accessibility. In that case, try to toggle, so users can selectively turn on/off an item.
- [[self window] makeFirstResponder: self];
-
- BOOL tryDraggingAgain = YES;
- BOOL shouldToggle = theEvent == nil || ([theEvent modifierFlags] & NSCommandKeyMask) or ([theEvent modifierFlags] & NSShiftKeyMask); // +++ Shift should really be a continuous selection.
- BOOL isSelected = [_selectedRows containsIndex: [theCell row]];
- NSIndexSet *clickedIndexSet = [NSIndexSet indexSetWithIndex: [theCell row]];
-
- // If a cell is already selected, we can drag it out, in which case we shouldn't toggle it:
- if( theEvent and isSelected and [self attemptDragWithMouseDown: theEvent inCell: theCell] )
- return;
-
- if( _allowsMultipleSelection )
- {
- if( isSelected && shouldToggle )
- {
- if( [_selectedRows count] == 1 && !_allowsEmptySelection )
- return;
- [self deselectRowIndexes: clickedIndexSet];
- }
- else if( !isSelected && shouldToggle )
- [self selectRowIndexes: clickedIndexSet byExtendingSelection: YES];
- else if( !isSelected && !shouldToggle )
- [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
- else if( isSelected && !shouldToggle && [_selectedRows count] != 1 )
- {
- [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
- tryDraggingAgain = NO;
- }
- }
- else if( shouldToggle && _allowsEmptySelection )
- {
- if( isSelected )
- {
- [self deselectRowIndexes: clickedIndexSet];
- tryDraggingAgain = NO;
- }
- else
- [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
- }
- else
- {
- [self selectRowIndexes: clickedIndexSet byExtendingSelection: NO];
- }
-
- // If a user selects a cell, they need to be able to drag it off right away, so check for that case here:
- if( tryDraggingAgain && theEvent and [_selectedRows containsIndex: [theCell row]] )
- [self attemptDragWithMouseDown: theEvent inCell: theCell];
-}
-
-
-- (void)handleMouseDownOutsideCells: (NSEvent*)theEvent
-{
-#pragma unused(theEvent)
- [[self window] makeFirstResponder: self];
-
- if( _allowsEmptySelection )
- [self deselectRows];
- else if( _numberOfRows > 1 )
- {
- NSUInteger idx = 0;
- NSPoint pos = [self convertPoint: [theEvent locationInWindow] fromView: nil];
- for( NSUInteger x = 0; x < _numberOfRows; x++ )
- {
- if( _cellYOffsets[x] > pos.y )
- break;
-
- idx = x;
- }
-
- [self setSelectedRow: idx];
- }
-}
-
-#pragma mark -
-#pragma mark NSResponder
-
-- (BOOL)canBecomeKeyView
-{
- return YES;
-}
-
-
-- (BOOL)acceptsFirstResponder
-{
- return YES;
-}
-
-- (BOOL)becomeFirstResponder
-{
- return YES;
-}
-
-
-- (BOOL)resignFirstResponder
-{
- return YES;
-}
-
-#pragma mark -
-#pragma mark Keyboard Handling
-
-- (void)keyDown:(NSEvent *)theEvent
-{
- [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
-}
-
-
-- (void)moveUp:(id)sender
-{
- if([_selectedRows count]>0) {
- NSUInteger firstIndex = [_selectedRows firstIndex];
-
- if(firstIndex>0) {
- NSUInteger newRow = firstIndex-1;
- [self setSelectedRow:newRow];
- [self scrollRowToVisible:newRow];
- }
- }
-}
-
-
-- (void)moveDown:(id)sender
-{
- if([_selectedRows count]>0) {
- NSUInteger lastIndex = [_selectedRows lastIndex];
-
- if(lastIndex<(_numberOfRows-1)) {
- NSUInteger newRow = lastIndex+1;
- [self setSelectedRow:newRow];
- [self scrollRowToVisible:newRow];
- }
- }
-}
-
-
-- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
-{
- if([menuItem action] == @selector(selectAll:))
- {
- return _allowsMultipleSelection && [_selectedRows count] != _numberOfRows; // No "select all" if everything's already selected or we can only select one row.
- }
-
- if([menuItem action] == @selector(deselectAll:))
- {
- return _allowsEmptySelection && [_selectedRows count] != 0; // No "deselect all" if nothing's selected or we must have at least one row selected.
- }
-
- return NO;
-}
-
#pragma mark -
#pragma mark Selection
@@ -854,327 +615,6 @@ - (void)viewDidEndLiveResize
}
}
-
-#pragma mark -
-#pragma mark Drag and Drop
-
--(NSImage*) dragImageForRowsWithIndexes: (NSIndexSet *)dragRows event: (NSEvent*)dragEvent clickedCell: (PXListViewCell*)clickedCell offset: (NSPointPointer)dragImageOffset
-{
-#pragma unused(dragEvent)
- CGFloat minX = CGFLOAT_MAX, maxX = CGFLOAT_MIN,
- minY = CGFLOAT_MAX, maxY = CGFLOAT_MIN;
- NSPoint localMouse = [self convertPoint: NSZeroPoint fromView: clickedCell];
-
- if ([clickedCell isFlipped]) {
- localMouse = [self convertPoint:CGPointMake(0, NSHeight(clickedCell.frame) * 2) fromView:clickedCell];
- }
-
- localMouse.y += [self documentVisibleRect].origin.y;
-
- // Determine how large an image we'll need to hold all cells, with their
- // *unclipped* rectangles:
- for( PXListViewCell* currCell in _visibleCells )
- {
- NSUInteger currRow = [currCell row];
- if( [dragRows containsIndex: currRow] )
- {
- NSRect rowRect = [self rectOfRow: currRow];
- if( rowRect.origin.x < minX )
- minX = rowRect.origin.x;
- if( rowRect.origin.y < minY )
- minY = rowRect.origin.y;
- if( NSMaxX(rowRect) > maxX )
- maxX = NSMaxX(rowRect);
- if( NSMaxY(rowRect) > maxY )
- maxY = NSMaxY(rowRect);
- }
- }
-
- // Now draw all cells into the image at the proper relative position:
- NSSize imageSize = NSMakeSize( maxX -minX, maxY -minY);
- NSImage* dragImage = [[[NSImage alloc] initWithSize: imageSize] autorelease];
-
- [dragImage lockFocus];
-
- for( PXListViewCell* currCell in _visibleCells )
- {
- NSUInteger currRow = [currCell row];
- if( [dragRows containsIndex: currRow] )
- {
- NSRect rowRect = [self rectOfRow: currRow];
- NSBitmapImageRep* bir = [currCell bitmapImageRepForCachingDisplayInRect: [currCell bounds]];
- [currCell cacheDisplayInRect: [currCell bounds] toBitmapImageRep: bir];
- NSPoint thePos = NSMakePoint( rowRect.origin.x -minX, rowRect.origin.y -minY);
- thePos.y = imageSize.height -(thePos.y +rowRect.size.height); // Document view is flipped, so flip the coordinates before drawing into image, or the list items will be reversed.
- [bir drawAtPoint: thePos];
- }
- }
-
- [dragImage unlockFocus];
-
- // Give caller the right offset so the image ends up right atop the actual views:
- if( dragImageOffset )
- {
- dragImageOffset->x = -(localMouse.x -minX);
- dragImageOffset->y = (localMouse.y -minY) -imageSize.height;
- }
-
- return dragImage;
-}
-
-
--(void) setShowsDropHighlight: (BOOL)inState
-{
- [[self documentView] setDropHighlight: (inState ? PXListViewDropOn : PXListViewDropNowhere)];
-}
-
-
--(NSUInteger) indexOfRowAtPoint: (NSPoint)pos returningProposedDropHighlight: (PXListViewDropHighlight*)outDropHighlight
-{
- PXLog( @"====================" );
- *outDropHighlight = PXListViewDropOn;
-
- if( _numberOfRows > 0 )
- {
- NSUInteger idx = 0;
- for( NSUInteger x = 0; x < _numberOfRows; x++ )
- {
- if( _cellYOffsets[x] > pos.y )
- {
- PXLog( @"cellYOffset[%ld] = %f > %f", x, _cellYOffsets[x], pos.y );
- break;
- }
-
- idx = x;
- }
-
- PXLog( @"idx = %ld", idx );
-
- CGFloat cellHeight = 0,
- cellOffset = 0,
- nextCellOffset = 0;
- if( (idx +1) < _numberOfRows )
- {
- cellOffset = _cellYOffsets[idx];
- nextCellOffset = _cellYOffsets[idx+1];
- cellHeight = nextCellOffset -cellOffset;
- if( cellHeight < 0 )
- PXLog( @"Urk. (1)" );
- }
- else if( idx < _numberOfRows && _numberOfRows > 0 ) // drag is somewhere close to or beyond end of list.
- {
- PXListViewCell* theCell = [self visibleCellForRow: idx];
- cellHeight = [theCell frame].size.height;
- cellOffset = [theCell frame].origin.y;
- nextCellOffset = cellOffset +cellHeight;
- if( cellHeight < 0 )
- PXLog( @"Urk. (2)" );
- }
- else if( idx >= _numberOfRows && _numberOfRows > 0 ) // drag is somewhere close to or beyond end of list.
- {
- cellHeight = 0;
- cellOffset = [[self documentView] frame].size.height;
- nextCellOffset = cellOffset;
- idx = NSUIntegerMax;
- if( cellHeight < 0 )
- PXLog( @"Urk. (3)" );
- }
-
- PXLog( @"cellHeight = %f", cellHeight );
- if( pos.y < (cellOffset +(cellHeight / 6.0)) )
- {
- *outDropHighlight = PXListViewDropAbove;
- PXLog( @"*** ABOVE %ld", idx );
- }
- else if( pos.y > (nextCellOffset -(cellHeight / 6.0)) )
- {
- idx++;
- *outDropHighlight = PXListViewDropAbove;
- PXLog( @"*** ABOVE %ld (below %d)", idx, idx -1 );
- }
- else
- PXLog( @"*** ON %ld", idx );
-
- if( idx > _numberOfRows )
- idx = NSUIntegerMax;
-
- return idx;
- }
- else
- {
- PXLog( @"*** ON %d", NSUIntegerMax );
- return NSUIntegerMax;
- }
-}
-
-
--(PXListViewCell*) cellForDropHighlight: (PXListViewDropHighlight*)dhl row: (NSUInteger*)idx
-{
- PXListViewCell* newCell = nil;
- if( (*idx) >= _numberOfRows && _numberOfRows > 0 )
- {
- *dhl = PXListViewDropBelow;
- *idx = _numberOfRows -1;
- newCell = [self visibleCellForRow: _numberOfRows -1];
- }
- else
- {
- newCell = ((*idx) >= _numberOfRows) ? nil : [self visibleCellForRow: *idx];
- }
-
- return newCell;
-}
-
-
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
-{
- PXLog( @"draggingEntered" );
-
- NSDragOperation theOperation = NSDragOperationNone;
-
- NSUInteger oldDropRow = _dropRow;
- PXListViewDropHighlight oldDropHighlight = _dropHighlight;
-
- if( [_delegate respondsToSelector: @selector(listView:validateDrop:proposedRow:proposedDropHighlight:)] )
- {
- NSPoint dragMouse = [[self documentView] convertPoint: [sender draggingLocation] fromView: nil];
- PXLog( @"dragMouse = %@", NSStringFromPoint(dragMouse) );
- _dropRow = [self indexOfRowAtPoint: dragMouse returningProposedDropHighlight: &_dropHighlight];
-
- theOperation = [_delegate listView: self validateDrop: sender proposedRow: _dropRow
- proposedDropHighlight: _dropHighlight];
- }
-
- PXLog( @"op = %lu, row = %ld, hl = %lu", theOperation, _dropRow, _dropHighlight );
-
- if( theOperation != NSDragOperationNone )
- {
- if( oldDropRow != _dropRow
- || oldDropHighlight != _dropHighlight )
- {
- PXListViewCell* newCell = [self cellForDropHighlight: &_dropHighlight row: &_dropRow];
- PXListViewCell* oldCell = [self cellForDropHighlight: &oldDropHighlight row: &oldDropRow];
-
- [oldCell setDropHighlight: PXListViewDropNowhere];
- [newCell setDropHighlight: _dropHighlight];
- PXListViewDropHighlight dropHL = ((_dropRow == _numberOfRows) ? PXListViewDropAbove : PXListViewDropOn);
- PXLog( @"TOTAL DROP %s", dropHL == PXListViewDropOn ? "on" : "above" );
- [[self documentView] setDropHighlight: dropHL];
- }
- else
- PXLog(@"TOTAL DROP unchanged");
- }
- else
- PXLog( @"TOTAL DROP NOWHERE" );
-
- return theOperation;
-}
-
-
-- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender /* if the destination responded to draggingEntered: but not to draggingUpdated: the return value from draggingEntered: is used */
-{
- PXLog( @"draggingUpdated" );
-
- NSDragOperation theOperation = NSDragOperationNone;
-
- NSUInteger oldDropRow = _dropRow;
- PXListViewDropHighlight oldDropHighlight = _dropHighlight;
-
- if( [_delegate respondsToSelector: @selector(listView:validateDrop:proposedRow:proposedDropHighlight:)] )
- {
- NSPoint dragMouse = [[self documentView] convertPoint: [sender draggingLocation] fromView: nil];
- PXLog( @"dragMouse = %@", NSStringFromPoint(dragMouse) );
- _dropRow = [self indexOfRowAtPoint: dragMouse returningProposedDropHighlight: &_dropHighlight];
-
- theOperation = [_delegate listView: self validateDrop: sender proposedRow: _dropRow
- proposedDropHighlight: _dropHighlight];
- }
-
- NSLog( @"op = %lu, row = %ld, hl = %lu", theOperation, _dropRow, _dropHighlight );
-
- if( theOperation != NSDragOperationNone )
- {
- if( oldDropRow != _dropRow
- || oldDropHighlight != _dropHighlight )
- {
- PXListViewCell* newCell = [self cellForDropHighlight: &_dropHighlight row: &_dropRow];
- PXListViewCell* oldCell = [self cellForDropHighlight: &oldDropHighlight row: &oldDropRow];
-
- [oldCell setDropHighlight: PXListViewDropNowhere];
- [newCell setDropHighlight: _dropHighlight];
- PXListViewDropHighlight dropHL = ((_dropRow == _numberOfRows) ? PXListViewDropAbove : PXListViewDropOn);
- NSLog( @"TOTAL DROP %s", dropHL == PXListViewDropOn ? "on" : "above" );
- [[self documentView] setDropHighlight: dropHL];
- }
- else
- PXLog(@"TOTAL DROP unchanged");
- }
- else
- {
- PXLog( @"TOTAL DROP NOWHERE" );
- [self setShowsDropHighlight: NO];
- }
-
- return theOperation;
-}
-
-- (void)draggingExited:(id <NSDraggingInfo>)sender
-{
-#pragma unused(sender)
- PXListViewCell* oldCell = _dropRow == NSUIntegerMax ? nil : [self visibleCellForRow: _dropRow];
- [oldCell setDropHighlight: PXListViewDropNowhere];
-
- [self setShowsDropHighlight: NO];
-
- _dropRow = 0;
- _dropHighlight = PXListViewDropNowhere;
-}
-
-
-- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
-{
- if( ![[self delegate] respondsToSelector: @selector(listView:acceptDrop:row:dropHighlight:)] )
- return NO;
-
- BOOL accepted = [[self delegate] listView: self acceptDrop: sender row: _dropRow dropHighlight: _dropHighlight];
-
- _dropRow = 0;
- _dropHighlight = PXListViewDropNowhere;
-
- return accepted;
-}
-
-
-- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
-{
-#pragma unused(sender)
-}
-
-
-- (void)draggingEnded:(id <NSDraggingInfo>)sender
-{
-#pragma unused(sender)
- PXListViewCell* oldCell = _dropRow == NSUIntegerMax ? nil : [self visibleCellForRow: _dropRow];
- [oldCell setDropHighlight: PXListViewDropNowhere];
-
- [self setShowsDropHighlight: NO];
-}
-
-
-- (BOOL)wantsPeriodicDraggingUpdates
-{
- return YES;
-}
-
-
--(void)setDropRow:(NSUInteger)row dropHighlight: (PXListViewDropHighlight)dropHighlight
-{
- _dropRow = row;
- _dropHighlight = dropHighlight;
-
- [self setNeedsDisplay: YES];
-}
-
#pragma mark -
#pragma mark Accessibility
@@ -1194,12 +634,12 @@ -(NSArray*) accessibilityAttributeNames
- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute
{
if( [attribute isEqualToString: NSAccessibilityRoleAttribute]
- or [attribute isEqualToString: NSAccessibilityVisibleChildrenAttribute]
- or [attribute isEqualToString: NSAccessibilitySelectedChildrenAttribute]
- or [attribute isEqualToString: NSAccessibilityContentsAttribute]
- or [attribute isEqualToString: NSAccessibilityOrientationAttribute]
- or [attribute isEqualToString: NSAccessibilityChildrenAttribute]
- or [attribute isEqualToString: NSAccessibilityEnabledAttribute] )
+ || [attribute isEqualToString: NSAccessibilityVisibleChildrenAttribute]
+ || [attribute isEqualToString: NSAccessibilitySelectedChildrenAttribute]
+ || [attribute isEqualToString: NSAccessibilityContentsAttribute]
+ || [attribute isEqualToString: NSAccessibilityOrientationAttribute]
+ || [attribute isEqualToString: NSAccessibilityChildrenAttribute]
+ || [attribute isEqualToString: NSAccessibilityEnabledAttribute] )
{
return NO;
}
View
4 Classes/PXListViewCell.h
@@ -21,9 +21,11 @@
PXListViewDropHighlight _dropHighlight;
}
-@property (readonly) NSString *reusableIdentifier;
@property (nonatomic, assign) PXListView *listView;
+
+@property (readonly, copy) NSString *reusableIdentifier;
@property (readonly) NSUInteger row;
+
@property (readonly,getter=isSelected) BOOL selected;
@property (assign) PXListViewDropHighlight dropHighlight;
View
16 Classes/PXListViewCell.m
@@ -13,6 +13,7 @@
#import "PXListView.h"
#import "PXListView+Private.h"
+#import "PXListView+UserInteraction.h"
#pragma mark -
@@ -63,7 +64,7 @@ - (id)initWithReusableIdentifier:(NSString*)identifier
}
-- (id)initWithCoder: (NSCoder *)aDecoder
+- (id)initWithCoder:(NSCoder *)aDecoder
{
if((self = [super initWithCoder: aDecoder]))
{
@@ -96,19 +97,18 @@ - (BOOL)isSelected
#pragma mark -
#pragma mark Drag & Drop
--(void) setDropHighlight: (PXListViewDropHighlight)inState
+- (void)setDropHighlight:(PXListViewDropHighlight)inState
{
[[self listView] setShowsDropHighlight: inState != PXListViewDropNowhere];
_dropHighlight = inState;
- [self setNeedsDisplay: YES];
+ [self setNeedsDisplay:YES];
}
--(void) drawRect:(NSRect)dirtyRect
+- (void)drawRect:(NSRect)dirtyRect
{
-#pragma unused(dirtyRect)
- if( _dropHighlight == PXListViewDropAbove )
+ if(_dropHighlight == PXListViewDropAbove)
{
[[NSColor alternateSelectedControlColor] set];
NSRect theBox = [self bounds];
@@ -117,7 +117,7 @@ -(void) drawRect:(NSRect)dirtyRect
[NSBezierPath setDefaultLineWidth: 2.0f];
[NSBezierPath strokeRect: theBox];
}
- else if( _dropHighlight == PXListViewDropBelow )
+ else if(_dropHighlight == PXListViewDropBelow)
{
[[NSColor alternateSelectedControlColor] set];
NSRect theBox = [self bounds];
@@ -126,7 +126,7 @@ -(void) drawRect:(NSRect)dirtyRect
[NSBezierPath setDefaultLineWidth: 2.0f];
[NSBezierPath strokeRect: theBox];
}
- else if( _dropHighlight == PXListViewDropOn )
+ else if(_dropHighlight == PXListViewDropOn)
{
[[NSColor alternateSelectedControlColor] set];
NSRect theBox = [self bounds];
View
14 PXListView.xcodeproj/project.pbxproj
@@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+ D25DDA7F133F58A20086783B /* PXListView+UserInteraction.m in Sources */ = {isa = PBXBuildFile; fileRef = D25DDA7E133F58A10086783B /* PXListView+UserInteraction.m */; };
D26669CB11B1B2F1007597F1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D26669CA11B1B2F1007597F1 /* AppDelegate.m */; };
D26669D211B1B302007597F1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D26669CE11B1B302007597F1 /* InfoPlist.strings */; };
D26669D311B1B302007597F1 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D26669D011B1B302007597F1 /* MainMenu.xib */; };
@@ -29,6 +30,8 @@
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
55B9AC9E11EA384C00416532 /* PXListViewDropHighlight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PXListViewDropHighlight.h; path = Classes/PXListViewDropHighlight.h; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* PXListView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PXListView.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ D25DDA7D133F58A10086783B /* PXListView+UserInteraction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "PXListView+UserInteraction.h"; path = "Classes/PXListView+UserInteraction.h"; sourceTree = "<group>"; };
+ D25DDA7E133F58A10086783B /* PXListView+UserInteraction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "PXListView+UserInteraction.m"; path = "Classes/PXListView+UserInteraction.m"; sourceTree = "<group>"; };
D26669C911B1B2F1007597F1 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Classes/AppDelegate.h; sourceTree = "<group>"; };
D26669CA11B1B2F1007597F1 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Classes/AppDelegate.m; sourceTree = "<group>"; };
D26669CC11B1B2F8007597F1 /* PXListView-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "PXListView-Info.plist"; path = "Resources/PXListView-Info.plist"; sourceTree = "<group>"; };
@@ -126,11 +129,9 @@
D27858D111B1B5EA00F1CF30 /* PXListView.m */,
D279A64311B4E95600771B2A /* PXListView+Private.h */,
D27858D711B1B6D400F1CF30 /* PXListViewDelegate.h */,
+ D25DDA7D133F58A10086783B /* PXListView+UserInteraction.h */,
+ D25DDA7E133F58A10086783B /* PXListView+UserInteraction.m */,
D279A68911B4ECAB00771B2A /* Cells */,
- 55B9AC9E11EA384C00416532 /* PXListViewDropHighlight.h */,
- D27858D311B1B5FC00F1CF30 /* PXListViewCell.h */,
- D27858D411B1B5FC00F1CF30 /* PXListViewCell.m */,
- D279A6DD11B4EFCD00771B2A /* PXListViewCell+Private.h */,
D278592911B1BA7900F1CF30 /* Misc */,
);
name = PXListView;
@@ -170,6 +171,10 @@
D279A68911B4ECAB00771B2A /* Cells */ = {
isa = PBXGroup;
children = (
+ 55B9AC9E11EA384C00416532 /* PXListViewDropHighlight.h */,
+ D27858D311B1B5FC00F1CF30 /* PXListViewCell.h */,
+ D27858D411B1B5FC00F1CF30 /* PXListViewCell.m */,
+ D279A6DD11B4EFCD00771B2A /* PXListViewCell+Private.h */,
);
name = Cells;
sourceTree = "<group>";
@@ -241,6 +246,7 @@
D27858D511B1B5FC00F1CF30 /* PXListViewCell.m in Sources */,
D278592411B1BA6C00F1CF30 /* PXListDocumentView.m in Sources */,
D278597011B1BBE800F1CF30 /* MyListViewCell.m in Sources */,
+ D25DDA7F133F58A20086783B /* PXListView+UserInteraction.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

0 comments on commit f89a40f

Please sign in to comment.
Something went wrong with that request. Please try again.