21 Commits

Author SHA1 Message Date
Alex Rozanski 294fd09a82 Bump project to 2.0.6 2015-05-08 11:01:03 +01:00
Alex Rozanski 2bf9e6a6f1 Merge pull request #49 from dusek/accessibility-badge-viewbased
Fix PXSourceListBadgeCell accessibility
2015-05-08 10:56:40 +01:00
Boris Dušek ab0408c8fe Fix PXSourceListBadgeCell accessibility
Now in the view-based source list, instead of just "Photos", VoiceOver
reads "Photos, 264"
2015-03-28 12:45:02 +01:00
Alex Rozanski 929b1651af Add badges to README. 2014-09-25 09:42:48 -04:00
Alex Rozanski 2eb6414e6b Bump project to 2.0.5 2014-06-07 14:45:37 -04:00
Alex Rozanski 2550dce3b7 Fix #43: sourceListDeleteKeyPressedOnRows: called twice.
This issue was being caused by the fact that the overridden
-setDelegate: method on PXSourceListDelegateDataSourceProxy doesn't
correctly remove the old delegate as observing the PXSourceList
notifications.

Setting the same delegate twice will cause this issue to
occur.
2014-06-07 14:39:44 -04:00
Alex Rozanski c62b8b2c92 Bump project to 2.0.4. 2014-05-11 13:17:39 -04:00
Alex Rozanski 67772622cf Remove unused badgeMargin constant. 2014-05-11 13:12:42 -04:00
Alex Rozanski a555035042 Merge pull request #41 from CrazyCatcher/master
fix a Zeroing Weak References problem
2014-05-11 12:59:55 -04:00
crazycatcher 0129de341e fix a Zeroing Weak References problem 2014-05-06 20:12:51 +08:00
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
Alex Rozanski 3eadddb784 Bump project to 2.0.1. 2014-01-29 13:25:34 +00:00
Alex Rozanski 20a6e83f86 Add Release Notes for 2.0.1. 2014-01-29 12:55:20 +00:00
Alex Rozanski 7548ffdd1b Update ReleaseNotes for 2.0.0.
The note about -[PXSourceList delegate] and -[PXSourceList dataSource]
being marked as unavailable was missing from the 2.0.0 release notes.
2014-01-29 12:50:24 +00:00
11 changed files with 95 additions and 24 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];
}
+3 -3
View File
@@ -17,13 +17,13 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>2.0.6</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.0.0</string>
<string>2.0.6</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>
+2 -2
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PXSourceList'
s.version = '2.0.0'
s.version = '2.0.6'
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.0' }
s.source = { :git => 'https://github.com/Perspx/PXSourceList.git', :tag => '2.0.6' }
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};
-1
View File
@@ -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.
+28 -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)
@@ -93,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
+5
View File
@@ -1,5 +1,10 @@
#PXSourceList
[![Pod Version](http://img.shields.io/cocoapods/v/PXSourceList.svg)](http://cocoadocs.org/docsets/PXSourceList/2.0.5/)
[![Platform](http://img.shields.io/cocoapods/p/PXSourceList.svg)](http://cocoadocs.org/docsets/PXSourceList/2.0.5/)
[![Licence](http://img.shields.io/cocoapods/l/PXSourceList.svg)](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.
+22 -1
View File
@@ -1,5 +1,25 @@
# PXSourceList Release Notes
## 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.
## 2.0.1
- Add missing note to the 2.0.0 release notes about marking `-[PXSourceList delegate]` and `-[PXSourceList dataSource]` as unavailable using \_\_attribute\_\_.
## 2.0.0
### New Features
@@ -11,6 +31,7 @@
- Added a generic `PXSourceListItem` data source model class which can be used for easily constructing data source models without having to implement your own class.
### API Changes
- **Incompatible change.* Marked `-[PXSourceList delegate]` and -[PXSourceList dataSource]` as unavailable using the “unavailable” \_\_attribute\_\_. These methods shouldnt be used because of the internal implementation of PXSourceList, and have been documented as such since version 0.8. However, adding this \_\_attribute\_\_ is more robust because a compile-time error will be generated if you use either of these methods.
- Added view-based Source List delegate methods to `PXSourceListDelegate`, namely:
- `-sourceList:viewForItem:`
- `-sourceList:rowViewForItem:`
@@ -67,4 +88,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 ;)