Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e0071d0aed | |||
| bc5727fba6 | |||
| b902e04b9c | |||
| 8f7081f4d5 | |||
| 2bf9e6a6f1 | |||
| ab0408c8fe | |||
| 929b1651af | |||
| 2eb6414e6b | |||
| 2550dce3b7 | |||
| c62b8b2c92 | |||
| 67772622cf | |||
| a555035042 | |||
| 0129de341e | |||
| 7a82f63e9b | |||
| b215e263ef | |||
| 5ce29c98c9 | |||
| 7df260c6f7 | |||
| 8407bc98bb |
@@ -116,7 +116,10 @@ static NSString * const draggingType = @"SourceListExampleDraggingType";
|
||||
NSImage *albumImage = [NSImage imageNamed:@"album"];
|
||||
[albumImage setTemplate:YES];
|
||||
|
||||
PXSourceListItem *newItem = [PXSourceListItem itemWithTitle:@"New Album" identifier:nil icon:albumImage];
|
||||
PhotoCollection *collection = [PhotoCollection collectionWithTitle:@"New Album" identifier:nil type:PhotoCollectionTypeUserCreated];
|
||||
[self.modelObjects addObject:collection];
|
||||
|
||||
PXSourceListItem *newItem = [PXSourceListItem itemWithRepresentedObject:collection icon:albumImage];
|
||||
[self.albumsItem addChildItem:newItem];
|
||||
|
||||
NSUInteger childIndex = [[self.albumsItem children] indexOfObject:newItem];
|
||||
@@ -132,11 +135,12 @@ static NSString * const draggingType = @"SourceListExampleDraggingType";
|
||||
PXSourceListItem *selectedItem = [self.sourceList itemAtRow:self.sourceList.selectedRow];
|
||||
PXSourceListItem *parentItem = self.albumsItem;
|
||||
|
||||
|
||||
[self.sourceList removeItemsAtIndexes:[NSIndexSet indexSetWithIndex:[parentItem.children indexOfObject:selectedItem]]
|
||||
inParent:parentItem
|
||||
withAnimation:NSTableViewAnimationSlideUp];
|
||||
|
||||
[self.modelObjects removeObject:selectedItem.representedObject];
|
||||
|
||||
// Only 'album' items can be deleted.
|
||||
[parentItem removeChildItem:selectedItem];
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.2</string>
|
||||
<string>2.0.7</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.0.2</string>
|
||||
<string>2.0.7</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2009-14 Alex Rozanski and other contributors. All rights reserved.</string>
|
||||
<string>Copyright © 2009-15 Alex Rozanski and other contributors. All rights reserved.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'PXSourceList'
|
||||
s.version = '2.0.2'
|
||||
s.version = '2.0.7'
|
||||
s.author = { 'Alex Rozanski' => 'alex@rozanski.me' }
|
||||
s.license = 'BSD'
|
||||
s.homepage = 'https://github.com/Perspx/PXSourceList'
|
||||
@@ -23,6 +23,6 @@ Pod::Spec.new do |s|
|
||||
s.osx.deployment_target = '10.7'
|
||||
|
||||
s.public_header_files = 'PXSourceList/*.h'
|
||||
s.source = { :git => 'https://github.com/Perspx/PXSourceList.git', :tag => '2.0.2' }
|
||||
s.source = { :git => 'https://github.com/Perspx/PXSourceList.git', :tag => '2.0.7' }
|
||||
s.source_files = 'PXSourceList/**/*.{h,m}'
|
||||
end
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
@interface PXSourceListDelegateDataSourceProxy : NSProxy <NSOutlineViewDelegate, NSOutlineViewDataSource, PXSourceListDelegate, PXSourceListDataSource>
|
||||
|
||||
@property (weak, nonatomic) PXSourceList *sourceList;
|
||||
@property (weak, nonatomic) id <PXSourceListDelegate> delegate;
|
||||
@property (weak, nonatomic) id <PXSourceListDataSource> dataSource;
|
||||
@property (unsafe_unretained, nonatomic) id <PXSourceListDelegate> delegate;
|
||||
@property (unsafe_unretained, nonatomic) id <PXSourceListDataSource> dataSource;
|
||||
|
||||
- (id)initWithSourceList:(PXSourceList *)sourceList;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ static NSArray * __fastPathForwardingDataSourceMethods = nil;
|
||||
{
|
||||
__outlineViewDelegateMethods = px_methodNamesForProtocol(@protocol(NSOutlineViewDelegate));
|
||||
__outlineViewDataSourceMethods = px_methodNamesForProtocol(@protocol(NSOutlineViewDataSource));
|
||||
__fastPathForwardingDelegateMethods = px_methodNamesForProtocol(@protocol(PXSourceListDelegate));
|
||||
__fastPathForwardingDelegateMethods = [self fastPathForwardingDelegateMethods];
|
||||
__fastPathForwardingDataSourceMethods = px_methodNamesForProtocol(@protocol(PXSourceListDataSource));
|
||||
|
||||
__requiredOutlineViewDataSourceMethods = @[NSStringFromSelector(@selector(outlineView:numberOfChildrenOfItem:)),
|
||||
@@ -70,7 +70,7 @@ static NSArray * __fastPathForwardingDataSourceMethods = nil;
|
||||
- (void)setDelegate:(id<PXSourceListDelegate>)delegate
|
||||
{
|
||||
if (self.delegate)
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self.delegate name:nil object:self];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self.delegate name:nil object:self.sourceList];
|
||||
|
||||
_delegate = delegate;
|
||||
|
||||
@@ -100,11 +100,12 @@ static NSArray * __fastPathForwardingDataSourceMethods = nil;
|
||||
|
||||
- (BOOL)respondsToSelector:(SEL)aSelector
|
||||
{
|
||||
if ([self.sourceList respondsToSelector:aSelector])
|
||||
return YES;
|
||||
|
||||
NSString *methodName = NSStringFromSelector(aSelector);
|
||||
|
||||
// Only let the source list override NSOutlineView delegate and data source methods.
|
||||
if ([self.sourceList respondsToSelector:aSelector] && ([__outlineViewDataSourceMethods containsObject:methodName] || [__outlineViewDelegateMethods containsObject:methodName]))
|
||||
return YES;
|
||||
|
||||
if ([__requiredOutlineViewDataSourceMethods containsObject:methodName])
|
||||
return YES;
|
||||
|
||||
@@ -127,17 +128,14 @@ static NSArray * __fastPathForwardingDataSourceMethods = nil;
|
||||
return class_conformsToProtocol(object_getClass(self), protocol);
|
||||
}
|
||||
|
||||
// Fast-path delegate and data source methods aren't handled here; they are taken care of in -forwardingTargetForSelector:.
|
||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
|
||||
{
|
||||
NSString *methodName = NSStringFromSelector(aSelector);
|
||||
|
||||
struct objc_method_description description = {NULL, NULL};
|
||||
|
||||
if ([__fastPathForwardingDelegateMethods containsObject:methodName])
|
||||
description = px_methodDescriptionForProtocolMethod(@protocol(PXSourceListDelegate), aSelector);
|
||||
else if ([__fastPathForwardingDataSourceMethods containsObject:methodName])
|
||||
description = px_methodDescriptionForProtocolMethod(@protocol(PXSourceListDataSource), aSelector);
|
||||
else if ([__outlineViewDelegateMethods containsObject:methodName])
|
||||
if ([__outlineViewDelegateMethods containsObject:methodName])
|
||||
description = px_methodDescriptionForProtocolMethod(@protocol(NSOutlineViewDelegate), aSelector);
|
||||
else if ([__outlineViewDataSourceMethods containsObject:methodName])
|
||||
description = px_methodDescriptionForProtocolMethod(@protocol(NSOutlineViewDataSource), aSelector);
|
||||
@@ -397,6 +395,18 @@ static NSArray * __fastPathForwardingDataSourceMethods = nil;
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (NSArray *)fastPathForwardingDelegateMethods
|
||||
{
|
||||
NSMutableArray *methods = [px_methodNamesForProtocol(@protocol(PXSourceListDelegate)) mutableCopy];
|
||||
|
||||
// Add the NSControl delegate methods manually (unfortunately these aren't part of a formal protocol).
|
||||
[methods addObject:px_methodNameForSelector(@selector(controlTextDidEndEditing:))];
|
||||
[methods addObject:px_methodNameForSelector(@selector(controlTextDidBeginEditing:))];
|
||||
[methods addObject:px_methodNameForSelector(@selector(controlTextDidChange:))];
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
#pragma mark - Notifications
|
||||
|
||||
- (void)registerDelegateToReceiveNotification:(NSString*)notification withSelector:(SEL)selector
|
||||
|
||||
@@ -16,5 +16,6 @@ extern NSString * const px_protocolIsRequiredMethodKey;
|
||||
|
||||
NSArray *px_allProtocolMethods(Protocol *protocol);
|
||||
NSArray *px_methodNamesForProtocol(Protocol *protocol);
|
||||
id px_methodNameForSelector(SEL selector);
|
||||
|
||||
struct objc_method_description px_methodDescriptionForProtocolMethod(Protocol *protocol, SEL selector);
|
||||
@@ -26,7 +26,7 @@ NSArray *px_allProtocolMethods(Protocol *protocol)
|
||||
|
||||
for (unsigned int j = 0; j < numberOfMethodDescriptions; ++j) {
|
||||
struct objc_method_description methodDescription = methodDescriptions[j];
|
||||
[methodList addObject:@{px_protocolMethodNameKey: NSStringFromSelector(methodDescription.name),
|
||||
[methodList addObject:@{px_protocolMethodNameKey: px_methodNameForSelector(methodDescription.name),
|
||||
px_protocolMethodArgumentTypesKey: [NSString stringWithUTF8String:methodDescription.types],
|
||||
px_protocolIsRequiredMethodKey: @(isRequiredMethod)}];
|
||||
}
|
||||
@@ -47,6 +47,11 @@ NSArray *px_methodNamesForProtocol(Protocol *protocol)
|
||||
return methodNames;
|
||||
}
|
||||
|
||||
id px_methodNameForSelector(SEL selector)
|
||||
{
|
||||
return NSStringFromSelector(selector);
|
||||
}
|
||||
|
||||
struct objc_method_description px_methodDescriptionForProtocolMethod(Protocol *protocol, SEL selector)
|
||||
{
|
||||
struct objc_method_description description = {NULL, NULL};
|
||||
|
||||
+320
-331
@@ -15,7 +15,6 @@
|
||||
//Layout constants
|
||||
static const CGFloat minBadgeWidth = 22.0; // The minimum badge width for each item (default 22.0).
|
||||
static const CGFloat badgeHeight = 14.0; // The badge height for each item (default 14.0).
|
||||
static const CGFloat badgeMargin = 5.0; // The spacing between the badge and the cell for that row.
|
||||
static const CGFloat rowRightMargin = 5.0; // The spacing between the right edge of the badge and the edge of the table column.
|
||||
static const CGFloat iconSpacing = 2.0; // The spacing between the icon and it's adjacent cell.
|
||||
static const CGFloat disclosureTriangleSpace = 18.0; // The indentation reserved for disclosure triangles for non-group items.
|
||||
@@ -45,12 +44,12 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
#pragma mark - Setup/Teardown
|
||||
|
||||
- (id)initWithCoder:(NSCoder*)decoder
|
||||
{
|
||||
if(self=[super initWithCoder:decoder]) {
|
||||
{
|
||||
if(self=[super initWithCoder:decoder]) {
|
||||
[self PXSL_setup];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(NSRect)frameRect
|
||||
@@ -58,7 +57,7 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
if((self = [super initWithFrame:frameRect])) {
|
||||
[self PXSL_setup];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -70,9 +69,9 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
//Remove ourselves as the delegate and data source to be safe
|
||||
[super setDataSource:nil];
|
||||
[super setDelegate:nil];
|
||||
//Remove ourselves as the delegate and data source to be safe
|
||||
[super setDataSource:nil];
|
||||
[super setDelegate:nil];
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +80,7 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)setDelegate:(id<PXSourceListDelegate>)aDelegate
|
||||
{
|
||||
self.delegateDataSourceProxy.delegate = aDelegate;
|
||||
self.delegateDataSourceProxy.delegate = aDelegate;
|
||||
|
||||
[super setDelegate:nil];
|
||||
if (aDelegate)
|
||||
@@ -91,27 +90,27 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)setDataSource:(id<PXSourceListDataSource>)aDataSource
|
||||
{
|
||||
self.delegateDataSourceProxy.dataSource = aDataSource;
|
||||
self.delegateDataSourceProxy.dataSource = aDataSource;
|
||||
|
||||
[super setDataSource:nil];
|
||||
if (aDataSource)
|
||||
[super setDataSource:self.delegateDataSourceProxy];
|
||||
|
||||
[self reloadData];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)setIconSize:(NSSize)newIconSize
|
||||
{
|
||||
_iconSize = newIconSize;
|
||||
|
||||
CGFloat rowHeight = [self rowHeight];
|
||||
|
||||
//Make sure icon height does not exceed row height; if so constrain, keeping width and height in proportion
|
||||
if(_iconSize.height>rowHeight)
|
||||
{
|
||||
_iconSize.width = _iconSize.width * (rowHeight/_iconSize.height);
|
||||
_iconSize.height = rowHeight;
|
||||
}
|
||||
_iconSize = newIconSize;
|
||||
|
||||
CGFloat rowHeight = [self rowHeight];
|
||||
|
||||
//Make sure icon height does not exceed row height; if so constrain, keeping width and height in proportion
|
||||
if(_iconSize.height>rowHeight)
|
||||
{
|
||||
_iconSize.width = _iconSize.width * (rowHeight/_iconSize.height);
|
||||
_iconSize.height = rowHeight;
|
||||
}
|
||||
}
|
||||
|
||||
- (PXSourceListBadgeCell *)reusableBadgeCell
|
||||
@@ -142,90 +141,90 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)reloadData
|
||||
{
|
||||
[super reloadData];
|
||||
|
||||
//Expand items that are displayed as always expanded
|
||||
if([self.delegateDataSourceProxy conformsToProtocol:@protocol(PXSourceListDataSource)] &&
|
||||
[self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)])
|
||||
{
|
||||
for(NSUInteger i=0;i<[self numberOfGroups];i++)
|
||||
{
|
||||
id item = [self.delegateDataSourceProxy sourceList:self child:i ofItem:nil];
|
||||
|
||||
if([self isGroupAlwaysExpanded:item]) {
|
||||
[self expandItem:item expandChildren:NO];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//If there are selected rows and the item hierarchy has changed, make sure a Group row isn't
|
||||
//selected
|
||||
if([self numberOfSelectedRows]>0) {
|
||||
NSIndexSet *selectedIndexes = [self selectedRowIndexes];
|
||||
NSUInteger firstSelectedRow = [selectedIndexes firstIndex];
|
||||
|
||||
//Is a group item selected?
|
||||
if([self isGroupItem:[self itemAtRow:firstSelectedRow]]) {
|
||||
//Work backwards to find the first non-group row
|
||||
BOOL foundRow = NO;
|
||||
for(NSUInteger i=firstSelectedRow;i>0;i--)
|
||||
{
|
||||
if(![self isGroupItem:[self itemAtRow:i]]) {
|
||||
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:i] byExtendingSelection:NO];
|
||||
foundRow = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//If there is no non-group row preceding the currently selected group item, remove the selection
|
||||
//from the Source List
|
||||
if(!foundRow) {
|
||||
[self deselectAll:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(![self allowsEmptySelection]&&[self numberOfSelectedRows]==0)
|
||||
{
|
||||
//Select the first non-group row if no rows are selected, and empty selection is disallowed
|
||||
for(NSUInteger i=0;i<[self numberOfRows];i++)
|
||||
{
|
||||
if(![self isGroupItem:[self itemAtRow:i]]) {
|
||||
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:i] byExtendingSelection:NO];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[super reloadData];
|
||||
|
||||
//Expand items that are displayed as always expanded
|
||||
if([self.delegateDataSourceProxy conformsToProtocol:@protocol(PXSourceListDataSource)] &&
|
||||
[self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)])
|
||||
{
|
||||
for(NSUInteger i=0;i<[self numberOfGroups];i++)
|
||||
{
|
||||
id item = [self.delegateDataSourceProxy sourceList:self child:i ofItem:nil];
|
||||
|
||||
if([self isGroupAlwaysExpanded:item]) {
|
||||
[self expandItem:item expandChildren:NO];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//If there are selected rows and the item hierarchy has changed, make sure a Group row isn't
|
||||
//selected
|
||||
if([self numberOfSelectedRows]>0) {
|
||||
NSIndexSet *selectedIndexes = [self selectedRowIndexes];
|
||||
NSUInteger firstSelectedRow = [selectedIndexes firstIndex];
|
||||
|
||||
//Is a group item selected?
|
||||
if([self isGroupItem:[self itemAtRow:firstSelectedRow]]) {
|
||||
//Work backwards to find the first non-group row
|
||||
BOOL foundRow = NO;
|
||||
for(NSUInteger i=firstSelectedRow;i>0;i--)
|
||||
{
|
||||
if(![self isGroupItem:[self itemAtRow:i]]) {
|
||||
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:i] byExtendingSelection:NO];
|
||||
foundRow = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//If there is no non-group row preceding the currently selected group item, remove the selection
|
||||
//from the Source List
|
||||
if(!foundRow) {
|
||||
[self deselectAll:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(![self allowsEmptySelection]&&[self numberOfSelectedRows]==0)
|
||||
{
|
||||
//Select the first non-group row if no rows are selected, and empty selection is disallowed
|
||||
for(NSUInteger i=0;i<[self numberOfRows];i++)
|
||||
{
|
||||
if(![self isGroupItem:[self itemAtRow:i]]) {
|
||||
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:i] byExtendingSelection:NO];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfGroups
|
||||
{
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:numberOfChildrenOfItem:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self numberOfChildrenOfItem:nil];
|
||||
}
|
||||
|
||||
return 0;
|
||||
{
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:numberOfChildrenOfItem:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self numberOfChildrenOfItem:nil];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isGroupItem:(id)item
|
||||
{
|
||||
//Groups are defined as root items (at level 0)
|
||||
return 0==[self levelForItem:item];
|
||||
//Groups are defined as root items (at level 0)
|
||||
return 0==[self levelForItem:item];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isGroupAlwaysExpanded:(id)group
|
||||
{
|
||||
//Make sure that the item IS a group to prevent unwanted queries sent to the data source
|
||||
if([self isGroupItem:group]) {
|
||||
//Query the data source
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self isGroupAlwaysExpanded:group];
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
//Make sure that the item IS a group to prevent unwanted queries sent to the data source
|
||||
if([self isGroupItem:group]) {
|
||||
//Query the data source
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:isGroupAlwaysExpanded:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self isGroupAlwaysExpanded:group];
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@@ -235,11 +234,11 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
if (self.isViewBasedSourceList)
|
||||
return NO;
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasBadge:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self itemHasBadge:item];
|
||||
}
|
||||
|
||||
return NO;
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasBadge:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self itemHasBadge:item];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSInteger)badgeValueForItem:(id)item
|
||||
@@ -247,12 +246,12 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
// Since badges are managed by custom views and logic in view-based mode, we can't determine this.
|
||||
if (self.isViewBasedSourceList || ![self itemHasBadge:item])
|
||||
return NSNotFound;
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:badgeValueForItem:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self badgeValueForItem:item];
|
||||
}
|
||||
|
||||
return NSNotFound;
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:badgeValueForItem:)]) {
|
||||
return [self.delegateDataSourceProxy sourceList:self badgeValueForItem:item];
|
||||
}
|
||||
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -260,53 +259,53 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)selectRowIndexes:(NSIndexSet*)indexes byExtendingSelection:(BOOL)extend
|
||||
{
|
||||
NSUInteger numberOfIndexes = [indexes count];
|
||||
|
||||
//Prevent empty selection if we don't want it
|
||||
if(![self allowsEmptySelection]&&0==numberOfIndexes) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Would use blocks but we're also targeting 10.5...
|
||||
//Get the selected indexes
|
||||
NSUInteger *selectedIndexes = malloc(sizeof(NSUInteger)*numberOfIndexes);
|
||||
[indexes getIndexes:selectedIndexes maxCount:numberOfIndexes inIndexRange:nil];
|
||||
|
||||
//Loop through the indexes and only add non-group row indexes
|
||||
//Allows selection across groups without selecting the group rows
|
||||
NSMutableIndexSet *newSelectionIndexes = [NSMutableIndexSet indexSet];
|
||||
for(NSInteger i=0;i<numberOfIndexes;i++)
|
||||
{
|
||||
if(![self isGroupItem:[self itemAtRow:selectedIndexes[i]]]) {
|
||||
[newSelectionIndexes addIndex:selectedIndexes[i]];
|
||||
}
|
||||
}
|
||||
|
||||
//If there are any non-group rows selected
|
||||
if([newSelectionIndexes count]>0) {
|
||||
[super selectRowIndexes:newSelectionIndexes byExtendingSelection:extend];
|
||||
}
|
||||
|
||||
//C memory management... *sigh*
|
||||
free(selectedIndexes);
|
||||
NSUInteger numberOfIndexes = [indexes count];
|
||||
|
||||
//Prevent empty selection if we don't want it
|
||||
if(![self allowsEmptySelection]&&0==numberOfIndexes) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Would use blocks but we're also targeting 10.5...
|
||||
//Get the selected indexes
|
||||
NSUInteger *selectedIndexes = malloc(sizeof(NSUInteger)*numberOfIndexes);
|
||||
[indexes getIndexes:selectedIndexes maxCount:numberOfIndexes inIndexRange:nil];
|
||||
|
||||
//Loop through the indexes and only add non-group row indexes
|
||||
//Allows selection across groups without selecting the group rows
|
||||
NSMutableIndexSet *newSelectionIndexes = [NSMutableIndexSet indexSet];
|
||||
for(NSInteger i=0;i<numberOfIndexes;i++)
|
||||
{
|
||||
if(![self isGroupItem:[self itemAtRow:selectedIndexes[i]]]) {
|
||||
[newSelectionIndexes addIndex:selectedIndexes[i]];
|
||||
}
|
||||
}
|
||||
|
||||
//If there are any non-group rows selected
|
||||
if([newSelectionIndexes count]>0) {
|
||||
[super selectRowIndexes:newSelectionIndexes byExtendingSelection:extend];
|
||||
}
|
||||
|
||||
//C memory management... *sigh*
|
||||
free(selectedIndexes);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Layout
|
||||
|
||||
- (NSRect)frameOfOutlineCellAtRow:(NSInteger)row
|
||||
{
|
||||
//Return a zero-rect if the item is always expanded (a disclosure triangle will not be drawn)
|
||||
if([self isGroupAlwaysExpanded:[self itemAtRow:row]]) {
|
||||
return NSZeroRect;
|
||||
}
|
||||
|
||||
{
|
||||
//Return a zero-rect if the item is always expanded (a disclosure triangle will not be drawn)
|
||||
if([self isGroupAlwaysExpanded:[self itemAtRow:row]]) {
|
||||
return NSZeroRect;
|
||||
}
|
||||
|
||||
NSRect frame = [super frameOfOutlineCellAtRow:row];
|
||||
|
||||
|
||||
if([self levelForRow:row] > 0) {
|
||||
frame.origin.x = [self levelForRow:row] * [self indentationPerLevel];
|
||||
}
|
||||
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
@@ -316,51 +315,51 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
if (self.isViewBasedSourceList)
|
||||
return [super frameOfCellAtColumn:column row:row];
|
||||
|
||||
id item = [self itemAtRow:row];
|
||||
|
||||
NSCell *cell = [self preparedCellAtColumn:column row:row];
|
||||
NSSize cellSize = [cell cellSize];
|
||||
if (!([cell type] == NSImageCellType) && !([cell type] == NSTextCellType))
|
||||
cellSize = [cell cellSizeForBounds:[super frameOfCellAtColumn:column row:row]];
|
||||
NSRect cellFrame = [super frameOfCellAtColumn:column row:row];
|
||||
|
||||
NSRect rowRect = [self rectOfRow:row];
|
||||
|
||||
if([self isGroupItem:item])
|
||||
{
|
||||
CGFloat minX = NSMinX(cellFrame);
|
||||
|
||||
//Set the origin x-coord; if there are no children of the group at current, there will still be a
|
||||
//margin to the left of the cell (in cellFrame), which we don't want
|
||||
if([self isGroupAlwaysExpanded:[self itemAtRow:row]]) {
|
||||
minX = 7;
|
||||
}
|
||||
|
||||
return NSMakeRect(minX,
|
||||
NSMidY(cellFrame)-(cellSize.height/2.0),
|
||||
NSWidth(rowRect)-minX,
|
||||
cellSize.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGFloat leftIndent = [self levelForRow:row]*[self indentationPerLevel]+disclosureTriangleSpace;
|
||||
|
||||
//Calculate space left for a badge if need be
|
||||
CGFloat rightIndent = [self sizeOfBadgeAtRow:row].width+rowRightMargin;
|
||||
|
||||
//Allow space for an icon if need be
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
{
|
||||
if([self.delegateDataSourceProxy sourceList:self itemHasIcon:item]) {
|
||||
leftIndent += [self iconSize].width+(iconSpacing*2);
|
||||
}
|
||||
}
|
||||
|
||||
return NSMakeRect(leftIndent,
|
||||
NSMidY(rowRect)-(cellSize.height/2.0),
|
||||
NSWidth(rowRect)-rightIndent-leftIndent,
|
||||
cellSize.height);
|
||||
}
|
||||
id item = [self itemAtRow:row];
|
||||
|
||||
NSCell *cell = [self preparedCellAtColumn:column row:row];
|
||||
NSSize cellSize = [cell cellSize];
|
||||
if (!([cell type] == NSImageCellType) && !([cell type] == NSTextCellType))
|
||||
cellSize = [cell cellSizeForBounds:[super frameOfCellAtColumn:column row:row]];
|
||||
NSRect cellFrame = [super frameOfCellAtColumn:column row:row];
|
||||
|
||||
NSRect rowRect = [self rectOfRow:row];
|
||||
|
||||
if([self isGroupItem:item])
|
||||
{
|
||||
CGFloat minX = NSMinX(cellFrame);
|
||||
|
||||
//Set the origin x-coord; if there are no children of the group at current, there will still be a
|
||||
//margin to the left of the cell (in cellFrame), which we don't want
|
||||
if([self isGroupAlwaysExpanded:[self itemAtRow:row]]) {
|
||||
minX = 7;
|
||||
}
|
||||
|
||||
return NSMakeRect(minX,
|
||||
NSMidY(cellFrame)-(cellSize.height/2.0),
|
||||
NSWidth(rowRect)-minX,
|
||||
cellSize.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGFloat leftIndent = [self levelForRow:row]*[self indentationPerLevel]+disclosureTriangleSpace;
|
||||
|
||||
//Calculate space left for a badge if need be
|
||||
CGFloat rightIndent = [self sizeOfBadgeAtRow:row].width+rowRightMargin;
|
||||
|
||||
//Allow space for an icon if need be
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
{
|
||||
if([self.delegateDataSourceProxy sourceList:self itemHasIcon:item]) {
|
||||
leftIndent += [self iconSize].width+(iconSpacing*2);
|
||||
}
|
||||
}
|
||||
|
||||
return NSMakeRect(leftIndent,
|
||||
NSMidY(rowRect)-(cellSize.height/2.0),
|
||||
NSWidth(rowRect)-rightIndent-leftIndent,
|
||||
cellSize.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -368,14 +367,14 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
//row for the row index passed to the method does not have a badge, then NSZeroSize is returned.
|
||||
- (NSSize)sizeOfBadgeAtRow:(NSInteger)rowIndex
|
||||
{
|
||||
id rowItem = [self itemAtRow:rowIndex];
|
||||
id rowItem = [self itemAtRow:rowIndex];
|
||||
|
||||
if (![self itemHasBadge:rowItem])
|
||||
return NSZeroSize;
|
||||
if (![self itemHasBadge:rowItem])
|
||||
return NSZeroSize;
|
||||
|
||||
self.reusableBadgeCell.integerValue = [self badgeValueForItem:rowItem];
|
||||
|
||||
return NSMakeSize(fmax(self.reusableBadgeCell.cellSize.width, minBadgeWidth), badgeHeight);
|
||||
return NSMakeSize(fmax(self.reusableBadgeCell.cellSize.width, minBadgeWidth), badgeHeight);
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToSuperview
|
||||
@@ -388,78 +387,68 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
#pragma mark Drawing
|
||||
|
||||
- (void)drawRow:(NSInteger)rowIndex clipRect:(NSRect)clipRect
|
||||
{
|
||||
[super drawRow:rowIndex clipRect:clipRect];
|
||||
{
|
||||
[super drawRow:rowIndex clipRect:clipRect];
|
||||
|
||||
// We only do drawing here if the Source List is cell-based.
|
||||
if (self.isViewBasedSourceList)
|
||||
return;
|
||||
|
||||
id item = [self itemAtRow:rowIndex];
|
||||
|
||||
//Draw an icon if the item has one
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
{
|
||||
if([self.delegateDataSourceProxy sourceList:self itemHasIcon:item])
|
||||
{
|
||||
NSRect cellFrame = [self frameOfCellAtColumn:0 row:rowIndex];
|
||||
NSSize iconSize = [self iconSize];
|
||||
NSRect iconRect = NSMakeRect(NSMinX(cellFrame)-iconSize.width-iconSpacing,
|
||||
NSMidY(cellFrame)-(iconSize.height/2.0f),
|
||||
iconSize.width,
|
||||
iconSize.height);
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:iconForItem:)])
|
||||
{
|
||||
NSImage *icon = [self.delegateDataSourceProxy sourceList:self iconForItem:item];
|
||||
|
||||
if(icon!=nil)
|
||||
{
|
||||
NSSize actualIconSize = [icon size];
|
||||
|
||||
//If the icon is *smaller* than the size retrieved from the -iconSize property, make sure we
|
||||
//reduce the size of the rectangle to draw the icon in, so that it is not stretched.
|
||||
if((actualIconSize.width<iconSize.width)||(actualIconSize.height<iconSize.height))
|
||||
{
|
||||
iconRect = NSMakeRect(NSMidX(iconRect)-(actualIconSize.width/2.0f),
|
||||
NSMidY(iconRect)-(actualIconSize.height/2.0f),
|
||||
actualIconSize.width,
|
||||
actualIconSize.height);
|
||||
}
|
||||
|
||||
//Use 10.6 NSImage drawing if we can
|
||||
if([icon respondsToSelector:@selector(drawInRect:fromRect:operation:fraction:respectFlipped:hints:)]) {
|
||||
[icon drawInRect:iconRect
|
||||
fromRect:NSZeroRect
|
||||
operation:NSCompositeSourceOver
|
||||
fraction:1
|
||||
respectFlipped:YES hints:nil];
|
||||
|
||||
id item = [self itemAtRow:rowIndex];
|
||||
|
||||
//Draw an icon if the item has one
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:itemHasIcon:)])
|
||||
{
|
||||
if([self.delegateDataSourceProxy sourceList:self itemHasIcon:item])
|
||||
{
|
||||
NSRect cellFrame = [self frameOfCellAtColumn:0 row:rowIndex];
|
||||
NSSize iconSize = [self iconSize];
|
||||
NSRect iconRect = NSMakeRect(NSMinX(cellFrame)-iconSize.width-iconSpacing,
|
||||
NSMidY(cellFrame)-(iconSize.height/2.0f),
|
||||
iconSize.width,
|
||||
iconSize.height);
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:iconForItem:)])
|
||||
{
|
||||
NSImage *icon = [self.delegateDataSourceProxy sourceList:self iconForItem:item];
|
||||
|
||||
if(icon!=nil)
|
||||
{
|
||||
NSSize actualIconSize = [icon size];
|
||||
|
||||
//If the icon is *smaller* than the size retrieved from the -iconSize property, make sure we
|
||||
//reduce the size of the rectangle to draw the icon in, so that it is not stretched.
|
||||
if((actualIconSize.width<iconSize.width)||(actualIconSize.height<iconSize.height))
|
||||
{
|
||||
iconRect = NSMakeRect(NSMidX(iconRect)-(actualIconSize.width/2.0f),
|
||||
NSMidY(iconRect)-(actualIconSize.height/2.0f),
|
||||
actualIconSize.width,
|
||||
actualIconSize.height);
|
||||
}
|
||||
else {
|
||||
[icon setFlipped:[self isFlipped]];
|
||||
[icon drawInRect:iconRect
|
||||
fromRect:NSZeroRect
|
||||
operation:NSCompositeSourceOver
|
||||
fraction:1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Draw the badge if the item has one
|
||||
if([self itemHasBadge:item])
|
||||
{
|
||||
NSRect rowRect = [self rectOfRow:rowIndex];
|
||||
NSSize badgeSize = [self sizeOfBadgeAtRow:rowIndex];
|
||||
|
||||
NSRect badgeFrame = NSMakeRect(NSMaxX(rowRect)-badgeSize.width-rowRightMargin,
|
||||
NSMidY(rowRect)-(badgeSize.height/2.0),
|
||||
badgeSize.width,
|
||||
badgeSize.height);
|
||||
|
||||
[self drawBadgeForRow:rowIndex inRect:badgeFrame];
|
||||
}
|
||||
|
||||
[icon drawInRect:iconRect
|
||||
fromRect:NSZeroRect
|
||||
operation:NSCompositeSourceOver
|
||||
fraction:1
|
||||
respectFlipped:YES hints:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Draw the badge if the item has one
|
||||
if([self itemHasBadge:item])
|
||||
{
|
||||
NSRect rowRect = [self rectOfRow:rowIndex];
|
||||
NSSize badgeSize = [self sizeOfBadgeAtRow:rowIndex];
|
||||
|
||||
NSRect badgeFrame = NSMakeRect(NSMaxX(rowRect)-badgeSize.width-rowRightMargin,
|
||||
NSMidY(rowRect)-(badgeSize.height/2.0),
|
||||
badgeSize.width,
|
||||
badgeSize.height);
|
||||
|
||||
[self drawBadgeForRow:rowIndex inRect:badgeFrame];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawBadgeForRow:(NSInteger)rowIndex inRect:(NSRect)badgeFrame
|
||||
@@ -481,53 +470,53 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (void)keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
NSIndexSet *selectedIndexes = [self selectedRowIndexes];
|
||||
|
||||
NSString *keyCharacters = [theEvent characters];
|
||||
|
||||
//Make sure we have a selection
|
||||
if([selectedIndexes count]>0)
|
||||
{
|
||||
if([keyCharacters length]>0)
|
||||
{
|
||||
unichar firstKey = [keyCharacters characterAtIndex:0];
|
||||
|
||||
if(firstKey==NSUpArrowFunctionKey||firstKey==NSDownArrowFunctionKey)
|
||||
{
|
||||
//Handle keyboard navigation across groups
|
||||
if([selectedIndexes count]==1&&!([theEvent modifierFlags] & NSShiftKeyMask))
|
||||
{
|
||||
int delta = firstKey==NSDownArrowFunctionKey?1:-1; //Search "backwards" if up arrow, "forwards" if down
|
||||
NSInteger newRow = [selectedIndexes firstIndex];
|
||||
|
||||
//Keep incrementing/decrementing the row until a non-header row is reached
|
||||
do {
|
||||
newRow+=delta;
|
||||
|
||||
//If out of bounds of the number of rows..
|
||||
if(newRow<0||newRow==[self numberOfRows])
|
||||
break;
|
||||
} while([self isGroupItem:[self itemAtRow:newRow]]);
|
||||
|
||||
|
||||
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO];
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(firstKey==NSDeleteCharacter||firstKey==NSBackspaceCharacter||firstKey==0xf728)
|
||||
{
|
||||
//Post the notification
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLDeleteKeyPressedOnRowsNotification
|
||||
object:self
|
||||
userInfo:[NSDictionary dictionaryWithObject:selectedIndexes forKey:@"rows"]];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//We don't care about it
|
||||
[super keyDown:theEvent];
|
||||
NSIndexSet *selectedIndexes = [self selectedRowIndexes];
|
||||
|
||||
NSString *keyCharacters = [theEvent characters];
|
||||
|
||||
//Make sure we have a selection
|
||||
if([selectedIndexes count]>0)
|
||||
{
|
||||
if([keyCharacters length]>0)
|
||||
{
|
||||
unichar firstKey = [keyCharacters characterAtIndex:0];
|
||||
|
||||
if(firstKey==NSUpArrowFunctionKey||firstKey==NSDownArrowFunctionKey)
|
||||
{
|
||||
//Handle keyboard navigation across groups
|
||||
if([selectedIndexes count]==1&&!([theEvent modifierFlags] & NSShiftKeyMask))
|
||||
{
|
||||
int delta = firstKey==NSDownArrowFunctionKey?1:-1; //Search "backwards" if up arrow, "forwards" if down
|
||||
NSInteger newRow = [selectedIndexes firstIndex];
|
||||
|
||||
//Keep incrementing/decrementing the row until a non-header row is reached
|
||||
do {
|
||||
newRow+=delta;
|
||||
|
||||
//If out of bounds of the number of rows..
|
||||
if(newRow<0||newRow==[self numberOfRows])
|
||||
break;
|
||||
} while([self isGroupItem:[self itemAtRow:newRow]]);
|
||||
|
||||
|
||||
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO];
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(firstKey==NSDeleteCharacter||firstKey==NSBackspaceCharacter||firstKey==0xf728)
|
||||
{
|
||||
//Post the notification
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:PXSLDeleteKeyPressedOnRowsNotification
|
||||
object:self
|
||||
userInfo:[NSDictionary dictionaryWithObject:selectedIndexes forKey:@"rows"]];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//We don't care about it
|
||||
[super keyDown:theEvent];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -536,53 +525,53 @@ NSString * const PXSLDeleteKeyPressedOnRowsNotification = @"PXSourceListDeleteKe
|
||||
|
||||
- (NSMenu *)menuForEvent:(NSEvent *)theEvent
|
||||
{
|
||||
NSMenu * m = nil;
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:menuForEvent:item:)]) {
|
||||
NSPoint clickPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
NSInteger row = [self rowAtPoint:clickPoint];
|
||||
id clickedItem = [self itemAtRow:row];
|
||||
m = [self.delegateDataSourceProxy sourceList:self menuForEvent:theEvent item:clickedItem];
|
||||
}
|
||||
if (m == nil) {
|
||||
m = [super menuForEvent:theEvent];
|
||||
}
|
||||
return m;
|
||||
NSMenu * m = nil;
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:menuForEvent:item:)]) {
|
||||
NSPoint clickPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
NSInteger row = [self rowAtPoint:clickPoint];
|
||||
id clickedItem = [self itemAtRow:row];
|
||||
m = [self.delegateDataSourceProxy sourceList:self menuForEvent:theEvent item:clickedItem];
|
||||
}
|
||||
if (m == nil) {
|
||||
m = [super menuForEvent:theEvent];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
#pragma mark - Custom NSOutlineView Delegate Method Implementations
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldCollapseItem:(id)item
|
||||
{
|
||||
// Make sure the item isn't displayed as always expanded
|
||||
if([self isGroupItem:item] && [self isGroupAlwaysExpanded:item])
|
||||
// Make sure the item isn't displayed as always expanded
|
||||
if([self isGroupItem:item] && [self isGroupAlwaysExpanded:item])
|
||||
return NO;
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldCollapseItem:)])
|
||||
return [self.delegateDataSourceProxy sourceList:self shouldCollapseItem:item];
|
||||
|
||||
return YES;
|
||||
|
||||
if([self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldCollapseItem:)])
|
||||
return [self.delegateDataSourceProxy sourceList:self shouldCollapseItem:item];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
|
||||
{
|
||||
// Make sure that the item isn't a group as they can't be selected
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldSelectItem:)])
|
||||
// Make sure that the item isn't a group as they can't be selected
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldSelectItem:)])
|
||||
return [self.delegateDataSourceProxy sourceList:self shouldSelectItem:item];
|
||||
|
||||
return ![self isGroupItem:item];
|
||||
return ![self isGroupItem:item];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldEditItem:)])
|
||||
return [self.delegateDataSourceProxy sourceList:self shouldEditItem:item];
|
||||
|
||||
return ![self isGroupItem:item];
|
||||
if(![self isGroupItem:item] && [self.delegateDataSourceProxy respondsToSelector:@selector(sourceList:shouldEditItem:)])
|
||||
return [self.delegateDataSourceProxy sourceList:self shouldEditItem:item];
|
||||
|
||||
return ![self isGroupItem:item];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
|
||||
{
|
||||
return [self isGroupItem:item];
|
||||
return [self isGroupItem:item];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -111,4 +111,12 @@ static const CGFloat badgeLeftAndRightPadding = 5.0;
|
||||
attributes:@{NSFontAttributeName: badgeFont()}];
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString *)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
|
||||
return @(_badgeValue).description;
|
||||
else
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#PXSourceList
|
||||
|
||||
|
||||
[](http://cocoadocs.org/docsets/PXSourceList/2.0.5/)
|
||||
[](http://cocoadocs.org/docsets/PXSourceList/2.0.5/)
|
||||
[](https://github.com/Perspx/PXSourceList/blob/master/LICENSE)
|
||||
|
||||
`PXSourceList` is an `NSOutlineView` subclass used for easily implementing source lists in your applications.
|
||||
|
||||
PXSourceList requires the OS X 10.7 SDK and above and is licensed under the New BSD License.
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# PXSourceList Release Notes
|
||||
|
||||
## 2.0.7
|
||||
- Remove -setFlipped: call which was causing a deprecation warning on OS X 10.10.
|
||||
- Fix whitespace in PXSourceList.m.
|
||||
|
||||
## 2.0.6
|
||||
- Merge PR #49: Fix PXSourceListBadgeCell accessibility. Adds accessibility for PXSourceListBadgeCell when using PXSourceList in view-based mode.
|
||||
|
||||
## 2.0.5
|
||||
- Fix #43: sourceListDeleteKeyPressedOnRows: called twice. This was caused by an issue where PXSourceList was incorrectly removing the old delegate as an observer of PXSourceList notifications in -setDelegate:.
|
||||
|
||||
## 2.0.4
|
||||
- PR #41: fix a Zeroing Weak References problem. This fixes an issue where using an `NSWindow`, `NSWindowController` or `NSViewController` as a PXSourceList delegate or dataSource would cause problems on 10.7 because prior to 10.8, these classes could not be referenced by zeroing weak references.
|
||||
- Remove unused `badgeMargin` constant from PXSourceList.m.
|
||||
|
||||
## 2.0.3
|
||||
- Fix #40: Editing titles on cell based source list causes exception.
|
||||
- Fix issue in view-based source list example where items created with the add button couldn't be dragged.
|
||||
|
||||
## 2.0.2
|
||||
- Fix #39: Badges not drawn correctly when Source List row is selected.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user