8 Commits

Author SHA1 Message Date
Alex Rozanski 7a82f63e9b Add Release Notes for 2.0.3. 2014-03-25 21:41:47 +00:00
Alex Rozanski b215e263ef Bump project to 2.0.3. 2014-03-25 21:41:41 +00:00
Alex Rozanski 5ce29c98c9 Fix issue in view-based source list example.
This fixes an issue where items created with the add button couldn't be
dragged.
2014-03-25 21:37:06 +00:00
Alex Rozanski 7df260c6f7 Fix #40: Editing titles on cell based source list causes exception.
The cause of this bug was returning YES in
-[PXSourceListDelegateDataSourceProxy respondsToSelector:] for the
NSControl delegate methods -controlTextDidEndEditing:,
-controlTextDidBeginEditing: and -controlTextDidChange: when they were
called on the proxy because NSOutlineView implements them internally.
However we weren't returning a method signature for them in -methodSignatureForSelector:
which was throwing an exception.

This fix has two components:
- We only allow forwarding of NSOutlineView(Delegate|DataSource) methods
  to the source list PXSourceListDelegateDataSourceProxy (which
  was the original intention). If PXSourceList returns YES for
  -respondsToSelector: we ignore it if the method is not from one of
  these two protocols.
- The NSControl delegate methods have been added to the fast-path
  forwarding delegate methods array in
  PXSourceListDelegateDataSourceProxy (the array which contains method
  names which can be forwarded to the source list's delegate as-is, without
  modifying the selector or arguments).

These fix the underlying cause of the exception and implement
the missing behaviour of allowing invocation of these NSControl methods
on the source list's delegate.
2014-03-25 21:29:31 +00:00
Alex Rozanski 8407bc98bb Remove unnecessary computation in -[PXSourceListDelegateDataSourceProxy methodSignatureForSelector:].
Fast-path delegate and data source methods (those whose method
signature doesn't need modification) don't need to be checked in
-methodSignatureForSelector: because they are handled in
-forwardingTargetForSelector: which bypasses the
-methodSignatureForSelector:/forwardInvocation: path.
2014-03-25 21:08:20 +00:00
Alex Rozanski 29d61656fe Add Release Notes for 2.0.2. 2014-03-06 00:01:22 +00:00
Alex Rozanski 52e21a8ced Bump project to 2.0.2. 2014-03-06 00:00:06 +00:00
Alex Rozanski 60974e14fd Fix #39: Badges not drawn correctly when Source List row is selected.
This fix consists of two parts:
1) We first need to check the backgroundStyle property in
PXSourceListBadgeCell to determine whether to draw the light badge
background or not.

2) Next we need to determine whether the enclosing Source List (or child
view) is focused to decide whether to draw the badge text using the bright
blue or grey-blue. To do this, we walk up the view hierarchy
from the common ancestor view of the controlView and firstResponder
until we hit a PXSourceList instance. If we find one, then the source
list is selected, otherwise not.

Walking up the tree from the common ancestor view catches the highly-
unlikely but possible scenario where there are two PXSourceList
instances on screen and one is focused.
2014-03-05 23:50:11 +00:00
8 changed files with 64 additions and 19 deletions
+6 -2
View File
@@ -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];
}
+2 -2
View File
@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.1</string>
<string>2.0.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.0.1</string>
<string>2.0.3</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2009-14 Alex Rozanski and other contributors. All rights reserved.</string>
<key>NSPrincipalClass</key>
+2 -2
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PXSourceList'
s.version = '2.0.1'
s.version = '2.0.3'
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.1' }
s.source = { :git => 'https://github.com/Perspx/PXSourceList.git', :tag => '2.0.3' }
s.source_files = 'PXSourceList/**/*.{h,m}'
end
@@ -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:)),
@@ -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};
+20 -2
View File
@@ -9,6 +9,8 @@
#import "PXSourceListBadgeCell.h"
#import "PXSourceList.h"
//Drawing constants
static inline NSColor *badgeBackgroundColor() { return [NSColor colorWithCalibratedRed:(152/255.0) green:(168/255.0) blue:(202/255.0) alpha:1]; }
static inline NSColor *badgeHiddenBackgroundColor() { return [NSColor colorWithDeviceWhite:(180/255.0) alpha:1]; }
@@ -40,11 +42,27 @@ static const CGFloat badgeLeftAndRightPadding = 5.0;
NSDictionary *attributes;
NSColor *backgroundColor;
if(self.isHighlighted) {
if(self.isHighlighted || self.backgroundStyle == NSBackgroundStyleDark) {
backgroundColor = [NSColor whiteColor];
NSResponder *firstResponder = controlView.window.firstResponder;
BOOL isFocused = [firstResponder isKindOfClass:[NSView class]] && [(NSView *)firstResponder isDescendantOf:controlView];
BOOL isFocused = NO;
// Starting with the closest ancestor of the control view and the first responder (to make sure both views are in the
// same subtree of the view hierarchy), keep going up the view hierarchy until we hit a PXSourceList instance to tell
// if the source list is focused.
// This covers both the cell-based and view-based cases as well as if a child view of the NSTableCellView (such as
// a text field) is focused.
if ([firstResponder isKindOfClass:[NSView class]]) {
NSView *view = [(NSView*)firstResponder ancestorSharedWithView:controlView];
do {
if ([view isKindOfClass:[PXSourceList class]]) {
isFocused = YES;
break;
}
} while ((view = [view superview]));
}
NSColor *textColor;
if (isMainWindowVisible && isFocused)
+8 -1
View File
@@ -1,5 +1,12 @@
# PXSourceList Release Notes
## 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.
## 2.0.1
- Add missing note to the 2.0.0 release notes about marking `-[PXSourceList delegate]` and `-[PXSourceList dataSource]` as unavailable using \_\_attribute\_\_.
@@ -71,4 +78,4 @@
- Removed `SourceListItem` from the old example project as it has been superseded by `PXSourceListItem`.
- Removed the TODO.rtf file from the project as all issues are now being tracked through GitHub.
- Upgraded the Xcode project to the Xcode 5 project format. `LastUpgradeCheck` was updated from `0450` to`0500`.
- Added a Release Notes file ;)
- Added a Release Notes file ;)